MDL-87648 core: Support multiple tests within a check
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
issueNumber: MDL-87648
|
||||
notes:
|
||||
core:
|
||||
- message: >
|
||||
The Checks API now supports multiple results being returned for a single
|
||||
instance of `\core\check\check`.
|
||||
|
||||
|
||||
To support this a new `get_results(): array;` method has been created
|
||||
which returns an array of `\core\check\result` objects.
|
||||
type: improved
|
||||
+34
-32
@@ -110,47 +110,49 @@ $exitcode = $exitcodes[result::OK];
|
||||
|
||||
foreach ($checks as $check) {
|
||||
$ref = $check->get_ref();
|
||||
$result = $check->get_result();
|
||||
|
||||
$status = $result->get_status();
|
||||
$checkexitcode = $exitcodes[$status];
|
||||
foreach ($check->get_results() as $result) {
|
||||
$status = $result->get_status();
|
||||
$checkexitcode = $exitcodes[$status];
|
||||
|
||||
// Summary is treated as html.
|
||||
$summary = $result->get_summary();
|
||||
$summary = html_to_text($summary, 60, false);
|
||||
// Summary is treated as html.
|
||||
$summary = $result->get_summary();
|
||||
$summary = html_to_text($summary, 60, false);
|
||||
|
||||
if ($checkexitcode > $exitcode) {
|
||||
$exitcode = $checkexitcode;
|
||||
$header = $exitlabel[$status] . ': ' . $check->get_name() . " (" . $check->get_ref() . ")\n";
|
||||
}
|
||||
if ($checkexitcode > $exitcode) {
|
||||
$exitcode = $checkexitcode;
|
||||
$header = $exitlabel[$status] . ': ' . $check->get_name() . " (" . $check->get_ref() . ")\n";
|
||||
}
|
||||
|
||||
if (empty($messages[$status])) {
|
||||
$messages[$status] = $result;
|
||||
}
|
||||
if (empty($messages[$status])) {
|
||||
$messages[$status] = $result;
|
||||
}
|
||||
|
||||
$len = strlen(get_string('status' . $status));
|
||||
$len = strlen(get_string('status' . $status));
|
||||
|
||||
if ($options['verbose'] ||
|
||||
$status == result::WARNING ||
|
||||
$status == result::CRITICAL ||
|
||||
$status == result::ERROR) {
|
||||
if (
|
||||
$options['verbose']
|
||||
|| $status == result::WARNING
|
||||
|| $status == result::CRITICAL
|
||||
|| $status == result::ERROR
|
||||
) {
|
||||
$output .= sprintf(
|
||||
$format,
|
||||
$OUTPUT->check_result($result),
|
||||
sprintf('%s (%s)', $check->get_name(), $ref),
|
||||
);
|
||||
|
||||
$output .= sprintf(
|
||||
$format,
|
||||
$OUTPUT->check_result($result),
|
||||
sprintf('%s (%s)', $check->get_name(), $ref)
|
||||
);
|
||||
$summary = str_replace("\n", "\n" . $prefix . ' ', $summary);
|
||||
$output .= sprintf($format, '', ' ' . $summary);
|
||||
$output .= sprintf($format, '', ' ' . html_to_text($result->get_details(), width: 0, dolinks: false));
|
||||
|
||||
$summary = str_replace("\n", "\n" . $prefix . ' ', $summary);
|
||||
$output .= sprintf($format, '', ' ' . $summary);
|
||||
$output .= sprintf($format, '', ' ' . html_to_text($result->get_details(), width: 0, dolinks: false));
|
||||
|
||||
if ($options['verbose']) {
|
||||
$actionlink = $check->get_action_link();
|
||||
if ($actionlink) {
|
||||
$output .= sprintf( $format, '', ' ' . $actionlink->url);
|
||||
if ($options['verbose']) {
|
||||
$actionlink = $check->get_action_link();
|
||||
if ($actionlink) {
|
||||
$output .= sprintf($format, '', ' ' . $actionlink->url);
|
||||
}
|
||||
$output .= sprintf($format, '', '');
|
||||
}
|
||||
$output .= sprintf( $format, '', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,5 +128,12 @@ abstract class check {
|
||||
*/
|
||||
abstract public function get_result(): result;
|
||||
|
||||
/**
|
||||
* Return all results for this check
|
||||
*
|
||||
* @return result[]
|
||||
*/
|
||||
public function get_results(): array {
|
||||
return [$this->get_result()];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,9 +79,11 @@ class router extends check {
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function get_result(): result {
|
||||
public function get_results(): array {
|
||||
global $CFG;
|
||||
|
||||
$results = [];
|
||||
|
||||
if (empty($CFG->routerconfigured)) {
|
||||
$result = new result(
|
||||
result::ERROR,
|
||||
@@ -91,7 +93,12 @@ class router extends check {
|
||||
]),
|
||||
);
|
||||
|
||||
return $result;
|
||||
return [$result];
|
||||
} else {
|
||||
$results[] = new result(
|
||||
result::OK,
|
||||
get_string('routerconfigurationset', 'admin'),
|
||||
);
|
||||
}
|
||||
|
||||
// The router is marked as configured. Check if it actually works though.
|
||||
@@ -128,9 +135,14 @@ class router extends check {
|
||||
'statuscode' => $code,
|
||||
'statuscodetitle' => $codetitle,
|
||||
];
|
||||
if ($code !== $test['expectedcode']) {
|
||||
if ($code === $test['expectedcode']) {
|
||||
$results[] = new result(
|
||||
result::OK,
|
||||
get_string('routerconfigureddetails', 'admin', $resultprops),
|
||||
);
|
||||
} else {
|
||||
$expectedgot = get_string('routerexpectedgot', 'admin', $resultprops);
|
||||
return new result(
|
||||
$results[] = new result(
|
||||
result::ERROR,
|
||||
get_string($test['failfeedbackstr'], 'admin', $resultprops),
|
||||
get_string('routernotconfigureddetailwithurl', 'admin', $resultprops) . " {$expectedgot}",
|
||||
@@ -142,17 +154,30 @@ class router extends check {
|
||||
}
|
||||
}
|
||||
|
||||
return new result(
|
||||
result::OK,
|
||||
get_string('routerconfiguredok', 'admin'),
|
||||
);
|
||||
return $results;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function get_action_link(): ?action_link {
|
||||
return new action_link(
|
||||
new \core\url(get_docs_url('Configuring_the_Router')),
|
||||
get_string('routerdocs', 'admin'),
|
||||
public function get_result(): result {
|
||||
// Aggregate the results.
|
||||
$failed = array_filter(
|
||||
$this->get_results(),
|
||||
fn ($result) => $result->get_status() !== result::OK,
|
||||
);
|
||||
|
||||
if (empty($failed)) {
|
||||
// Nothing failed. Return the OK result.
|
||||
return new result(
|
||||
result::OK,
|
||||
get_string('routerconfiguredok', 'admin'),
|
||||
);
|
||||
}
|
||||
|
||||
// Some form of failure. Return the generic failure result.
|
||||
return new result(
|
||||
result::ERROR,
|
||||
get_string('routerconfiguredwithissues', 'admin'),
|
||||
get_string('routerconfiguredwithissuesdetail', 'admin', ['count' => count($failed)]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
namespace core\check;
|
||||
|
||||
use core\output\action_link;
|
||||
|
||||
/**
|
||||
* A check object returns a result object
|
||||
*
|
||||
@@ -29,7 +31,6 @@ namespace core\check;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class result implements \renderable {
|
||||
|
||||
/**
|
||||
* This is used to notify if a check does not apply.
|
||||
*
|
||||
@@ -99,7 +100,14 @@ class result implements \renderable {
|
||||
* This may be a large amount of preformatted html text, possibly describing all the
|
||||
* different states and actions to address them.
|
||||
*/
|
||||
protected $details = '';
|
||||
protected string $details = '';
|
||||
|
||||
/**
|
||||
* @var null|action_link An action link which is more specific than the general check link, if relvant
|
||||
*
|
||||
* If no specific check link is specified, then the check link will be used.
|
||||
*/
|
||||
protected ?action_link $actionlink = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -107,11 +115,18 @@ class result implements \renderable {
|
||||
* @param string $status code
|
||||
* @param string $summary a 1 liner summary
|
||||
* @param string $details as a html chunk
|
||||
* @param ?action_link $details An action link which is more specific than the general check link, if relevant
|
||||
*/
|
||||
public function __construct($status, $summary, $details = '') {
|
||||
public function __construct(
|
||||
string $status,
|
||||
string $summary,
|
||||
string $details = '',
|
||||
?action_link $actionlink = null,
|
||||
) {
|
||||
$this->status = $status;
|
||||
$this->summary = $summary;
|
||||
$this->details = $details;
|
||||
$this->actionlink = $actionlink;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,5 +181,13 @@ class result implements \renderable {
|
||||
public function get_template_name(): string {
|
||||
return 'core/check/result';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an action link if a more specific one was specified.
|
||||
*
|
||||
* @return null|action_link
|
||||
*/
|
||||
public function get_action_link(): ?action_link {
|
||||
return $this->actionlink;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,26 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\check;
|
||||
|
||||
use core\output\html_writer;
|
||||
|
||||
/**
|
||||
* A table of check results
|
||||
* A table of check results.
|
||||
*
|
||||
* @package core
|
||||
* @category check
|
||||
* @copyright 2020 Brendan Heywood <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core\check;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* A table of check results
|
||||
*
|
||||
* @copyright 2020 Brendan Heywood <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class table implements \renderable {
|
||||
|
||||
class table implements \core\output\renderable {
|
||||
/**
|
||||
* @var \moodle_url $url
|
||||
*/
|
||||
@@ -49,6 +42,13 @@ class table implements \renderable {
|
||||
*/
|
||||
public $detail = '';
|
||||
|
||||
/**
|
||||
* The name of the check that was requested.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $checkname = '';
|
||||
|
||||
/**
|
||||
* @var array $checks shown in this table
|
||||
*/
|
||||
@@ -62,7 +62,6 @@ class table implements \renderable {
|
||||
* @param string $detail check to focus on
|
||||
*/
|
||||
public function __construct($type, $url, $detail = '') {
|
||||
|
||||
// We may need a bit more memory and this may take a long time to process.
|
||||
\raise_memory_limit(MEMORY_EXTRA);
|
||||
\core_php_time_limit::raise();
|
||||
@@ -70,6 +69,7 @@ class table implements \renderable {
|
||||
$this->type = $type;
|
||||
$this->url = $url;
|
||||
$this->checks = \core\check\manager::get_checks($type);
|
||||
$this->checkname = $detail;
|
||||
|
||||
if ($detail) {
|
||||
$this->checks = array_filter($this->checks, function($check) use ($detail) {
|
||||
@@ -84,63 +84,91 @@ class table implements \renderable {
|
||||
/**
|
||||
* Render a table of checks
|
||||
*
|
||||
* @param renderer $output to use
|
||||
* @param \core\output\renderer $output to use
|
||||
* @return string html output
|
||||
*/
|
||||
public function render($output) {
|
||||
$html = '';
|
||||
|
||||
$table = new \html_table();
|
||||
$table = new \core_table\output\html_table();
|
||||
$table->data = [];
|
||||
$table->head = [
|
||||
get_string('status'),
|
||||
get_string('check'),
|
||||
get_string('summary'),
|
||||
get_string('action'),
|
||||
];
|
||||
$table->colclasses = [
|
||||
'rightalign status',
|
||||
'leftalign check',
|
||||
'leftalign summary',
|
||||
'leftalign action',
|
||||
];
|
||||
$table->head = [get_string('status')];
|
||||
$table->colclasses = ['rightalign status'];
|
||||
|
||||
if (empty($this->checkname)) {
|
||||
$table->head[] = get_string('check');
|
||||
$table->colclasses[] = 'leftalign check';
|
||||
} else {
|
||||
$html .= html_writer::tag('h3', $this->detail->get_name());
|
||||
}
|
||||
|
||||
$table->head[] = get_string('summary');
|
||||
$table->colclasses[] = 'leftalign summary';
|
||||
$table->head[] = get_string('action');
|
||||
$table->colclasses[] = 'leftalign action';
|
||||
|
||||
$table->id = $this->type . 'reporttable';
|
||||
$table->attributes = ['class' => 'admintable ' . $this->type . 'report table generaltable'];
|
||||
|
||||
$fails = [];
|
||||
foreach ($this->checks as $check) {
|
||||
$ref = $check->get_ref();
|
||||
$result = $check->get_result();
|
||||
$component = $check->get_component();
|
||||
$actionlink = $check->get_action_link();
|
||||
|
||||
$link = new \moodle_url($this->url, ['detail' => $ref]);
|
||||
|
||||
$row = [];
|
||||
$row[] = $output->check_result($result);
|
||||
$row[] = $output->action_link($link, $check->get_name());
|
||||
$results = empty($this->checkname)
|
||||
? [$check->get_result()]
|
||||
: $check->get_results();
|
||||
|
||||
$row[] = $result->get_summary()
|
||||
. '<br>'
|
||||
. \html_writer::start_tag('small')
|
||||
. $output->action_link($link, get_string('moreinfo'))
|
||||
. \html_writer::end_tag('small');
|
||||
if ($actionlink) {
|
||||
$row[] = $output->render($actionlink);
|
||||
} else {
|
||||
$row[] = '';
|
||||
foreach ($results as $result) {
|
||||
$row = [];
|
||||
if ($result->get_status() !== result::OK) {
|
||||
$fails[] = $result;
|
||||
}
|
||||
$row[] = $output->check_result($result);
|
||||
|
||||
if (empty($this->checkname)) {
|
||||
$row[] = $output->action_link($link, $check->get_name());
|
||||
}
|
||||
|
||||
$row[] = $result->get_summary()
|
||||
. '<br>'
|
||||
. \html_writer::start_tag('small')
|
||||
. $output->action_link($link, get_string('moreinfo'))
|
||||
. \html_writer::end_tag('small');
|
||||
|
||||
$actionlink = $result->get_action_link() ?? $check->get_action_link();
|
||||
if ($actionlink) {
|
||||
$row[] = $output->render($actionlink);
|
||||
} else {
|
||||
$row[] = '';
|
||||
}
|
||||
|
||||
$table->data[] = $row;
|
||||
}
|
||||
|
||||
$table->data[] = $row;
|
||||
}
|
||||
$html = \html_writer::table($table);
|
||||
$html .= \html_writer::table($table);
|
||||
|
||||
if ($this->detail && $result) {
|
||||
$details = $result->get_details();
|
||||
$details = array_filter(array_map(
|
||||
fn ($result) => $result->get_details(),
|
||||
$fails,
|
||||
));
|
||||
if (count($details) > 0) {
|
||||
$html .= $output->heading(get_string('details'), 3);
|
||||
|
||||
if (!empty($details)) {
|
||||
$html .= $output->heading(get_string('details'), 3);
|
||||
$html .= $output->box($details, 'generalbox boxwidthnormal boxaligncenter');
|
||||
if (count($details) === 1) {
|
||||
$result = reset($fails);
|
||||
$html .= $output->box($result->get_details(), 'generalbox boxwidthnormal boxaligncenter');
|
||||
} else {
|
||||
$html .= html_writer::start_tag('ul');
|
||||
foreach ($details as $detail) {
|
||||
$html .= html_writer::tag('li', $detail);
|
||||
}
|
||||
$html .= html_writer::end_tag('ul');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->detail) {
|
||||
$html .= $output->continue_button($this->url);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user