[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/classes/plugininfo/ -> base.php (source)

   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 core_component, core_plugin_manager, moodle_url, coding_exception;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  
  31  /**
  32   * Base class providing access to the information about a plugin
  33   *
  34   * @property-read string component the component name, type_name
  35   */
  36  abstract class base {
  37  
  38      /** @var string the plugintype name, eg. mod, auth or workshopform */
  39      public $type;
  40      /** @var string full path to the location of all the plugins of this type */
  41      public $typerootdir;
  42      /** @var string the plugin name, eg. assignment, ldap */
  43      public $name;
  44      /** @var string the localized plugin name */
  45      public $displayname;
  46      /** @var string the plugin source, one of core_plugin_manager::PLUGIN_SOURCE_xxx constants */
  47      public $source;
  48      /** @var string fullpath to the location of this plugin */
  49      public $rootdir;
  50      /** @var int|string the version of the plugin's source code */
  51      public $versiondisk;
  52      /** @var int|string the version of the installed plugin */
  53      public $versiondb;
  54      /** @var int|float|string required version of Moodle core  */
  55      public $versionrequires;
  56      /** @var mixed human-readable release information */
  57      public $release;
  58      /** @var array other plugins that this one depends on, lazy-loaded by {@link get_other_required_plugins()} */
  59      public $dependencies;
  60      /** @var int number of instances of the plugin - not supported yet */
  61      public $instances;
  62      /** @var int order of the plugin among other plugins of the same type - not supported yet */
  63      public $sortorder;
  64      /** @var core_plugin_manager the plugin manager this plugin info is part of */
  65      public $pluginman;
  66  
  67      /** @var array|null array of {@link \core\update\info} for this plugin */
  68      protected $availableupdates;
  69  
  70      /**
  71       * Finds all enabled plugins, the result may include missing plugins.
  72       * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
  73       */
  74      public static function get_enabled_plugins() {
  75          return null;
  76      }
  77  
  78      /**
  79       * Gathers and returns the information about all plugins of the given type,
  80       * either on disk or previously installed.
  81       *
  82       * This is supposed to be used exclusively by the plugin manager when it is
  83       * populating its tree of plugins.
  84       *
  85       * @param string $type the name of the plugintype, eg. mod, auth or workshopform
  86       * @param string $typerootdir full path to the location of the plugin dir
  87       * @param string $typeclass the name of the actually called class
  88       * @param core_plugin_manager $pluginman the plugin manager calling this method
  89       * @return array of plugintype classes, indexed by the plugin name
  90       */
  91      public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) {
  92          // Get the information about plugins at the disk.
  93          $plugins = core_component::get_plugin_list($type);
  94          $return = array();
  95          foreach ($plugins as $pluginname => $pluginrootdir) {
  96              $return[$pluginname] = self::make_plugin_instance($type, $typerootdir,
  97                  $pluginname, $pluginrootdir, $typeclass, $pluginman);
  98          }
  99  
 100          // Fetch missing incorrectly uninstalled plugins.
 101          $plugins = $pluginman->get_installed_plugins($type);
 102  
 103          foreach ($plugins as $name => $version) {
 104              if (isset($return[$name])) {
 105                  continue;
 106              }
 107              $plugin              = new $typeclass();
 108              $plugin->type        = $type;
 109              $plugin->typerootdir = $typerootdir;
 110              $plugin->name        = $name;
 111              $plugin->rootdir     = null;
 112              $plugin->displayname = $name;
 113              $plugin->versiondb   = $version;
 114              $plugin->pluginman   = $pluginman;
 115              $plugin->init_is_standard();
 116  
 117              $return[$name] = $plugin;
 118          }
 119  
 120          return $return;
 121      }
 122  
 123      /**
 124       * Makes a new instance of the plugininfo class
 125       *
 126       * @param string $type the plugin type, eg. 'mod'
 127       * @param string $typerootdir full path to the location of all the plugins of this type
 128       * @param string $name the plugin name, eg. 'workshop'
 129       * @param string $namerootdir full path to the location of the plugin
 130       * @param string $typeclass the name of class that holds the info about the plugin
 131       * @param core_plugin_manager $pluginman the plugin manager of the new instance
 132       * @return base the instance of $typeclass
 133       */
 134      protected static function make_plugin_instance($type, $typerootdir, $name, $namerootdir, $typeclass, $pluginman) {
 135          $plugin              = new $typeclass();
 136          $plugin->type        = $type;
 137          $plugin->typerootdir = $typerootdir;
 138          $plugin->name        = $name;
 139          $plugin->rootdir     = $namerootdir;
 140          $plugin->pluginman   = $pluginman;
 141  
 142          $plugin->init_display_name();
 143          $plugin->load_disk_version();
 144          $plugin->load_db_version();
 145          $plugin->init_is_standard();
 146  
 147          return $plugin;
 148      }
 149  
 150      /**
 151       * Is this plugin already installed and updated?
 152       * @return bool true if plugin installed and upgraded.
 153       */
 154      public function is_installed_and_upgraded() {
 155          if (!$this->rootdir) {
 156              return false;
 157          }
 158          if ($this->versiondb === null and $this->versiondisk === null) {
 159              // There is no version.php or version info inside it.
 160              return false;
 161          }
 162  
 163          return ((float)$this->versiondb === (float)$this->versiondisk);
 164      }
 165  
 166      /**
 167       * Sets {@link $displayname} property to a localized name of the plugin
 168       */
 169      public function init_display_name() {
 170          if (!get_string_manager()->string_exists('pluginname', $this->component)) {
 171              $this->displayname = '[pluginname,' . $this->component . ']';
 172          } else {
 173              $this->displayname = get_string('pluginname', $this->component);
 174          }
 175      }
 176  
 177      /**
 178       * Magic method getter, redirects to read only values.
 179       *
 180       * @param string $name
 181       * @return mixed
 182       */
 183      public function __get($name) {
 184          switch ($name) {
 185              case 'component': return $this->type . '_' . $this->name;
 186  
 187              default:
 188                  debugging('Invalid plugin property accessed! '.$name);
 189                  return null;
 190          }
 191      }
 192  
 193      /**
 194       * Return the full path name of a file within the plugin.
 195       *
 196       * No check is made to see if the file exists.
 197       *
 198       * @param string $relativepath e.g. 'version.php'.
 199       * @return string e.g. $CFG->dirroot . '/mod/quiz/version.php'.
 200       */
 201      public function full_path($relativepath) {
 202          if (empty($this->rootdir)) {
 203              return '';
 204          }
 205          return $this->rootdir . '/' . $relativepath;
 206      }
 207  
 208      /**
 209       * Sets {@link $versiondisk} property to a numerical value representing the
 210       * version of the plugin's source code.
 211       *
 212       * If the value is null after calling this method, either the plugin
 213       * does not use versioning (typically does not have any database
 214       * data) or is missing from disk.
 215       */
 216      public function load_disk_version() {
 217          $versions = $this->pluginman->get_present_plugins($this->type);
 218  
 219          $this->versiondisk = null;
 220          $this->versionrequires = null;
 221          $this->dependencies = array();
 222  
 223          if (!isset($versions[$this->name])) {
 224              return;
 225          }
 226  
 227          $plugin = $versions[$this->name];
 228  
 229          if (isset($plugin->version)) {
 230              $this->versiondisk = $plugin->version;
 231          }
 232          if (isset($plugin->requires)) {
 233              $this->versionrequires = $plugin->requires;
 234          }
 235          if (isset($plugin->release)) {
 236              $this->release = $plugin->release;
 237          }
 238          if (isset($plugin->dependencies)) {
 239              $this->dependencies = $plugin->dependencies;
 240          }
 241      }
 242  
 243      /**
 244       * Get the list of other plugins that this plugin requires to be installed.
 245       *
 246       * @return array with keys the frankenstyle plugin name, and values either
 247       *      a version string (like '2011101700') or the constant ANY_VERSION.
 248       */
 249      public function get_other_required_plugins() {
 250          if (is_null($this->dependencies)) {
 251              $this->load_disk_version();
 252          }
 253          return $this->dependencies;
 254      }
 255  
 256      /**
 257       * Is this is a subplugin?
 258       *
 259       * @return boolean
 260       */
 261      public function is_subplugin() {
 262          return ($this->get_parent_plugin() !== false);
 263      }
 264  
 265      /**
 266       * If I am a subplugin, return the name of my parent plugin.
 267       *
 268       * @return string|bool false if not a subplugin, name of the parent otherwise
 269       */
 270      public function get_parent_plugin() {
 271          return $this->pluginman->get_parent_of_subplugin($this->type);
 272      }
 273  
 274      /**
 275       * Sets {@link $versiondb} property to a numerical value representing the
 276       * currently installed version of the plugin.
 277       *
 278       * If the value is null after calling this method, either the plugin
 279       * does not use versioning (typically does not have any database
 280       * data) or has not been installed yet.
 281       */
 282      public function load_db_version() {
 283          $versions = $this->pluginman->get_installed_plugins($this->type);
 284  
 285          if (isset($versions[$this->name])) {
 286              $this->versiondb = $versions[$this->name];
 287          } else {
 288              $this->versiondb = null;
 289          }
 290      }
 291  
 292      /**
 293       * Sets {@link $source} property to one of core_plugin_manager::PLUGIN_SOURCE_xxx
 294       * constants.
 295       *
 296       * If the property's value is null after calling this method, then
 297       * the type of the plugin has not been recognized and you should throw
 298       * an exception.
 299       */
 300      public function init_is_standard() {
 301  
 302          $pluginman = $this->pluginman;
 303          $standard = $pluginman::standard_plugins_list($this->type);
 304  
 305          if ($standard !== false) {
 306              $standard = array_flip($standard);
 307              if (isset($standard[$this->name])) {
 308                  $this->source = core_plugin_manager::PLUGIN_SOURCE_STANDARD;
 309              } else if (!is_null($this->versiondb) and is_null($this->versiondisk)
 310                  and $pluginman::is_deleted_standard_plugin($this->type, $this->name)) {
 311                  $this->source = core_plugin_manager::PLUGIN_SOURCE_STANDARD; // To be deleted.
 312              } else {
 313                  $this->source = core_plugin_manager::PLUGIN_SOURCE_EXTENSION;
 314              }
 315          }
 316      }
 317  
 318      /**
 319       * Returns true if the plugin is shipped with the official distribution
 320       * of the current Moodle version, false otherwise.
 321       *
 322       * @return bool
 323       */
 324      public function is_standard() {
 325          return $this->source === core_plugin_manager::PLUGIN_SOURCE_STANDARD;
 326      }
 327  
 328      /**
 329       * Returns true if the the given Moodle version is enough to run this plugin
 330       *
 331       * @param string|int|double $moodleversion
 332       * @return bool
 333       */
 334      public function is_core_dependency_satisfied($moodleversion) {
 335  
 336          if (empty($this->versionrequires)) {
 337              return true;
 338  
 339          } else {
 340              return (double)$this->versionrequires <= (double)$moodleversion;
 341          }
 342      }
 343  
 344      /**
 345       * Returns the status of the plugin
 346       *
 347       * @return string one of core_plugin_manager::PLUGIN_STATUS_xxx constants
 348       */
 349      public function get_status() {
 350  
 351          $pluginman = $this->pluginman;
 352  
 353          if (is_null($this->versiondb) and is_null($this->versiondisk)) {
 354              return core_plugin_manager::PLUGIN_STATUS_NODB;
 355  
 356          } else if (is_null($this->versiondb) and !is_null($this->versiondisk)) {
 357              return core_plugin_manager::PLUGIN_STATUS_NEW;
 358  
 359          } else if (!is_null($this->versiondb) and is_null($this->versiondisk)) {
 360              if ($pluginman::is_deleted_standard_plugin($this->type, $this->name)) {
 361                  return core_plugin_manager::PLUGIN_STATUS_DELETE;
 362              } else {
 363                  return core_plugin_manager::PLUGIN_STATUS_MISSING;
 364              }
 365  
 366          } else if ((float)$this->versiondb === (float)$this->versiondisk) {
 367              // Note: the float comparison should work fine here
 368              //       because there are no arithmetic operations with the numbers.
 369              return core_plugin_manager::PLUGIN_STATUS_UPTODATE;
 370  
 371          } else if ($this->versiondb < $this->versiondisk) {
 372              return core_plugin_manager::PLUGIN_STATUS_UPGRADE;
 373  
 374          } else if ($this->versiondb > $this->versiondisk) {
 375              return core_plugin_manager::PLUGIN_STATUS_DOWNGRADE;
 376  
 377          } else {
 378              // $version = pi(); and similar funny jokes - hopefully Donald E. Knuth will never contribute to Moodle ;-)
 379              throw new coding_exception('Unable to determine plugin state, check the plugin versions');
 380          }
 381      }
 382  
 383      /**
 384       * Returns the information about plugin availability
 385       *
 386       * True means that the plugin is enabled. False means that the plugin is
 387       * disabled. Null means that the information is not available, or the
 388       * plugin does not support configurable availability or the availability
 389       * can not be changed.
 390       *
 391       * @return null|bool
 392       */
 393      public function is_enabled() {
 394          if (!$this->rootdir) {
 395              // Plugin missing.
 396              return false;
 397          }
 398  
 399          $enabled = $this->pluginman->get_enabled_plugins($this->type);
 400  
 401          if (!is_array($enabled)) {
 402              return null;
 403          }
 404  
 405          return isset($enabled[$this->name]);
 406      }
 407  
 408      /**
 409       * If there are updates for this plugin available, returns them.
 410       *
 411       * Returns array of {@link \core\update\info} objects, if some update
 412       * is available. Returns null if there is no update available or if the update
 413       * availability is unknown.
 414       *
 415       * Populates the property {@link $availableupdates} on first call (lazy
 416       * loading).
 417       *
 418       * @return array|null
 419       */
 420      public function available_updates() {
 421  
 422          if ($this->availableupdates === null) {
 423              // Lazy load the information about available updates.
 424              $this->availableupdates = $this->pluginman->load_available_updates_for_plugin($this->component);
 425          }
 426  
 427          if (empty($this->availableupdates) or !is_array($this->availableupdates)) {
 428              $this->availableupdates = array();
 429              return null;
 430          }
 431  
 432          $updates = array();
 433  
 434          foreach ($this->availableupdates as $availableupdate) {
 435              if ($availableupdate->version > $this->versiondisk) {
 436                  $updates[] = $availableupdate;
 437              }
 438          }
 439  
 440          if (empty($updates)) {
 441              return null;
 442          }
 443  
 444          return $updates;
 445      }
 446  
 447      /**
 448       * Returns the node name used in admin settings menu for this plugin settings (if applicable)
 449       *
 450       * @return null|string node name or null if plugin does not create settings node (default)
 451       */
 452      public function get_settings_section_name() {
 453          return null;
 454      }
 455  
 456      /**
 457       * Returns the URL of the plugin settings screen
 458       *
 459       * Null value means that the plugin either does not have the settings screen
 460       * or its location is not available via this library.
 461       *
 462       * @return null|moodle_url
 463       */
 464      public function get_settings_url() {
 465          $section = $this->get_settings_section_name();
 466          if ($section === null) {
 467              return null;
 468          }
 469          $settings = admin_get_root()->locate($section);
 470          if ($settings && $settings instanceof \admin_settingpage) {
 471              return new moodle_url('/admin/settings.php', array('section' => $section));
 472          } else if ($settings && $settings instanceof \admin_externalpage) {
 473              return new moodle_url($settings->url);
 474          } else {
 475              return null;
 476          }
 477      }
 478  
 479      /**
 480       * Loads plugin settings to the settings tree
 481       *
 482       * This function usually includes settings.php file in plugins folder.
 483       * Alternatively it can create a link to some settings page (instance of admin_externalpage)
 484       *
 485       * @param \part_of_admin_tree $adminroot
 486       * @param string $parentnodename
 487       * @param bool $hassiteconfig whether the current user has moodle/site:config capability
 488       */
 489      public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) {
 490      }
 491  
 492      /**
 493       * Should there be a way to uninstall the plugin via the administration UI.
 494       *
 495       * By default uninstallation is not allowed, plugin developers must enable it explicitly!
 496       *
 497       * @return bool
 498       */
 499      public function is_uninstall_allowed() {
 500          return false;
 501      }
 502  
 503      /**
 504       * Optional extra warning before uninstallation, for example number of uses in courses.
 505       *
 506       * @return string
 507       */
 508      public function get_uninstall_extra_warning() {
 509          return '';
 510      }
 511  
 512      /**
 513       * Pre-uninstall hook.
 514       *
 515       * This is intended for disabling of plugin, some DB table purging, etc.
 516       *
 517       * NOTE: to be called from uninstall_plugin() only.
 518       * @private
 519       */
 520      public function uninstall_cleanup() {
 521          // Override when extending class,
 522          // do not forget to call parent::pre_uninstall_cleanup() at the end.
 523      }
 524  
 525      /**
 526       * Returns relative directory of the plugin with heading '/'
 527       *
 528       * @return string
 529       */
 530      public function get_dir() {
 531          global $CFG;
 532  
 533          return substr($this->rootdir, strlen($CFG->dirroot));
 534      }
 535  
 536      /**
 537       * Hook method to implement certain steps when uninstalling the plugin.
 538       *
 539       * This hook is called by {@link core_plugin_manager::uninstall_plugin()} so
 540       * it is basically usable only for those plugin types that use the default
 541       * uninstall tool provided by {@link self::get_default_uninstall_url()}.
 542       *
 543       * @param \progress_trace $progress traces the process
 544       * @return bool true on success, false on failure
 545       */
 546      public function uninstall(\progress_trace $progress) {
 547          return true;
 548      }
 549  
 550      /**
 551       * Where should we return after plugin of this type is uninstalled?
 552       * @param string $return
 553       * @return moodle_url
 554       */
 555      public function get_return_url_after_uninstall($return) {
 556          if ($return === 'manage') {
 557              if ($url = $this->get_manage_url()) {
 558                  return $url;
 559              }
 560          }
 561          return new moodle_url('/admin/plugins.php#plugin_type_cell_'.$this->type);
 562      }
 563  
 564      /**
 565       * Return URL used for management of plugins of this type.
 566       * @return moodle_url
 567       */
 568      public static function get_manage_url() {
 569          return null;
 570      }
 571  
 572      /**
 573       * Returns URL to a script that handles common plugin uninstall procedure.
 574       *
 575       * This URL is intended for all plugin uninstallations.
 576       *
 577       * @param string $return either 'overview' or 'manage'
 578       * @return moodle_url
 579       */
 580      public final function get_default_uninstall_url($return = 'overview') {
 581          return new moodle_url('/admin/plugins.php', array(
 582              'sesskey' => sesskey(),
 583              'uninstall' => $this->component,
 584              'confirm' => 0,
 585              'return' => $return,
 586          ));
 587      }
 588  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1