Permalink
Browse files

MDL-35238 Inform the admin if the update can not be deployed due to w…

…rite permissions
  • Loading branch information...
1 parent d80f80f commit 0daa642894c21179cbc96f810ffccbe2a2bbc733 @mudrd8mz mudrd8mz committed Nov 8, 2012
Showing with 97 additions and 14 deletions.
  1. +8 −3 admin/renderer.php
  2. +4 −0 lang/en/plugin.php
  3. +79 −10 lib/pluginlib.php
  4. +6 −1 mdeploy.php
View
@@ -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();
View
@@ -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}';
View
@@ -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;
}
/**
@@ -1783,7 +1789,6 @@ public function prepare_authorization() {
}
}
-
// End of external API
/**
@@ -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;
+ }
}
View
@@ -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 {
@@ -1072,7 +1076,8 @@ protected function move_directory_source_precheck($source) {
}
closedir($handle);
- return $result && is_writable($source);
+
+ return $result;
}
/**

0 comments on commit 0daa642

Please sign in to comment.