diff --git a/admin/tool/installaddon/classes/installfromzip_form.php b/admin/tool/installaddon/classes/installfromzip_form.php index 9942679cb7d..18552faadb7 100644 --- a/admin/tool/installaddon/classes/installfromzip_form.php +++ b/admin/tool/installaddon/classes/installfromzip_form.php @@ -43,6 +43,9 @@ class tool_installaddon_installfromzip extends moodleform { $mform = $this->_form; $installer = $this->_customdata['installer']; + $mform->addElement('header', 'general', get_string('installfromzip', 'tool_installaddon')); + $mform->addHelpButton('general', 'installfromzip', 'tool_installaddon'); + $options = $installer->get_plugin_types_menu(); $mform->addElement('select', 'plugintype', get_string('installfromziptype', 'tool_installaddon'), $options, array('id' => 'tool_installaddon_installfromzip_plugintype')); @@ -58,6 +61,11 @@ class tool_installaddon_installfromzip extends moodleform { $mform->addHelpButton('zipfile', 'installfromzipfile', 'tool_installaddon'); $mform->addRule('zipfile', null, 'required', null, 'client'); + $mform->addElement('text', 'rootdir', get_string('installfromziprootdir', 'tool_installaddon')); + $mform->addHelpButton('rootdir', 'installfromziprootdir', 'tool_installaddon'); + $mform->setType('rootdir', PARAM_PLUGIN); + $mform->setAdvanced('rootdir'); + $mform->addElement('checkbox', 'acknowledgement', get_string('acknowledgement', 'tool_installaddon'), ' '.get_string('acknowledgementtext', 'tool_installaddon')); $mform->addRule('acknowledgement', get_string('acknowledgementmust', 'tool_installaddon'), 'required', null, 'client'); diff --git a/admin/tool/installaddon/renderer.php b/admin/tool/installaddon/renderer.php index e670c6d5e08..0cc273dd8c6 100644 --- a/admin/tool/installaddon/renderer.php +++ b/admin/tool/installaddon/renderer.php @@ -37,6 +37,9 @@ class tool_installaddon_renderer extends plugin_renderer_base { /** @var tool_installaddon_installer */ protected $installer = null; + /** @var tool_installaddon_validator */ + protected $validator = null; + /** * Sets the tool_installaddon_installer instance being used. * @@ -51,6 +54,20 @@ class tool_installaddon_renderer extends plugin_renderer_base { } } + /** + * Sets the tool_installaddon_validator instance being used. + * + * @throws coding_exception if the validator has been already set + * @param tool_installaddon_validator $validator + */ + public function set_validator_instance(tool_installaddon_validator $validator) { + if (is_null($this->validator)) { + $this->validator = $validator; + } else { + throw new coding_exception('Attempting to reset the validator instance.'); + } + } + /** * Defines the index page layout * @@ -58,6 +75,10 @@ class tool_installaddon_renderer extends plugin_renderer_base { */ public function index_page() { + if (is_null($this->installer)) { + throw new coding_exception('Installer instance has not been set.'); + } + $permcheckurl = new moodle_url('/admin/tool/installaddon/permcheck.php'); $this->page->requires->yui_module('moodle-tool_installaddon-permcheck', 'M.tool_installaddon.permcheck.init', array(array('permcheckurl' => $permcheckurl->out()))); @@ -73,6 +94,33 @@ class tool_installaddon_renderer extends plugin_renderer_base { return $out; } + /** + * Defines the validation results page layout + * + * @return string + */ + public function validation_page() { + + if (is_null($this->installer)) { + throw new coding_exception('Installer instance has not been set.'); + } + + if (is_null($this->validator)) { + throw new coding_exception('Validator instance has not been set.'); + } + + $out = $this->output->header(); + $out .= $this->validation_page_heading(); + $out .= $this->validation_page_messages(); + $out .= $this->validation_page_continue(); + $out .= $this->output->footer(); + + return $out; + + } + + // End of the external API ///////////////////////////////////////////////// + /** * Renders the index page heading * @@ -117,4 +165,116 @@ class tool_installaddon_renderer extends plugin_renderer_base { return $out; } + + /** + * Renders the page title and the overall validation verdict + * + * @return string + */ + protected function validation_page_heading() { + + $heading = $this->output->heading(get_string('validation', 'tool_installaddon')); + + if ($this->validator->get_result()) { + $status = $this->output->container( + html_writer::span(get_string('validationresult1', 'tool_installaddon'), 'verdict'). + $this->output->help_icon('validationresult1', 'tool_installaddon'), + array('validationresult', 'success') + ); + } else { + $status = $this->output->container( + html_writer::span(get_string('validationresult0', 'tool_installaddon'), 'verdict'). + $this->output->help_icon('validationresult0', 'tool_installaddon'), + array('validationresult', 'failure') + ); + } + + return $heading . $status; + } + + /** + * Renders validation log messages. + * + * @return string + */ + protected function validation_page_messages() { + + $validator = $this->validator; // We need this to be able to use their constants. + $messages = $validator->get_messages(); + + if (empty($messages)) { + return ''; + } + + $table = new html_table(); + $table->attributes['class'] = 'validationmessages generaltable'; + $table->head = array( + get_string('validationresultstatus', 'tool_installaddon'), + get_string('validationresultmsg', 'tool_installaddon'), + get_string('validationresultinfo', 'tool_installaddon') + ); + $table->colclasses = array('msgstatus', 'msgtext', 'msginfo'); + + $stringman = get_string_manager(); + + foreach ($messages as $message) { + + if ($message->level === $validator::DEBUG and !debugging()) { + continue; + } + + $msgstatus = get_string('validationmsglevel_'.$message->level, 'tool_installaddon'); + $msgtext = $msgtext = s($message->msgcode); + if (is_null($message->addinfo)) { + $msginfo = ''; + } else { + $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); + } + + $row = new html_table_row(array($msgstatus, $msgtext.$msghelp, $msginfo)); + $row->attributes['class'] = 'level-'.$message->level.' '.$message->msgcode; + + $table->data[] = $row; + } + + return html_writer::table($table); + } + + /** + * Renders widgets to continue from the validation results page + * + * @return string + */ + protected function validation_page_continue() { + + $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')); + } + + $cancelbutton = $this->output->single_button( + new moodle_url('/admin/tool/installaddon/index.php'), get_string('cancel', 'core'), 'get', + array('class' => 'singlebutton cancelbutton')); + + return $this->output->container($cancelbutton.$contbutton, 'postvalidationbuttons'); + } } diff --git a/admin/tool/installaddon/settings.php b/admin/tool/installaddon/settings.php index 326f0309a5a..0c03c736fb1 100644 --- a/admin/tool/installaddon/settings.php +++ b/admin/tool/installaddon/settings.php @@ -29,6 +29,11 @@ if ($hassiteconfig and empty($CFG->disableonclickaddoninstall)) { $ADMIN->add('modules', new admin_externalpage('tool_installaddon_index', get_string('installaddons', 'tool_installaddon'), - "$CFG->wwwroot/$CFG->admin/tool/installaddon/")); + "$CFG->wwwroot/$CFG->admin/tool/installaddon/index.php")); + $ADMIN->add('modules', new admin_externalpage('tool_installaddon_validate', + get_string('validation', 'tool_installaddon'), + "$CFG->wwwroot/$CFG->admin/tool/installaddon/validate.php", + 'moodle/site:config', + true)); } diff --git a/admin/tool/installaddon/styles.css b/admin/tool/installaddon/styles.css index 3de50f35259..05155ca612c 100644 --- a/admin/tool/installaddon/styles.css +++ b/admin/tool/installaddon/styles.css @@ -11,3 +11,58 @@ #page-admin-tool-installaddon-index #installfromrepobox .singlebutton input[type=submit] { padding: 1em; } + +#page-admin-tool-installaddon-validate .validationresult { + margin: 2em auto; + text-align: center; +} + +#page-admin-tool-installaddon-validate .validationresult .verdict { + margin: 0em 0.5em; + padding: 0.5em; + border: 2px solid; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + font-weight: bold; +} + +#page-admin-tool-installaddon-validate .validationresult.success .verdict { + background-color: #e7f1c3; + border-color: #aaeeaa; +} + +#page-admin-tool-installaddon-validate .validationresult.failure .verdict { + background-color: #ffd3d9; + border-color: #eeaaaa; +} + +#page-admin-tool-installaddon-validate .validationmessages { + margin: 0px auto; +} + +#page-admin-tool-installaddon-validate .validationmessages .level-error .msgstatus { + background-color: #ffd3d9; +} + +#page-admin-tool-installaddon-validate .validationmessages .level-warning .msgstatus { + background-color: #f3f2aa; +} + +#page-admin-tool-installaddon-validate .validationmessages .level-info .msgstatus { + background-color: #e7f1c3; +} + +#page-admin-tool-installaddon-validate .validationmessages .level-debug .msgstatus { + background-color: #d2ebff; +} + +#page-admin-tool-installaddon-validate .postvalidationbuttons { + text-align: center; + margin: 1em auto; +} + +#page-admin-tool-installaddon-validate .postvalidationbuttons .singlebutton { + display: inline-block; + margin: 1em 1em; +} diff --git a/admin/tool/installaddon/validate.php b/admin/tool/installaddon/validate.php new file mode 100644 index 00000000000..2fc66cf3bc9 --- /dev/null +++ b/admin/tool/installaddon/validate.php @@ -0,0 +1,80 @@ +. + +/** + * The ZIP package validation. + * + * @package tool_installaddon + * @copyright 2013 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require(dirname(__FILE__) . '/../../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); +require_once($CFG->libdir.'/filelib.php'); +require_once(dirname(__FILE__).'/classes/installer.php'); +require_once(dirname(__FILE__).'/classes/validator.php'); + +navigation_node::override_active_url(new moodle_url('/admin/tool/installaddon/index.php')); +admin_externalpage_setup('tool_installaddon_validate'); + +if (!empty($CFG->disableonclickaddoninstall)) { + notice(get_string('featuredisabled', 'tool_installaddon')); +} + +require_sesskey(); + +$jobid = required_param('jobid', PARAM_ALPHANUM); +$zipfilename = required_param('zip', PARAM_FILE); +$plugintype = required_param('type', PARAM_ALPHANUMEXT); +$rootdir = optional_param('rootdir', '', PARAM_PLUGIN); + +$zipfilepath = $CFG->tempdir.'/tool_installaddon/'.$jobid.'/source/'.$zipfilename; +if (!file_exists($zipfilepath)) { + redirect(new moodle_url('/admin/tool/installaddon/index.php'), + get_string('invaliddata', 'core_error')); +} + +$installer = tool_installaddon_installer::instance(); + +// Extract the ZIP contents. +fulldelete($CFG->tempdir.'/tool_installaddon/'.$jobid.'/contents'); +$zipcontentpath = make_temp_directory('tool_installaddon/'.$jobid.'/contents'); +$zipcontentfiles = $installer->extract_installfromzip_file($zipfilepath, $zipcontentpath, $rootdir); + +// Validate the contents of the plugin ZIP file. +$validator = tool_installaddon_validator::instance($zipcontentpath, $zipcontentfiles); +$validator->assert_plugin_type($plugintype); +$validator->assert_moodle_version($CFG->version); +$result = $validator->execute(); + +if ($result) { + $validator->set_continue_url(new moodle_url('/admin/tool/installaddon/deploy.php', array( + 'sesskey' => sesskey(), + 'jobid' => $jobid, + 'type' => $plugintype, + 'name' => $validator->get_rootdir()))); + +} else { + 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();