Skip to content

Commit

Permalink
MDL-49329 admin: Convert install plugins tool to use new APIs
Browse files Browse the repository at this point in the history
Most of the functionality provided by this tool (typically the
validation and actual deployment of the plugin package) has been moved
to the core level. So this is becoming just a thin wrapper and user
interface for installing new plugins via the administration UI.

Also fixes MDL-49600 as we no longer keep the unzipped contents of the
packages in the persistent temp directories.
  • Loading branch information
mudrd8mz committed Oct 9, 2015
1 parent 2d00be6 commit 4fff948
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 837 deletions.
381 changes: 24 additions & 357 deletions admin/tool/installaddon/classes/installer.php

Large diffs are not rendered by default.

21 changes: 18 additions & 3 deletions admin/tool/installaddon/classes/installfromzip_form.php
Expand Up @@ -86,6 +86,21 @@ public function require_explicit_plugintype() {
$mform->insertElementBefore($typedetectionfailed, 'permcheck');
}

/**
* Warn that the selected plugin type does not match the detected one.
*
* @param string $detected detected plugin type
*/
public function selected_plugintype_mismatch($detected) {

$mform = $this->_form;
$mform->addRule('plugintype', get_string('required'), 'required', null, 'client');
$mform->setAdvanced('plugintype', false);
$mform->setAdvanced('permcheck', false);
$mform->insertElementBefore($mform->createElement('static', 'selectedplugintypemismatch', '',
html_writer::span(get_string('typedetectionmismatch', 'tool_installaddon', $detected), 'error')), 'permcheck');
}

