Merge branch 'MDL-39087-plugins-uninstall' of git://github.com/mudrd8mz/moodle
This commit is contained in:
+446
-27
@@ -107,6 +107,27 @@ class plugin_manager {
|
||||
return $this->reorder_plugin_types(get_plugin_types($fullpaths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of known plugins of the given type
|
||||
*
|
||||
* This method returns the subset of the tree returned by {@link self::get_plugins()}.
|
||||
* If the given type is not known, empty array is returned.
|
||||
*
|
||||
* @param string $type plugin type, e.g. 'mod' or 'workshopallocation'
|
||||
* @param bool $disablecache force reload, cache can be used otherwise
|
||||
* @return array (string)plugin name (e.g. 'workshop') => corresponding subclass of {@link plugininfo_base}
|
||||
*/
|
||||
public function get_plugins_of_type($type, $disablecache=false) {
|
||||
|
||||
$plugins = $this->get_plugins($disablecache);
|
||||
|
||||
if (!isset($plugins[$type])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return $plugins[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a tree of known plugins and information about them
|
||||
*
|
||||
@@ -161,6 +182,41 @@ class plugin_manager {
|
||||
return $this->pluginsinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all known subplugins of the given plugin
|
||||
*
|
||||
* For plugins that do not provide subplugins (i.e. there is no support for it),
|
||||
* empty array is returned.
|
||||
*
|
||||
* @param string $component full component name, e.g. 'mod_workshop'
|
||||
* @param bool $disablecache force reload, cache can be used otherwise
|
||||
* @return array (string) component name (e.g. 'workshopallocation_random') => subclass of {@link plugininfo_base}
|
||||
*/
|
||||
public function get_subplugins_of_plugin($component, $disablecache=false) {
|
||||
|
||||
$pluginfo = $this->get_plugin_info($component, $disablecache);
|
||||
|
||||
if (is_null($pluginfo)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$subplugins = $this->get_subplugins($disablecache);
|
||||
|
||||
if (!isset($subplugins[$pluginfo->component])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$list = array();
|
||||
|
||||
foreach ($subplugins[$pluginfo->component] as $subdata) {
|
||||
foreach ($this->get_plugins_of_type($subdata->type) as $subpluginfo) {
|
||||
$list[$subpluginfo->component] = $subpluginfo;
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of plugins that define their subplugins and the information
|
||||
* about them from the db/subplugins.php file.
|
||||
@@ -221,12 +277,18 @@ class plugin_manager {
|
||||
/**
|
||||
* Returns a localized name of a given plugin
|
||||
*
|
||||
* @param string $plugin name of the plugin, eg mod_workshop or auth_ldap
|
||||
* @param string $component name of the plugin, eg mod_workshop or auth_ldap
|
||||
* @return string
|
||||
*/
|
||||
public function plugin_name($plugin) {
|
||||
list($type, $name) = normalize_component($plugin);
|
||||
return $this->pluginsinfo[$type][$name]->displayname;
|
||||
public function plugin_name($component) {
|
||||
|
||||
$pluginfo = $this->get_plugin_info($component);
|
||||
|
||||
if (is_null($pluginfo)) {
|
||||
throw new moodle_exception('err_unknown_plugin', 'core_plugin', '', array('plugin' => $component));
|
||||
}
|
||||
|
||||
return $pluginfo->displayname;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,12 +350,15 @@ class plugin_manager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the known plugin, or null
|
||||
*
|
||||
* @param string $component frankenstyle component name.
|
||||
* @param bool $disablecache force reload, cache can be used otherwise
|
||||
* @return plugininfo_base|null the corresponding plugin information.
|
||||
*/
|
||||
public function get_plugin_info($component) {
|
||||
list($type, $name) = normalize_component($component);
|
||||
$plugins = $this->get_plugins();
|
||||
public function get_plugin_info($component, $disablecache=false) {
|
||||
list($type, $name) = $this->normalize_component($component);
|
||||
$plugins = $this->get_plugins($disablecache);
|
||||
if (isset($plugins[$type][$name])) {
|
||||
return $plugins[$type][$name];
|
||||
} else {
|
||||
@@ -301,6 +366,38 @@ class plugin_manager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the current version of the plugin seems to be a checkout of an external repository.
|
||||
*
|
||||
* @see available_update_deployer::plugin_external_source()
|
||||
* @param string $component frankenstyle component name
|
||||
* @return false|string
|
||||
*/
|
||||
public function plugin_external_source($component) {
|
||||
|
||||
$plugininfo = $this->get_plugin_info($component);
|
||||
|
||||
if (is_null($plugininfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pluginroot = $plugininfo->rootdir;
|
||||
|
||||
if (is_dir($pluginroot.'/.git')) {
|
||||
return 'git';
|
||||
}
|
||||
|
||||
if (is_dir($pluginroot.'/CVS')) {
|
||||
return 'cvs';
|
||||
}
|
||||
|
||||
if (is_dir($pluginroot.'/.svn')) {
|
||||
return 'svn';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of any other plugins that require this one.
|
||||
* @param string $component frankenstyle component name.
|
||||
@@ -371,6 +468,94 @@ class plugin_manager {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it possible to uninstall the given plugin?
|
||||
*
|
||||
* False is returned if the plugininfo subclass declares the uninstall should
|
||||
* not be allowed via {@link plugininfo_base::is_uninstall_allowed()} or if the
|
||||
* core vetoes it (e.g. becase the plugin or some of its subplugins is required
|
||||
* by some other installed plugin).
|
||||
*
|
||||
* @param string $component full frankenstyle name, e.g. mod_foobar
|
||||
* @return bool
|
||||
*/
|
||||
public function can_uninstall_plugin($component) {
|
||||
|
||||
$pluginfo = $this->get_plugin_info($component);
|
||||
|
||||
if (is_null($pluginfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->common_uninstall_check($pluginfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it has subplugins, check they can be uninstalled too.
|
||||
$subplugins = $this->get_subplugins_of_plugin($pluginfo->component);
|
||||
foreach ($subplugins as $subpluginfo) {
|
||||
if (!$this->common_uninstall_check($subpluginfo)) {
|
||||
return false;
|
||||
}
|
||||
// Check if there are some other plugins requiring this subplugin
|
||||
// (but the parent and siblings).
|
||||
foreach ($this->other_plugins_that_require($subpluginfo->component) as $requiresme) {
|
||||
$ismyparent = ($pluginfo->component === $requiresme);
|
||||
$ismysibling = in_array($requiresme, array_keys($subplugins));
|
||||
if (!$ismyparent and !$ismysibling) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are some other plugins requiring this plugin
|
||||
// (but its subplugins).
|
||||
foreach ($this->other_plugins_that_require($pluginfo->component) as $requiresme) {
|
||||
$ismysubplugin = in_array($requiresme, array_keys($subplugins));
|
||||
if (!$ismysubplugin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall the given plugin.
|
||||
*
|
||||
* Automatically cleans-up all remaining configuration data, log records, events,
|
||||
* files from the file pool etc.
|
||||
*
|
||||
* In the future, the functionality of {@link uninstall_plugin()} function may be moved
|
||||
* into this method and all the code should be refactored to use it. At the moment, we
|
||||
* mimic this future behaviour by wrapping that function call.
|
||||
*
|
||||
* @param string $component
|
||||
* @param progress_trace $progress traces the process
|
||||
* @return bool true on success, false on errors/problems
|
||||
*/
|
||||
public function uninstall_plugin($component, progress_trace $progress) {
|
||||
|
||||
$pluginfo = $this->get_plugin_info($component);
|
||||
|
||||
if (is_null($pluginfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Give the pluginfo class a chance to execute some steps.
|
||||
$result = $pluginfo->uninstall($progress);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call the legacy core function to uninstall the plugin.
|
||||
ob_start();
|
||||
uninstall_plugin($pluginfo->type, $pluginfo->name);
|
||||
$progress->output(ob_get_clean());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are some plugins with a known available update
|
||||
*
|
||||
@@ -388,6 +573,29 @@ class plugin_manager {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the given plugin folder can be removed by the web server process.
|
||||
*
|
||||
* @param string $component full frankenstyle component
|
||||
* @return bool
|
||||
*/
|
||||
public function is_plugin_folder_removable($component) {
|
||||
|
||||
$pluginfo = $this->get_plugin_info($component);
|
||||
|
||||
if (is_null($pluginfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// To be able to remove the plugin folder, its parent must be writable, too.
|
||||
if (!is_writable(dirname($pluginfo->rootdir))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the folder and all its content is writable (thence removable).
|
||||
return $this->is_directory_removable($pluginfo->rootdir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a list of all plugins that were originally shipped in the standard Moodle distribution,
|
||||
* but are not anymore and are deleted during upgrades.
|
||||
@@ -640,6 +848,18 @@ class plugin_manager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for the core function {@link normalize_component()}.
|
||||
*
|
||||
* This is here just to make it possible to mock it in unit tests.
|
||||
*
|
||||
* @param string $component
|
||||
* @return array
|
||||
*/
|
||||
protected function normalize_component($component) {
|
||||
return normalize_component($component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorders plugin types into a sequence to be displayed
|
||||
*
|
||||
@@ -670,6 +890,73 @@ class plugin_manager {
|
||||
}
|
||||
return $fix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given directory can be removed by the web server process.
|
||||
*
|
||||
* This recursively checks that the given directory and all its contents
|
||||
* it writable.
|
||||
*
|
||||
* @param string $fullpath
|
||||
* @return boolean
|
||||
*/
|
||||
protected function is_directory_removable($fullpath) {
|
||||
|
||||
if (!is_writable($fullpath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_dir($fullpath)) {
|
||||
$handle = opendir($fullpath);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = true;
|
||||
|
||||
while ($filename = readdir($handle)) {
|
||||
|
||||
if ($filename === '.' or $filename === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$subfilepath = $fullpath.'/'.$filename;
|
||||
|
||||
if (is_dir($subfilepath)) {
|
||||
$result = $result && $this->is_directory_removable($subfilepath);
|
||||
|
||||
} else {
|
||||
$result = $result && is_writable($subfilepath);
|
||||
}
|
||||
}
|
||||
|
||||
closedir($handle);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that implements common uninstall prerequisities
|
||||
*
|
||||
* @param plugininfo_base $pluginfo
|
||||
* @return bool
|
||||
*/
|
||||
protected function common_uninstall_check(plugininfo_base $pluginfo) {
|
||||
|
||||
if (!$pluginfo->is_uninstall_allowed()) {
|
||||
// The plugin's plugininfo class declares it should not be uninstalled.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_null($pluginfo->get_uninstall_url())) {
|
||||
// Backwards compatibility.
|
||||
debugging('plugininfo_base subclasses should use is_uninstall_allowed() instead of returning null in get_uninstall_url()',
|
||||
DEBUG_DEVELOPER);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1662,6 +1949,7 @@ class available_update_deployer {
|
||||
/**
|
||||
* Check to see if the current version of the plugin seems to be a checkout of an external repository.
|
||||
*
|
||||
* @see plugin_manager::plugin_external_source()
|
||||
* @param available_update_info $info
|
||||
* @return false|string
|
||||
*/
|
||||
@@ -2287,6 +2575,24 @@ abstract class plugininfo_base {
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this is a subplugin?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_subplugin() {
|
||||
return ($this->get_parent_plugin() !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* If I am a subplugin, return the name of my parent plugin.
|
||||
*
|
||||
* @return string|bool false if not a subplugin, name of the parent otherwise
|
||||
*/
|
||||
public function get_parent_plugin() {
|
||||
return $this->get_plugin_manager()->get_parent_of_subplugin($this->type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link $versiondb} property to a numerical value representing the
|
||||
* currently installed version of the plugin.
|
||||
@@ -2496,19 +2802,43 @@ abstract class plugininfo_base {
|
||||
public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Should there be a way to uninstall the plugin via the administration UI
|
||||
*
|
||||
* By default, uninstallation is allowed for all non-standard add-ons. Subclasses
|
||||
* may want to override this to allow uninstallation of all plugins (simply by
|
||||
* returning true unconditionally). Subplugins follow their parent plugin's
|
||||
* decision by default.
|
||||
*
|
||||
* Note that even if true is returned, the core may still prohibit the uninstallation,
|
||||
* e.g. in case there are other plugins that depend on this one.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_uninstall_allowed() {
|
||||
|
||||
if ($this->is_subplugin()) {
|
||||
return $this->get_plugin_manager()->get_plugin_info($this->get_parent_plugin())->is_uninstall_allowed();
|
||||
}
|
||||
|
||||
if ($this->is_standard()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL of the screen where this plugin can be uninstalled
|
||||
*
|
||||
* Visiting that URL must be safe, that is a manual confirmation is needed
|
||||
* for actual uninstallation of the plugin. Null value means that the
|
||||
* plugin either does not support uninstallation, or does not require any
|
||||
* database cleanup or the location of the screen is not available via this
|
||||
* library.
|
||||
* for actual uninstallation of the plugin. By default, URL to a common
|
||||
* uninstalling tool is returned.
|
||||
*
|
||||
* @return null|moodle_url
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_uninstall_url() {
|
||||
return null;
|
||||
return $this->get_default_uninstall_url();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2522,6 +2852,36 @@ abstract class plugininfo_base {
|
||||
return substr($this->rootdir, strlen($CFG->dirroot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method to implement certain steps when uninstalling the plugin.
|
||||
*
|
||||
* This hook is called by {@link plugin_manager::uninstall_plugin()} so
|
||||
* it is basically usable only for those plugin types that use the default
|
||||
* uninstall tool provided by {@link self::get_default_uninstall_url()}.
|
||||
*
|
||||
* @param progress_trace $progress traces the process
|
||||
* @return bool true on success, false on failure
|
||||
*/
|
||||
public function uninstall(progress_trace $progress) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns URL to a script that handles common plugin uninstall procedure.
|
||||
*
|
||||
* This URL is suitable for plugins that do not have their own UI
|
||||
* for uninstalling.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
protected final function get_default_uninstall_url() {
|
||||
return new moodle_url('/admin/plugins.php', array(
|
||||
'sesskey' => sesskey(),
|
||||
'uninstall' => $this->component,
|
||||
'confirm' => 0,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to plugin versions from the {config_plugins} table
|
||||
*
|
||||
@@ -2552,6 +2912,15 @@ abstract class plugininfo_base {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the plugin_manager singleton.
|
||||
*
|
||||
* @return plugin_manmager
|
||||
*/
|
||||
protected function get_plugin_manager() {
|
||||
return plugin_manager::instance();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2678,8 +3047,11 @@ class plugininfo_block extends plugininfo_base {
|
||||
}
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
$blocksinfo = self::get_blocks_info();
|
||||
return new moodle_url('/admin/blocks.php', array('delete' => $blocksinfo[$this->name]->id, 'sesskey' => sesskey()));
|
||||
}
|
||||
@@ -2814,6 +3186,10 @@ class plugininfo_filter extends plugininfo_base {
|
||||
}
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/filters.php', array('sesskey' => sesskey(), 'filterpath' => $this->name, 'action' => 'delete'));
|
||||
}
|
||||
@@ -2997,15 +3373,24 @@ class plugininfo_mod extends plugininfo_base {
|
||||
}
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
/**
|
||||
* Allow all activity modules but Forum to be uninstalled.
|
||||
|
||||
if ($this->name !== 'forum') {
|
||||
return new moodle_url('/admin/modules.php', array('delete' => $this->name, 'sesskey' => sesskey()));
|
||||
* This exception for the Forum has been hard-coded in Moodle since ages,
|
||||
* we may want to re-think it one day.
|
||||
*/
|
||||
public function is_uninstall_allowed() {
|
||||
if ($this->name === 'forum') {
|
||||
return false;
|
||||
} else {
|
||||
return null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/modules.php', array('delete' => $this->name, 'sesskey' => sesskey()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the records in {modules} table
|
||||
*
|
||||
@@ -3039,6 +3424,10 @@ class plugininfo_mod extends plugininfo_base {
|
||||
*/
|
||||
class plugininfo_qbehaviour extends plugininfo_base {
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/qbehaviours.php',
|
||||
array('delete' => $this->name, 'sesskey' => sesskey()));
|
||||
@@ -3051,6 +3440,10 @@ class plugininfo_qbehaviour extends plugininfo_base {
|
||||
*/
|
||||
class plugininfo_qtype extends plugininfo_base {
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/qtypes.php',
|
||||
array('delete' => $this->name, 'sesskey' => sesskey()));
|
||||
@@ -3175,6 +3568,10 @@ class plugininfo_enrol extends plugininfo_base {
|
||||
}
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/enrol.php', array('action' => 'uninstall', 'enrol' => $this->name, 'sesskey' => sesskey()));
|
||||
}
|
||||
@@ -3225,16 +3622,21 @@ class plugininfo_message extends plugininfo_base {
|
||||
}
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
$processors = get_message_processors();
|
||||
if (isset($processors[$this->name])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see plugintype_interface::get_uninstall_url()
|
||||
*/
|
||||
public function get_uninstall_url() {
|
||||
$processors = get_message_processors();
|
||||
if (isset($processors[$this->name])) {
|
||||
return new moodle_url('/admin/message.php', array('uninstall' => $processors[$this->name]->id, 'sesskey' => sesskey()));
|
||||
} else {
|
||||
return parent::get_uninstall_url();
|
||||
}
|
||||
return new moodle_url('/admin/message.php', array('uninstall' => $processors[$this->name]->id, 'sesskey' => sesskey()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3379,6 +3781,10 @@ class plugininfo_mnetservice extends plugininfo_base {
|
||||
*/
|
||||
class plugininfo_tool extends plugininfo_base {
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/tools.php', array('delete' => $this->name, 'sesskey' => sesskey()));
|
||||
}
|
||||
@@ -3390,6 +3796,10 @@ class plugininfo_tool extends plugininfo_base {
|
||||
*/
|
||||
class plugininfo_report extends plugininfo_base {
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/reports.php', array('delete' => $this->name, 'sesskey' => sesskey()));
|
||||
}
|
||||
@@ -3513,6 +3923,10 @@ class plugininfo_webservice extends plugininfo_base {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/webservice/protocols.php',
|
||||
array('sesskey' => sesskey(), 'action' => 'uninstall', 'webservice' => $this->name));
|
||||
@@ -3568,11 +3982,16 @@ class plugininfo_format extends plugininfo_base {
|
||||
return !get_config($this->component, 'disabled');
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
public function is_uninstall_allowed() {
|
||||
if ($this->name !== get_config('moodlecourse', 'format') && $this->name !== 'site') {
|
||||
return new moodle_url('/admin/courseformats.php',
|
||||
array('sesskey' => sesskey(), 'action' => 'uninstall', 'format' => $this->name));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return parent::get_uninstall_url();
|
||||
}
|
||||
|
||||
public function get_uninstall_url() {
|
||||
return new moodle_url('/admin/courseformats.php',
|
||||
array('sesskey' => sesskey(), 'action' => 'uninstall', 'format' => $this->name));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user