| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 3 | //
 | 
        
           |  |  | 4 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 5 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 6 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 7 | // (at your option) any later version.
 | 
        
           |  |  | 8 | //
 | 
        
           |  |  | 9 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 12 | // GNU General Public License for more details.
 | 
        
           |  |  | 13 | //
 | 
        
           |  |  | 14 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 15 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 16 |   | 
        
           |  |  | 17 | /**
 | 
        
           |  |  | 18 |  * Defines classes used for plugin info.
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @package    core
 | 
        
           |  |  | 21 |  * @copyright  2011 David Mudrak <david@moodle.com>
 | 
        
           |  |  | 22 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 23 |  */
 | 
        
           |  |  | 24 | namespace core\plugininfo;
 | 
        
           |  |  | 25 |   | 
        
           |  |  | 26 | use coding_exception;
 | 
        
           |  |  | 27 | use core_component;
 | 
        
           |  |  | 28 | use core_plugin_manager;
 | 
        
           |  |  | 29 | use moodle_url;
 | 
        
           |  |  | 30 |   | 
        
           |  |  | 31 | /**
 | 
        
           |  |  | 32 |  * Base class providing access to the information about a plugin
 | 
        
           |  |  | 33 |  */
 | 
        
           |  |  | 34 | abstract class base {
 | 
        
           |  |  | 35 |   | 
        
           |  |  | 36 |     /** @var string the plugintype name, eg. mod, auth or workshopform */
 | 
        
           |  |  | 37 |     public $type;
 | 
        
           |  |  | 38 |     /** @var string full path to the location of all the plugins of this type */
 | 
        
           |  |  | 39 |     public $typerootdir;
 | 
        
           |  |  | 40 |     /** @var string the plugin name, eg. assignment, ldap */
 | 
        
           |  |  | 41 |     public $name;
 | 
        
           |  |  | 42 |     /** @var string the localized plugin name */
 | 
        
           |  |  | 43 |     public $displayname;
 | 
        
           |  |  | 44 |     /** @var string the plugin source, one of core_plugin_manager::PLUGIN_SOURCE_xxx constants */
 | 
        
           |  |  | 45 |     public $source;
 | 
        
           |  |  | 46 |     /** @var string fullpath to the location of this plugin */
 | 
        
           |  |  | 47 |     public $rootdir;
 | 
        
           |  |  | 48 |     /** @var int|string the version of the plugin's source code */
 | 
        
           |  |  | 49 |     public $versiondisk;
 | 
        
           |  |  | 50 |     /** @var int|string the version of the installed plugin */
 | 
        
           |  |  | 51 |     public $versiondb;
 | 
        
           |  |  | 52 |     /** @var int|float|string required version of Moodle core  */
 | 
        
           |  |  | 53 |     public $versionrequires;
 | 
        
           |  |  | 54 |     /** @var array explicitly supported branches of Moodle core  */
 | 
        
           |  |  | 55 |     public $pluginsupported;
 | 
        
           |  |  | 56 |     /** @var int first incompatible branch of Moodle core  */
 | 
        
           |  |  | 57 |     public $pluginincompatible;
 | 
        
           |  |  | 58 |     /** @var mixed human-readable release information */
 | 
        
           |  |  | 59 |     public $release;
 | 
        
           |  |  | 60 |     /** @var array other plugins that this one depends on, lazy-loaded by {@link get_other_required_plugins()} */
 | 
        
           |  |  | 61 |     public $dependencies;
 | 
        
           |  |  | 62 |     /** @var int number of instances of the plugin - not supported yet */
 | 
        
           |  |  | 63 |     public $instances;
 | 
        
           |  |  | 64 |     /** @var int order of the plugin among other plugins of the same type - not supported yet */
 | 
        
           |  |  | 65 |     public $sortorder;
 | 
        
           |  |  | 66 |     /** @var core_plugin_manager the plugin manager this plugin info is part of */
 | 
        
           |  |  | 67 |     public $pluginman;
 | 
        
           |  |  | 68 |   | 
        
           |  |  | 69 |     /** @var array|null array of {@link \core\update\info} for this plugin */
 | 
        
           |  |  | 70 |     protected $availableupdates;
 | 
        
           |  |  | 71 |   | 
        
           |  |  | 72 |     /** @var int Move a plugin up in the plugin order */
 | 
        
           |  |  | 73 |     public const MOVE_UP = -1;
 | 
        
           |  |  | 74 |   | 
        
           |  |  | 75 |     /** @var int Move a plugin down in the plugin order */
 | 
        
           |  |  | 76 |     public const MOVE_DOWN = 1;
 | 
        
           |  |  | 77 |   | 
        
           |  |  | 78 |     /** @var array hold $plugin->supported in version.php */
 | 
        
           |  |  | 79 |     public $supported;
 | 
        
           |  |  | 80 |   | 
        
           |  |  | 81 |     /** @var int hold $plugin->incompatible in version.php  */
 | 
        
           |  |  | 82 |     public $incompatible;
 | 
        
           |  |  | 83 |   | 
        
           |  |  | 84 |     /** @var string Name of the plugin */
 | 
        
           |  |  | 85 |     public $component = '';
 | 
        
           |  |  | 86 |   | 
        
           | 1441 | ariadna | 87 |     /** @var bool whether the plugin is that of a phase 1 deprecated type or subplugin type. */
 | 
        
           |  |  | 88 |     public $deprecatedtype = false;
 | 
        
           |  |  | 89 |   | 
        
           |  |  | 90 |     /** @var bool whether the plugin is that of a phase 2 deprecated (deleted) type or subplugin type. */
 | 
        
           |  |  | 91 |     public $deletedtype = false;
 | 
        
           |  |  | 92 |   | 
        
           | 1 | efrain | 93 |     /**
 | 
        
           |  |  | 94 |      * Whether this plugintype supports its plugins being disabled.
 | 
        
           |  |  | 95 |      *
 | 
        
           |  |  | 96 |      * @return bool
 | 
        
           |  |  | 97 |      */
 | 
        
           |  |  | 98 |     public static function plugintype_supports_disabling(): bool {
 | 
        
           |  |  | 99 |         return false;
 | 
        
           |  |  | 100 |     }
 | 
        
           |  |  | 101 |   | 
        
           |  |  | 102 |     /**
 | 
        
           |  |  | 103 |      * Finds all enabled plugins, the result may include missing plugins.
 | 
        
           |  |  | 104 |      * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
 | 
        
           |  |  | 105 |      */
 | 
        
           |  |  | 106 |     public static function get_enabled_plugins() {
 | 
        
           |  |  | 107 |         return null;
 | 
        
           |  |  | 108 |     }
 | 
        
           |  |  | 109 |   | 
        
           |  |  | 110 |     /**
 | 
        
           |  |  | 111 |      * Enable or disable a plugin.
 | 
        
           |  |  | 112 |      * When possible, the change will be stored into the config_log table, to let admins check when/who has modified it.
 | 
        
           |  |  | 113 |      *
 | 
        
           |  |  | 114 |      * @param string $pluginname The plugin name to enable/disable.
 | 
        
           |  |  | 115 |      * @param int $enabled Whether the pluginname should be enabled (1) or not (0). This is an integer because some plugins, such
 | 
        
           |  |  | 116 |      * as filters or repositories, might support more statuses than just enabled/disabled.
 | 
        
           |  |  | 117 |      *
 | 
        
           |  |  | 118 |      * @return bool Whether $pluginname has been updated or not.
 | 
        
           |  |  | 119 |      */
 | 
        
           |  |  | 120 |     public static function enable_plugin(string $pluginname, int $enabled): bool {
 | 
        
           |  |  | 121 |         return false;
 | 
        
           |  |  | 122 |     }
 | 
        
           |  |  | 123 |   | 
        
           |  |  | 124 |     /**
 | 
        
           |  |  | 125 |      * Returns current status for a pluginname.
 | 
        
           |  |  | 126 |      *
 | 
        
           |  |  | 127 |      * @param string $pluginname The plugin name to check.
 | 
        
           |  |  | 128 |      * @return int The current status (enabled, disabled...) of $pluginname.
 | 
        
           |  |  | 129 |      */
 | 
        
           |  |  | 130 |     public static function get_enabled_plugin(string $pluginname): int {
 | 
        
           |  |  | 131 |         $enabledplugins = static::get_enabled_plugins();
 | 
        
           |  |  | 132 |         $value = $enabledplugins && array_key_exists($pluginname, $enabledplugins);
 | 
        
           |  |  | 133 |         return (int) $value;
 | 
        
           |  |  | 134 |     }
 | 
        
           |  |  | 135 |   | 
        
           |  |  | 136 |     /**
 | 
        
           |  |  | 137 |      * Gathers and returns the information about all plugins of the given type,
 | 
        
           |  |  | 138 |      * either on disk or previously installed.
 | 
        
           |  |  | 139 |      *
 | 
        
           |  |  | 140 |      * This is supposed to be used exclusively by the plugin manager when it is
 | 
        
           |  |  | 141 |      * populating its tree of plugins.
 | 
        
           |  |  | 142 |      *
 | 
        
           |  |  | 143 |      * @param string $type the name of the plugintype, eg. mod, auth or workshopform
 | 
        
           |  |  | 144 |      * @param string $typerootdir full path to the location of the plugin dir
 | 
        
           |  |  | 145 |      * @param string $typeclass the name of the actually called class
 | 
        
           |  |  | 146 |      * @param core_plugin_manager $pluginman the plugin manager calling this method
 | 
        
           |  |  | 147 |      * @return array of plugintype classes, indexed by the plugin name
 | 
        
           |  |  | 148 |      */
 | 
        
           |  |  | 149 |     public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) {
 | 
        
           | 1441 | ariadna | 150 |         // Get the information about plugins at the disk, including deprecated plugins.
 | 
        
           |  |  | 151 |         $plugins = core_component::get_all_plugins_list($type);
 | 
        
           |  |  | 152 |   | 
        
           |  |  | 153 |         // Also included deleted plugins.
 | 
        
           |  |  | 154 |   | 
        
           | 1 | efrain | 155 |         $return = array();
 | 
        
           |  |  | 156 |         foreach ($plugins as $pluginname => $pluginrootdir) {
 | 
        
           |  |  | 157 |             $return[$pluginname] = self::make_plugin_instance($type, $typerootdir,
 | 
        
           |  |  | 158 |                 $pluginname, $pluginrootdir, $typeclass, $pluginman);
 | 
        
           |  |  | 159 |         }
 | 
        
           |  |  | 160 |   | 
        
           | 1441 | ariadna | 161 |         // Fetch missing incorrectly uninstalled plugins, including deprecated plugins which are not included above.
 | 
        
           | 1 | efrain | 162 |         $plugins = $pluginman->get_installed_plugins($type);
 | 
        
           |  |  | 163 |   | 
        
           |  |  | 164 |         foreach ($plugins as $name => $version) {
 | 
        
           |  |  | 165 |             if (isset($return[$name])) {
 | 
        
           |  |  | 166 |                 continue;
 | 
        
           |  |  | 167 |             }
 | 
        
           |  |  | 168 |             $plugin              = new $typeclass();
 | 
        
           |  |  | 169 |             $plugin->type        = $type;
 | 
        
           |  |  | 170 |             $plugin->typerootdir = $typerootdir;
 | 
        
           |  |  | 171 |             $plugin->name        = $name;
 | 
        
           |  |  | 172 |             $plugin->component   = $plugin->type.'_'.$plugin->name;
 | 
        
           |  |  | 173 |             $plugin->rootdir     = null;
 | 
        
           |  |  | 174 |             $plugin->displayname = $name;
 | 
        
           |  |  | 175 |             $plugin->versiondb   = $version;
 | 
        
           |  |  | 176 |             $plugin->pluginman   = $pluginman;
 | 
        
           |  |  | 177 |             $plugin->init_is_standard();
 | 
        
           | 1441 | ariadna | 178 |             $plugin->init_is_deprecated();
 | 
        
           | 1 | efrain | 179 |   | 
        
           |  |  | 180 |             $return[$name] = $plugin;
 | 
        
           |  |  | 181 |         }
 | 
        
           |  |  | 182 |   | 
        
           |  |  | 183 |         return $return;
 | 
        
           |  |  | 184 |     }
 | 
        
           |  |  | 185 |   | 
        
           |  |  | 186 |     /**
 | 
        
           |  |  | 187 |      * Makes a new instance of the plugininfo class
 | 
        
           |  |  | 188 |      *
 | 
        
           |  |  | 189 |      * @param string $type the plugin type, eg. 'mod'
 | 
        
           |  |  | 190 |      * @param string $typerootdir full path to the location of all the plugins of this type
 | 
        
           |  |  | 191 |      * @param string $name the plugin name, eg. 'workshop'
 | 
        
           |  |  | 192 |      * @param string $namerootdir full path to the location of the plugin
 | 
        
           |  |  | 193 |      * @param string $typeclass the name of class that holds the info about the plugin
 | 
        
           |  |  | 194 |      * @param core_plugin_manager $pluginman the plugin manager of the new instance
 | 
        
           |  |  | 195 |      * @return base the instance of $typeclass
 | 
        
           |  |  | 196 |      */
 | 
        
           |  |  | 197 |     protected static function make_plugin_instance($type, $typerootdir, $name, $namerootdir, $typeclass, $pluginman) {
 | 
        
           |  |  | 198 |         $plugin              = new $typeclass();
 | 
        
           |  |  | 199 |         $plugin->type        = $type;
 | 
        
           |  |  | 200 |         $plugin->typerootdir = $typerootdir;
 | 
        
           |  |  | 201 |         $plugin->name        = $name;
 | 
        
           |  |  | 202 |         $plugin->rootdir     = $namerootdir;
 | 
        
           |  |  | 203 |         $plugin->pluginman   = $pluginman;
 | 
        
           |  |  | 204 |         $plugin->component   = $plugin->type.'_'.$plugin->name;
 | 
        
           |  |  | 205 |   | 
        
           |  |  | 206 |         $plugin->init_display_name();
 | 
        
           |  |  | 207 |         $plugin->load_disk_version();
 | 
        
           |  |  | 208 |         $plugin->load_db_version();
 | 
        
           |  |  | 209 |         $plugin->init_is_standard();
 | 
        
           | 1441 | ariadna | 210 |         $plugin->init_is_deprecated();
 | 
        
           | 1 | efrain | 211 |   | 
        
           |  |  | 212 |         return $plugin;
 | 
        
           |  |  | 213 |     }
 | 
        
           |  |  | 214 |   | 
        
           |  |  | 215 |     /**
 | 
        
           |  |  | 216 |      * Is this plugin already installed and updated?
 | 
        
           |  |  | 217 |      * @return bool true if plugin installed and upgraded.
 | 
        
           |  |  | 218 |      */
 | 
        
           |  |  | 219 |     public function is_installed_and_upgraded() {
 | 
        
           |  |  | 220 |         if (!$this->rootdir) {
 | 
        
           |  |  | 221 |             return false;
 | 
        
           |  |  | 222 |         }
 | 
        
           |  |  | 223 |         if ($this->versiondb === null and $this->versiondisk === null) {
 | 
        
           |  |  | 224 |             // There is no version.php or version info inside it.
 | 
        
           |  |  | 225 |             return false;
 | 
        
           |  |  | 226 |         }
 | 
        
           |  |  | 227 |   | 
        
           |  |  | 228 |         return ((float)$this->versiondb === (float)$this->versiondisk);
 | 
        
           |  |  | 229 |     }
 | 
        
           |  |  | 230 |   | 
        
           |  |  | 231 |     /**
 | 
        
           |  |  | 232 |      * Sets {@link $displayname} property to a localized name of the plugin
 | 
        
           |  |  | 233 |      */
 | 
        
           |  |  | 234 |     public function init_display_name() {
 | 
        
           |  |  | 235 |         if (!get_string_manager()->string_exists('pluginname', $this->component)) {
 | 
        
           |  |  | 236 |             $this->displayname = '[pluginname,' . $this->component . ']';
 | 
        
           |  |  | 237 |         } else {
 | 
        
           |  |  | 238 |             $this->displayname = get_string('pluginname', $this->component);
 | 
        
           |  |  | 239 |         }
 | 
        
           |  |  | 240 |     }
 | 
        
           |  |  | 241 |   | 
        
           |  |  | 242 |     /**
 | 
        
           |  |  | 243 |      * Magic method getter, redirects to read only values.
 | 
        
           |  |  | 244 |      *
 | 
        
           |  |  | 245 |      * @param string $name
 | 
        
           |  |  | 246 |      * @return mixed
 | 
        
           |  |  | 247 |      */
 | 
        
           |  |  | 248 |     public function __get($name) {
 | 
        
           |  |  | 249 |         switch ($name) {
 | 
        
           |  |  | 250 |             case 'component': return $this->type . '_' . $this->name;
 | 
        
           |  |  | 251 |   | 
        
           |  |  | 252 |             default:
 | 
        
           |  |  | 253 |                 debugging('Invalid plugin property accessed! '.$name);
 | 
        
           |  |  | 254 |                 return null;
 | 
        
           |  |  | 255 |         }
 | 
        
           |  |  | 256 |     }
 | 
        
           |  |  | 257 |   | 
        
           |  |  | 258 |     /**
 | 
        
           |  |  | 259 |      * Return the full path name of a file within the plugin.
 | 
        
           |  |  | 260 |      *
 | 
        
           |  |  | 261 |      * No check is made to see if the file exists.
 | 
        
           |  |  | 262 |      *
 | 
        
           |  |  | 263 |      * @param string $relativepath e.g. 'version.php'.
 | 
        
           |  |  | 264 |      * @return string e.g. $CFG->dirroot . '/mod/quiz/version.php'.
 | 
        
           |  |  | 265 |      */
 | 
        
           |  |  | 266 |     public function full_path($relativepath) {
 | 
        
           |  |  | 267 |         if (empty($this->rootdir)) {
 | 
        
           |  |  | 268 |             return '';
 | 
        
           |  |  | 269 |         }
 | 
        
           |  |  | 270 |         return $this->rootdir . '/' . $relativepath;
 | 
        
           |  |  | 271 |     }
 | 
        
           |  |  | 272 |   | 
        
           |  |  | 273 |     /**
 | 
        
           |  |  | 274 |      * Sets {@link $versiondisk} property to a numerical value representing the
 | 
        
           |  |  | 275 |      * version of the plugin's source code.
 | 
        
           |  |  | 276 |      *
 | 
        
           |  |  | 277 |      * If the value is null after calling this method, either the plugin
 | 
        
           |  |  | 278 |      * does not use versioning (typically does not have any database
 | 
        
           |  |  | 279 |      * data) or is missing from disk.
 | 
        
           |  |  | 280 |      */
 | 
        
           |  |  | 281 |     public function load_disk_version() {
 | 
        
           | 1441 | ariadna | 282 |         // Note: this includes deprecated plugins.
 | 
        
           | 1 | efrain | 283 |         $versions = $this->pluginman->get_present_plugins($this->type);
 | 
        
           |  |  | 284 |   | 
        
           |  |  | 285 |         $this->versiondisk = null;
 | 
        
           |  |  | 286 |         $this->versionrequires = null;
 | 
        
           |  |  | 287 |         $this->pluginsupported = null;
 | 
        
           |  |  | 288 |         $this->pluginincompatible = null;
 | 
        
           |  |  | 289 |         $this->dependencies = array();
 | 
        
           |  |  | 290 |   | 
        
           |  |  | 291 |         if (!isset($versions[$this->name])) {
 | 
        
           |  |  | 292 |             return;
 | 
        
           |  |  | 293 |         }
 | 
        
           |  |  | 294 |   | 
        
           |  |  | 295 |         $plugin = $versions[$this->name];
 | 
        
           |  |  | 296 |   | 
        
           |  |  | 297 |         if (isset($plugin->version)) {
 | 
        
           |  |  | 298 |             $this->versiondisk = $plugin->version;
 | 
        
           |  |  | 299 |         }
 | 
        
           |  |  | 300 |         if (isset($plugin->requires)) {
 | 
        
           |  |  | 301 |             $this->versionrequires = $plugin->requires;
 | 
        
           |  |  | 302 |         }
 | 
        
           |  |  | 303 |         if (isset($plugin->release)) {
 | 
        
           |  |  | 304 |             $this->release = $plugin->release;
 | 
        
           |  |  | 305 |         }
 | 
        
           |  |  | 306 |         if (isset($plugin->dependencies)) {
 | 
        
           |  |  | 307 |             $this->dependencies = $plugin->dependencies;
 | 
        
           |  |  | 308 |         }
 | 
        
           |  |  | 309 |   | 
        
           |  |  | 310 |         // Check that supports and incompatible are wellformed, exception otherwise.
 | 
        
           |  |  | 311 |         if (isset($plugin->supported)) {
 | 
        
           |  |  | 312 |             // Checks for structure of supported.
 | 
        
           |  |  | 313 |             $isint = (is_int($plugin->supported[0]) && is_int($plugin->supported[1]));
 | 
        
           |  |  | 314 |             $isrange = ($plugin->supported[0] <= $plugin->supported[1] && count($plugin->supported) == 2);
 | 
        
           |  |  | 315 |   | 
        
           |  |  | 316 |             if (is_array($plugin->supported) && $isint && $isrange) {
 | 
        
           |  |  | 317 |                 $this->pluginsupported = $plugin->supported;
 | 
        
           |  |  | 318 |             } else {
 | 
        
           |  |  | 319 |                 throw new coding_exception('Incorrect syntax in plugin supported declaration in '."$this->name");
 | 
        
           |  |  | 320 |             }
 | 
        
           |  |  | 321 |         }
 | 
        
           |  |  | 322 |   | 
        
           |  |  | 323 |         if (isset($plugin->incompatible) && $plugin->incompatible !== null) {
 | 
        
           |  |  | 324 |             if (((is_string($plugin->incompatible) && ctype_digit($plugin->incompatible)) || is_int($plugin->incompatible))
 | 
        
           |  |  | 325 |                     && (int) $plugin->incompatible > 0) {
 | 
        
           |  |  | 326 |                 $this->pluginincompatible = intval($plugin->incompatible);
 | 
        
           |  |  | 327 |             } else {
 | 
        
           |  |  | 328 |                 throw new coding_exception('Incorrect syntax in plugin incompatible declaration in '."$this->name");
 | 
        
           |  |  | 329 |             }
 | 
        
           |  |  | 330 |         }
 | 
        
           |  |  | 331 |   | 
        
           |  |  | 332 |     }
 | 
        
           |  |  | 333 |   | 
        
           |  |  | 334 |     /**
 | 
        
           |  |  | 335 |      * Get the list of other plugins that this plugin requires to be installed.
 | 
        
           |  |  | 336 |      *
 | 
        
           |  |  | 337 |      * @return array with keys the frankenstyle plugin name, and values either
 | 
        
           |  |  | 338 |      *      a version string (like '2011101700') or the constant ANY_VERSION.
 | 
        
           |  |  | 339 |      */
 | 
        
           |  |  | 340 |     public function get_other_required_plugins() {
 | 
        
           |  |  | 341 |         if (is_null($this->dependencies)) {
 | 
        
           |  |  | 342 |             $this->load_disk_version();
 | 
        
           |  |  | 343 |         }
 | 
        
           |  |  | 344 |         return $this->dependencies;
 | 
        
           |  |  | 345 |     }
 | 
        
           |  |  | 346 |   | 
        
           |  |  | 347 |     /**
 | 
        
           |  |  | 348 |      * Is this is a subplugin?
 | 
        
           |  |  | 349 |      *
 | 
        
           |  |  | 350 |      * @return boolean
 | 
        
           |  |  | 351 |      */
 | 
        
           |  |  | 352 |     public function is_subplugin() {
 | 
        
           |  |  | 353 |         return ($this->get_parent_plugin() !== false);
 | 
        
           |  |  | 354 |     }
 | 
        
           |  |  | 355 |   | 
        
           |  |  | 356 |     /**
 | 
        
           |  |  | 357 |      * If I am a subplugin, return the name of my parent plugin.
 | 
        
           |  |  | 358 |      *
 | 
        
           |  |  | 359 |      * @return string|bool false if not a subplugin, name of the parent otherwise
 | 
        
           |  |  | 360 |      */
 | 
        
           |  |  | 361 |     public function get_parent_plugin() {
 | 
        
           | 1441 | ariadna | 362 |         return $this->pluginman->get_parent_of_subplugin($this->type, true);
 | 
        
           | 1 | efrain | 363 |     }
 | 
        
           |  |  | 364 |   | 
        
           |  |  | 365 |     /**
 | 
        
           |  |  | 366 |      * Sets {@link $versiondb} property to a numerical value representing the
 | 
        
           |  |  | 367 |      * currently installed version of the plugin.
 | 
        
           |  |  | 368 |      *
 | 
        
           |  |  | 369 |      * If the value is null after calling this method, either the plugin
 | 
        
           |  |  | 370 |      * does not use versioning (typically does not have any database
 | 
        
           |  |  | 371 |      * data) or has not been installed yet.
 | 
        
           |  |  | 372 |      */
 | 
        
           |  |  | 373 |     public function load_db_version() {
 | 
        
           |  |  | 374 |         $versions = $this->pluginman->get_installed_plugins($this->type);
 | 
        
           |  |  | 375 |   | 
        
           |  |  | 376 |         if (isset($versions[$this->name])) {
 | 
        
           |  |  | 377 |             $this->versiondb = $versions[$this->name];
 | 
        
           |  |  | 378 |         } else {
 | 
        
           |  |  | 379 |             $this->versiondb = null;
 | 
        
           |  |  | 380 |         }
 | 
        
           |  |  | 381 |     }
 | 
        
           |  |  | 382 |   | 
        
           |  |  | 383 |     /**
 | 
        
           |  |  | 384 |      * Sets {@link $source} property to one of core_plugin_manager::PLUGIN_SOURCE_xxx
 | 
        
           |  |  | 385 |      * constants.
 | 
        
           |  |  | 386 |      *
 | 
        
           |  |  | 387 |      * If the property's value is null after calling this method, then
 | 
        
           |  |  | 388 |      * the type of the plugin has not been recognized and you should throw
 | 
        
           |  |  | 389 |      * an exception.
 | 
        
           |  |  | 390 |      */
 | 
        
           |  |  | 391 |     public function init_is_standard() {
 | 
        
           |  |  | 392 |   | 
        
           |  |  | 393 |         $pluginman = $this->pluginman;
 | 
        
           |  |  | 394 |         $standard = $pluginman::standard_plugins_list($this->type);
 | 
        
           |  |  | 395 |   | 
        
           |  |  | 396 |         if ($standard !== false) {
 | 
        
           |  |  | 397 |             $standard = array_flip($standard);
 | 
        
           |  |  | 398 |             if (isset($standard[$this->name])) {
 | 
        
           |  |  | 399 |                 $this->source = core_plugin_manager::PLUGIN_SOURCE_STANDARD;
 | 
        
           |  |  | 400 |             } else if (!is_null($this->versiondb) and is_null($this->versiondisk)
 | 
        
           |  |  | 401 |                 and $pluginman::is_deleted_standard_plugin($this->type, $this->name)) {
 | 
        
           |  |  | 402 |                 $this->source = core_plugin_manager::PLUGIN_SOURCE_STANDARD; // To be deleted.
 | 
        
           |  |  | 403 |             } else {
 | 
        
           |  |  | 404 |                 $this->source = core_plugin_manager::PLUGIN_SOURCE_EXTENSION;
 | 
        
           |  |  | 405 |             }
 | 
        
           |  |  | 406 |         }
 | 
        
           |  |  | 407 |     }
 | 
        
           |  |  | 408 |   | 
        
           |  |  | 409 |     /**
 | 
        
           | 1441 | ariadna | 410 |      * Init some instance props denoting the deprecation state of the plugin.
 | 
        
           |  |  | 411 |      *
 | 
        
           |  |  | 412 |      * Sets {@see $deprecatedtype} property, indicating whether the plugintype is phase 1 deprecated.
 | 
        
           |  |  | 413 |      * Sets {@see $deletedtype} property, indicating whether the plugintype is phase 2 deprecated.
 | 
        
           |  |  | 414 |      * Sets {@see $displayname} property to the plugin name phase 2 deprecated plugins since lang string support has then ended.
 | 
        
           |  |  | 415 |      *
 | 
        
           |  |  | 416 |      * @return void
 | 
        
           |  |  | 417 |      */
 | 
        
           |  |  | 418 |     final public function init_is_deprecated(): void {
 | 
        
           |  |  | 419 |         $this->deprecatedtype = \core_component::is_deprecated_plugin_type($this->type);
 | 
        
           |  |  | 420 |         $this->deletedtype = \core_component::is_deleted_plugin_type($this->type);
 | 
        
           |  |  | 421 |         $this->displayname = $this->deletedtype ? $this->name : $this->displayname;
 | 
        
           |  |  | 422 |     }
 | 
        
           |  |  | 423 |   | 
        
           |  |  | 424 |     /**
 | 
        
           | 1 | efrain | 425 |      * Returns true if the plugin is shipped with the official distribution
 | 
        
           |  |  | 426 |      * of the current Moodle version, false otherwise.
 | 
        
           |  |  | 427 |      *
 | 
        
           |  |  | 428 |      * @return bool
 | 
        
           |  |  | 429 |      */
 | 
        
           |  |  | 430 |     public function is_standard() {
 | 
        
           |  |  | 431 |         return $this->source === core_plugin_manager::PLUGIN_SOURCE_STANDARD;
 | 
        
           |  |  | 432 |     }
 | 
        
           |  |  | 433 |   | 
        
           |  |  | 434 |     /**
 | 
        
           |  |  | 435 |      * Returns true if the the given Moodle version is enough to run this plugin
 | 
        
           |  |  | 436 |      *
 | 
        
           |  |  | 437 |      * @param string|int|double $moodleversion
 | 
        
           |  |  | 438 |      * @return bool
 | 
        
           |  |  | 439 |      */
 | 
        
           |  |  | 440 |     public function is_core_dependency_satisfied($moodleversion) {
 | 
        
           |  |  | 441 |   | 
        
           |  |  | 442 |         if (empty($this->versionrequires)) {
 | 
        
           |  |  | 443 |             return true;
 | 
        
           |  |  | 444 |   | 
        
           |  |  | 445 |         } else {
 | 
        
           |  |  | 446 |             return (double)$this->versionrequires <= (double)$moodleversion;
 | 
        
           |  |  | 447 |         }
 | 
        
           |  |  | 448 |     }
 | 
        
           |  |  | 449 |   | 
        
           |  |  | 450 |     /**
 | 
        
           |  |  | 451 |      * Returns true if the the given moodle branch is not stated incompatible with the plugin
 | 
        
           |  |  | 452 |      *
 | 
        
           |  |  | 453 |      * @param int $branch the moodle branch number
 | 
        
           |  |  | 454 |      * @return bool true if not incompatible with moodle branch
 | 
        
           |  |  | 455 |      */
 | 
        
           |  |  | 456 |     public function is_core_compatible_satisfied(int $branch): bool {
 | 
        
           |  |  | 457 |         if (!empty($this->pluginincompatible) && ($branch >= $this->pluginincompatible)) {
 | 
        
           |  |  | 458 |             return false;
 | 
        
           |  |  | 459 |         } else {
 | 
        
           |  |  | 460 |             return true;
 | 
        
           |  |  | 461 |         }
 | 
        
           |  |  | 462 |     }
 | 
        
           |  |  | 463 |   | 
        
           |  |  | 464 |     /**
 | 
        
           |  |  | 465 |      * Returns the status of the plugin
 | 
        
           |  |  | 466 |      *
 | 
        
           |  |  | 467 |      * @return string one of core_plugin_manager::PLUGIN_STATUS_xxx constants
 | 
        
           |  |  | 468 |      */
 | 
        
           |  |  | 469 |     public function get_status() {
 | 
        
           |  |  | 470 |   | 
        
           |  |  | 471 |         $pluginman = $this->pluginman;
 | 
        
           |  |  | 472 |   | 
        
           |  |  | 473 |         if (is_null($this->versiondb) and is_null($this->versiondisk)) {
 | 
        
           |  |  | 474 |             return core_plugin_manager::PLUGIN_STATUS_NODB;
 | 
        
           |  |  | 475 |   | 
        
           |  |  | 476 |         } else if (is_null($this->versiondb) and !is_null($this->versiondisk)) {
 | 
        
           |  |  | 477 |             return core_plugin_manager::PLUGIN_STATUS_NEW;
 | 
        
           |  |  | 478 |   | 
        
           |  |  | 479 |         } else if (!is_null($this->versiondb) and is_null($this->versiondisk)) {
 | 
        
           |  |  | 480 |             if ($pluginman::is_deleted_standard_plugin($this->type, $this->name)) {
 | 
        
           |  |  | 481 |                 return core_plugin_manager::PLUGIN_STATUS_DELETE;
 | 
        
           |  |  | 482 |             } else {
 | 
        
           |  |  | 483 |                 return core_plugin_manager::PLUGIN_STATUS_MISSING;
 | 
        
           |  |  | 484 |             }
 | 
        
           |  |  | 485 |   | 
        
           |  |  | 486 |         } else if ((float)$this->versiondb === (float)$this->versiondisk) {
 | 
        
           |  |  | 487 |             // Note: the float comparison should work fine here
 | 
        
           |  |  | 488 |             //       because there are no arithmetic operations with the numbers.
 | 
        
           |  |  | 489 |             return core_plugin_manager::PLUGIN_STATUS_UPTODATE;
 | 
        
           |  |  | 490 |   | 
        
           |  |  | 491 |         } else if ($this->versiondb < $this->versiondisk) {
 | 
        
           |  |  | 492 |             return core_plugin_manager::PLUGIN_STATUS_UPGRADE;
 | 
        
           |  |  | 493 |   | 
        
           |  |  | 494 |         } else if ($this->versiondb > $this->versiondisk) {
 | 
        
           |  |  | 495 |             return core_plugin_manager::PLUGIN_STATUS_DOWNGRADE;
 | 
        
           |  |  | 496 |   | 
        
           |  |  | 497 |         } else {
 | 
        
           |  |  | 498 |             // $version = pi(); and similar funny jokes - hopefully Donald E. Knuth will never contribute to Moodle ;-)
 | 
        
           |  |  | 499 |             throw new coding_exception('Unable to determine plugin state, check the plugin versions');
 | 
        
           |  |  | 500 |         }
 | 
        
           |  |  | 501 |     }
 | 
        
           |  |  | 502 |   | 
        
           |  |  | 503 |     /**
 | 
        
           |  |  | 504 |      * Returns the information about plugin availability
 | 
        
           |  |  | 505 |      *
 | 
        
           |  |  | 506 |      * True means that the plugin is enabled. False means that the plugin is
 | 
        
           |  |  | 507 |      * disabled. Null means that the information is not available, or the
 | 
        
           |  |  | 508 |      * plugin does not support configurable availability or the availability
 | 
        
           |  |  | 509 |      * can not be changed.
 | 
        
           |  |  | 510 |      *
 | 
        
           |  |  | 511 |      * @return null|bool
 | 
        
           |  |  | 512 |      */
 | 
        
           |  |  | 513 |     public function is_enabled() {
 | 
        
           |  |  | 514 |         if (!$this->rootdir) {
 | 
        
           |  |  | 515 |             // Plugin missing.
 | 
        
           |  |  | 516 |             return false;
 | 
        
           |  |  | 517 |         }
 | 
        
           |  |  | 518 |   | 
        
           |  |  | 519 |         $enabled = $this->pluginman->get_enabled_plugins($this->type);
 | 
        
           |  |  | 520 |   | 
        
           |  |  | 521 |         if (!is_array($enabled)) {
 | 
        
           |  |  | 522 |             return null;
 | 
        
           |  |  | 523 |         }
 | 
        
           |  |  | 524 |   | 
        
           |  |  | 525 |         return isset($enabled[$this->name]);
 | 
        
           |  |  | 526 |     }
 | 
        
           |  |  | 527 |   | 
        
           |  |  | 528 |     /**
 | 
        
           | 1441 | ariadna | 529 |      * Return whether this plugin is deprecated (i.e. the plugin type to which it belongs is deprecated).
 | 
        
           |  |  | 530 |      *
 | 
        
           |  |  | 531 |      * @return bool
 | 
        
           |  |  | 532 |      */
 | 
        
           |  |  | 533 |     public function is_deprecated(): bool {
 | 
        
           |  |  | 534 |         return $this->deprecatedtype;
 | 
        
           |  |  | 535 |     }
 | 
        
           |  |  | 536 |   | 
        
           |  |  | 537 |     /**
 | 
        
           |  |  | 538 |      * Return whether this plugin is deleted (i.e. the plugin type to which it belongs is deleted).
 | 
        
           |  |  | 539 |      *
 | 
        
           |  |  | 540 |      * @return bool
 | 
        
           |  |  | 541 |      */
 | 
        
           |  |  | 542 |     public function is_deleted(): bool {
 | 
        
           |  |  | 543 |         return $this->deletedtype;
 | 
        
           |  |  | 544 |     }
 | 
        
           |  |  | 545 |   | 
        
           |  |  | 546 |     /**
 | 
        
           | 1 | efrain | 547 |      * If there are updates for this plugin available, returns them.
 | 
        
           |  |  | 548 |      *
 | 
        
           |  |  | 549 |      * Returns array of {@link \core\update\info} objects, if some update
 | 
        
           |  |  | 550 |      * is available. Returns null if there is no update available or if the update
 | 
        
           |  |  | 551 |      * availability is unknown.
 | 
        
           |  |  | 552 |      *
 | 
        
           |  |  | 553 |      * Populates the property {@link $availableupdates} on first call (lazy
 | 
        
           |  |  | 554 |      * loading).
 | 
        
           |  |  | 555 |      *
 | 
        
           |  |  | 556 |      * @return array|null
 | 
        
           |  |  | 557 |      */
 | 
        
           |  |  | 558 |     public function available_updates() {
 | 
        
           |  |  | 559 |   | 
        
           |  |  | 560 |         if ($this->availableupdates === null) {
 | 
        
           |  |  | 561 |             // Lazy load the information about available updates.
 | 
        
           |  |  | 562 |             $this->availableupdates = $this->pluginman->load_available_updates_for_plugin($this->component);
 | 
        
           |  |  | 563 |         }
 | 
        
           |  |  | 564 |   | 
        
           |  |  | 565 |         if (empty($this->availableupdates) or !is_array($this->availableupdates)) {
 | 
        
           |  |  | 566 |             $this->availableupdates = array();
 | 
        
           |  |  | 567 |             return null;
 | 
        
           |  |  | 568 |         }
 | 
        
           |  |  | 569 |   | 
        
           |  |  | 570 |         $updates = array();
 | 
        
           |  |  | 571 |   | 
        
           |  |  | 572 |         foreach ($this->availableupdates as $availableupdate) {
 | 
        
           |  |  | 573 |             if ($availableupdate->version > $this->versiondisk) {
 | 
        
           |  |  | 574 |                 $updates[] = $availableupdate;
 | 
        
           |  |  | 575 |             }
 | 
        
           |  |  | 576 |         }
 | 
        
           |  |  | 577 |   | 
        
           |  |  | 578 |         if (empty($updates)) {
 | 
        
           |  |  | 579 |             return null;
 | 
        
           |  |  | 580 |         }
 | 
        
           |  |  | 581 |   | 
        
           |  |  | 582 |         return $updates;
 | 
        
           |  |  | 583 |     }
 | 
        
           |  |  | 584 |   | 
        
           |  |  | 585 |     /**
 | 
        
           |  |  | 586 |      * Returns the node name used in admin settings menu for this plugin settings (if applicable)
 | 
        
           |  |  | 587 |      *
 | 
        
           |  |  | 588 |      * @return null|string node name or null if plugin does not create settings node (default)
 | 
        
           |  |  | 589 |      */
 | 
        
           |  |  | 590 |     public function get_settings_section_name() {
 | 
        
           |  |  | 591 |         return null;
 | 
        
           |  |  | 592 |     }
 | 
        
           |  |  | 593 |   | 
        
           |  |  | 594 |     /**
 | 
        
           |  |  | 595 |      * Returns the URL of the plugin settings screen
 | 
        
           |  |  | 596 |      *
 | 
        
           |  |  | 597 |      * Null value means that the plugin either does not have the settings screen
 | 
        
           |  |  | 598 |      * or its location is not available via this library.
 | 
        
           |  |  | 599 |      *
 | 
        
           |  |  | 600 |      * @return null|moodle_url
 | 
        
           |  |  | 601 |      */
 | 
        
           |  |  | 602 |     public function get_settings_url(): ?moodle_url {
 | 
        
           |  |  | 603 |         $section = $this->get_settings_section_name();
 | 
        
           |  |  | 604 |         if ($section === null) {
 | 
        
           |  |  | 605 |             return null;
 | 
        
           |  |  | 606 |         }
 | 
        
           |  |  | 607 |   | 
        
           |  |  | 608 |         $settings = admin_get_root()->locate($section);
 | 
        
           |  |  | 609 |         if ($settings && $settings instanceof \core_admin\local\settings\linkable_settings_page) {
 | 
        
           |  |  | 610 |             return $settings->get_settings_page_url();
 | 
        
           |  |  | 611 |         }
 | 
        
           |  |  | 612 |   | 
        
           |  |  | 613 |         return null;
 | 
        
           |  |  | 614 |     }
 | 
        
           |  |  | 615 |   | 
        
           |  |  | 616 |     /**
 | 
        
           |  |  | 617 |      * Loads plugin settings to the settings tree
 | 
        
           |  |  | 618 |      *
 | 
        
           |  |  | 619 |      * This function usually includes settings.php file in plugins folder.
 | 
        
           |  |  | 620 |      * Alternatively it can create a link to some settings page (instance of admin_externalpage)
 | 
        
           |  |  | 621 |      *
 | 
        
           |  |  | 622 |      * @param \part_of_admin_tree $adminroot
 | 
        
           |  |  | 623 |      * @param string $parentnodename
 | 
        
           |  |  | 624 |      * @param bool $hassiteconfig whether the current user has moodle/site:config capability
 | 
        
           |  |  | 625 |      */
 | 
        
           |  |  | 626 |     public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
 | 
        
           |  |  | 627 |     }
 | 
        
           |  |  | 628 |   | 
        
           |  |  | 629 |     /**
 | 
        
           |  |  | 630 |      * Should there be a way to uninstall the plugin via the administration UI.
 | 
        
           |  |  | 631 |      *
 | 
        
           |  |  | 632 |      * By default uninstallation is not allowed, plugin developers must enable it explicitly!
 | 
        
           |  |  | 633 |      *
 | 
        
           |  |  | 634 |      * @return bool
 | 
        
           |  |  | 635 |      */
 | 
        
           |  |  | 636 |     public function is_uninstall_allowed() {
 | 
        
           |  |  | 637 |         return false;
 | 
        
           |  |  | 638 |     }
 | 
        
           |  |  | 639 |   | 
        
           |  |  | 640 |     /**
 | 
        
           |  |  | 641 |      * Optional extra warning before uninstallation, for example number of uses in courses.
 | 
        
           |  |  | 642 |      *
 | 
        
           |  |  | 643 |      * @return string
 | 
        
           |  |  | 644 |      */
 | 
        
           |  |  | 645 |     public function get_uninstall_extra_warning() {
 | 
        
           |  |  | 646 |         return '';
 | 
        
           |  |  | 647 |     }
 | 
        
           |  |  | 648 |   | 
        
           |  |  | 649 |     /**
 | 
        
           |  |  | 650 |      * Pre-uninstall hook.
 | 
        
           |  |  | 651 |      *
 | 
        
           |  |  | 652 |      * This is intended for disabling of plugin, some DB table purging, etc.
 | 
        
           |  |  | 653 |      *
 | 
        
           |  |  | 654 |      * NOTE: to be called from uninstall_plugin() only.
 | 
        
           |  |  | 655 |      * @private
 | 
        
           |  |  | 656 |      */
 | 
        
           |  |  | 657 |     public function uninstall_cleanup() {
 | 
        
           |  |  | 658 |         // Override when extending class,
 | 
        
           |  |  | 659 |         // do not forget to call parent::pre_uninstall_cleanup() at the end.
 | 
        
           |  |  | 660 |     }
 | 
        
           |  |  | 661 |   | 
        
           |  |  | 662 |     /**
 | 
        
           |  |  | 663 |      * Returns relative directory of the plugin with heading '/'
 | 
        
           |  |  | 664 |      *
 | 
        
           |  |  | 665 |      * @return string
 | 
        
           |  |  | 666 |      */
 | 
        
           |  |  | 667 |     public function get_dir() {
 | 
        
           |  |  | 668 |         global $CFG;
 | 
        
           |  |  | 669 |   | 
        
           |  |  | 670 |         if (!isset($this->rootdir)) {
 | 
        
           |  |  | 671 |             return '';
 | 
        
           |  |  | 672 |         }
 | 
        
           |  |  | 673 |   | 
        
           |  |  | 674 |         return substr($this->rootdir, strlen($CFG->dirroot));
 | 
        
           |  |  | 675 |     }
 | 
        
           |  |  | 676 |   | 
        
           |  |  | 677 |     /**
 | 
        
           |  |  | 678 |      * Hook method to implement certain steps when uninstalling the plugin.
 | 
        
           |  |  | 679 |      *
 | 
        
           |  |  | 680 |      * This hook is called by {@link core_plugin_manager::uninstall_plugin()} so
 | 
        
           |  |  | 681 |      * it is basically usable only for those plugin types that use the default
 | 
        
           |  |  | 682 |      * uninstall tool provided by {@link self::get_default_uninstall_url()}.
 | 
        
           |  |  | 683 |      *
 | 
        
           |  |  | 684 |      * @param \progress_trace $progress traces the process
 | 
        
           |  |  | 685 |      * @return bool true on success, false on failure
 | 
        
           |  |  | 686 |      */
 | 
        
           |  |  | 687 |     public function uninstall(\progress_trace $progress) {
 | 
        
           |  |  | 688 |         return true;
 | 
        
           |  |  | 689 |     }
 | 
        
           |  |  | 690 |   | 
        
           |  |  | 691 |     /**
 | 
        
           |  |  | 692 |      * Where should we return after plugin of this type is uninstalled?
 | 
        
           |  |  | 693 |      * @param string $return
 | 
        
           |  |  | 694 |      * @return moodle_url
 | 
        
           |  |  | 695 |      */
 | 
        
           |  |  | 696 |     public function get_return_url_after_uninstall($return) {
 | 
        
           |  |  | 697 |         if ($return === 'manage') {
 | 
        
           |  |  | 698 |             if ($url = $this->get_manage_url()) {
 | 
        
           |  |  | 699 |                 return $url;
 | 
        
           |  |  | 700 |             }
 | 
        
           |  |  | 701 |         }
 | 
        
           |  |  | 702 |         return new moodle_url('/admin/plugins.php#plugin_type_cell_'.$this->type);
 | 
        
           |  |  | 703 |     }
 | 
        
           |  |  | 704 |   | 
        
           |  |  | 705 |     /**
 | 
        
           |  |  | 706 |      * Return URL used for management of plugins of this type.
 | 
        
           |  |  | 707 |      * @return moodle_url
 | 
        
           |  |  | 708 |      */
 | 
        
           |  |  | 709 |     public static function get_manage_url() {
 | 
        
           |  |  | 710 |         return null;
 | 
        
           |  |  | 711 |     }
 | 
        
           |  |  | 712 |   | 
        
           |  |  | 713 |     /**
 | 
        
           |  |  | 714 |      * Returns URL to a script that handles common plugin uninstall procedure.
 | 
        
           |  |  | 715 |      *
 | 
        
           |  |  | 716 |      * This URL is intended for all plugin uninstallations.
 | 
        
           |  |  | 717 |      *
 | 
        
           |  |  | 718 |      * @param string $return either 'overview' or 'manage'
 | 
        
           |  |  | 719 |      * @return moodle_url
 | 
        
           |  |  | 720 |      */
 | 
        
           |  |  | 721 |     final public function get_default_uninstall_url($return = 'overview') {
 | 
        
           |  |  | 722 |         return new moodle_url('/admin/plugins.php', array(
 | 
        
           |  |  | 723 |             'uninstall' => $this->component,
 | 
        
           |  |  | 724 |             'confirm' => 0,
 | 
        
           |  |  | 725 |             'return' => $return,
 | 
        
           |  |  | 726 |         ));
 | 
        
           |  |  | 727 |     }
 | 
        
           |  |  | 728 |   | 
        
           |  |  | 729 |     /**
 | 
        
           |  |  | 730 |      * Whether this plugintype supports ordering of plugins using native functionality.
 | 
        
           |  |  | 731 |      *
 | 
        
           |  |  | 732 |      * Please note that plugintypes which pre-date this native functionality may still support ordering
 | 
        
           |  |  | 733 |      * but will not use the built-in functionality.
 | 
        
           |  |  | 734 |      *
 | 
        
           |  |  | 735 |      * @return bool
 | 
        
           |  |  | 736 |      */
 | 
        
           |  |  | 737 |     public static function plugintype_supports_ordering(): bool {
 | 
        
           |  |  | 738 |         return false;
 | 
        
           |  |  | 739 |     }
 | 
        
           |  |  | 740 |   | 
        
           |  |  | 741 |     /**
 | 
        
           |  |  | 742 |      * Finds all enabled plugins, the result may include missing plugins.
 | 
        
           |  |  | 743 |      *
 | 
        
           |  |  | 744 |      * @param bool $enabledonly Show all plugins, or only those which are enabled
 | 
        
           |  |  | 745 |      * @return array|null of sorted plugins $pluginname => $pluginname, null means unknown
 | 
        
           |  |  | 746 |      */
 | 
        
           |  |  | 747 |     public static function get_sorted_plugins(bool $enabledonly = false): ?array {
 | 
        
           |  |  | 748 |         return null;
 | 
        
           |  |  | 749 |     }
 | 
        
           |  |  | 750 |   | 
        
           |  |  | 751 |     /**
 | 
        
           |  |  | 752 |      * Change the order of the plugin relative to other plugins in the plugintype.
 | 
        
           |  |  | 753 |      *
 | 
        
           |  |  | 754 |      * When possible, the change will be stored into the config_log table, to let admins check when/who has modified it.
 | 
        
           |  |  | 755 |      *
 | 
        
           |  |  | 756 |      * @param string $pluginname The plugin name to enable/disable.
 | 
        
           |  |  | 757 |      * @param int $direction The direction to move the plugin. Negative numbers mean up, Positive mean down.
 | 
        
           |  |  | 758 |      * @return bool Whether $pluginname has been updated or not.
 | 
        
           |  |  | 759 |      */
 | 
        
           |  |  | 760 |     public static function change_plugin_order(string $pluginname, int $direction): bool {
 | 
        
           |  |  | 761 |         return false;
 | 
        
           |  |  | 762 |     }
 | 
        
           |  |  | 763 | }
 |