/**
* Validate the form fields
*
Expand All @@ -95,12 +110,12 @@ public function require_explicit_plugintype() {
*/
public function validation($data, $files) {

$installer = $this->_customdata['installer'];
$pluginman = core_plugin_manager::instance();
$errors = parent::validation($data, $files);

if (!empty($data['plugintype'])) {
if (!$installer->is_plugintype_writable($data['plugintype'])) {
$path = $installer->get_plugintype_root($data['plugintype']);
if (!$pluginman->is_plugintype_writable($data['plugintype'])) {
$path = $pluginman->get_plugintype_root($data['plugintype']);
$errors['plugintype'] = get_string('permcheckresultno', 'tool_installaddon', array('path' => $path));
}
}
Expand Down
78 changes: 0 additions & 78 deletions admin/tool/installaddon/deploy.php

This file was deleted.

114 changes: 87 additions & 27 deletions admin/tool/installaddon/index.php
Expand Up @@ -32,51 +32,111 @@
notice(get_string('featuredisabled', 'tool_installaddon'));
}

$pluginman = core_plugin_manager::instance();
$installer = tool_installaddon_installer::instance();

$output = $PAGE->get_renderer('tool_installaddon');
$output->set_installer_instance($installer);

// Handle the eventual request for installing from remote repository.
$remoterequest = optional_param('installaddonrequest', null, PARAM_RAW);
$confirmed = optional_param('confirm', false, PARAM_BOOL);
$installer->handle_remote_request($output, $remoterequest, $confirmed);
$installer->handle_remote_request($output, $remoterequest);

// Handle the confirmed installation request.
$installremote = optional_param('installremote', null, PARAM_COMPONENT);
$installremoteversion = optional_param('installremoteversion', null, PARAM_INT);
$installremoteconfirm = optional_param('installremoteconfirm', false, PARAM_BOOL);

if ($installremote and $installremoteversion) {
require_sesskey();
require_once($CFG->libdir.'/upgradelib.php');

$PAGE->set_pagelayout('maintenance');
$PAGE->set_popup_notification_allowed(false);

if ($pluginman->is_remote_plugin_installable($installremote, $installremoteversion)) {
$installable = array($pluginman->get_remote_plugin_info($installremote, $installremoteversion, true));
upgrade_install_plugins($installable, $installremoteconfirm,
get_string('installfromrepo', 'tool_installaddon'),
new moodle_url($PAGE->url, array('installremote' => $installremote,
'installremoteversion' => $installremoteversion, 'installremoteconfirm' => 1)
)
);
}
// We should never get here.
throw new moodle_exception('installing_non_installable_component', 'tool_installaddon');
}

// Handle installation of a plugin from the ZIP file.
$installzipcomponent = optional_param('installzipcomponent', null, PARAM_COMPONENT);
$installzipstorage = optional_param('installzipstorage', null, PARAM_FILE);
$installzipconfirm = optional_param('installzipconfirm', false, PARAM_BOOL);

if ($installzipcomponent and $installzipstorage) {
require_sesskey();
require_once($CFG->libdir.'/upgradelib.php');

$PAGE->set_pagelayout('maintenance');
$PAGE->set_popup_notification_allowed(false);

$installable = array((object)array(
'component' => $installzipcomponent,
'zipfilepath' => make_temp_directory('tool_installaddon').'/'.$installzipstorage.'/plugin.zip',
));
upgrade_install_plugins($installable, $installzipconfirm, get_string('installfromzip', 'tool_installaddon'),
new moodle_url($installer->index_url(), array('installzipcomponent' => $installzipcomponent,
'installzipstorage' => $installzipstorage, 'installzipconfirm' => 1)
)
);
}

$form = $installer->get_installfromzip_form();

if ($form->is_cancelled()) {
redirect($PAGE->url);

} else if ($data = $form->get_data()) {
// Save the ZIP file into a temporary location.
$jobid = md5(rand().uniqid('', true));
$sourcedir = make_temp_directory('tool_installaddon/'.$jobid.'/source');
$zipfilename = $installer->save_installfromzip_file($form, $sourcedir);
if (empty($data->plugintype)) {
$versiondir = make_temp_directory('tool_installaddon/'.$jobid.'/version');
$detected = $installer->detect_plugin_component($sourcedir.'/'.$zipfilename, $versiondir);
if (empty($detected)) {
$storage = $installer->make_installfromzip_storage();
$form->save_file('zipfile', $storage.'/plugin.zip');

$ziprootdir = $pluginman->get_plugin_zip_root_dir($storage.'/plugin.zip');
if (empty($ziprootdir)) {
echo $output->zip_not_valid_plugin_package_page($installer->index_url());
die();
}

$component = $installer->detect_plugin_component($storage.'/plugin.zip');
if (!empty($component) and !empty($data->plugintype)) {
// If the plugin type was explicitly set, make sure it matches the detected one.
list($detectedtype, $detectedname) = core_component::normalize_component($component);
if ($detectedtype !== $data->plugintype) {
$form->selected_plugintype_mismatch($detectedtype);
echo $output->index_page();
die();
}
}
if (empty($component)) {
// This should not happen as all plugins are supposed to declare their
// component. Still, let admins upload legacy packages if they want/need.
if (empty($data->plugintype)) {
$form->require_explicit_plugintype();
echo $output->index_page();
die();
}
if (!empty($data->rootdir)) {
$usepluginname = $data->rootdir;
} else {
list($detectedtype, $detectedname) = core_component::normalize_component($detected);
if ($detectedtype and $detectedname and $detectedtype !== 'core') {
$data->plugintype = $detectedtype;
} else {
$form->require_explicit_plugintype();
}
$usepluginname = $ziprootdir;
}
$component = $data->plugintype.'_'.$usepluginname;
}
// Redirect to the validation page.
if (!empty($data->plugintype)) {
$nexturl = new moodle_url('/admin/tool/installaddon/validate.php', array(
'sesskey' => sesskey(),
'jobid' => $jobid,
'zip' => $zipfilename,
'type' => $data->plugintype,
'rootdir' => $data->rootdir));
redirect($nexturl);
}

redirect($installer->index_url(array(
'installzipcomponent' => $component,
'installzipstorage' => basename($storage),
'sesskey' => sesskey(),
)));
}

// Output starts here.
// Display the tool main page.
echo $output->index_page();
15 changes: 4 additions & 11 deletions admin/tool/installaddon/lang/en/tool_installaddon.php
Expand Up @@ -31,13 +31,13 @@
$string['featuredisabled'] = 'The plugin installer is disabled on this site.';
$string['installaddon'] = 'Install plugin!';
$string['installaddons'] = 'Install plugins';
$string['installexception'] = 'Oops... An error occurred while trying to install the plugin. Turn debugging mode on to see details of the error.';
$string['installfromrepo'] = 'Install plugins from the Moodle plugins directory';
$string['installfromrepo_help'] = 'You will be redirected to the Moodle plugins directory to search for and install a plugin. Note that your site full name, URL and Moodle version will be sent as well, to make the installation process easier for you.';
$string['installfromzip'] = 'Install plugin from ZIP file';
$string['installfromzip_help'] = 'An alternative to installing a plugin directly from the Moodle plugins directory is to upload a ZIP package of the plugin. The ZIP package should have the same structure as a package downloaded from the Moodle plugins directory.';
$string['installfromzipfile'] = 'ZIP package';
$string['installfromzipfile_help'] = 'The plugin ZIP package must contain just one directory, named to match the plugin. The ZIP will be extracted into an appropriate location for the plugin type. If the package has been downloaded from the Moodle plugins directory then it will have this structure.';
$string['installfromzipfile_help'] = 'The plugin ZIP package must contain just one directory, named to match the plugin name. The ZIP will be extracted into an appropriate location for the plugin type. If the package has been downloaded from the Moodle plugins directory then it will have this structure.';
$string['installfromzipinvalid'] = 'The plugin ZIP package must contain just one directory, named to match the plugin name. Provided file is not a valid plugin ZIP package.';
$string['installfromziprootdir'] = 'Rename the root directory';
$string['installfromziprootdir_help'] = 'Some ZIP packages, such as those generated by Github, may contain an incorrect root directory name. If so, the correct name may be entered here.';
$string['installfromzipsubmit'] = 'Install plugin from the ZIP file';
Expand All @@ -56,13 +56,6 @@
$string['remoterequestinvalid'] = 'There is a request to install a plugin from the Moodle plugins directory on this site. Unfortunately the request is not valid and so the plugin cannot be installed.';
$string['remoterequestpermcheck'] = 'There is a request to install plugin {$a->name} ({$a->component}) version {$a->version} from the Moodle plugins directory on this site. However, the location <strong>{$a->typepath}</strong> is <strong>not writable</strong>. You need to give write access for the web server user to the location, then press the continue button to repeat the check.';
$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['remoterequestnoninstallable'] = 'There is a request to install plugin {$a->name} ({$a->component}) version {$a->version} from the Moodle plugins directory on this site. However, the plugin installation pre-check failed (reason code: {$a->reason}).';
$string['typedetectionfailed'] = 'Unable to detect the plugin type. Please choose the plugin type manually.';
$string['validation'] = 'Plugin package validation';
$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!';
$string['validationresult2_help'] = 'No serious problems were detected. You can continue with the plugin installation. See the validation log messages for more details and eventual warnings.';
$string['validationresult1_help'] = 'The plugin package has been validated and no serious problems were detected.';
$string['validationresultinfo'] = 'Info';
$string['validationresultmsg'] = 'Message';
$string['validationresultstatus'] = 'Status';
$string['typedetectionmismatch'] = 'The selected plugin type does not match the one declared by the plugin: {$a}';
6 changes: 3 additions & 3 deletions admin/tool/installaddon/permcheck.php
Expand Up @@ -52,9 +52,9 @@
die();
}

$installer = tool_installaddon_installer::instance();
$pluginman = core_plugin_manager::instance();

$plugintypepath = $installer->get_plugintype_root($plugintype);
$plugintypepath = $pluginman->get_plugintype_root($plugintype);

if (empty($plugintypepath)) {
header('HTTP/1.1 400 Bad Request');
Expand All @@ -63,7 +63,7 @@

$response = array('path' => $plugintypepath);

if ($installer->is_plugintype_writable($plugintype)) {
if ($pluginman->is_plugintype_writable($plugintype)) {
$response['writable'] = 1;
} else {
$response['writable'] = 0;
Expand Down

0 comments on commit 4fff948

Please sign in to comment.