weekly release 2.2dev
[moodle.git] / lib / pluginlib.php
CommitLineData
b9934a17
DM
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 plugins management
19 *
20 * This library provides a unified interface to various plugin types in
21 * Moodle. It is mainly used by the plugins management admin page and the
22 * plugins check page during the upgrade.
23 *
24 * @package core
25 * @subpackage admin
26 * @copyright 2011 David Mudrak <david@moodle.com>
27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 */
29
30defined('MOODLE_INTERNAL') || die();
31
32/**
33 * Singleton class providing general plugins management functionality
34 */
35class plugin_manager {
36
37 /** the plugin is shipped with standard Moodle distribution */
38 const PLUGIN_SOURCE_STANDARD = 'std';
39 /** the plugin is added extension */
40 const PLUGIN_SOURCE_EXTENSION = 'ext';
41
42 /** the plugin uses neither database nor capabilities, no versions */
43 const PLUGIN_STATUS_NODB = 'nodb';
44 /** the plugin is up-to-date */
45 const PLUGIN_STATUS_UPTODATE = 'uptodate';
46 /** the plugin is about to be installed */
47 const PLUGIN_STATUS_NEW = 'new';
48 /** the plugin is about to be upgraded */
49 const PLUGIN_STATUS_UPGRADE = 'upgrade';
50 /** the version at the disk is lower than the one already installed */
51 const PLUGIN_STATUS_DOWNGRADE = 'downgrade';
52 /** the plugin is installed but missing from disk */
53 const PLUGIN_STATUS_MISSING = 'missing';
54
55 /** @var plugin_manager holds the singleton instance */
56 protected static $singletoninstance;
57 /** @var array of raw plugins information */
58 protected $pluginsinfo = null;
59 /** @var array of raw subplugins information */
60 protected $subpluginsinfo = null;
61
62 /**
63 * Direct initiation not allowed, use the factory method {@link self::instance()}
64 *
65 * @todo we might want to specify just a single plugin type to work with
66 */
67 protected function __construct() {
68 $this->get_plugins(true);
69 }
70
71 /**
72 * Sorry, this is singleton
73 */
74 protected function __clone() {
75 }
76
77 /**
78 * Factory method for this class
79 *
80 * @return plugin_manager the singleton instance
81 */
82 public static function instance() {
83 global $CFG;
84
85 if (is_null(self::$singletoninstance)) {
86 self::$singletoninstance = new self();
87 }
88 return self::$singletoninstance;
89 }
90
91 /**
92 * Returns a tree of known plugins and information about them
93 *
94 * @param bool $disablecache force reload, cache can be used otherwise
e61aaece
TH
95 * @return array 2D array. The first keys are plugin type names (e.g. qtype);
96 * the second keys are the plugin local name (e.g. multichoice); and
97 * the values are the corresponding {@link plugin_information} objects.
b9934a17
DM
98 */
99 public function get_plugins($disablecache=false) {
100
101 if ($disablecache or is_null($this->pluginsinfo)) {
102 $this->pluginsinfo = array();
103 $plugintypes = get_plugin_types();
104 foreach ($plugintypes as $plugintype => $plugintyperootdir) {
105 if (in_array($plugintype, array('base', 'general'))) {
106 throw new coding_exception('Illegal usage of reserved word for plugin type');
107 }
108 if (class_exists('plugintype_' . $plugintype)) {
109 $plugintypeclass = 'plugintype_' . $plugintype;
110 } else {
111 $plugintypeclass = 'plugintype_general';
112 }
e61aaece
TH
113 if (!in_array('plugin_information', class_implements($plugintypeclass))) {
114 throw new coding_exception('Class ' . $plugintypeclass . ' must implement plugin_information');
b9934a17
DM
115 }
116 $plugins = call_user_func(array($plugintypeclass, 'get_plugins'), $plugintype, $plugintyperootdir, $plugintypeclass);
117 $this->pluginsinfo[$plugintype] = $plugins;
118 }
119 }
120
121 return $this->pluginsinfo;
122 }
123
124 /**
0242bdc7
TH
125 * Returns list of plugins that define their subplugins and the information
126 * about them from the db/subplugins.php file.
b9934a17
DM
127 *
128 * At the moment, only activity modules can define subplugins.
129 *
0242bdc7
TH
130 * @param bool $disablecache force reload, cache can be used otherwise
131 * @return array with keys like 'mod_quiz', and values the data from the
132 * corresponding db/subplugins.php file.
b9934a17
DM
133 */
134 public function get_subplugins($disablecache=false) {
135
136 if ($disablecache or is_null($this->subpluginsinfo)) {
137 $this->subpluginsinfo = array();
138 $mods = get_plugin_list('mod');
139 foreach ($mods as $mod => $moddir) {
140 $modsubplugins = array();
141 if (file_exists($moddir . '/db/subplugins.php')) {
142 include($moddir . '/db/subplugins.php');
143 foreach ($subplugins as $subplugintype => $subplugintyperootdir) {
144 $subplugin = new stdClass();
145 $subplugin->type = $subplugintype;
146 $subplugin->typerootdir = $subplugintyperootdir;
147 $modsubplugins[$subplugintype] = $subplugin;
148 }
149 $this->subpluginsinfo['mod_' . $mod] = $modsubplugins;
150 }
151 }
152 }
153
154 return $this->subpluginsinfo;
155 }
156
157 /**
158 * Returns the name of the plugin that defines the given subplugin type
159 *
160 * If the given subplugin type is not actually a subplugin, returns false.
161 *
162 * @param string $subplugintype the name of subplugin type, eg. workshopform or quiz
163 * @return false|string the name of the parent plugin, eg. mod_workshop
164 */
165 public function get_parent_of_subplugin($subplugintype) {
166
167 $parent = false;
168 foreach ($this->get_subplugins() as $pluginname => $subplugintypes) {
169 if (isset($subplugintypes[$subplugintype])) {
170 $parent = $pluginname;
171 break;
172 }
173 }
174
175 return $parent;
176 }
177
178 /**
179 * Returns a localized name of a given plugin
180 *
181 * @param string $plugin name of the plugin, eg mod_workshop or auth_ldap
182 * @return string
183 */
184 public function plugin_name($plugin) {
185 list($type, $name) = normalize_component($plugin);
186 return $this->pluginsinfo[$type][$name]->displayname;
187 }
188
189 /**
190 * Returns a localized name of a plugin type in plural form
191 *
192 * Most plugin types define their names in core_plugin lang file. In case of subplugins,
193 * we try to ask the parent plugin for the name. In the worst case, we will return
194 * the value of the passed $type parameter.
195 *
196 * @param string $type the type of the plugin, e.g. mod or workshopform
197 * @return string
198 */
199 public function plugintype_name_plural($type) {
200
201 if (get_string_manager()->string_exists('type_' . $type . '_plural', 'core_plugin')) {
202 // for most plugin types, their names are defined in core_plugin lang file
203 return get_string('type_' . $type . '_plural', 'core_plugin');
204
205 } else if ($parent = $this->get_parent_of_subplugin($type)) {
206 // if this is a subplugin, try to ask the parent plugin for the name
207 if (get_string_manager()->string_exists('subplugintype_' . $type . '_plural', $parent)) {
208 return $this->plugin_name($parent) . ' / ' . get_string('subplugintype_' . $type . '_plural', $parent);
209 } else {
210 return $this->plugin_name($parent) . ' / ' . $type;
211 }
212
213 } else {
214 return $type;
215 }
216 }
217
e61aaece
TH
218 /**
219 * @param string $component frankenstyle component name.
220 * @return plugin_information|null the corresponding plugin information.
221 */
222 public function get_plugin_info($component) {
223 list($type, $name) = normalize_component($component);
224 $plugins = $this->get_plugins();
225 if (isset($plugins[$type][$name])) {
226 return $plugins[$type][$name];
227 } else {
228 return null;
229 }
230 }
231
232 /**
777781d1
TH
233 * Check a dependencies list against the list of installed plugins.
234 * @param array $dependencies compenent name to required version or ANY_VERSION.
235 * @return bool true if all the dependencies are satisfied.
e61aaece 236 */
777781d1
TH
237 public function are_dependencies_satisfied($dependencies) {
238 foreach ($dependencies as $component => $requiredversion) {
e61aaece
TH
239 $otherplugin = $this->get_plugin_info($component);
240 if (is_null($otherplugin)) {
0242bdc7
TH
241 return false;
242 }
243
3f123d92 244 if ($requiredversion != ANY_VERSION and $otherplugin->versiondisk < $requiredversion) {
0242bdc7
TH
245 return false;
246 }
247 }
248
249 return true;
250 }
251
faadd326 252 /**
777781d1 253 * Checks all dependencies for all installed plugins. Used by install and upgrade.
faadd326 254 * @param int $moodleversion the version from version.php.
777781d1 255 * @return bool true if all the dependencies are satisfied for all plugins.
faadd326
TH
256 */
257 public function all_plugins_ok($moodleversion) {
258 foreach ($this->get_plugins() as $type => $plugins) {
259 foreach ($plugins as $plugin) {
260
261 if (!empty($plugin->versionrequires) && $plugin->versionrequires > $moodleversion) {
262 return false;
263 }
264
777781d1 265 if (!$this->are_dependencies_satisfied($plugin->get_other_required_plugins())) {
faadd326
TH
266 return false;
267 }
268 }
269 }
270
271 return true;
272 }
273
b9934a17
DM
274 /**
275 * Defines a white list of all plugins shipped in the standard Moodle distribution
276 *
277 * @return false|array array of standard plugins or false if the type is unknown
278 */
279 public static function standard_plugins_list($type) {
280 static $standard_plugins = array(
281
282 'assignment' => array(
283 'offline', 'online', 'upload', 'uploadsingle'
284 ),
285
286 'auth' => array(
287 'cas', 'db', 'email', 'fc', 'imap', 'ldap', 'manual', 'mnet',
288 'nntp', 'nologin', 'none', 'pam', 'pop3', 'radius',
289 'shibboleth', 'webservice'
290 ),
291
292 'block' => array(
293 'activity_modules', 'admin_bookmarks', 'blog_menu',
294 'blog_recent', 'blog_tags', 'calendar_month',
295 'calendar_upcoming', 'comments', 'community',
296 'completionstatus', 'course_list', 'course_overview',
297 'course_summary', 'feedback', 'glossary_random', 'html',
298 'login', 'mentees', 'messages', 'mnet_hosts', 'myprofile',
299 'navigation', 'news_items', 'online_users', 'participants',
300 'private_files', 'quiz_results', 'recent_activity',
f68cef22 301 'rss_client', 'search_forums', 'section_links',
b9934a17
DM
302 'selfcompletion', 'settings', 'site_main_menu',
303 'social_activities', 'tag_flickr', 'tag_youtube', 'tags'
304 ),
305
306 'coursereport' => array(
307 'completion', 'log', 'outline', 'participation', 'progress', 'stats'
308 ),
309
310 'datafield' => array(
311 'checkbox', 'date', 'file', 'latlong', 'menu', 'multimenu',
312 'number', 'picture', 'radiobutton', 'text', 'textarea', 'url'
313 ),
314
315 'datapreset' => array(
316 'imagegallery'
317 ),
318
319 'editor' => array(
320 'textarea', 'tinymce'
321 ),
322
323 'enrol' => array(
324 'authorize', 'category', 'cohort', 'database', 'flatfile',
325 'guest', 'imsenterprise', 'ldap', 'manual', 'meta', 'mnet',
326 'paypal', 'self'
327 ),
328
329 'filter' => array(
330 'activitynames', 'algebra', 'censor', 'emailprotect',
331 'emoticon', 'mediaplugin', 'multilang', 'tex', 'tidy',
332 'urltolink', 'mod_data', 'mod_glossary'
333 ),
334
335 'format' => array(
336 'scorm', 'social', 'topics', 'weeks'
337 ),
338
339 'gradeexport' => array(
340 'ods', 'txt', 'xls', 'xml'
341 ),
342
343 'gradeimport' => array(
344 'csv', 'xml'
345 ),
346
347 'gradereport' => array(
348 'grader', 'outcomes', 'overview', 'user'
349 ),
350
351 'local' => array(
352 ),
353
354 'message' => array(
355 'email', 'jabber', 'popup'
356 ),
357
358 'mnetservice' => array(
359 'enrol'
360 ),
361
362 'mod' => array(
363 'assignment', 'chat', 'choice', 'data', 'feedback', 'folder',
364 'forum', 'glossary', 'imscp', 'label', 'lesson', 'page',
365 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop'
366 ),
367
368 'plagiarism' => array(
369 ),
370
371 'portfolio' => array(
372 'boxnet', 'download', 'flickr', 'googledocs', 'mahara', 'picasa'
373 ),
374
375 'profilefield' => array(
376 'checkbox', 'datetime', 'menu', 'text', 'textarea'
377 ),
378
d1c77ac3
DM
379 'qbehaviour' => array(
380 'adaptive', 'adaptivenopenalty', 'deferredcbm',
381 'deferredfeedback', 'immediatecbm', 'immediatefeedback',
382 'informationitem', 'interactive', 'interactivecountback',
383 'manualgraded', 'missing'
384 ),
385
b9934a17
DM
386 'qformat' => array(
387 'aiken', 'blackboard', 'blackboard_six', 'examview', 'gift',
2dc54611 388 'learnwise', 'missingword', 'multianswer', 'webct',
b9934a17
DM
389 'xhtml', 'xml'
390 ),
391
392 'qtype' => array(
393 'calculated', 'calculatedmulti', 'calculatedsimple',
394 'description', 'essay', 'match', 'missingtype', 'multianswer',
395 'multichoice', 'numerical', 'random', 'randomsamatch',
396 'shortanswer', 'truefalse'
397 ),
398
399 'quiz' => array(
400 'grading', 'overview', 'responses', 'statistics'
401 ),
402
c999d841
TH
403 'quizaccess' => array(
404 'delaybetweenattempts', 'ipaddress', 'numattempts', 'openclosedate',
405 'password', 'safebrowser', 'securewindow', 'timelimit'
406 ),
407
b9934a17 408 'report' => array(
4211dfa4 409 'backups', 'configlog', 'courseoverview',
17a14fbd 410 'log', 'questioninstances', 'security', 'stats'
b9934a17
DM
411 ),
412
413 'repository' => array(
414 'alfresco', 'boxnet', 'coursefiles', 'dropbox', 'filesystem',
415 'flickr', 'flickr_public', 'googledocs', 'local', 'merlot',
416 'picasa', 'recent', 's3', 'upload', 'url', 'user', 'webdav',
417 'wikimedia', 'youtube'
418 ),
419
99e86561
PS
420 'scormreport' => array(
421 'basic'
422 ),
423
b9934a17 424 'theme' => array(
bef9ad95
DM
425 'afterburner', 'anomaly', 'arialist', 'base', 'binarius',
426 'boxxie', 'brick', 'canvas', 'formal_white', 'formfactor',
427 'fusion', 'leatherbound', 'magazine', 'nimble', 'nonzero',
428 'overlay', 'serenity', 'sky_high', 'splash', 'standard',
429 'standardold'
b9934a17
DM
430 ),
431
11b24ce7 432 'tool' => array(
b703861f 433 'bloglevelupgrade', 'capability', 'customlang', 'dbtransfer', 'generator',
cff8fc8d 434 'health', 'innodb', 'langimport', 'multilangupgrade', 'profiling',
fab6f7b7 435 'qeupgradehelper', 'replace', 'spamcleaner', 'timezoneimport', 'unittest',
9597e00b 436 'uploaduser', 'unsuproles', 'xmldb'
11b24ce7
PS
437 ),
438
b9934a17
DM
439 'webservice' => array(
440 'amf', 'rest', 'soap', 'xmlrpc'
441 ),
442
443 'workshopallocation' => array(
444 'manual', 'random'
445 ),
446
447 'workshopeval' => array(
448 'best'
449 ),
450
451 'workshopform' => array(
452 'accumulative', 'comments', 'numerrors', 'rubric'
453 )
454 );
455
456 if (isset($standard_plugins[$type])) {
457 return $standard_plugins[$type];
458
459 } else {
460 return false;
461 }
462 }
463}
464
465/**
e61aaece
TH
466 * Interface for making information about a plugin available.
467 *
468 * Note that most of the useful information is made available in pubic fields,
469 * which cannot be documented in this interface. See the field definitions on
470 * {@link plugintype_base} to find out what information is available.
b9934a17 471 */
e61aaece 472interface plugin_information {
b9934a17
DM
473
474 /**
475 * Gathers and returns the information about all plugins of the given type
476 *
477 * Passing the parameter $typeclass allows us to reach the same effect as with the
478 * late binding in PHP 5.3. Once PHP 5.3 is required, we can refactor this to use
479 * {@example $plugin = new static();} instead of {@example $plugin = new $typeclass()}
480 *
481 * @param string $type the name of the plugintype, eg. mod, auth or workshopform
482 * @param string $typerootdir full path to the location of the plugin dir
483 * @param string $typeclass the name of the actually called class
484 * @return array of plugintype classes, indexed by the plugin name
485 */
486 public static function get_plugins($type, $typerootdir, $typeclass);
487
488 /**
489 * Sets $displayname property to a localized name of the plugin
490 *
491 * @return void
492 */
b8343e68 493 public function init_display_name();
b9934a17
DM
494
495 /**
496 * Sets $versiondisk property to a numerical value representing the
497 * version of the plugin's source code.
498 *
499 * If the value is null after calling this method, either the plugin
500 * does not use versioning (typically does not have any database
501 * data) or is missing from disk.
502 *
503 * @return void
504 */
b8343e68 505 public function load_disk_version();
b9934a17
DM
506
507 /**
508 * Sets $versiondb property to a numerical value representing the
509 * currently installed version of the plugin.
510 *
511 * If the value is null after calling this method, either the plugin
512 * does not use versioning (typically does not have any database
513 * data) or has not been installed yet.
514 *
515 * @return void
516 */
b8343e68 517 public function load_db_version();
b9934a17
DM
518
519 /**
520 * Sets $versionrequires property to a numerical value representing
521 * the version of Moodle core that this plugin requires.
522 *
523 * @return void
524 */
b8343e68 525 public function load_required_main_version();
b9934a17
DM
526
527 /**
528 * Sets $source property to one of plugin_manager::PLUGIN_SOURCE_xxx
529 * constants.
530 *
531 * If the property's value is null after calling this method, then
532 * the type of the plugin has not been recognized and you should throw
533 * an exception.
534 *
535 * @return void
536 */
b8343e68 537 public function init_is_standard();
b9934a17
DM
538
539 /**
540 * Returns true if the plugin is shipped with the official distribution
541 * of the current Moodle version, false otherwise.
542 *
543 * @return bool
544 */
545 public function is_standard();
546
547 /**
548 * Returns the status of the plugin
549 *
550 * @return string one of plugin_manager::PLUGIN_STATUS_xxx constants
551 */
552 public function get_status();
553
0242bdc7
TH
554 /**
555 * Get the list of other plugins that this plugin requires ot be installed.
556 * @return array with keys the frankenstyle plugin name, and values either
557 * a version string (like '2011101700') or the constant ANY_VERSION.
558 */
559 public function get_other_required_plugins();
560
b9934a17
DM
561 /**
562 * Returns the information about plugin availability
563 *
564 * True means that the plugin is enabled. False means that the plugin is
565 * disabled. Null means that the information is not available, or the
566 * plugin does not support configurable availability or the availability
567 * can not be changed.
568 *
569 * @return null|bool
570 */
571 public function is_enabled();
572
573 /**
574 * Returns the URL of the plugin settings screen
575 *
576 * Null value means that the plugin either does not have the settings screen
577 * or its location is not available via this library.
578 *
579 * @return null|moodle_url
580 */
581 public function get_settings_url();
582
583 /**
584 * Returns the URL of the screen where this plugin can be uninstalled
585 *
586 * Visiting that URL must be safe, that is a manual confirmation is needed
587 * for actual uninstallation of the plugin. Null value means that the
588 * plugin either does not support uninstallation, or does not require any
589 * database cleanup or the location of the screen is not available via this
590 * library.
591 *
592 * @return null|moodle_url
593 */
594 public function get_uninstall_url();
595
596 /**
597 * Returns relative directory of the plugin with heading '/'
598 *
599 * @example /mod/workshop
600 * @return string
601 */
602 public function get_dir();
473289a0
TH
603
604 /**
605 * Return the full path name of a file within the plugin.
606 * No check is made to see if the file exists.
607 * @param string $relativepath e.g. 'version.php'.
608 * @return string e.g. $CFG->dirroot . '/mod/quiz/version.php'.
609 */
610 public function full_path($relativepath);
b9934a17
DM
611}
612
613/**
614 * Defines public properties that all plugintype classes must have
615 * and provides default implementation of required methods.
616 */
617abstract class plugintype_base {
618
619 /** @var string the plugintype name, eg. mod, auth or workshopform */
620 public $type;
621 /** @var string full path to the location of all the plugins of this type */
622 public $typerootdir;
623 /** @var string the plugin name, eg. assignment, ldap */
624 public $name;
625 /** @var string the localized plugin name */
626 public $displayname;
627 /** @var string the plugin source, one of plugin_manager::PLUGIN_SOURCE_xxx constants */
628 public $source;
629 /** @var fullpath to the location of this plugin */
630 public $rootdir;
631 /** @var int|string the version of the plugin's source code */
632 public $versiondisk;
633 /** @var int|string the version of the installed plugin */
634 public $versiondb;
635 /** @var int|float|string required version of Moodle core */
636 public $versionrequires;
0242bdc7
TH
637 /** @var array other plugins that this one depends on.
638 * Lazy-loaded by {@link get_other_required_plugins()} */
777781d1 639 public $dependencies = null;
b9934a17
DM
640 /** @var int number of instances of the plugin - not supported yet */
641 public $instances;
642 /** @var int order of the plugin among other plugins of the same type - not supported yet */
643 public $sortorder;
644
645 /**
e61aaece 646 * @see plugin_information::get_plugins()
b9934a17
DM
647 */
648 public static function get_plugins($type, $typerootdir, $typeclass) {
649
650 // get the information about plugins at the disk
651 $plugins = get_plugin_list($type);
652 $ondisk = array();
653 foreach ($plugins as $pluginname => $pluginrootdir) {
654 $plugin = new $typeclass();
655 $plugin->type = $type;
656 $plugin->typerootdir = $typerootdir;
657 $plugin->name = $pluginname;
658 $plugin->rootdir = $pluginrootdir;
659
b8343e68
TH
660 $plugin->init_display_name();
661 $plugin->load_disk_version();
662 $plugin->load_db_version();
663 $plugin->load_required_main_version();
664 $plugin->init_is_standard();
b9934a17
DM
665
666 $ondisk[$pluginname] = $plugin;
667 }
668 return $ondisk;
669 }
670
671 /**
e61aaece 672 * @see plugin_information::init_display_name()
b9934a17 673 */
b8343e68 674 public function init_display_name() {
b9934a17
DM
675 if (! get_string_manager()->string_exists('pluginname', $this->type . '_' . $this->name)) {
676 $this->displayname = '[pluginname,' . $this->type . '_' . $this->name . ']';
677 } else {
678 $this->displayname = get_string('pluginname', $this->type . '_' . $this->name);
679 }
680 }
681
682 /**
e61aaece 683 * @see plugin_information::full_path()
b9934a17 684 */
473289a0 685 public function full_path($relativepath) {
b9934a17 686 if (empty($this->rootdir)) {
473289a0 687 return '';
b9934a17 688 }
473289a0
TH
689 return $this->rootdir . '/' . $relativepath;
690 }
b9934a17 691
473289a0
TH
692 /**
693 * Load the data from version.php.
694 * @return object the data object defined in version.php.
695 */
696 protected function load_version_php() {
697 $versionfile = $this->full_path('version.php');
b9934a17 698
473289a0 699 $plugin = new stdClass();
b9934a17
DM
700 if (is_readable($versionfile)) {
701 include($versionfile);
b9934a17 702 }
473289a0 703 return $plugin;
b9934a17
DM
704 }
705
706 /**
e61aaece 707 * @see plugin_information::load_disk_version()
b9934a17 708 */
473289a0
TH
709 public function load_disk_version() {
710 $plugin = $this->load_version_php();
711 if (isset($plugin->version)) {
712 $this->versiondisk = $plugin->version;
b9934a17
DM
713 }
714 }
715
716 /**
e61aaece 717 * @see plugin_information::load_required_main_version()
b9934a17 718 */
b8343e68 719 public function load_required_main_version() {
473289a0
TH
720 $plugin = $this->load_version_php();
721 if (isset($plugin->requires)) {
722 $this->versionrequires = $plugin->requires;
b9934a17 723 }
473289a0 724 }
b9934a17 725
0242bdc7 726 /**
777781d1 727 * Initialise {@link $dependencies} to the list of other plugins (in any)
0242bdc7
TH
728 * that this one requires to be installed.
729 */
730 protected function load_other_required_plugins() {
731 $plugin = $this->load_version_php();
777781d1
TH
732 if (!empty($plugin->dependencies)) {
733 $this->dependencies = $plugin->dependencies;
0242bdc7 734 } else {
777781d1 735 $this->dependencies = array(); // By default, no dependencies.
0242bdc7
TH
736 }
737 }
738
739 /**
e61aaece 740 * @see plugin_information::get_other_required_plugins()
0242bdc7
TH
741 */
742 public function get_other_required_plugins() {
777781d1 743 if (is_null($this->dependencies)) {
0242bdc7
TH
744 $this->load_other_required_plugins();
745 }
777781d1 746 return $this->dependencies;
0242bdc7
TH
747 }
748
473289a0 749 /**
e61aaece 750 * @see plugin_information::load_db_version()
473289a0
TH
751 */
752 public function load_db_version() {
b9934a17 753
473289a0
TH
754 if ($ver = self::get_version_from_config_plugins($this->type . '_' . $this->name)) {
755 $this->versiondb = $ver;
b9934a17
DM
756 }
757 }
758
759 /**
e61aaece 760 * @see plugin_information::init_is_standard()
b9934a17 761 */
b8343e68 762 public function init_is_standard() {
b9934a17
DM
763
764 $standard = plugin_manager::standard_plugins_list($this->type);
765
766 if ($standard !== false) {
767 $standard = array_flip($standard);
768 if (isset($standard[$this->name])) {
769 $this->source = plugin_manager::PLUGIN_SOURCE_STANDARD;
770 } else {
771 $this->source = plugin_manager::PLUGIN_SOURCE_EXTENSION;
772 }
773 }
774 }
775
776 /**
e61aaece 777 * @see plugin_information::is_standard()
b9934a17
DM
778 */
779 public function is_standard() {
780 return $this->source === plugin_manager::PLUGIN_SOURCE_STANDARD;
781 }
782
783 /**
e61aaece 784 * @see plugin_information::get_status()
b9934a17
DM
785 */
786 public function get_status() {
787
788 if (is_null($this->versiondb) and is_null($this->versiondisk)) {
789 return plugin_manager::PLUGIN_STATUS_NODB;
790
791 } else if (is_null($this->versiondb) and !is_null($this->versiondisk)) {
792 return plugin_manager::PLUGIN_STATUS_NEW;
793
794 } else if (!is_null($this->versiondb) and is_null($this->versiondisk)) {
795 return plugin_manager::PLUGIN_STATUS_MISSING;
796
797 } else if ((string)$this->versiondb === (string)$this->versiondisk) {
798 return plugin_manager::PLUGIN_STATUS_UPTODATE;
799
800 } else if ($this->versiondb < $this->versiondisk) {
801 return plugin_manager::PLUGIN_STATUS_UPGRADE;
802
803 } else if ($this->versiondb > $this->versiondisk) {
804 return plugin_manager::PLUGIN_STATUS_DOWNGRADE;
805
806 } else {
807 // $version = pi(); and similar funny jokes - hopefully Donald E. Knuth will never contribute to Moodle ;-)
808 throw new coding_exception('Unable to determine plugin state, check the plugin versions');
809 }
810 }
811
812 /**
e61aaece 813 * @see plugin_information::is_enabled()
b9934a17
DM
814 */
815 public function is_enabled() {
816 return null;
817 }
818
819 /**
e61aaece 820 * @see plugin_information::get_settings_url()
b9934a17
DM
821 */
822 public function get_settings_url() {
823 return null;
824 }
825
826 /**
e61aaece 827 * @see plugin_information::get_uninstall_url()
b9934a17
DM
828 */
829 public function get_uninstall_url() {
830 return null;
831 }
832
833 /**
e61aaece 834 * @see plugin_information::get_dir()
b9934a17
DM
835 */
836 public function get_dir() {
837 global $CFG;
838
839 return substr($this->rootdir, strlen($CFG->dirroot));
840 }
841
842 /**
843 * Provides access to plugin versions from {config_plugins}
844 *
845 * @param string $plugin plugin name
846 * @param double $disablecache optional, defaults to false
847 * @return int|false the stored value or false if not found
848 */
849 protected function get_version_from_config_plugins($plugin, $disablecache=false) {
850 global $DB;
851 static $pluginversions = null;
852
853 if (is_null($pluginversions) or $disablecache) {
f433088d
PS
854 try {
855 $pluginversions = $DB->get_records_menu('config_plugins', array('name' => 'version'), 'plugin', 'plugin,value');
856 } catch (dml_exception $e) {
857 // before install
858 $pluginversions = array();
859 }
b9934a17
DM
860 }
861
862 if (!array_key_exists($plugin, $pluginversions)) {
863 return false;
864 }
865
866 return $pluginversions[$plugin];
867 }
868}
869
870/**
871 * General class for all plugin types that do not have their own class
872 */
e61aaece 873class plugintype_general extends plugintype_base implements plugin_information {
b9934a17
DM
874
875}
876
877/**
878 * Class for page side blocks
879 */
e61aaece 880class plugintype_block extends plugintype_base implements plugin_information {
b9934a17
DM
881
882 /**
e61aaece 883 * @see plugin_information::get_plugins()
b9934a17
DM
884 */
885 public static function get_plugins($type, $typerootdir, $typeclass) {
886
887 // get the information about blocks at the disk
888 $blocks = parent::get_plugins($type, $typerootdir, $typeclass);
889
890 // add blocks missing from disk
891 $blocksinfo = self::get_blocks_info();
892 foreach ($blocksinfo as $blockname => $blockinfo) {
893 if (isset($blocks[$blockname])) {
894 continue;
895 }
896 $plugin = new $typeclass();
897 $plugin->type = $type;
898 $plugin->typerootdir = $typerootdir;
899 $plugin->name = $blockname;
900 $plugin->rootdir = null;
901 $plugin->displayname = $blockname;
902 $plugin->versiondb = $blockinfo->version;
b8343e68 903 $plugin->init_is_standard();
b9934a17
DM
904
905 $blocks[$blockname] = $plugin;
906 }
907
908 return $blocks;
909 }
910
911 /**
e61aaece 912 * @see plugin_information::init_display_name()
b9934a17 913 */
b8343e68 914 public function init_display_name() {
b9934a17
DM
915
916 if (get_string_manager()->string_exists('pluginname', 'block_' . $this->name)) {
917 $this->displayname = get_string('pluginname', 'block_' . $this->name);
918
919 } else if (($block = block_instance($this->name)) !== false) {
920 $this->displayname = $block->get_title();
921
922 } else {
b8343e68 923 parent::init_display_name();
b9934a17
DM
924 }
925 }
926
927 /**
e61aaece 928 * @see plugin_information::load_db_version()
b9934a17 929 */
b8343e68 930 public function load_db_version() {
b9934a17
DM
931 global $DB;
932
933 $blocksinfo = self::get_blocks_info();
934 if (isset($blocksinfo[$this->name]->version)) {
935 $this->versiondb = $blocksinfo[$this->name]->version;
936 }
937 }
938
939 /**
e61aaece 940 * @see plugin_information::is_enabled()
b9934a17
DM
941 */
942 public function is_enabled() {
943
944 $blocksinfo = self::get_blocks_info();
945 if (isset($blocksinfo[$this->name]->visible)) {
946 if ($blocksinfo[$this->name]->visible) {
947 return true;
948 } else {
949 return false;
950 }
951 } else {
952 return parent::is_enabled();
953 }
954 }
955
956 /**
e61aaece 957 * @see plugin_information::get_settings_url()
b9934a17
DM
958 */
959 public function get_settings_url() {
960
961 if (($block = block_instance($this->name)) === false) {
962 return parent::get_settings_url();
963
964 } else if ($block->has_config()) {
6740c605 965 if (file_exists($this->full_path('settings.php'))) {
b9934a17
DM
966 return new moodle_url('/admin/settings.php', array('section' => 'blocksetting' . $this->name));
967 } else {
968 $blocksinfo = self::get_blocks_info();
969 return new moodle_url('/admin/block.php', array('block' => $blocksinfo[$this->name]->id));
970 }
971
972 } else {
973 return parent::get_settings_url();
974 }
975 }
976
977 /**
e61aaece 978 * @see plugin_information::get_uninstall_url()
b9934a17
DM
979 */
980 public function get_uninstall_url() {
981
982 $blocksinfo = self::get_blocks_info();
983 return new moodle_url('/admin/blocks.php', array('delete' => $blocksinfo[$this->name]->id, 'sesskey' => sesskey()));
984 }
985
986 /**
987 * Provides access to the records in {block} table
988 *
989 * @param bool $disablecache do not use internal static cache
990 * @return array array of stdClasses
991 */
992 protected static function get_blocks_info($disablecache=false) {
993 global $DB;
994 static $blocksinfocache = null;
995
996 if (is_null($blocksinfocache) or $disablecache) {
f433088d
PS
997 try {
998 $blocksinfocache = $DB->get_records('block', null, 'name', 'name,id,version,visible');
999 } catch (dml_exception $e) {
1000 // before install
1001 $blocksinfocache = array();
1002 }
b9934a17
DM
1003 }
1004
1005 return $blocksinfocache;
1006 }
1007}
1008
1009/**
1010 * Class for text filters
1011 */
e61aaece 1012class plugintype_filter extends plugintype_base implements plugin_information {
b9934a17
DM
1013
1014 /**
e61aaece 1015 * @see plugin_information::get_plugins()
b9934a17
DM
1016 */
1017 public static function get_plugins($type, $typerootdir, $typeclass) {
7c9b837e 1018 global $CFG, $DB;
b9934a17
DM
1019
1020 $filters = array();
1021
1022 // get the list of filters from both /filter and /mod location
1023 $installed = filter_get_all_installed();
1024
1025 foreach ($installed as $filterlegacyname => $displayname) {
1026 $plugin = new $typeclass();
1027 $plugin->type = $type;
1028 $plugin->typerootdir = $typerootdir;
1029 $plugin->name = self::normalize_legacy_name($filterlegacyname);
1030 $plugin->rootdir = $CFG->dirroot . '/' . $filterlegacyname;
1031 $plugin->displayname = $displayname;
1032
b8343e68
TH
1033 $plugin->load_disk_version();
1034 $plugin->load_db_version();
1035 $plugin->load_required_main_version();
1036 $plugin->init_is_standard();
b9934a17
DM
1037
1038 $filters[$plugin->name] = $plugin;
1039 }
1040
b9934a17 1041 $globalstates = self::get_global_states();
7c9b837e
DM
1042
1043 if ($DB->get_manager()->table_exists('filter_active')) {
1044 // if we're upgrading from 1.9, the table does not exist yet
1045 // if it does, make sure that all installed filters are registered
1046 $needsreload = false;
1047 foreach (array_keys($installed) as $filterlegacyname) {
1048 if (!isset($globalstates[self::normalize_legacy_name($filterlegacyname)])) {
1049 filter_set_global_state($filterlegacyname, TEXTFILTER_DISABLED);
1050 $needsreload = true;
1051 }
1052 }
1053 if ($needsreload) {
1054 $globalstates = self::get_global_states(true);
b9934a17 1055 }
b9934a17
DM
1056 }
1057
1058 // make sure that all registered filters are installed, just in case
1059 foreach ($globalstates as $name => $info) {
1060 if (!isset($filters[$name])) {
1061 // oops, there is a record in filter_active but the filter is not installed
1062 $plugin = new $typeclass();
1063 $plugin->type = $type;
1064 $plugin->typerootdir = $typerootdir;
1065 $plugin->name = $name;
1066 $plugin->rootdir = $CFG->dirroot . '/' . $info->legacyname;
1067 $plugin->displayname = $info->legacyname;
1068
b8343e68 1069 $plugin->load_db_version();
b9934a17
DM
1070
1071 if (is_null($plugin->versiondb)) {
1072 // this is a hack to stimulate 'Missing from disk' error
1073 // because $plugin->versiondisk will be null !== false
1074 $plugin->versiondb = false;
1075 }
1076
1077 $filters[$plugin->name] = $plugin;
1078 }
1079 }
1080
1081 return $filters;
1082 }
1083
1084 /**
e61aaece 1085 * @see plugin_information::init_display_name()
b9934a17 1086 */
b8343e68 1087 public function init_display_name() {
b9934a17
DM
1088 // do nothing, the name is set in self::get_plugins()
1089 }
1090
1091 /**
473289a0 1092 * @see plugintype_base::load_version_php().
b9934a17 1093 */
473289a0 1094 protected function load_version_php() {
b9934a17 1095 if (strpos($this->name, 'mod_') === 0) {
473289a0
TH
1096 // filters bundled with modules do not have a version.php and so
1097 // do not provide their own versioning information.
1098 return new stdClass();
b9934a17 1099 }
473289a0 1100 return parent::load_version_php();
b9934a17
DM
1101 }
1102
1103 /**
e61aaece 1104 * @see plugin_information::is_enabled()
b9934a17
DM
1105 */
1106 public function is_enabled() {
1107
1108 $globalstates = self::get_global_states();
1109
1110 foreach ($globalstates as $filterlegacyname => $info) {
1111 $name = self::normalize_legacy_name($filterlegacyname);
1112 if ($name === $this->name) {
1113 if ($info->active == TEXTFILTER_DISABLED) {
1114 return false;
1115 } else {
1116 // it may be 'On' or 'Off, but available'
1117 return null;
1118 }
1119 }
1120 }
1121
1122 return null;
1123 }
1124
1125 /**
e61aaece 1126 * @see plugin_information::get_settings_url()
b9934a17
DM
1127 */
1128 public function get_settings_url() {
1129
1130 $globalstates = self::get_global_states();
1131 $legacyname = $globalstates[$this->name]->legacyname;
1132 if (filter_has_global_settings($legacyname)) {
1133 return new moodle_url('/admin/settings.php', array('section' => 'filtersetting' . str_replace('/', '', $legacyname)));
1134 } else {
1135 return null;
1136 }
1137 }
1138
1139 /**
e61aaece 1140 * @see plugin_information::get_uninstall_url()
b9934a17
DM
1141 */
1142 public function get_uninstall_url() {
1143
1144 if (strpos($this->name, 'mod_') === 0) {
1145 return null;
1146 } else {
1147 $globalstates = self::get_global_states();
1148 $legacyname = $globalstates[$this->name]->legacyname;
1149 return new moodle_url('/admin/filters.php', array('sesskey' => sesskey(), 'filterpath' => $legacyname, 'action' => 'delete'));
1150 }
1151 }
1152
1153 /**
1154 * Convert legacy filter names like 'filter/foo' or 'mod/bar' into frankenstyle
1155 *
1156 * @param string $legacyfiltername legacy filter name
1157 * @return string frankenstyle-like name
1158 */
1159 protected static function normalize_legacy_name($legacyfiltername) {
1160
1161 $name = str_replace('/', '_', $legacyfiltername);
1162 if (strpos($name, 'filter_') === 0) {
1163 $name = substr($name, 7);
1164 if (empty($name)) {
1165 throw new coding_exception('Unable to determine filter name: ' . $legacyfiltername);
1166 }
1167 }
1168
1169 return $name;
1170 }
1171
1172 /**
1173 * Provides access to the results of {@link filter_get_global_states()}
1174 * but indexed by the normalized filter name
1175 *
1176 * The legacy filter name is available as ->legacyname property.
1177 *
1178 * @param bool $disablecache
1179 * @return array
1180 */
1181 protected static function get_global_states($disablecache=false) {
1182 global $DB;
1183 static $globalstatescache = null;
1184
1185 if ($disablecache or is_null($globalstatescache)) {
1186
1187 if (!$DB->get_manager()->table_exists('filter_active')) {
1188 // we're upgrading from 1.9 and the table used by {@link filter_get_global_states()}
1189 // does not exist yet
1190 $globalstatescache = array();
1191
1192 } else {
1193 foreach (filter_get_global_states() as $legacyname => $info) {
1194 $name = self::normalize_legacy_name($legacyname);
1195 $filterinfo = new stdClass();
1196 $filterinfo->legacyname = $legacyname;
1197 $filterinfo->active = $info->active;
1198 $filterinfo->sortorder = $info->sortorder;
1199 $globalstatescache[$name] = $filterinfo;
1200 }
1201 }
1202 }
1203
1204 return $globalstatescache;
1205 }
1206}
1207
1208/**
1209 * Class for activity modules
1210 */
e61aaece 1211class plugintype_mod extends plugintype_base implements plugin_information {
b9934a17
DM
1212
1213 /**
e61aaece 1214 * @see plugin_information::get_plugins()
b9934a17
DM
1215 */
1216 public static function get_plugins($type, $typerootdir, $typeclass) {
1217
1218 // get the information about plugins at the disk
1219 $modules = parent::get_plugins($type, $typerootdir, $typeclass);
1220
1221 // add modules missing from disk
1222 $modulesinfo = self::get_modules_info();
1223 foreach ($modulesinfo as $modulename => $moduleinfo) {
1224 if (isset($modules[$modulename])) {
1225 continue;
1226 }
1227 $plugin = new $typeclass();
1228 $plugin->type = $type;
1229 $plugin->typerootdir = $typerootdir;
1230 $plugin->name = $modulename;
1231 $plugin->rootdir = null;
1232 $plugin->displayname = $modulename;
1233 $plugin->versiondb = $moduleinfo->version;
b8343e68 1234 $plugin->init_is_standard();
b9934a17
DM
1235
1236 $modules[$modulename] = $plugin;
1237 }
1238
1239 return $modules;
1240 }
1241
1242 /**
e61aaece 1243 * @see plugin_information::init_display_name()
b9934a17 1244 */
b8343e68 1245 public function init_display_name() {
b9934a17
DM
1246 if (get_string_manager()->string_exists('pluginname', $this->type . '_' . $this->name)) {
1247 $this->displayname = get_string('pluginname', $this->type . '_' . $this->name);
1248 } else {
1249 $this->displayname = get_string('modulename', $this->type . '_' . $this->name);
1250 }
1251 }
1252
1253 /**
473289a0
TH
1254 * Load the data from version.php.
1255 * @return object the data object defined in version.php.
b9934a17 1256 */
473289a0
TH
1257 protected function load_version_php() {
1258 $versionfile = $this->full_path('version.php');
b9934a17 1259
473289a0 1260 $module = new stdClass();
b9934a17
DM
1261 if (is_readable($versionfile)) {
1262 include($versionfile);
b9934a17 1263 }
473289a0 1264 return $module;
b9934a17
DM
1265 }
1266
1267 /**
e61aaece 1268 * @see plugin_information::load_db_version()
b9934a17 1269 */
b8343e68 1270 public function load_db_version() {
b9934a17
DM
1271 global $DB;
1272
1273 $modulesinfo = self::get_modules_info();
1274 if (isset($modulesinfo[$this->name]->version)) {
1275 $this->versiondb = $modulesinfo[$this->name]->version;
1276 }
1277 }
1278
b9934a17 1279 /**
e61aaece 1280 * @see plugin_information::is_enabled()
b9934a17
DM
1281 */
1282 public function is_enabled() {
1283
1284 $modulesinfo = self::get_modules_info();
1285 if (isset($modulesinfo[$this->name]->visible)) {
1286 if ($modulesinfo[$this->name]->visible) {
1287 return true;
1288 } else {
1289 return false;
1290 }
1291 } else {
1292 return parent::is_enabled();
1293 }
1294 }
1295
1296 /**
e61aaece 1297 * @see plugin_information::get_settings_url()
b9934a17
DM
1298 */
1299 public function get_settings_url() {
1300
6740c605 1301 if (file_exists($this->full_path('settings.php')) or file_exists($this->full_path('settingstree.php'))) {
b9934a17
DM
1302 return new moodle_url('/admin/settings.php', array('section' => 'modsetting' . $this->name));
1303 } else {
1304 return parent::get_settings_url();
1305 }
1306 }
1307
1308 /**
e61aaece 1309 * @see plugin_information::get_uninstall_url()
b9934a17
DM
1310 */
1311 public function get_uninstall_url() {
1312
1313 if ($this->name !== 'forum') {
1314 return new moodle_url('/admin/modules.php', array('delete' => $this->name, 'sesskey' => sesskey()));
1315 } else {
1316 return null;
1317 }
1318 }
1319
1320 /**
1321 * Provides access to the records in {modules} table
1322 *
1323 * @param bool $disablecache do not use internal static cache
1324 * @return array array of stdClasses
1325 */
1326 protected static function get_modules_info($disablecache=false) {
1327 global $DB;
1328 static $modulesinfocache = null;
1329
1330 if (is_null($modulesinfocache) or $disablecache) {
f433088d
PS
1331 try {
1332 $modulesinfocache = $DB->get_records('modules', null, 'name', 'name,id,version,visible');
1333 } catch (dml_exception $e) {
1334 // before install
1335 $modulesinfocache = array();
1336 }
b9934a17
DM
1337 }
1338
1339 return $modulesinfocache;
1340 }
1341}
1342
0242bdc7
TH
1343
1344/**
1345 * Class for question behaviours.
1346 */
e61aaece 1347class plugintype_qbehaviour extends plugintype_base implements plugin_information {
0242bdc7
TH
1348
1349 /**
1350 * @see plugintype_base::load_other_required_plugins().
1351 */
1352 protected function load_other_required_plugins() {
1353 parent::load_other_required_plugins();
777781d1 1354 if (!empty($this->dependencies)) {
0242bdc7
TH
1355 return;
1356 }
1357
1358 // Standard mechanism did not find anything, so try the legacy way.
1359 global $CFG;
1360 require_once($CFG->libdir . '/questionlib.php');
1361 $required = question_engine::get_behaviour_required_behaviours($this->name);
1362 foreach ($required as $other) {
777781d1 1363 $this->dependencies['qbehaviour_' . $other] = ANY_VERSION;
0242bdc7
TH
1364 }
1365 }
1366}
1367
1368
b9934a17
DM
1369/**
1370 * Class for question types
1371 */
e61aaece 1372class plugintype_qtype extends plugintype_base implements plugin_information {
b9934a17
DM
1373
1374 /**
e61aaece 1375 * @see plugin_information::init_display_name()
b9934a17 1376 */
b8343e68 1377 public function init_display_name() {
44a7f384
TH
1378 if (get_string_manager()->string_exists('pluginname', $this->type . '_' . $this->name)) {
1379 $this->displayname = get_string('pluginname', $this->type . '_' . $this->name);
1380 } else {
1381 $this->displayname = get_string($this->name, 'qtype_' . $this->name);
1382 }
b9934a17 1383 }
0242bdc7
TH
1384
1385 /**
1386 * @see plugintype_base::load_other_required_plugins().
1387 */
1388 protected function load_other_required_plugins() {
1389 parent::load_other_required_plugins();
777781d1 1390 if (!empty($this->dependencies)) {
0242bdc7
TH
1391 return;
1392 }
1393
1394 // Standard mechanism did not find anything, so try the legacy way.
1395 global $CFG;
1396 require_once($CFG->libdir . '/questionlib.php');
1397 $required = question_bank::get_qtype($this->name)->requires_qtypes();
1398 foreach ($required as $other) {
777781d1 1399 $this->dependencies['qtype_' . $other] = ANY_VERSION;
0242bdc7
TH
1400 }
1401 }
b9934a17
DM
1402}
1403
1404/**
1405 * Class for question formats
1406 */
e61aaece 1407class plugintype_qformat extends plugintype_base implements plugin_information {
b9934a17
DM
1408
1409 /**
e61aaece 1410 * @see plugin_information::init_display_name()
b9934a17 1411 */
b8343e68 1412 public function init_display_name() {
44a7f384
TH
1413 if (get_string_manager()->string_exists('pluginname', $this->type . '_' . $this->name)) {
1414 $this->displayname = get_string('pluginname', $this->type . '_' . $this->name);
1415 } else {
1416 $this->displayname = get_string($this->name, 'qformat_' . $this->name);
1417 }
b9934a17
DM
1418 }
1419}
1420
1421/**
1422 * Class for authentication plugins
1423 */
e61aaece 1424class plugintype_auth extends plugintype_base implements plugin_information {
b9934a17
DM
1425
1426 /**
e61aaece 1427 * @see plugin_information::is_enabled()
b9934a17
DM
1428 */
1429 public function is_enabled() {
1430 global $CFG;
1431 /** @var null|array list of enabled authentication plugins */
1432 static $enabled = null;
1433
1434 if (in_array($this->name, array('nologin', 'manual'))) {
1435 // these two are always enabled and can't be disabled
1436 return null;
1437 }
1438
1439 if (is_null($enabled)) {
1440 $enabled = explode(',', $CFG->auth);
1441 }
1442
1443 return isset($enabled[$this->name]);
1444 }
1445
1446 /**
e61aaece 1447 * @see plugin_information::get_settings_url()
b9934a17
DM
1448 */
1449 public function get_settings_url() {
6740c605 1450 if (file_exists($this->full_path('settings.php'))) {
b9934a17
DM
1451 return new moodle_url('/admin/settings.php', array('section' => 'authsetting' . $this->name));
1452 } else {
1453 return new moodle_url('/admin/auth_config.php', array('auth' => $this->name));
1454 }
1455 }
1456}
1457
1458/**
1459 * Class for enrolment plugins
1460 */
e61aaece 1461class plugintype_enrol extends plugintype_base implements plugin_information {
b9934a17
DM
1462
1463 /**
1464 * We do not actually need whole enrolment classes here so we do not call
1465 * {@link enrol_get_plugins()}. Note that this may produce slightly different
1466 * results, for example if the enrolment plugin does not contain lib.php
1467 * but it is listed in $CFG->enrol_plugins_enabled
1468 *
e61aaece 1469 * @see plugin_information::is_enabled()
b9934a17
DM
1470 */
1471 public function is_enabled() {
1472 global $CFG;
1473 /** @var null|array list of enabled enrolment plugins */
1474 static $enabled = null;
1475
1476 if (is_null($enabled)) {
1477 $enabled = explode(',', $CFG->enrol_plugins_enabled);
1478 }
1479
1480 return isset($enabled[$this->name]);
1481 }
1482
1483 /**
e61aaece 1484 * @see plugin_information::get_settings_url()
b9934a17
DM
1485 */
1486 public function get_settings_url() {
1487
6740c605 1488 if ($this->is_enabled() or file_exists($this->full_path('settings.php'))) {
b9934a17
DM
1489 return new moodle_url('/admin/settings.php', array('section' => 'enrolsettings' . $this->name));
1490 } else {
1491 return parent::get_settings_url();
1492 }
1493 }
1494
1495 /**
e61aaece 1496 * @see plugin_information::get_uninstall_url()
b9934a17
DM
1497 */
1498 public function get_uninstall_url() {
1499 return new moodle_url('/admin/enrol.php', array('action' => 'uninstall', 'enrol' => $this->name, 'sesskey' => sesskey()));
1500 }
1501}
1502
1503/**
1504 * Class for messaging processors
1505 */
e61aaece 1506class plugintype_message extends plugintype_base implements plugin_information {
b9934a17
DM
1507
1508 /**
e61aaece 1509 * @see plugin_information::get_settings_url()
b9934a17
DM
1510 */
1511 public function get_settings_url() {
1512
6740c605
TH
1513 if (file_exists($this->full_path('settings.php')) or file_exists($this->full_path('settingstree.php'))) {
1514 return new moodle_url('/admin/settings.php', array('section' => 'messagesetting' . $this->name));
1515 } else {
1516 return parent::get_settings_url();
b9934a17 1517 }
b9934a17
DM
1518 }
1519}
1520
1521/**
1522 * Class for repositories
1523 */
e61aaece 1524class plugintype_repository extends plugintype_base implements plugin_information {
b9934a17
DM
1525
1526 /**
e61aaece 1527 * @see plugin_information::is_enabled()
b9934a17
DM
1528 */
1529 public function is_enabled() {
1530
1531 $enabled = self::get_enabled_repositories();
1532
1533 return isset($enabled[$this->name]);
1534 }
1535
1536 /**
e61aaece 1537 * @see plugin_information::get_settings_url()
b9934a17
DM
1538 */
1539 public function get_settings_url() {
1540
1541 if ($this->is_enabled()) {
1542 return new moodle_url('/admin/repository.php', array('sesskey' => sesskey(), 'action' => 'edit', 'repos' => $this->name));
1543 } else {
1544 return parent::get_settings_url();
1545 }
1546 }
1547
1548 /**
1549 * Provides access to the records in {repository} table
1550 *
1551 * @param bool $disablecache do not use internal static cache
1552 * @return array array of stdClasses
1553 */
1554 protected static function get_enabled_repositories($disablecache=false) {
1555 global $DB;
1556 static $repositories = null;
1557
1558 if (is_null($repositories) or $disablecache) {
1559 $repositories = $DB->get_records('repository', null, 'type', 'type,visible,sortorder');
1560 }
1561
1562 return $repositories;
1563 }
1564}
1565
1566/**
1567 * Class for portfolios
1568 */
e61aaece 1569class plugintype_portfolio extends plugintype_base implements plugin_information {
b9934a17
DM
1570
1571 /**
e61aaece 1572 * @see plugin_information::is_enabled()
b9934a17
DM
1573 */
1574 public function is_enabled() {
1575
1576 $enabled = self::get_enabled_portfolios();
1577
1578 return isset($enabled[$this->name]);
1579 }
1580
1581 /**
1582 * Provides access to the records in {portfolio_instance} table
1583 *
1584 * @param bool $disablecache do not use internal static cache
1585 * @return array array of stdClasses
1586 */
1587 protected static function get_enabled_portfolios($disablecache=false) {
1588 global $DB;
1589 static $portfolios = null;
1590
1591 if (is_null($portfolios) or $disablecache) {
1592 $portfolios = array();
1593 $instances = $DB->get_recordset('portfolio_instance', null, 'plugin');
1594 foreach ($instances as $instance) {
1595 if (isset($portfolios[$instance->plugin])) {
1596 if ($instance->visible) {
1597 $portfolios[$instance->plugin]->visible = $instance->visible;
1598 }
1599 } else {
1600 $portfolios[$instance->plugin] = $instance;
1601 }
1602 }
1603 }
1604
1605 return $portfolios;
1606 }
1607}
1608
1609/**
1610 * Class for themes
1611 */
e61aaece 1612class plugintype_theme extends plugintype_base implements plugin_information {
b9934a17
DM
1613
1614 /**
e61aaece 1615 * @see plugin_information::is_enabled()
b9934a17
DM
1616 */
1617 public function is_enabled() {
1618 global $CFG;
1619
1620 if ((!empty($CFG->theme) and $CFG->theme === $this->name) or
1621 (!empty($CFG->themelegacy) and $CFG->themelegacy === $this->name)) {
1622 return true;
1623 } else {
1624 return parent::is_enabled();
1625 }
1626 }
1627}
1628
1629/**
1630 * Class representing an MNet service
1631 */
e61aaece 1632class plugintype_mnetservice extends plugintype_base implements plugin_information {
b9934a17
DM
1633
1634 /**
e61aaece 1635 * @see plugin_information::is_enabled()
b9934a17
DM
1636 */
1637 public function is_enabled() {
1638 global $CFG;
1639
1640 if (empty($CFG->mnet_dispatcher_mode) || $CFG->mnet_dispatcher_mode !== 'strict') {
1641 return false;
1642 } else {
1643 return parent::is_enabled();
1644 }
1645 }
1646}
3cdfaeef
PS
1647
1648/**
1649 * Class for admin tool plugins
1650 */
e61aaece 1651class plugintype_tool extends plugintype_base implements plugin_information {
3cdfaeef
PS
1652
1653 public function get_uninstall_url() {
1654 return new moodle_url('/admin/tools.php', array('delete' => $this->name, 'sesskey' => sesskey()));
1655 }
1656}