mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 08:56:36 +02:00
MDL-38509 Check for writable plugin type location in install from ZIP form
Standard mform validation is implemented as well as progressively enhanced AJAX version.
This commit is contained in:
parent
2459758b30
commit
ddab904ba8
6 changed files with 245 additions and 2 deletions
|
@ -34,6 +34,9 @@ defined('MOODLE_INTERNAL') || die();
|
|||
*/
|
||||
class tool_installaddon_installer {
|
||||
|
||||
/** @var tool_installaddon_installfromzip */
|
||||
protected $installfromzipform = null;
|
||||
|
||||
/**
|
||||
* Factory method returning an instance of this class.
|
||||
*
|
||||
|
@ -80,10 +83,16 @@ class tool_installaddon_installer {
|
|||
global $CFG;
|
||||
require_once(dirname(__FILE__).'/installfromzip_form.php');
|
||||
|
||||
if (!is_null($this->installfromzipform)) {
|
||||
return $this->installfromzipform;
|
||||
}
|
||||
|
||||
$action = new moodle_url('/admin/tool/installaddon/index.php');
|
||||
$customdata = array('installer' => $this);
|
||||
|
||||
return new tool_installaddon_installfromzip($action, $customdata);
|
||||
$this->installfromzipform = new tool_installaddon_installfromzip($action, $customdata);
|
||||
|
||||
return $this->installfromzipform;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,6 +114,33 @@ class tool_installaddon_installer {
|
|||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it possible to create a new plugin directory for the given plugin type?
|
||||
*
|
||||
* @throws coding_exception for invalid plugin types or non-existing plugin type locations
|
||||
* @param string $plugintype
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_plugintype_writable($plugintype) {
|
||||
|
||||
$plugintypepath = null;
|
||||
foreach (get_plugin_types() as $type => $fullpath) {
|
||||
if ($type === $plugintype) {
|
||||
$plugintypepath = $fullpath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_null($plugintypepath)) {
|
||||
throw new coding_exception('Unknown plugin type!');
|
||||
}
|
||||
|
||||
if (!is_dir($plugintypepath)) {
|
||||
throw new coding_exception('Plugin type location does not exist!');
|
||||
}
|
||||
|
||||
return is_writable($plugintypepath);
|
||||
}
|
||||
|
||||
//// End of external API ///////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,10 +44,15 @@ class tool_installaddon_installfromzip extends moodleform {
|
|||
$installer = $this->_customdata['installer'];
|
||||
|
||||
$options = $installer->get_plugin_types_menu();
|
||||
$mform->addElement('select', 'plugintype', get_string('installfromziptype', 'tool_installaddon'), $options);
|
||||
$mform->addElement('select', 'plugintype', get_string('installfromziptype', 'tool_installaddon'), $options,
|
||||
array('id' => 'tool_installaddon_installfromzip_plugintype'));
|
||||
$mform->addHelpButton('plugintype', 'installfromziptype', 'tool_installaddon');
|
||||
$mform->addRule('plugintype', null, 'required', null, 'client');
|
||||
|
||||
$mform->addElement('static', 'permcheck', '',
|
||||
html_writer::span(get_string('permcheck', 'tool_installaddon'), '',
|
||||
array('id' => 'tool_installaddon_installfromzip_permcheck')));
|
||||
|
||||
$mform->addElement('filepicker', 'zipfile', get_string('installfromzipfile', 'tool_installaddon'),
|
||||
null, array('accepted_types' => '.zip'));
|
||||
$mform->addHelpButton('zipfile', 'installfromzipfile', 'tool_installaddon');
|
||||
|
@ -69,8 +74,15 @@ class tool_installaddon_installfromzip extends moodleform {
|
|||
*/
|
||||
public function validation($data, $files) {
|
||||
|
||||
$installer = $this->_customdata['installer'];
|
||||
$errors = parent::validation($data, $files);
|
||||
|
||||
if (!$installer->is_plugintype_writable($data['plugintype'])) {
|
||||
$paths = get_plugin_types(true);
|
||||
$path = $paths[$data['plugintype']];
|
||||
$errors['plugintype'] = get_string('permcheckresultno', 'tool_installaddon', array('path' => $path));
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,4 +38,9 @@ $string['installfromzipfile_help'] = 'The plugin ZIP package must contain just o
|
|||
$string['installfromzipsubmit'] = 'Install add-on from the ZIP file';
|
||||
$string['installfromziptype'] = 'Plugin type';
|
||||
$string['installfromziptype_help'] = 'Choose the correct type of plugin you are about to install. The installation procedure may fail badly when incorrect plugin type is provided.';
|
||||
$string['permcheck'] = 'Make sure the plugin type root location is writable by the web server process';
|
||||
$string['permcheckerror'] = 'Error while checking for write permission';
|
||||
$string['permcheckprogress'] = 'Checking for write permission ...';
|
||||
$string['permcheckresultno'] = 'Plugin type location <em>{$a->path}</em> not writable';
|
||||
$string['permcheckresultyes'] = 'Plugin type location <em>{$a->path}</em> is writable';
|
||||
$string['pluginname'] = 'Add-on installer';
|
||||
|
|
79
admin/tool/installaddon/permcheck.php
Normal file
79
admin/tool/installaddon/permcheck.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Checks the write permission for the given plugin type
|
||||
*
|
||||
* @package tool_installaddon
|
||||
* @subpackage ajax
|
||||
* @copyright 2013 David Mudrak <david@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('AJAX_SCRIPT', true);
|
||||
|
||||
require(dirname(__FILE__) . '/../../../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once(dirname(__FILE__).'/classes/installer.php');
|
||||
|
||||
require_login();
|
||||
|
||||
if (!has_capability('moodle/site:config', context_system::instance())) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
if (!empty($CFG->disableonclickaddoninstall)) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
if (!confirm_sesskey()) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
die();
|
||||
}
|
||||
|
||||
$plugintype = optional_param('plugintype', null, PARAM_ALPHANUMEXT);
|
||||
if (is_null($plugintype)) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
die();
|
||||
}
|
||||
|
||||
$plugintypepath = null;
|
||||
foreach (get_plugin_types() as $type => $fullpath) {
|
||||
if ($type === $plugintype) {
|
||||
$plugintypepath = $fullpath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_null($plugintypepath)) {
|
||||
header('HTTP/1.1 400 Bad Request');
|
||||
die();
|
||||
}
|
||||
|
||||
$installer = tool_installaddon_installer::instance();
|
||||
|
||||
$response = array('path' => $plugintypepath);
|
||||
|
||||
if ($installer->is_plugintype_writable($plugintype)) {
|
||||
$response['writable'] = 1;
|
||||
} else {
|
||||
$response['writable'] = 0;
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset: utf-8');
|
||||
echo json_encode($response);
|
|
@ -58,6 +58,12 @@ class tool_installaddon_renderer extends plugin_renderer_base {
|
|||
*/
|
||||
public function index_page() {
|
||||
|
||||
$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())));
|
||||
$this->page->requires->strings_for_js(
|
||||
array('permcheckprogress', 'permcheckresultno', 'permcheckresultyes', 'permcheckerror'), 'tool_installaddon');
|
||||
|
||||
$out = $this->output->header();
|
||||
$out .= $this->index_page_heading();
|
||||
$out .= $this->index_page_repository();
|
||||
|
|
105
admin/tool/installaddon/yui/permcheck/permcheck.js
vendored
Normal file
105
admin/tool/installaddon/yui/permcheck/permcheck.js
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* Check for write permission for the selected plugin type
|
||||
*
|
||||
* @module moodle-tool_installaddon-permcheck
|
||||
* @author David Mudrak <david@moodle.com>
|
||||
*/
|
||||
YUI.add('moodle-tool_installaddon-permcheck', function(Y) {
|
||||
|
||||
M.tool_installaddon = M.tool_installaddon || {};
|
||||
|
||||
/**
|
||||
* @class permcheck
|
||||
* @static
|
||||
*/
|
||||
M.tool_installaddon.permcheck = {
|
||||
|
||||
/**
|
||||
* @method init
|
||||
* @param {Object} config Configuration passed from the PHP
|
||||
*/
|
||||
init : function(config) {
|
||||
this.config = config;
|
||||
var plugintypesel = Y.one('#tool_installaddon_installfromzip_plugintype');
|
||||
if (plugintypesel) {
|
||||
plugintypesel.on('change', this.check_for_permission, this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @method check_for_permission
|
||||
* @param {Event} e
|
||||
*/
|
||||
check_for_permission : function(e) {
|
||||
var plugintype = e.currentTarget.get('value');
|
||||
if (plugintype == '') {
|
||||
return;
|
||||
}
|
||||
Y.log('Selected plugin type: ' + plugintype, 'debug', 'moodle-tool_installaddon-permcheck');
|
||||
Y.io(this.config.permcheckurl, {
|
||||
'method' : 'GET',
|
||||
'data' : {
|
||||
'sesskey' : M.cfg.sesskey,
|
||||
'plugintype' : plugintype
|
||||
},
|
||||
'arguments' : {
|
||||
'plugintypeselector' : e.currentTarget,
|
||||
'showresult' : function(msg, status) {
|
||||
var resultline = Y.one('#tool_installaddon_installfromzip_permcheck');
|
||||
if (resultline) {
|
||||
if (status === 'success') {
|
||||
resultline.setContent('<span class="success"><img src="' + M.util.image_url('i/tick_green_big') + '" /> ' +
|
||||
msg + '</span>');
|
||||
} else if (status === 'progress') {
|
||||
resultline.setContent('<span class="progress"><img src="' + M.cfg.loadingicon + '" /> ' +
|
||||
msg + '</span>');
|
||||
} else {
|
||||
resultline.setContent('<span class="error"><img src="' + M.util.image_url('i/cross_red_big') + '" /> ' +
|
||||
msg + '</span>');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'on' : {
|
||||
'start' : function(transid, args) {
|
||||
args.showresult(M.util.get_string('permcheckprogress', 'tool_installaddon'), 'progress');
|
||||
},
|
||||
'success': function(transid, outcome, args) {
|
||||
var response;
|
||||
try {
|
||||
response = Y.JSON.parse(outcome.responseText);
|
||||
if (response.error) {
|
||||
Y.log(response.error, 'error', 'moodle-tool_installaddon-permcheck');
|
||||
args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon', response), 'error');
|
||||
} else if (response.path && response.writable == 1) {
|
||||
args.showresult(M.util.get_string('permcheckresultyes', 'tool_installaddon', response), 'success');
|
||||
} else if (response.path && response.writable == 0) {
|
||||
args.showresult(M.util.get_string('permcheckresultno', 'tool_installaddon', response), 'error');
|
||||
} else {
|
||||
Y.log(response, 'debug', 'moodle-tool_installaddon-permcheck');
|
||||
args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon', response), 'error');
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
Y.log(e, 'error', 'moodle-tool_installaddon-permcheck');
|
||||
args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon'), 'error');
|
||||
}
|
||||
},
|
||||
'failure': function(transid, outcome, args) {
|
||||
Y.log(outcome.statusText, 'error', 'moodle-tool_installaddon-permcheck');
|
||||
args.showresult(M.util.get_string('permcheckerror', 'tool_installaddon'));
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @property
|
||||
* @type {Object}
|
||||
*/
|
||||
config : null
|
||||
};
|
||||
|
||||
}, '@VERSION@', {
|
||||
requires:['node', 'event', 'io-base']
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue