Skip to content

Commit

Permalink
MDL-49329 admin: Introduce new \core\update\validator class
Browse files Browse the repository at this point in the history
This is not really new class. Originally, the validator was implemented
in the scope of the tool_installaddon plugin. But we need its features
in other parts at the core level (e.g. during the upgrade to validate
available missing dependencies or available updates). Looking back, it
was a mistake to have it implemented at the plugin level rather than the
core level.

So this patch moves the tool_installaddon_validator class to
\core\update\validator class, together with associated unit tests,
fixture files and strings. There were changes made in the
tool_installaddon to make use of this new class instead of the old one.

This is a great step towards the bright future, hopefully there won't be
many regressions.

AMOS BEGIN
 MOV [validationmsg_componentmatch,tool_installaddon],[validationmsg_componentmatch,core_plugin]
 MOV [validationmsg_componentmismatchname,tool_installaddon],[validationmsg_componentmismatchname,core_plugin]
 MOV [validationmsg_componentmismatchname_help,tool_installaddon],[validationmsg_componentmismatchname_help,core_plugin]
 MOV [validationmsg_componentmismatchname_info,tool_installaddon],[validationmsg_componentmismatchname_info,core_plugin]
 MOV [validationmsg_componentmismatchtype,tool_installaddon],[validationmsg_componentmismatchtype,core_plugin]
 MOV [validationmsg_componentmismatchtype_info,tool_installaddon],[validationmsg_componentmismatchtype_info,core_plugin]
 MOV [validationmsg_filenotexists,tool_installaddon],[validationmsg_filenotexists,core_plugin]
 MOV [validationmsg_filesnumber,tool_installaddon],[validationmsg_filesnumber,core_plugin]
 MOV [validationmsg_filestatus,tool_installaddon],[validationmsg_filestatus,core_plugin]
 MOV [validationmsg_filestatus_info,tool_installaddon],[validationmsg_filestatus_info,core_plugin]
 MOV [validationmsg_foundlangfile,tool_installaddon],[validationmsg_foundlangfile,core_plugin]
 MOV [validationmsg_maturity,tool_installaddon],[validationmsg_maturity,core_plugin]
 MOV [validationmsg_maturity_help,tool_installaddon],[validationmsg_maturity_help,core_plugin]
 MOV [validationmsg_missingcomponent,tool_installaddon],[validationmsg_missingcomponent,core_plugin]
 MOV [validationmsg_missingcomponent_help,tool_installaddon],[validationmsg_missingcomponent_help,core_plugin]
 MOV [validationmsg_missingcomponent_link,tool_installaddon],[validationmsg_missingcomponent_link,core_plugin]
 MOV [validationmsg_missingexpectedlangenfile,tool_installaddon],[validationmsg_missingexpectedlangenfile,core_plugin]
 MOV [validationmsg_missingexpectedlangenfile_info,tool_installaddon],[validationmsg_missingexpectedlangenfile_info,core_plugin]
 MOV [validationmsg_missinglangenfile,tool_installaddon],[validationmsg_missinglangenfile,core_plugin]
 MOV [validationmsg_missinglangenfolder,tool_installaddon],[validationmsg_missinglangenfolder,core_plugin]
 MOV [validationmsg_missingversion,tool_installaddon],[validationmsg_missingversion,core_plugin]
 MOV [validationmsg_missingversionphp,tool_installaddon],[validationmsg_missingversionphp,core_plugin]
 MOV [validationmsg_multiplelangenfiles,tool_installaddon],[validationmsg_multiplelangenfiles,core_plugin]
 MOV [validationmsg_onedir,tool_installaddon],[validationmsg_onedir,core_plugin]
 MOV [validationmsg_onedir_help,tool_installaddon],[validationmsg_onedir_help,core_plugin]
 MOV [validationmsg_pathwritable,tool_installaddon],[validationmsg_pathwritable,core_plugin]
 MOV [validationmsg_pluginversion,tool_installaddon],[validationmsg_pluginversion,core_plugin]
 MOV [validationmsg_release,tool_installaddon],[validationmsg_release,core_plugin]
 MOV [validationmsg_requiresmoodle,tool_installaddon],[validationmsg_requiresmoodle,core_plugin]
 MOV [validationmsg_rootdir,tool_installaddon],[validationmsg_rootdir,core_plugin]
 MOV [validationmsg_rootdir_help,tool_installaddon],[validationmsg_rootdir_help,core_plugin]
 MOV [validationmsg_rootdirinvalid,tool_installaddon],[validationmsg_rootdirinvalid,core_plugin]
 MOV [validationmsg_rootdirinvalid_help,tool_installaddon],[validationmsg_rootdirinvalid_help,core_plugin]
 MOV [validationmsg_targetexists,tool_installaddon],[validationmsg_targetexists,core_plugin]
 MOV [validationmsg_targetexists_help,tool_installaddon],[validationmsg_targetexists_help,core_plugin]
 MOV [validationmsg_unknowntype,tool_installaddon],[validationmsg_unknowntype,core_plugin]
 MOV [validationmsg_versionphpsyntax,tool_installaddon],[validationmsg_versionphpsyntax,core_plugin]
 MOV [validationmsglevel_debug,tool_installaddon],[validationmsglevel_debug,core_plugin]
 MOV [validationmsglevel_error,tool_installaddon],[validationmsglevel_error,core_plugin]
 MOV [validationmsglevel_info,tool_installaddon],[validationmsglevel_info,core_plugin]
 MOV [validationmsglevel_warning,tool_installaddon],[validationmsglevel_warning,core_plugin]
