Skip to content

Commit

Permalink
MDL-35238 Inform the admin if the update can not be deployed due to w…
Browse files Browse the repository at this point in the history
…rite permissions
  • Loading branch information
mudrd8mz committed Nov 8, 2012
1 parent d80f80f commit 0daa642
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 14 deletions.
11 changes: 8 additions & 3 deletions admin/renderer.php
Expand Up @@ -1206,9 +1206,14 @@ protected function plugin_available_update_info(available_update_info $updateinf
$box .= $this->output->box(implode(html_writer::tag('span', ' ', array('class' => 'separator')), $info), '');

$deployer = available_update_deployer::instance();
if ($deployer->initialized() and $deployer->can_deploy($updateinfo)) {
$widget = $deployer->make_confirm_widget($updateinfo);
$box .= $this->output->render($widget);
if ($deployer->initialized()) {
$impediments = $deployer->deployment_impediments($updateinfo);
if (empty($impediments)) {
$widget = $deployer->make_confirm_widget($updateinfo);
$box .= $this->output->render($widget);
} else if (isset($impediments['notwritable'])) {
$box .= $this->output->help_icon('notwritable', 'core_plugin', get_string('notwritable', 'core_plugin'));
}
}

$box .= $this->output->box_end();
Expand Down
4 changes: 4 additions & 0 deletions lang/en/plugin.php
Expand Up @@ -41,6 +41,10 @@
$string['nonehighlightedinfo'] = 'Display the list of all installed plugins anyway';
$string['noneinstalled'] = 'No plugins of this type are installed';
$string['notes'] = 'Notes';
$string['notwritable'] = 'Plugin files not writable';
$string['notwritable_help'] = 'You have enabled automatic updates deployment and there is available update for this plugin. However, the plugin files are not writable by the web server so the update can not be installed at the moment.
Make the plugin folder and all its contents writable to be able to install the available update automatically.';
$string['numtotal'] = 'Installed: {$a}';
$string['numdisabled'] = 'Disabled: {$a}';
$string['numextension'] = 'Contributions: {$a}';
Expand Down
89 changes: 79 additions & 10 deletions lib/pluginlib.php
Expand Up @@ -1538,26 +1538,32 @@ public function initialized() {
}

/**
* Check if the available update info contains all required data for deployment.
* Returns a list of reasons why the deployment can not happen
*
* All instances of {@link available_update_info} class always provide at least the
* component name and component version. Additionally, we also need the URL to download
* the ZIP package from and MD5 hash of the ZIP's content.
* If the returned array is empty, the deployment seems to be possible. The returned
* structure is an associative array with keys representing individual impediments.
* Possible keys are: missingdownloadurl, missingdownloadmd5, notwritable.
*
* @param available_update_info $info
* @return bool
* @return array
*/
public function can_deploy(available_update_info $info) {
public function deployment_impediments(available_update_info $info) {

$impediments = array();

if (empty($info->download)) {
return false;
$impediments['missingdownloadurl'] = true;
}

if (empty($info->downloadmd5)) {
return false;
$impediments['missingdownloadmd5'] = true;
}

return true;
if (!$this->component_writable($info->component)) {
$impediments['notwritable'] = true;
}

return $impediments;
}

/**
Expand Down Expand Up @@ -1783,7 +1789,6 @@ public function prepare_authorization() {
}
}


// End of external API

/**
Expand Down Expand Up @@ -1857,6 +1862,70 @@ protected function generate_passfile() {
protected function generate_password() {
return complex_random_string();
}

/**
* Checks if the given component's directory is writable
*
* For the purpose of the deployment, the web server process has to have
* write access to all files in the component's directory (recursively) and for the
* directory itself.
*
* @see worker::move_directory_source_precheck()
* @param string $component normalized component name
* @return boolean
*/
protected function component_writable($component) {

list($plugintype, $pluginname) = normalize_component($component);

$directory = get_plugin_directory($plugintype, $pluginname);

if (is_null($directory)) {
throw new coding_exception('Unknown component location', $component);
}

return $this->directory_writable($directory);
}

/**
* Checks if the directory and all its contents (recursively) is writable
*
* @param string $path full path to a directory
* @return boolean
*/
private function directory_writable($path) {

if (!is_writable($path)) {
return false;
}

if (is_dir($path)) {
$handle = opendir($path);
} else {
return false;
}

$result = true;

while ($filename = readdir($handle)) {
$filepath = $path.'/'.$filename;

if ($filename === '.' or $filename === '..') {
continue;
}

if (is_dir($filepath)) {
$result = $result && $this->directory_writable($filepath);

} else {
$result = $result && is_writable($filepath);
}
}

closedir($handle);

return $result;
}
}


Expand Down
7 changes: 6 additions & 1 deletion mdeploy.php
Expand Up @@ -1048,6 +1048,10 @@ protected function format_log_message($msg) {
*/
protected function move_directory_source_precheck($source) {

if (!is_writable($source)) {
return false;
}

if (is_dir($source)) {
$handle = opendir($source);
} else {
Expand All @@ -1072,7 +1076,8 @@ protected function move_directory_source_precheck($source) {
}

closedir($handle);
return $result && is_writable($source);

return $result;
}

/**
Expand Down

0 comments on commit 0daa642

Please sign in to comment.