AMOS END
  • Loading branch information
mudrd8mz committed Oct 8, 2015
1 parent 0e442ee commit f2d8ed4
Show file tree
Hide file tree
Showing 42 changed files with 292 additions and 223 deletions.
41 changes: 0 additions & 41 deletions admin/tool/installaddon/lang/en/tool_installaddon.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,47 +58,6 @@
$string['remoterequestpluginfoexception'] = 'Oops... An error occurred while trying to obtain information about the plugin {$a->name} ({$a->component}) version {$a->version}. The plugin cannot be installed. Turn debugging mode on to see details of the error.';
$string['typedetectionfailed'] = 'Unable to detect the plugin type. Please choose the plugin type manually.';
$string['validation'] = 'Plugin package validation';
$string['validationmsg_componentmatch'] = 'Full component name';
$string['validationmsg_componentmismatchname'] = 'Plugin name mismatch';
$string['validationmsg_componentmismatchname_help'] = 'Some ZIP packages, such as those generated by Github, may contain an incorrect root directory name. You need to fix the name of the root directory to match the declared plugin name.';
$string['validationmsg_componentmismatchname_info'] = 'The plugin declares its name is \'{$a}\' but that does not match the name of the root directory.';
$string['validationmsg_componentmismatchtype'] = 'Plugin type mismatch';
$string['validationmsg_componentmismatchtype_info'] = 'Expected type \'{$a->expected}\' but the plugin declares its type is \'{$a->found}\'.';
$string['validationmsg_filenotexists'] = 'Extracted file not found';
$string['validationmsg_filesnumber'] = 'Not enough files found in the package';
$string['validationmsg_filestatus'] = 'Unable to extract all files';
$string['validationmsg_filestatus_info'] = 'Attempting to extract file {$a->file} resulted in error \'{$a->status}\'.';
$string['validationmsg_foundlangfile'] = 'Found language file';
$string['validationmsg_maturity'] = 'Declared maturity level';
$string['validationmsg_maturity_help'] = 'The plugin can declare its maturity level. If the maintainer considers the plugin stable, the declared maturity level will read MATURITY_STABLE. All other maturity levels (such as alpha or beta) should be considered unstable and a warning is raised.';
$string['validationmsg_missingcomponent'] = 'Plugin does not declare its component name';
$string['validationmsg_missingcomponent_help'] = 'All plugins must provide their full component name via the `$plugin->component` declaration in the version.php file.';
$string['validationmsg_missingcomponent_link'] = 'Development:version.php';
$string['validationmsg_missingexpectedlangenfile'] = 'English language file name mismatch';
$string['validationmsg_missingexpectedlangenfile_info'] = 'The given plugin type is missing the expected English language file {$a}.';
$string['validationmsg_missinglangenfile'] = 'No English language file found';
$string['validationmsg_missinglangenfolder'] = 'Missing English language folder';
$string['validationmsg_missingversion'] = 'Plugin does not declare its version';
$string['validationmsg_missingversionphp'] = 'File version.php not found';
$string['validationmsg_multiplelangenfiles'] = 'Multiple English language files found';
$string['validationmsg_onedir'] = 'Invalid structure of the ZIP package.';
$string['validationmsg_onedir_help'] = 'The ZIP package must contain just one root directory that holds the plugin code. The name of that root directory must match the name of the plugin.';
$string['validationmsg_pathwritable'] = 'Write access check';
$string['validationmsg_pluginversion'] = 'Plugin version';
$string['validationmsg_release'] = 'Plugin release';
$string['validationmsg_requiresmoodle'] = 'Required Moodle version';
$string['validationmsg_rootdir'] = 'Name of the plugin to be installed';
$string['validationmsg_rootdir_help'] = 'The name of the root directory in the ZIP package forms the name of the plugin to be installed. If the name is not correct, you may wish to rename the root directory in the ZIP prior to installing the plugin.';
$string['validationmsg_rootdirinvalid'] = 'Invalid plugin name';
$string['validationmsg_rootdirinvalid_help'] = 'The name of the root directory in the ZIP package violates formal syntax requirements. Some ZIP packages, such as those generated by Github, may contain an incorrect root directory name. You need to fix the name of the root directory to match the plugin name.';
$string['validationmsg_targetexists'] = 'Target location already exists';
$string['validationmsg_targetexists_help'] = 'The directory that the plugin is to be installed to must not yet exist.';
$string['validationmsg_unknowntype'] = 'Unknown plugin type';
$string['validationmsg_versionphpsyntax'] = 'Unsupported syntax detected in version.php file';
$string['validationmsglevel_debug'] = 'Debug';
$string['validationmsglevel_error'] = 'Error';
$string['validationmsglevel_info'] = 'OK';
$string['validationmsglevel_warning'] = 'Warning';
$string['validationresult0'] = 'Validation failed!';
$string['validationresult0_help'] = 'A serious problem was detected and so it is not safe to install the plugin. See the validation log messages for details.';
$string['validationresult1'] = 'Validation passed!';
Expand Down
71 changes: 14 additions & 57 deletions admin/tool/installaddon/renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class tool_installaddon_renderer extends plugin_renderer_base {
/** @var tool_installaddon_installer */
protected $installer = null;

/** @var tool_installaddon_validator */
/** @var \core\update\validator */
protected $validator = null;

/**
Expand All @@ -55,12 +55,12 @@ public function set_installer_instance(tool_installaddon_installer $installer) {
}

/**
* Sets the tool_installaddon_validator instance being used.
* Sets the \core\update\validator instance being used.
*
* @throws coding_exception if the validator has been already set
* @param tool_installaddon_validator $validator
* @param \core\update\validator $validator
*/
public function set_validator_instance(tool_installaddon_validator $validator) {
public function set_validator_instance(\core\update\validator $validator) {
if (is_null($this->validator)) {
$this->validator = $validator;
} else {
Expand Down Expand Up @@ -110,11 +110,8 @@ public function validation_page() {
throw new coding_exception('Validator instance has not been set.');
}

$out = $this->output->header();
$out .= $this->validation_page_heading();
$out = $this->validation_page_heading();
$out .= $this->validation_page_messages();
$out .= $this->validation_page_continue();
$out .= $this->output->footer();

return $out;
}
Expand Down Expand Up @@ -337,27 +334,17 @@ protected function validation_page_messages() {
continue;
}

$msgstatus = get_string('validationmsglevel_'.$message->level, 'tool_installaddon');
$msgtext = $msgtext = s($message->msgcode);
if (is_null($message->addinfo)) {
$msginfo = '';
} else {
$msgstatus = $validator->message_level_name($message->level);
$msgtext = $validator->message_code_name($message->msgcode);
$msginfo = $validator->message_code_info($message->msgcode, $message->addinfo);
if (empty($msginfo) and $message->addinfo !== null) {
$msginfo = html_writer::tag('pre', s(print_r($message->addinfo, true)));
}
$msghelp = '';

// Replace the message code with the string if it is defined.
if ($stringman->string_exists('validationmsg_'.$message->msgcode, 'tool_installaddon')) {
$msgtext = get_string('validationmsg_'.$message->msgcode, 'tool_installaddon');
// And check for the eventual help, too.
if ($stringman->string_exists('validationmsg_'.$message->msgcode.'_help', 'tool_installaddon')) {
$msghelp = $this->output->help_icon('validationmsg_'.$message->msgcode, 'tool_installaddon');
}
}

// Re-format the message info using a string if it is define.
if (!is_null($message->addinfo) and $stringman->string_exists('validationmsg_'.$message->msgcode.'_info', 'tool_installaddon')) {
$msginfo = get_string('validationmsg_'.$message->msgcode.'_info', 'tool_installaddon', $message->addinfo);
$msghelpicon = $validator->message_help_icon($message->msgcode);
if ($msghelpicon) {
$msghelp = $this->output->render($msghelpicon);
} else {
$msghelp = '';
}

$row = new html_table_row(array($msgstatus, $msgtext.$msghelp, $msginfo));
Expand All @@ -368,34 +355,4 @@ protected function validation_page_messages() {

return html_writer::table($table);
}

/**
* Renders widgets to continue from the validation results page
*
* @return string
*/
protected function validation_page_continue() {

$output = '';
$conturl = $this->validator->get_continue_url();

if (is_null($conturl)) {
$contbutton = '';

} else {
$contbutton = $this->output->single_button(
$conturl, get_string('installaddon', 'tool_installaddon'), 'post',
array('class' => 'singlebutton continuebutton'));
$output .= $this->output->heading(get_string('acknowledgement', 'tool_installaddon'), 3);
$output .= $this->output->container(get_string('acknowledgementtext', 'tool_installaddon'));
}

$cancelbutton = $this->output->single_button(
new moodle_url('/admin/tool/installaddon/index.php'), get_string('cancel', 'core'), 'get',
array('class' => 'singlebutton cancelbutton'));

$output .= $this->output->container($cancelbutton.$contbutton, 'postvalidationbuttons');

return $output;
}
}
8 changes: 6 additions & 2 deletions admin/tool/installaddon/tests/installer_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ public function test_get_addons_repository_url() {
}

public function test_extract_installfromzip_file() {
global $CFG;

$jobid = md5(rand().uniqid('test_', true));
$sourcedir = make_temp_directory('tool_installaddon/'.$jobid.'/source');
$contentsdir = make_temp_directory('tool_installaddon/'.$jobid.'/contents');
copy(dirname(__FILE__).'/fixtures/zips/invalidroot.zip', $sourcedir.'/testinvalidroot.zip');
copy($CFG->libdir.'/tests/fixtures/update_validator/zips/invalidroot.zip', $sourcedir.'/testinvalidroot.zip');

$installer = tool_installaddon_installer::instance();
$files = $installer->extract_installfromzip_file($sourcedir.'/testinvalidroot.zip', $contentsdir, 'fixed_root');
Expand Down Expand Up @@ -145,9 +147,11 @@ public function test_move_directory() {
}

public function test_detect_plugin_component() {
global $CFG;

$jobid = md5(rand().uniqid('test_', true));
$workdir = make_temp_directory('tool_installaddon/'.$jobid.'/version');
$zipfile = __DIR__.'/fixtures/zips/bar.zip';
$zipfile = $CFG->libdir.'/tests/fixtures/update_validator/zips/bar.zip';
$installer = tool_installaddon_installer::instance();
$this->assertEquals('foo_bar', $installer->detect_plugin_component($zipfile, $workdir));
}
Expand Down
30 changes: 22 additions & 8 deletions admin/tool/installaddon/validate.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,38 @@
$zipcontentfiles = $installer->extract_installfromzip_file($zipfilepath, $zipcontentpath, $rootdir);

// Validate the contents of the plugin ZIP file.
$validator = tool_installaddon_validator::instance($zipcontentpath, $zipcontentfiles);
$validator = \core\update\validator::instance($zipcontentpath, $zipcontentfiles);
$validator->assert_plugin_type($plugintype);
$validator->assert_moodle_version($CFG->version);
$result = $validator->execute();

// Display the validation results.
$output = $PAGE->get_renderer('tool_installaddon');
$output->set_installer_instance($installer);
$output->set_validator_instance($validator);

echo $output->header();
echo $output->validation_page();

if ($result) {
$validator->set_continue_url(new moodle_url('/admin/tool/installaddon/deploy.php', array(
$conturl = new moodle_url('/admin/tool/installaddon/deploy.php', array(
'sesskey' => sesskey(),
'jobid' => $jobid,
'type' => $plugintype,
'name' => $validator->get_rootdir())));
'name' => $validator->get_rootdir())
);
$contbutton = $output->single_button($conturl, get_string('installaddon', 'tool_installaddon'), 'post',
array('class' => 'singlebutton continuebutton'));
echo $output->heading(get_string('acknowledgement', 'tool_installaddon'), 3);
echo $output->container(get_string('acknowledgementtext', 'tool_installaddon'));

} else {
$contbutton = '';
fulldelete($CFG->tempdir.'/tool_installaddon/'.$jobid);
}

// Display the validation results.
$output = $PAGE->get_renderer('tool_installaddon');
$output->set_installer_instance($installer);
$output->set_validator_instance($validator);
echo $output->validation_page();
$cancelbutton = $output->single_button(new moodle_url('/admin/tool/installaddon/index.php'), get_string('cancel', 'core'),
'get', array('class' => 'singlebutton cancelbutton'));

echo $output->container($cancelbutton.$contbutton, 'postvalidationbuttons');
echo $output->footer();
41 changes: 41 additions & 0 deletions lang/en/plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,47 @@
$string['uninstallextraconfirmenrol'] = 'There are {$a->enrolments} user enrolments.';
$string['uninstallextraconfirmmod'] = 'There are {$a->instances} instances of this module in {$a->courses} courses.';
$string['uninstalling'] = 'Uninstalling {$a->name}';
$string['validationmsg_componentmatch'] = 'Full component name';
$string['validationmsg_componentmismatchname'] = 'Plugin name mismatch';
$string['validationmsg_componentmismatchname_help'] = 'Some ZIP packages, such as those generated by Github, may contain an incorrect root directory name. You need to fix the name of the root directory to match the declared plugin name.';
$string['validationmsg_componentmismatchname_info'] = 'The plugin declares its name is \'{$a}\' but that does not match the name of the root directory.';
$string['validationmsg_componentmismatchtype'] = 'Plugin type mismatch';
$string['validationmsg_componentmismatchtype_info'] = 'Expected type \'{$a->expected}\' but the plugin declares its type is \'{$a->found}\'.';
$string['validationmsg_filenotexists'] = 'Extracted file not found';
$string['validationmsg_filesnumber'] = 'Not enough files found in the package';
$string['validationmsg_filestatus'] = 'Unable to extract all files';
$string['validationmsg_filestatus_info'] = 'Attempting to extract file {$a->file} resulted in error \'{$a->status}\'.';
$string['validationmsg_foundlangfile'] = 'Found language file';
$string['validationmsg_maturity'] = 'Declared maturity level';
$string['validationmsg_maturity_help'] = 'The plugin can declare its maturity level. If the maintainer considers the plugin stable, the declared maturity level will read MATURITY_STABLE. All other maturity levels (such as alpha or beta) should be considered unstable and a warning is raised.';
$string['validationmsg_missingcomponent'] = 'Plugin does not declare its component name';
$string['validationmsg_missingcomponent_help'] = 'All plugins must provide their full component name via the `$plugin->component` declaration in the version.php file.';
$string['validationmsg_missingcomponent_link'] = 'Development:version.php';
$string['validationmsg_missingexpectedlangenfile'] = 'English language file name mismatch';
$string['validationmsg_missingexpectedlangenfile_info'] = 'The given plugin type is missing the expected English language file {$a}.';
$string['validationmsg_missinglangenfile'] = 'No English language file found';
$string['validationmsg_missinglangenfolder'] = 'Missing English language folder';
$string['validationmsg_missingversion'] = 'Plugin does not declare its version';
$string['validationmsg_missingversionphp'] = 'File version.php not found';
$string['validationmsg_multiplelangenfiles'] = 'Multiple English language files found';
$string['validationmsg_onedir'] = 'Invalid structure of the ZIP package.';
$string['validationmsg_onedir_help'] = 'The ZIP package must contain just one root directory that holds the plugin code. The name of that root directory must match the name of the plugin.';
$string['validationmsg_pathwritable'] = 'Write access check';
$string['validationmsg_pluginversion'] = 'Plugin version';
$string['validationmsg_release'] = 'Plugin release';
$string['validationmsg_requiresmoodle'] = 'Required Moodle version';
$string['validationmsg_rootdir'] = 'Name of the plugin to be installed';
$string['validationmsg_rootdir_help'] = 'The name of the root directory in the ZIP package forms the name of the plugin to be installed. If the name is not correct, you may wish to rename the root directory in the ZIP prior to installing the plugin.';
$string['validationmsg_rootdirinvalid'] = 'Invalid plugin name';
$string['validationmsg_rootdirinvalid_help'] = 'The name of the root directory in the ZIP package violates formal syntax requirements. Some ZIP packages, such as those generated by Github, may contain an incorrect root directory name. You need to fix the name of the root directory to match the plugin name.';
$string['validationmsg_targetexists'] = 'Target location already exists';
$string['validationmsg_targetexists_help'] = 'The directory that the plugin is to be installed to must not yet exist.';
$string['validationmsg_unknowntype'] = 'Unknown plugin type';
$string['validationmsg_versionphpsyntax'] = 'Unsupported syntax detected in version.php file';
$string['validationmsglevel_debug'] = 'Debug';
$string['validationmsglevel_error'] = 'Error';
$string['validationmsglevel_info'] = 'OK';
$string['validationmsglevel_warning'] = 'Warning';
$string['version'] = 'Version';
$string['versiondb'] = 'Current version';
$string['versiondisk'] = 'New version';
Loading

0 comments on commit f2d8ed4

Please sign in to comment.