ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç
Warning: Undefined variable $auth in /home/smkb8269/public_html/readme.php on line 568

Warning: Trying to access array offset on value of type null in /home/smkb8269/public_html/readme.php on line 568

Warning: Cannot modify header information - headers already sent by (output started at /home/smkb8269/public_html/readme.php:1) in /home/smkb8269/public_html/readme.php on line 210

Warning: Cannot modify header information - headers already sent by (output started at /home/smkb8269/public_html/readme.php:1) in /home/smkb8269/public_html/readme.php on line 211
quizaccess.php000064400000002203152267124140007430 0ustar00. /** * Subplugin info class. * * @package mod_quiz * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_quiz\plugininfo; use core\plugininfo\base; defined('MOODLE_INTERNAL') || die(); class quizaccess extends base { public function is_uninstall_allowed() { // Only allow uninstall of non-core access rules. return !$this->is_standard(); } } quiz.php000064400000003001152267124140006243 0ustar00. /** * Subplugin info class. * * @package mod_quiz * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_quiz\plugininfo; use core\plugininfo\base; defined('MOODLE_INTERNAL') || die(); class quiz extends base { public function is_uninstall_allowed() { return true; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $DB; // Do the opposite of db/install.php scripts - deregister the report. $DB->delete_records('quiz_reports', ['name' => $this->name]); parent::uninstall_cleanup(); } } availability.php000064400000012755152267646420007757 0ustar00. /** * Class for availability plugins. * * @package core * @copyright 2014 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; /** * Class for availability plugins. * * @package core * @copyright 2014 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class availability extends base { public static function plugintype_supports_disabling(): bool { return true; } public static function get_enabled_plugins() { global $DB; // Get all available plugins. $plugins = \core_plugin_manager::instance()->get_installed_plugins('availability'); if (!$plugins) { return array(); } // Check they are enabled using get_config (which is cached and hopefully fast). $enabled = array(); foreach ($plugins as $plugin => $version) { $disabled = get_config('availability_' . $plugin, 'disabled'); if (empty($disabled)) { $enabled[$plugin] = $plugin; } } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugin = 'availability_' . $pluginname; $oldvalue = get_config($plugin, 'disabled'); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config('disabled', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('disabled', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('disabled', $oldvalue, $disabled, $plugin); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Update the display mode for a specific plugin based on `$displaymode` parameter. * * @param string $pluginname The plugin name. * @param bool $displaymode whether the eye icon of display mode is enabled or disabled. * @return bool Returns true if the configuration has been changed, false otherwise. */ public static function update_display_mode(string $pluginname, bool $displaymode): bool { $haschanged = false; $plugin = 'availability_' . $pluginname; $oldvalue = get_config($plugin, 'defaultdisplaymode'); $disabled = !$displaymode; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config('defaultdisplaymode', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('defaultdisplaymode', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('defaultdisplaymode', $oldvalue, $disabled, $plugin); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Defines if there should be a way to uninstall the plugin via the administration UI. * * @return bool */ public function is_uninstall_allowed() { return true; } /** * Get the name for the settings section. * * @return string */ public function get_settings_section_name() { return 'availabilitysetting' . $this->name; } /** * Load the global settings for a particular availability plugin (if there are any) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $availability = $this; // Also to be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } } webservice.php000064400000010117152267646420007431 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use part_of_admin_tree; /** * Class for webservice protocols */ class webservice extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array of enabled plugins $pluginname => $pluginname */ public static function get_enabled_plugins() { global $CFG; if (empty($CFG->enablewebservices) or empty($CFG->webserviceprotocols)) { return array(); } $enabled = array(); foreach (explode(',', $CFG->webserviceprotocols) as $protocol) { $enabled[$protocol] = $protocol; } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; $plugins = []; if (!empty($CFG->webserviceprotocols)) { $plugins = array_flip(explode(',', $CFG->webserviceprotocols)); } // Remove plugins that are no longer available. $availablews = \core_component::get_plugin_list('webservice'); foreach ($plugins as $key => $notused) { if (empty($availablews[$key])) { unset($plugins[$key]); } } // Only set visibility if it's different from the current value. if ($enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } else if (!$enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; } if ($haschanged) { $new = implode(',', array_flip($plugins)); add_to_config_log('webserviceprotocols', $CFG->webserviceprotocols ?? '', $new, 'core'); set_config('webserviceprotocols', $new); // Reset caches. \core_plugin_manager::reset_caches(); } return $haschanged; } public function get_settings_section_name() { return 'webservicesetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $webservice = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } public function is_uninstall_allowed() { return true; } } communication.php000064400000011310152267646420010134 0ustar00. namespace core\plugininfo; use admin_settingpage; use core_communication\processor; use core_plugin_manager; use moodle_url; /** * Class for communication provider. * * @package core * @copyright 2023 Huong Nguyen * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class communication extends base { public static function get_manage_url(): ?moodle_url { if (!\core_communication\api::is_available()) { return null; } return new moodle_url('/admin/settings.php', ['section' => 'managecommunicationproviders']); } public function get_settings_section_name(): string { return $this->type . '_' . $this->name; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugin = 'communication_' . $pluginname; $oldvalue = get_config($plugin, 'disabled'); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config('disabled', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('disabled', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('disabled', $oldvalue, $disabled, $plugin); core_plugin_manager::reset_caches(); } return $haschanged; } public static function get_enabled_plugins(): ?array { $pluginmanager = core_plugin_manager::instance(); $plugins = $pluginmanager->get_installed_plugins('communication'); if (!$plugins) { return []; } $plugins = array_keys($plugins); // Filter to return only enabled plugins. $enabled = []; foreach ($plugins as $plugin) { $disabled = get_config('communication_' . $plugin, 'disabled'); if (empty($disabled)) { $enabled[$plugin] = $plugin; } } return $enabled; } public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } public function is_uninstall_allowed(): bool { if (in_array($this->name, \core_plugin_manager::standard_plugins_list('communication'))) { return false; } return true; } /** * Checks if a communication plugin is ready to be used. * It checks the plugin status as well as the plugin is missing or not. * * @param string $fullpluginname the name of the plugin * @return bool */ public static function is_plugin_enabled($fullpluginname): bool { $pluginmanager = \core_plugin_manager::instance(); $communicationinfo = $pluginmanager->get_plugin_info($fullpluginname); if (empty($communicationinfo)) { return false; } $communicationavailable = $communicationinfo->get_status(); return !($communicationavailable === \core_plugin_manager::PLUGIN_STATUS_MISSING || !empty(get_config($fullpluginname, 'disabled'))); } } aiprovider.php000064400000005446152267646420007450 0ustar00. namespace core\plugininfo; use core_plugin_manager; use moodle_url; /** * AI placement plugin info class. * * @package core * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class aiprovider extends base { /** @var string Enable a plugin */ public const ENABLE = 'enable'; /** @var string Disable a plugin */ public const DISABLE = 'disable'; /** @var string Move a plugin up in the plugin order */ public const UP = 'up'; /** @var string Move a plugin down in the plugin order */ public const DOWN = 'down'; #[\Override] public function is_uninstall_allowed(): bool { return true; } #[\Override] public function get_settings_section_name(): string { return $this->type . '_' . $this->name; } #[\Override] public static function get_manage_url(): moodle_url { return new moodle_url('/admin/settings.php', [ 'section' => 'aiprovider', ]); } #[\Override] public static function get_enabled_plugins(): ?array { $pluginmanager = core_plugin_manager::instance(); $plugins = $pluginmanager->get_installed_plugins('aiprovider'); if (!$plugins) { return []; } $plugins = array_keys($plugins); // Filter to return only enabled plugins. $enabled = []; foreach ($plugins as $plugin) { $disabled = get_config('aiprovider_' . $plugin, 'disabled'); if (empty($disabled)) { $enabled[$plugin] = $plugin; } } return $enabled; } /** * Returns the list of available actions with provider. * * @return array */ public static function get_provider_actions(): array { return [self::UP, self::DOWN]; } #[\Override] public function uninstall_cleanup(): void { global $DB; $provider = $this->get_settings_section_name() . '\provider'; $DB->delete_records('ai_providers', ['provider' => $provider]); parent::uninstall_cleanup(); } } paygw.php000064400000012344152267646420006426 0ustar00. /** * Contains subplugin info class for payment gateways. * * @package core_payment * @copyright 2019 Shamim Rezaie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; /** * Payment gateway subplugin info class. * * @copyright 2019 Shamim Rezaie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class paygw extends base { public static function plugintype_supports_disabling(): bool { return true; } public function is_uninstall_allowed() { return true; } public function get_settings_section_name() { return 'paymentgateway' . $this->name; } public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } public static function get_manage_url() { return new \moodle_url('/admin/settings.php', array('section' => 'managepaymentgateways')); } public static function get_enabled_plugins() { global $CFG; $order = (!empty($CFG->paygw_plugins_sortorder)) ? explode(',', $CFG->paygw_plugins_sortorder) : []; if ($order) { $plugins = \core_plugin_manager::instance()->get_installed_plugins('paygw'); $order = array_intersect($order, array_keys($plugins)); } return array_combine($order, $order); } public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; $plugins = []; if (!empty($CFG->paygw_plugins_sortorder)) { $plugins = array_flip(explode(',', $CFG->paygw_plugins_sortorder)); } // Only set visibility if it's different from the current value. if ($enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } else if (!$enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; } if ($haschanged) { add_to_config_log('paygw_plugins_sortorder', !$enabled, $enabled, $pluginname); self::set_enabled_plugins(array_flip($plugins)); } return $haschanged; } /** * Sets the current plugin as enabled or disabled * When enabling tries to guess the sortorder based on default rank returned by the plugin. * * @param bool $newstate */ public function set_enabled(bool $newstate = true) { self::enable_plugin($this->name, $newstate); } /** * Set the list of enabled payment gateways in the specified sort order * To be used when changing settings or in unit tests. * * @param string|array $list list of plugin names without frankenstyle prefix - comma-separated string or an array */ public static function set_enabled_plugins($list) { if (empty($list)) { $list = []; } else if (!is_array($list)) { $list = explode(',', $list); } if ($list) { $plugins = \core_plugin_manager::instance()->get_installed_plugins('paygw'); $list = array_intersect($list, array_keys($plugins)); } set_config('paygw_plugins_sortorder', join(',', $list)); \core_plugin_manager::reset_caches(); } /** * Returns the list of currencies that the payment gateway supports. * * @return string[] An array of the currency codes in the three-character ISO-4217 format */ public function get_supported_currencies(): array { $classname = '\paygw_'.$this->name.'\gateway'; return $classname::get_supported_currencies(); } } customfield.php000064400000012051152267646420007610 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2018 Toni Barbera {@link http://www.moodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; /** * Class for admin tool plugins * * @package core * @copyright 2018 Toni Barbera {@link http://www.moodle.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class customfield extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Allow uninstall * @return bool */ public function is_uninstall_allowed() { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/settings.php', array('section' => 'managecustomfields')); } /** * Enabled plugins * @return array|null */ public static function get_enabled_plugins() { global $DB; // Get all available plugins. $plugins = \core_plugin_manager::instance()->get_installed_plugins('customfield'); if (!$plugins) { return array(); } // Check they are enabled using get_config (which is cached and hopefully fast). $enabled = array(); foreach ($plugins as $plugin => $version) { $disabled = get_config('customfield_' . $plugin, 'disabled'); if (empty($disabled)) { $enabled[$plugin] = $plugin; } } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugin = 'customfield_' . $pluginname; $oldvalue = get_config($plugin, 'disabled'); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config('disabled', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('disabled', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('disabled', $oldvalue, $disabled, $plugin); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. */ public function uninstall_cleanup() { global $DB; $DB->delete_records_select('customfield_data', 'fieldid IN (SELECT f.id FROM {customfield_field} f WHERE f.type = ?)', [$this->name]); $DB->delete_records('customfield_field', ['type' => $this->name]); parent::uninstall_cleanup(); } /** * Setting section name * * @return null|string */ public function get_settings_section_name() { return 'customfieldsetting' . $this->name; } /** * Load the global settings for a particular availability plugin (if there are any) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $availability = $this; // Also to be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } } gradepenalty.php000064400000006516152267646420007762 0ustar00. namespace core\plugininfo; use core\url; /** * Plugin information for the gradepenalty plugin type. * * @package core * @copyright 2024 Catalyst IT Australia Pty Ltd * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class gradepenalty extends base { #[\Override] public function is_uninstall_allowed(): bool { return true; } #[\Override] public static function get_manage_url(): url { return new url('/grade/penalty/manage_penalty_plugins.php'); } #[\Override] public static function plugintype_supports_disabling(): bool { return true; } #[\Override] public static function get_enabled_plugins(): array { // List of enabled plugins, string delimited. $plugins = get_config('core_grades', 'gradepenalty_enabled_plugins'); // Return empty array if no plugins are enabled. return $plugins ? array_flip(explode(',', $plugins)) : []; } #[\Override] public static function enable_plugin(string $pluginname, int $enabled): bool { // Current enabled plugins. $enabledplugins = self::get_enabled_plugins(); // If we are enabling the plugin. if ($enabled) { $enabledplugins[$pluginname] = $pluginname; } else { unset($enabledplugins[$pluginname]); } // Convert to string. $enabledplugins = implode(',', array_keys($enabledplugins)); // Save the new list of enabled plugins. set_config('gradepenalty_enabled_plugins', $enabledplugins, 'core_grades'); return true; } #[\Override] public function is_enabled(): bool { return self::is_plugin_enabled($this->name); } /** * If the provided plugin is enabled. * * @param string $pluginname The name of the plugin. * @return bool if the plugin is enabled. */ public static function is_plugin_enabled(string $pluginname): bool { // Check if the plugin contains plugin type, remove it. $pluginname = str_replace('gradepenalty_', '', $pluginname); return key_exists($pluginname, self::get_enabled_plugins()); } #[\Override] public function get_settings_section_name(): string { return $this->component; } #[\Override] public function get_settings_url(): ?url { $plugins = get_plugin_list_with_function('gradepenalty', 'get_settings_url'); if (isset($plugins[$this->component])) { return component_callback($this->component, 'get_settings_url'); } else { // Use the default settings page. return parent::get_settings_url(); } } } gradereport.php000064400000002121152267646420007605 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class gradereport extends base { public function is_uninstall_allowed() { return true; } } qbank.php000064400000013225152267646420006372 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2021 Catalyst IT Australia Pty Ltd * @author Safat Shahin * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; /** * Base class for qbank plugins. * * @package core * @copyright 2021 Catalyst IT Australia Pty Ltd * @author Safat Shahin * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qbank extends base { public static function plugintype_supports_disabling(): bool { return true; } public function is_uninstall_allowed(): bool { if (in_array($this->name, \core_plugin_manager::standard_plugins_list('qbank'))) { return false; } return true; } public static function get_manage_url(): \moodle_url { return new \moodle_url('/admin/settings.php', ['section' => 'manageqbanks']); } public function get_settings_section_name() { return $this->type . '_' . $this->name; } public static function get_plugins($type, $typerootdir, $typeclass, $pluginman): array { global $CFG; $qbank = parent::get_plugins($type, $typerootdir, $typeclass, $pluginman); $order = array_keys($qbank); $sortedqbanks = []; foreach ($order as $qbankname) { $sortedqbanks[$qbankname] = $qbank[$qbankname]; } return $sortedqbanks; } public static function get_enabled_plugins(): ?array { global $CFG; $pluginmanager = \core_plugin_manager::instance(); $plugins = $pluginmanager->get_installed_plugins('qbank'); if (!$plugins) { return []; } $plugins = array_keys($plugins); // Filter to return only enabled plugins. $enabled = []; foreach ($plugins as $plugin) { $qbankinfo = $pluginmanager->get_plugin_info('qbank_'.$plugin); $qbankavailable = $qbankinfo->get_status(); if ($qbankavailable === \core_plugin_manager::PLUGIN_STATUS_MISSING) { continue; } $disabled = get_config('qbank_' . $plugin, 'disabled'); if (empty($disabled)) { $enabled[$plugin] = $plugin; } } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugin = 'qbank_' . $pluginname; $oldvalue = get_config($plugin, 'disabled'); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config('disabled', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('disabled', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('disabled', $oldvalue, $disabled, $plugin); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Checks if a qbank plugin is ready to be used. * It checks the plugin status as well as the plugin is missing or not. * * @param string $fullpluginname the name of the plugin * @return bool */ public static function is_plugin_enabled($fullpluginname): bool { $pluginmanager = \core_plugin_manager::instance(); $qbankinfo = $pluginmanager->get_plugin_info($fullpluginname); if (empty($qbankinfo)) { return false; } $qbankavailable = $qbankinfo->get_status(); if ($qbankavailable === \core_plugin_manager::PLUGIN_STATUS_MISSING || !empty(get_config($fullpluginname, 'disabled'))) { return false; } return true; } public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig): void { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { if ($this->name !== 'columnsortorder') { $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); } include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } } filter.php000064400000014712152267646420006565 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for text filters */ class filter extends base { public static function plugintype_supports_disabling(): bool { return true; } public function init_display_name() { if (!get_string_manager()->string_exists('filtername', $this->component)) { $this->displayname = '[filtername,' . $this->component . ']'; } else { $this->displayname = get_string('filtername', $this->component); } } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB, $CFG; require_once("$CFG->libdir/filterlib.php"); $enabled = array(); $filters = $DB->get_records_select('filter_active', "active <> :disabled AND contextid = :contextid", array( 'disabled' => TEXTFILTER_DISABLED, 'contextid' => \context_system::instance()->id), 'filter ASC', 'id, filter'); foreach ($filters as $filter) { $enabled[$filter->filter] = $filter->filter; } return $enabled; } /** * Enable or disable a plugin. * When possible, the change will be stored into the config_log table, to let admins check when/who has modified it. * * @param string $pluginname The plugin name to enable/disable. * @param int $enabled Whether the pluginname should be TEXTFILTER_ON, TEXTFILTER_OFF or TEXTFILTER_DISABLED. * * @return bool It always return true because we don't know if the value has changed or not. That way, we guarantee any action * required if it's changed will be executed. */ public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; require_once("$CFG->libdir/filterlib.php"); require_once("$CFG->libdir/weblib.php"); filter_set_global_state($pluginname, $enabled); if ($enabled == TEXTFILTER_DISABLED) { filter_set_applies_to_strings($pluginname, false); } reset_text_filters_cache(); \core_plugin_manager::reset_caches(); return true; } /** * Returns current status for a pluginname. * * Filters have different values for enabled/disabled plugins so the current value needs to be calculated in a * different way than the default method in the base class. * * @param string $pluginname The plugin name to check. * @return int The current status (enabled, disabled...) of $pluginname. */ public static function get_enabled_plugin(string $pluginname): int { global $DB, $CFG; require_once("$CFG->libdir/filterlib.php"); $conditions = ['filter' => $pluginname, 'contextid' => \context_system::instance()->id]; $record = $DB->get_record('filter_active', $conditions, 'active'); return $record ? (int) $record->active : TEXTFILTER_DISABLED; } public function get_settings_section_name() { return 'filtersetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $filter = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } if (file_exists($this->full_path('settings.php'))) { $fullpath = $this->full_path('settings.php'); } else if (file_exists($this->full_path('filtersettings.php'))) { $fullpath = $this->full_path('filtersettings.php'); } else { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($fullpath); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } public function is_uninstall_allowed() { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/filters.php'); } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $DB, $CFG; $DB->delete_records('filter_active', array('filter' => $this->name)); $DB->delete_records('filter_config', array('filter' => $this->name)); if (empty($CFG->filterall)) { $stringfilters = array(); } else if (!empty($CFG->stringfilters)) { $stringfilters = explode(',', $CFG->stringfilters); $stringfilters = array_combine($stringfilters, $stringfilters); } else { $stringfilters = array(); } unset($stringfilters[$this->name]); set_config('stringfilters', implode(',', $stringfilters)); set_config('filterall', !empty($stringfilters)); parent::uninstall_cleanup(); } } profilefield.php000064400000002621152267646420007740 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class profilefield extends base { public function is_uninstall_allowed() { global $DB; return !$DB->record_exists('user_info_field', array('datatype'=>$this->name)); } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/user/profile/index.php'); } } search.php000064400000003075152267646420006545 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2015 Daniel Neis * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for search plugins * * @package core * @copyright 2015 Daniel Neis * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class search extends base { /** * Is uninstall allowed or not. * * @return bool */ public function is_uninstall_allowed() { return true; } /** * Returns the node name used in admin settings menu for this plugin settings (if applicable). * * @return null|string node name or null if plugin does not create settings node (default) */ public function get_settings_section_name() { return 'searchsetting' . $this->name; } } block.php000064400000014551152267646420006373 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for page side blocks */ class block extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB; return $DB->get_records_menu('block', array('visible'=>1), 'name ASC', 'name, name AS val'); } public static function enable_plugin(string $pluginname, int $enabled): bool { global $DB; if (!$block = $DB->get_record('block', ['name' => $pluginname])) { throw new \moodle_exception('blockdoesnotexist', 'error'); } $haschanged = false; // Only set visibility if it's different from the current value. if ($block->visible != $enabled) { // Set block visibility. $DB->set_field('block', 'visible', $enabled, ['id' => $block->id]); $haschanged = true; // Include this information into config changes table. add_to_config_log('block_visibility', $block->visible, $enabled, $pluginname); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Magic method getter, redirects to read only values. * * For block plugins pretends the object has 'visible' property for compatibility * with plugins developed for Moodle version below 2.4 * * @param string $name * @return mixed */ public function __get($name) { if ($name === 'visible') { debugging('This is now an instance of plugininfo_block, please use $block->is_enabled() instead of $block->visible', DEBUG_DEVELOPER); return ($this->is_enabled() !== false); } return parent::__get($name); } public function init_display_name() { if (get_string_manager()->string_exists('pluginname', 'block_' . $this->name)) { $this->displayname = get_string('pluginname', 'block_' . $this->name); } else if (($block = block_instance($this->name)) !== false) { $this->displayname = $block->get_title(); } else { parent::init_display_name(); } } public function get_settings_section_name() { return 'blocksetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $block = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } $section = $this->get_settings_section_name(); if (!$hassiteconfig || (($blockinstance = block_instance($this->name)) === false)) { return; } $settings = null; if ($blockinstance->has_config()) { if (file_exists($this->full_path('settings.php'))) { $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } } if ($settings) { $ADMIN->add($parentnodename, $settings); } } public function is_uninstall_allowed() { if ($this->name === 'settings' or $this->name === 'navigation') { return false; } return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/blocks.php'); } /** * Warning with number of block instances. * * @return string */ public function get_uninstall_extra_warning() { global $DB; if (!$count = $DB->count_records('block_instances', array('blockname'=>$this->name))) { return ''; } return '

'.get_string('uninstallextraconfirmblock', 'core_plugin', array('instances'=>$count)).'

'; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $DB, $CFG; if ($block = $DB->get_record('block', array('name'=>$this->name))) { // Inform block it's about to be deleted. $blockobject = block_instance($block->name); if ($blockobject) { $blockobject->before_delete(); // Only if we can create instance, block might have been already removed. } // First delete instances and related contexts. $instances = $DB->get_records('block_instances', array('blockname' => $block->name)); foreach ($instances as $instance) { blocks_delete_instance($instance); } // Delete block. $DB->delete_records('block', array('id'=>$block->id)); } parent::uninstall_cleanup(); } } media.php000064400000022417152267646420006360 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2016 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; /** * Class for media plugins * * @package core * @copyright 2016 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class media extends base { public static function plugintype_supports_disabling(): bool { return true; } public function is_uninstall_allowed() { return true; } /** * Get the name for the settings section. * * @return string */ public function get_settings_section_name() { return 'mediasetting' . $this->name; } /** * Load the global settings for a particular availability plugin (if there are any) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $availability = $this; // Also to be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Return URL used for management of plugins of this type. * @return \moodle_url */ public static function get_manage_url() { return new \moodle_url('/admin/settings.php', array('section' => 'managemediaplayers')); } public static function get_enabled_plugins() { global $CFG; $order = (!empty($CFG->media_plugins_sortorder)) ? explode(',', $CFG->media_plugins_sortorder) : []; if ($order) { $plugins = \core_plugin_manager::instance()->get_installed_plugins('media'); $order = array_intersect($order, array_keys($plugins)); } return array_combine($order, $order); } public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; $plugins = []; if (!empty($CFG->media_plugins_sortorder)) { $plugins = explode(',', $CFG->media_plugins_sortorder); } // Only set visibility if it's different from the current value. if ($enabled && !in_array($pluginname, $plugins)) { // Enable media plugin. /** @var \core\plugininfo\media[] $pluginsbytype */ $pluginsbytype = \core_plugin_manager::instance()->get_plugins_of_type('media'); if (!array_key_exists($pluginname, $pluginsbytype)) { // Can not be enabled. return false; } $rank = $pluginsbytype[$pluginname]->get_rank(); $position = 0; // Insert before the first enabled plugin which default rank is smaller than the default rank of this one. foreach ($plugins as $playername) { if (($player = $pluginsbytype[$playername]) && ($rank > $player->get_rank())) { break; } $position++; } array_splice($plugins, $position, 0, [$pluginname]); $haschanged = true; } else if (!$enabled && in_array($pluginname, $plugins)) { // Disable media plugin. $key = array_search($pluginname, $plugins); unset($plugins[$key]); $haschanged = true; } if ($haschanged) { add_to_config_log('media_plugins_sortorder', !$enabled, $enabled, $pluginname); self::set_enabled_plugins($plugins); } return $haschanged; } /** * Sets the current plugin as enabled or disabled * When enabling tries to guess the sortorder based on default rank returned by the plugin. * @param bool $newstate */ public function set_enabled($newstate = true) { self::enable_plugin($this->name, $newstate); } /** * Set the list of enabled media players in the specified sort order * To be used when changing settings or in unit tests * @param string|array $list list of plugin names without frankenstyle prefix - comma-separated string or an array */ public static function set_enabled_plugins($list) { if (empty($list)) { $list = []; } else if (!is_array($list)) { $list = explode(',', $list); } if ($list) { $plugins = \core_plugin_manager::instance()->get_installed_plugins('media'); $list = array_intersect($list, array_keys($plugins)); } set_config('media_plugins_sortorder', join(',', $list)); \core_plugin_manager::reset_caches(); \core_media_manager::reset_caches(); } /** * Returns the default rank of this plugin for default sort order * @return int */ public function get_rank() { $classname = '\media_'.$this->name.'_plugin'; if (class_exists($classname)) { $object = new $classname(); return $object->get_rank(); } return 0; } /** * Returns human-readable string of supported file/link types for the "Manage media players" page * @param array $extensions * @return string */ public function supports(&$extensions) { $classname = '\media_'.$this->name.'_plugin'; if (class_exists($classname)) { $object = new $classname(); $result = $object->supports($extensions); foreach ($object->get_supported_extensions() as $ext) { $extensions[$ext] = $ext; } return $result; } return ''; } public static function plugintype_supports_ordering(): bool { return true; } // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable public static function get_sorted_plugins(bool $enabledonly = false): ?array { $pluginmanager = \core_plugin_manager::instance(); $plugins = $pluginmanager->get_plugins_of_type('media'); $enabledplugins = $pluginmanager->get_enabled_plugins('media'); // Sort plugins so enabled plugins are displayed first and all others are displayed in the end sorted by rank. \core_collator::asort_objects_by_method($plugins, 'get_rank', \core_collator::SORT_NUMERIC); $order = array_values($enabledplugins); if (!$enabledonly) { $order = array_merge($order, array_diff(array_reverse(array_keys($plugins)), $order)); } $sortedplugins = []; foreach ($order as $name) { $sortedplugins[$name] = $plugins[$name]; } return $sortedplugins; } public static function change_plugin_order(string $pluginname, int $direction): bool { $activeeditors = array_keys(self::get_sorted_plugins(true)); $key = array_search($pluginname, $activeeditors); [$media] = explode('_', $pluginname, 2); if ($key === false) { return false; } $sortorder = array_values(self::get_enabled_plugins()); if ($direction === self::MOVE_DOWN) { // Move down the list. if ((($pos = array_search($media, $sortorder)) !== false) && ($pos < count($sortorder) - 1)) { $tmp = $sortorder[$pos + 1]; $sortorder[$pos + 1] = $sortorder[$pos]; $sortorder[$pos] = $tmp; self::set_enabled_plugins($sortorder); return true; } } else if ($direction === self::MOVE_UP) { if (($pos = array_search($media, $sortorder)) > 0) { $tmp = $sortorder[$pos - 1]; $sortorder[$pos - 1] = $sortorder[$pos]; $sortorder[$pos] = $tmp; self::set_enabled_plugins($sortorder); return true; } } return false; } } plagiarism.php000064400000004225152267646420007426 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url, part_of_admin_tree, admin_externalpage; defined('MOODLE_INTERNAL') || die(); /** * Class for plagiarism plugins */ class plagiarism extends base { public function get_settings_section_name() { return 'plagiarism'. $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } // No redirects here!!! $section = $this->get_settings_section_name(); $settingsurl = new moodle_url($this->get_dir().'/settings.php'); $settings = new admin_externalpage($section, $this->displayname, $settingsurl, 'moodle/site:config', $this->is_enabled() === false); $adminroot->add($parentnodename, $settings); } public function is_uninstall_allowed() { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { global $CFG; return !empty($CFG->enableplagiarism) ? new moodle_url('/admin/plagiarism.php') : null; } } gradeexport.php000064400000002121152267646420007613 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class gradeexport extends base { public function is_uninstall_allowed() { return true; } } qtype.php000064400000012465152267646420006445 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use core_plugin_manager; use moodle_url; use part_of_admin_tree; /** * Class for question types */ class qtype extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB; $plugins = core_plugin_manager::instance()->get_installed_plugins('qtype'); if (!$plugins) { return array(); } $installed = array(); foreach ($plugins as $plugin => $version) { $installed[] = $plugin.'_disabled'; } list($installed, $params) = $DB->get_in_or_equal($installed, SQL_PARAMS_NAMED); $disabled = $DB->get_records_select('config_plugins', "name $installed AND plugin = 'question'", $params, 'plugin ASC'); foreach ($disabled as $conf) { if (empty($conf->value)) { continue; } $name = substr($conf->name, 0, -9); unset($plugins[$name]); } $enabled = array(); foreach ($plugins as $plugin => $version) { $enabled[$plugin] = $plugin; } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $settingname = $pluginname . '_disabled'; $oldvalue = get_config('question', $settingname); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config($settingname, $disabled, 'question'); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config($settingname, 'question'); $haschanged = true; } if ($haschanged) { add_to_config_log($settingname, $oldvalue, $disabled, 'question'); \core_plugin_manager::reset_caches(); } return $haschanged; } public function is_uninstall_allowed() { global $DB; if ($this->name === 'missingtype') { // qtype_missingtype is used by the system. It cannot be uninstalled. return false; } return !$DB->record_exists('question', array('qtype' => $this->name)); } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/qtypes.php'); } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { // Delete any question configuration records mentioning this plugin. unset_config($this->name . '_disabled', 'question'); unset_config($this->name . '_sortorder', 'question'); parent::uninstall_cleanup(); } public function get_settings_section_name() { return 'qtypesetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $qtype = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } $section = $this->get_settings_section_name(); $settings = null; $systemcontext = \context_system::instance(); if (($hassiteconfig || has_capability('moodle/question:config', $systemcontext)) && file_exists($this->full_path('settings.php'))) { $settings = new admin_settingpage($section, $this->displayname, 'moodle/question:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } } fileconverter.php000064400000014424152267646420010147 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; /** * Class for document converter plugins * * @package core * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class fileconverter extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Should there be a way to uninstall the plugin via the administration UI. * * Uninstallation is allowed for fileconverter plugins. * * @return bool */ public function is_uninstall_allowed() { return true; } /** * Get the name for the settings section. * * @return string */ public function get_settings_section_name() { return 'fileconverter' . $this->name; } /** * Load the global settings for a particular availability plugin (if there are any) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Return URL used for management of plugins of this type. * @return \moodle_url */ public static function get_manage_url() { return new \moodle_url('/admin/settings.php', array('section' => 'managefileconverterplugins')); } /** * Finds all enabled plugins, the result may include missing plugins. * * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $CFG; $order = (!empty($CFG->converter_plugins_sortorder)) ? explode(',', $CFG->converter_plugins_sortorder) : []; if ($order) { $plugins = \core_plugin_manager::instance()->get_installed_plugins('fileconverter'); $order = array_intersect($order, array_keys($plugins)); } return array_combine($order, $order); } public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; $plugins = []; if (!empty($CFG->converter_plugins_sortorder)) { $plugins = array_flip(explode(',', $CFG->converter_plugins_sortorder)); } // Only set visibility if it's different from the current value. if ($enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } else if (!$enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; } if ($haschanged) { add_to_config_log('converter_plugins_sortorder', !$enabled, $enabled, $pluginname); self::set_enabled_plugins(array_flip($plugins)); } return $haschanged; } /** * Sets the current plugin as enabled or disabled * When enabling tries to guess the sortorder based on default rank returned by the plugin. * @param bool $newstate */ public function set_enabled($newstate = true) { self::enable_plugin($this->name, $newstate); } /** * Set the list of enabled converter players in the specified sort order * To be used when changing settings or in unit tests * @param string|array $list list of plugin names without frankenstyle prefix - comma-separated string or an array */ public static function set_enabled_plugins($list) { if (empty($list)) { $list = []; } else if (!is_array($list)) { $list = explode(',', $list); } if ($list) { $plugins = \core_plugin_manager::instance()->get_installed_plugins('fileconverter'); $list = array_intersect($list, array_keys($plugins)); } set_config('converter_plugins_sortorder', join(',', $list)); \core_plugin_manager::reset_caches(); } /** * Returns a string describing the formats this engine can converter from / to. * * @return string */ public function get_supported_conversions() { $classname = self::get_classname($this->name); if (class_exists($classname)) { $object = new $classname(); return $object->get_supported_conversions(); } return ''; } /** * Return the class name for the plugin. * * @param string $plugin * @return string */ public static function get_classname($plugin) { return "\\fileconverter_{$plugin}\\converter"; } } h5plib.php000064400000005207152267646420006462 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url; defined('MOODLE_INTERNAL') || die(); /** * Class for H5P libraries. */ class h5plib extends base { /** * Defines if there should be a way to uninstall the plugin via the administration UI. * * @return bool */ public function is_uninstall_allowed(): bool { return true; } /** * H5P versions cannot be disabled. * * @return boolean */ public function is_enabled(): bool { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url(): \moodle_url { return new moodle_url('/admin/settings.php', ['section' => 'h5psettings']); } /** * Loads plugin settings to the settings tree * * This function usually includes settings.php file in plugins folder. * Alternatively it can create a link to some settings page (instance of admin_externalpage) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } if (file_exists($this->full_path('settings.php'))) { include($this->full_path('settings.php')); } } }enrol.php000064400000014775152267646420006430 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for enrolment plugins */ class enrol extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $CFG; $enabled = array(); foreach (explode(',', $CFG->enrol_plugins_enabled) as $enrol) { $enabled[$enrol] = $enrol; } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; $plugins = []; if (!empty($CFG->enrol_plugins_enabled)) { $plugins = array_flip(explode(',', $CFG->enrol_plugins_enabled)); } // Only set visibility if it's different from the current value. if ($enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } else if (!$enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; } if ($haschanged) { $new = implode(',', array_flip($plugins)); add_to_config_log('enrol_plugins_enabled', !$enabled, $enabled, $pluginname); set_config('enrol_plugins_enabled', $new); // Reset caches. \core_plugin_manager::reset_caches(); // Resets all enrol caches. $syscontext = \context_system::instance(); $syscontext->mark_dirty(); } return $haschanged; } public function get_settings_section_name() { if (file_exists($this->full_path('settings.php'))) { return 'enrolsettings' . $this->name; } else { return null; } } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $enrol = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null! if ($settings) { $ADMIN->add($parentnodename, $settings); } } public function is_uninstall_allowed() { if ($this->name === 'manual') { return false; } return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/settings.php', array('section'=>'manageenrols')); } /** * Return warning with number of activities and number of affected courses. * * @return string */ public function get_uninstall_extra_warning() { global $DB, $OUTPUT; $sql = "SELECT COUNT('x') FROM {user_enrolments} ue JOIN {enrol} e ON e.id = ue.enrolid WHERE e.enrol = :plugin"; $count = $DB->count_records_sql($sql, array('plugin'=>$this->name)); if (!$count) { return ''; } $migrateurl = new moodle_url('/admin/enrol.php', array('action'=>'migrate', 'enrol'=>$this->name, 'sesskey'=>sesskey())); $migrate = new \single_button($migrateurl, get_string('migratetomanual', 'core_enrol')); $button = $OUTPUT->render($migrate); $result = '

'.get_string('uninstallextraconfirmenrol', 'core_plugin', array('enrolments'=>$count)).'

'; $result .= $button; return $result; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $DB, $CFG; // NOTE: this is a bit brute force way - it will not trigger events and hooks properly. // Nuke all role assignments. role_unassign_all(array('component'=>'enrol_'.$this->name)); // Purge participants. $DB->delete_records_select('user_enrolments', "enrolid IN (SELECT id FROM {enrol} WHERE enrol = ?)", array($this->name)); // Purge enrol instances. $DB->delete_records('enrol', array('enrol'=>$this->name)); // Tweak enrol settings. if (!empty($CFG->enrol_plugins_enabled)) { $enabledenrols = explode(',', $CFG->enrol_plugins_enabled); $enabledenrols = array_unique($enabledenrols); $enabledenrols = array_flip($enabledenrols); unset($enabledenrols[$this->name]); $enabledenrols = array_flip($enabledenrols); if (is_array($enabledenrols)) { set_config('enrol_plugins_enabled', implode(',', $enabledenrols)); } } parent::uninstall_cleanup(); } } editor.php000064400000015762152267646420006574 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for HTML editors */ class editor extends base { #[\Override] public static function plugintype_supports_disabling(): bool { return true; } #[\Override] public static function get_enabled_plugins() { global $CFG; if (empty($CFG->texteditors)) { return [ 'tiny' => 'tiny', 'textarea' => 'textarea', ]; } $enabled = []; foreach (explode(',', $CFG->texteditors) as $editor) { $enabled[$editor] = $editor; } return $enabled; } #[\Override] public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; if (!empty($CFG->texteditors)) { $plugins = array_flip(explode(',', $CFG->texteditors)); } else { $plugins = []; } // Only set visibility if it's different from the current value. if ($enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } else if (!$enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; } // At least one editor must be active. if (empty($plugins)) { $plugins['textarea'] = 'textarea'; $haschanged = true; } if ($haschanged) { $new = implode(',', array_flip($plugins)); add_to_config_log('editor_visibility', !$enabled, $enabled, $pluginname); set_config('texteditors', $new); // Reset caches. \core_plugin_manager::reset_caches(); } return $haschanged; } #[\Override] public function get_settings_section_name() { return 'editorsettings' . $this->name; } #[\Override] public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $editor = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } #[\Override] public function is_uninstall_allowed() { if ($this->name === 'textarea') { return false; } else { return true; } } #[\Override] public function uninstall_cleanup(): void { global $DB; self::enable_plugin($this->name, 0); $DB->delete_records_select( 'user_preferences', "name = :name AND " . $DB->sql_compare_text('value') . " = " . $DB->sql_compare_text(':value'), [ 'name' => 'htmleditor', 'value' => $this->name, ], ); } #[\Override] public static function get_manage_url() { return new moodle_url('/admin/settings.php', array('section'=>'manageeditors')); } #[\Override] public static function plugintype_supports_ordering(): bool { return true; } #[\Override] public static function get_sorted_plugins(bool $enabledonly = false): ?array { global $CFG; $pluginmanager = \core_plugin_manager::instance(); $plugins = $pluginmanager->get_plugins_of_type('editor'); // The Editor list is stored in an ordered string. $activeeditors = explode(',', $CFG->texteditors); $sortedplugins = []; foreach ($activeeditors as $editor) { if (isset($plugins[$editor])) { $sortedplugins[$editor] = $plugins[$editor]; unset($plugins[$editor]); } } if ($enabledonly) { return $sortedplugins; } // Sort the rest of the plugins lexically. uasort($plugins, function ($a, $b) { return strnatcasecmp($a->name, $b->name); }); return array_merge( $sortedplugins, $plugins, ); } #[\Override] public static function change_plugin_order(string $pluginname, int $direction): bool { $activeeditors = array_keys(self::get_sorted_plugins(true)); $key = array_search($pluginname, $activeeditors); if ($key === false) { return false; } if ($direction === self::MOVE_DOWN) { // Move down the list. if ($key < (count($activeeditors) - 1)) { $fsave = $activeeditors[$key]; $activeeditors[$key] = $activeeditors[$key + 1]; $activeeditors[$key + 1] = $fsave; add_to_config_log('editor_position', $key, $key + 1, $pluginname); set_config('texteditors', implode(',', $activeeditors)); \core_plugin_manager::reset_caches(); return true; } } else if ($direction === self::MOVE_UP) { if ($key >= 1) { $fsave = $activeeditors[$key]; $activeeditors[$key] = $activeeditors[$key - 1]; $activeeditors[$key - 1] = $fsave; add_to_config_log('editor_position', $key, $key - 1, $pluginname); set_config('texteditors', implode(',', $activeeditors)); \core_plugin_manager::reset_caches(); return true; } } return false; } } mnetservice.php000064400000002403152267646420007616 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class representing an MNet service */ class mnetservice extends base { public function is_enabled() { global $CFG; if (empty($CFG->mnet_dispatcher_mode) || $CFG->mnet_dispatcher_mode !== 'strict') { return false; } else { return parent::is_enabled(); } } } mod.php000064400000023124152267646420006054 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for activity modules */ class mod extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB; return $DB->get_records_menu('modules', array('visible'=>1), 'name ASC', 'name, name AS val'); } public static function enable_plugin(string $pluginname, int $enabled): bool { global $DB; if (!$module = $DB->get_record('modules', ['name' => $pluginname])) { throw new \moodle_exception('moduledoesnotexist', 'error'); } $haschanged = false; // Only set visibility if it's different from the current value. if ($module->visible != $enabled) { if ($enabled && component_callback_exists("mod_{$pluginname}", 'pre_enable_plugin_actions')) { // This callback may be used to perform actions that must be completed prior to enabling a plugin. // Example of this may include: // - making a configuration change // - adding an alert // - checking a pre-requisite // // If the return value is falsy, then the change will be prevented. if (!component_callback("mod_{$pluginname}", 'pre_enable_plugin_actions')) { return false; } } // Set module visibility. $DB->set_field('modules', 'visible', $enabled, ['id' => $module->id]); $haschanged = true; if ($enabled) { // Revert the previous saved visible state for the course module. $DB->set_field('course_modules', 'visible', '1', ['visibleold' => 1, 'module' => $module->id]); // Increment course.cacherev for courses where we just made something visible. // This will force cache rebuilding on the next request. increment_revision_number('course', 'cacherev', "id IN (SELECT DISTINCT course FROM {course_modules} WHERE visible = 1 AND module = ?)", [$module->id] ); } else { // Remember the visibility status in visibleold and hide. $sql = "UPDATE {course_modules} SET visibleold = visible, visible = 0 WHERE module = ?"; $DB->execute($sql, [$module->id]); // Increment course.cacherev for courses where we just made something invisible. // This will force cache rebuilding on the next request. increment_revision_number('course', 'cacherev', 'id IN (SELECT DISTINCT course FROM {course_modules} WHERE visibleold = 1 AND module = ?)', [$module->id] ); } // Include this information into config changes table. add_to_config_log('mod_visibility', $module->visible, $enabled, $pluginname); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Magic method getter, redirects to read only values. * * For module plugins we pretend the object has 'visible' property for compatibility * with plugins developed for Moodle version below 2.4 * * @param string $name * @return mixed */ public function __get($name) { if ($name === 'visible') { debugging('This is now an instance of plugininfo_mod, please use $module->is_enabled() instead of $module->visible', DEBUG_DEVELOPER); return ($this->is_enabled() !== false); } return parent::__get($name); } public function init_display_name() { if (get_string_manager()->string_exists('pluginname', $this->component)) { $this->displayname = get_string('pluginname', $this->component); } else { $this->displayname = get_string('modulename', $this->component); } } public function get_settings_section_name() { return 'modsetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $module = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Activity modules that declare feature flag FEATURE_CAN_UNINSTALL as false cannot be uninstalled. */ public function is_uninstall_allowed() { return plugin_supports('mod', $this->name, FEATURE_CAN_UNINSTALL, true); } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/modules.php'); } /** * Return warning with number of activities and number of affected courses. * * @return string */ public function get_uninstall_extra_warning() { global $DB; if (!$module = $DB->get_record('modules', array('name'=>$this->name))) { return ''; } if (!$count = $DB->count_records('course_modules', array('module'=>$module->id))) { return ''; } $sql = "SELECT COUNT('x') FROM ( SELECT course FROM {course_modules} WHERE module = :mid GROUP BY course ) c"; $courses = $DB->count_records_sql($sql, array('mid'=>$module->id)); return '

'.get_string('uninstallextraconfirmmod', 'core_plugin', array('instances'=>$count, 'courses'=>$courses)).'

'; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $DB, $CFG; if (!$module = $DB->get_record('modules', array('name' => $this->name))) { parent::uninstall_cleanup(); return; } // Delete all the relevant instances from all course sections. if ($coursemods = $DB->get_records('course_modules', array('module' => $module->id))) { foreach ($coursemods as $coursemod) { // Do not verify results, there is not much we can do anyway. delete_mod_from_section($coursemod->id, $coursemod->section); } } // Increment course.cacherev for courses that used this module. // This will force cache rebuilding on the next request. increment_revision_number('course', 'cacherev', "id IN (SELECT DISTINCT course FROM {course_modules} WHERE module=?)", array($module->id)); // Delete all the course module records. $DB->delete_records('course_modules', array('module' => $module->id)); // Delete module contexts. if ($coursemods) { foreach ($coursemods as $coursemod) { \context_helper::delete_instance(CONTEXT_MODULE, $coursemod->id); } } // Delete the module entry itself. $DB->delete_records('modules', array('name' => $module->name)); // Cleanup the gradebook. require_once($CFG->libdir.'/gradelib.php'); grade_uninstalled_module($module->name); // Do not look for legacy $module->name . '_uninstall any more, // they should have migrated to db/uninstall.php by now. parent::uninstall_cleanup(); } } report.php000064400000002460152267646420006610 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class report extends base { public function is_uninstall_allowed() { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/reports.php'); } } antivirus.php000064400000012637152267646420007330 0ustar00. /** * Defines classes used for plugin info. * * @package core_antivirus * @copyright 2015 Ruslan Kabalin, Lancaster University. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for Antiviruses * * @package core_antivirus * @copyright 2015 Ruslan Kabalin, Lancaster University. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class antivirus extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $CFG; if (empty($CFG->antiviruses)) { return array(); } $enabled = array(); foreach (explode(',', $CFG->antiviruses) as $antivirus) { $enabled[$antivirus] = $antivirus; } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; $plugins = []; if (!empty($CFG->antiviruses)) { $plugins = array_flip(explode(',', $CFG->antiviruses)); } // Only set visibility if it's different from the current value. if ($enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } else if (!$enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; } if ($haschanged) { $new = implode(',', array_flip($plugins)); add_to_config_log('antiviruses', $CFG->antiviruses, $new, 'core'); set_config('antiviruses', $new); // Reset caches. \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Return the node name to use in admin settings menu for this plugin. * * @return string node name */ public function get_settings_section_name() { return 'antivirussettings' . $this->name; } /** * Loads plugin settings to the settings tree * * This function usually includes settings.php file in plugins folder. * Alternatively it can create a link to some settings page (instance of admin_externalpage) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $antivirus = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Clamav antivirus can not be uninstalled. */ public function is_uninstall_allowed() { if ($this->name === 'clamav') { return false; } else { return true; } } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/settings.php', array('section' => 'manageantiviruses')); } /** * Pre-uninstall hook. */ public function uninstall_cleanup() { global $CFG; if (!empty($CFG->antiviruses)) { $antiviruses = explode(',', $CFG->antiviruses); $antiviruses = array_unique($antiviruses); } else { $antiviruses = array(); } if (($key = array_search($this->name, $antiviruses)) !== false) { unset($antiviruses[$key]); set_config('antiviruses', implode(',', $antiviruses)); } parent::uninstall_cleanup(); } } message.php000064400000010452152267646420006721 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for messaging processors */ class message extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB; return $DB->get_records_menu('message_processors', array('enabled'=>1), 'name ASC', 'name, name AS val'); } public static function enable_plugin(string $pluginname, int $enabled): bool { global $DB; if (!$plugin = $DB->get_record('message_processors', ['name' => $pluginname])) { throw new \moodle_exception('invalidplugin', 'message', '', $pluginname); } $haschanged = false; // Only set visibility if it's different from the current value. if ($plugin->enabled != $enabled) { $haschanged = true; $processor = \core_message\api::get_processed_processor_object($plugin); // Include this information into config changes table. add_to_config_log($processor->name, $processor->enabled, $enabled, 'core'); // Save processor enabled/disabled status. \core_message\api::update_processor_status($processor, $enabled); } return $haschanged; } public function get_settings_section_name() { return 'messagesetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; $processors = get_message_processors(); if (isset($processors[$this->name])) { $processor = $processors[$this->name]; if ($processor->available && $processor->hassettings) { $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } } if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/message.php'); } public function is_uninstall_allowed() { return true; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $CFG; require_once($CFG->libdir.'/messagelib.php'); message_processor_uninstall($this->name); parent::uninstall_cleanup(); } } contenttype.php000064400000017256152267646420007662 0ustar00. /** * Defines classes used for plugin info. * * @package core_contentbank * @copyright 2020 Amaia Anabitarte * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; /** * Class for contentbank plugins * * @package core_contentbank * @copyright 2020 Amaia Anabitarte * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class contenttype extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Defines if there should be a way to uninstall the plugin via the administration UI. * * @return bool */ public function is_uninstall_allowed() { return true; } /** * Get the name for the settings section. * * @return string */ public function get_settings_section_name() { return 'contentbanksetting' . $this->name; } /** * Load the global settings for a particular contentbank plugin (if there are any) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $contenttype = $this; // Also to be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Return URL used for management of plugins of this type. * @return \moodle_url */ public static function get_manage_url() { return new \moodle_url('/admin/settings.php', array('section' => 'managecontentbanktypes')); } /** * Gathers and returns the information about all plugins of the given type * * @param string $type the name of the plugintype, eg. mod, auth or workshopform * @param string $typerootdir full path to the location of the plugin dir * @param string $typeclass the name of the actually called class * @param \core_plugin_manager $pluginman the plugin manager calling this method * @return array of plugintype classes, indexed by the plugin name */ public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) { global $CFG; $contents = parent::get_plugins($type, $typerootdir, $typeclass, $pluginman); if (!empty($CFG->contentbank_plugins_sortorder)) { $order = explode(',', $CFG->contentbank_plugins_sortorder); $order = array_merge(array_intersect($order, array_keys($contents)), array_diff(array_keys($contents), $order)); } else { $order = array_keys($contents); } $sortedcontents = array(); foreach ($order as $contentname) { $sortedcontents[$contentname] = $contents[$contentname]; } return $sortedcontents; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $CFG; $plugins = \core_plugin_manager::instance()->get_installed_plugins('contenttype'); if (!$plugins) { return array(); } $plugins = array_keys($plugins); // Order the plugins. if (!empty($CFG->contentbank_plugins_sortorder)) { $order = explode(',', $CFG->contentbank_plugins_sortorder); $order = array_merge(array_intersect($order, $plugins), array_diff($plugins, $order)); } else { $order = $plugins; } // Filter to return only enabled plugins. $enabled = array(); foreach ($order as $plugin) { $disabled = get_config('contentbank_' . $plugin, 'disabled'); if (empty($disabled)) { $enabled[$plugin] = $plugin; } } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugin = 'contentbank_' . $pluginname; $oldvalue = get_config($plugin, 'disabled'); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config('disabled', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('disabled', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('disabled', $oldvalue, $disabled, $plugin); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Optional extra warning before uninstallation adding number of existing contenttype contents. * * @return string */ public function get_uninstall_extra_warning() { global $DB; $contentcount = $DB->count_records('contentbank_content', ['contenttype' => "contenttype_$this->name"]); if (!$contentcount) { return ''; } $message = get_string('contenttypeuninstalling', 'core_admin', (object)['count' => $contentcount, 'type' => $this->displayname] ); return $message; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. */ public function uninstall_cleanup() { global $DB; $records = $DB->get_records('contentbank_content', ['contenttype' => 'contenttype_'.$this->name]); $contenttypename = 'contenttype_'.$this->name; $contenttypeclass = "\\$contenttypename\\contenttype"; foreach ($records as $record) { $context = \context::instance_by_id($record->contextid, MUST_EXIST); $contenttype = new $contenttypeclass($context); $contentclass = "\\$contenttypename\\content"; $content = new $contentclass($record); $contenttype->delete_content($content); } parent::uninstall_cleanup(); } } qbehaviour.php000064400000011326152267646420007443 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use core_plugin_manager; use moodle_url; /** * Class for question behaviours. */ class qbehaviour extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { $plugins = core_plugin_manager::instance()->get_installed_plugins('qbehaviour'); if (!$plugins) { return array(); } if ($disabled = get_config('question', 'disabledbehaviours')) { $disabled = explode(',', $disabled); } else { $disabled = array(); } $enabled = array(); foreach ($plugins as $plugin => $version) { if (in_array($plugin, $disabled)) { continue; } $enabled[$plugin] = $plugin; } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugins = []; $oldvalue = get_config('question', 'disabledbehaviours'); if (!empty($oldvalue)) { $plugins = array_flip(explode(',', $oldvalue)); } // Only set visibility if it's different from the current value. if ($enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; } else if (!$enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } if ($haschanged) { $new = implode(',', array_flip($plugins)); add_to_config_log('disabledbehaviours', $oldvalue, $new, 'question'); set_config('disabledbehaviours', $new, 'question'); // Reset caches. \core_plugin_manager::reset_caches(); } return $haschanged; } public function is_uninstall_allowed() { global $DB; if ($this->name === 'missing') { // qbehaviour_missing is used by the system. It cannot be uninstalled. return false; } return !$DB->record_exists('question_attempts', array('behaviour' => $this->name)); } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { if ($disabledbehaviours = get_config('question', 'disabledbehaviours')) { $disabledbehaviours = explode(',', $disabledbehaviours); $disabledbehaviours = array_unique($disabledbehaviours); } else { $disabledbehaviours = array(); } if (($key = array_search($this->name, $disabledbehaviours)) !== false) { unset($disabledbehaviours[$key]); set_config('disabledbehaviours', implode(',', $disabledbehaviours), 'question'); } if ($behaviourorder = get_config('question', 'behavioursortorder')) { $behaviourorder = explode(',', $behaviourorder); $behaviourorder = array_unique($behaviourorder); } else { $behaviourorder = array(); } if (($key = array_search($this->name, $behaviourorder)) !== false) { unset($behaviourorder[$key]); set_config('behavioursortorder', implode(',', $behaviourorder), 'question'); } parent::uninstall_cleanup(); } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/qbehaviours.php'); } } coursereport.php000064400000002122152267646420010024 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class coursereport extends base { public function is_uninstall_allowed() { return true; } } local.php000064400000004366152267646420006376 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url; defined('MOODLE_INTERNAL') || die(); /** * Class for local plugins */ class local extends base { public function is_uninstall_allowed() { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/localplugins.php'); } /** * Loads plugin settings to the settings tree * * This function usually includes settings.php file in plugins folder. * Alternatively it can create a link to some settings page (instance of admin_externalpage) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (file_exists($this->full_path('settings.php'))) { include($this->full_path('settings.php')); } } } cachelock.php000064400000002120152267646420007202 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class cachelock extends base { public function is_uninstall_allowed() { return false; } } general.php000064400000002160152267646420006707 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * General class for all plugin types that do not have their own class */ class general extends base { public function is_uninstall_allowed() { return false; } } calendartype.php000064400000005304152267646420007750 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use part_of_admin_tree, admin_settingpage; defined('MOODLE_INTERNAL') || die(); /** * Class for calendar type plugins. */ class calendartype extends base { public function is_uninstall_allowed() { // We can delete all calendar types, except Gregorian. Gregorian comes with core and was the calendar // type used before the calendar types were introduced as plugins in Moodle. If all calendar types were // deleted then Moodle would break completely wherever any dates are displayed. if ($this->name !== 'gregorian') { return true; } return false; } public function get_settings_section_name() { return 'calendartype_' . $this->name . '_settings'; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $qtype = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } $section = $this->get_settings_section_name(); $settings = null; $systemcontext = \context_system::instance(); if (($hassiteconfig) && file_exists($this->full_path('settings.php'))) { $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } } gradeimport.php000064400000002121152267646420007604 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class gradeimport extends base { public function is_uninstall_allowed() { return true; } } aiplacement.php000064400000014526152267646420007565 0ustar00. namespace core\plugininfo; use core_plugin_manager; use moodle_url; /** * AI placement plugin info class. * * @package core * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class aiplacement extends base { /** * Should there be a way to uninstall the plugin via the administration UI. * * By default, uninstallation is allowed. * * @return bool */ public function is_uninstall_allowed(): bool { return true; } /** * This plugintype supports its plugins being disabled. * * @return bool */ public static function plugintype_supports_disabling(): bool { return true; } /** * Returns the node name used in admin settings menu for this plugin settings. * * @return string node name. */ public function get_settings_section_name(): string { return $this->type . '_' . $this->name; } /** * Loads plugin settings to the settings tree. * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ public function load_settings( \part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig, ): void { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); // Load the specific settings. $settings = new \core_ai\admin\admin_settingspage_provider( name: $section, visiblename: $this->displayname, req_capability: 'moodle/site:config', hidden: true, ); if (file_exists($this->full_path('settings.php'))) { include($this->full_path('settings.php')); // This may also set $settings to null. // Show the save changes button between the specific settings and the actions table. $settings->add(new \admin_setting_savebutton("{$section}/savebutton")); } // Load the actions table. if (file_exists($this->full_path('setting_actions.php'))) { include($this->full_path('setting_actions.php')); // This may also set $settings to null. } else { $settings->add(new \admin_setting_heading("{$section}/generals", new \lang_string('placementactionsettings', 'core_ai'), new \lang_string('placementactionsettings_desc', 'core_ai'))); // Load the setting table of actions that this provider supports. $settings->add(new \core_ai\admin\admin_setting_action_manager( $section, \core_ai\table\aiplacement_action_management_table::class, 'manageaiplacements', new \lang_string('manageaiproviders', 'core_ai'), )); } if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Return URL used for management of plugins of this type. * * @return moodle_url */ public static function get_manage_url(): moodle_url { return new moodle_url('/admin/settings.php', [ 'section' => 'aiplacement', ]); } /** * Enable or disable a plugin. * When possible, the change will be stored into the config_log table, to let admins check when/who has modified it. * * @param string $pluginname The plugin name to enable/disable. * @param int $enabled Whether the pluginname should be enabled (1) or not (0). * @return bool Whether $pluginname has been updated or not. */ public static function enable_plugin(string $pluginname, int $enabled): bool { $plugin = "aiplacement_$pluginname"; $oldvalue = self::is_plugin_enabled($pluginname); $newvalue = (bool)$enabled; if ($oldvalue !== $newvalue) { if ($newvalue) { set_config('enabled', $enabled, $plugin); } else { unset_config('enabled', $plugin); } add_to_config_log('enabled', $oldvalue, $newvalue, $plugin); core_plugin_manager::reset_caches(); return true; } return false; } /** * Finds all enabled plugins, the result may include missing plugins. * * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown. */ public static function get_enabled_plugins(): ?array { $pluginmanager = core_plugin_manager::instance(); $plugins = $pluginmanager->get_installed_plugins('aiplacement'); if (!$plugins) { return []; } $plugins = array_keys($plugins); // Filter to return only enabled plugins. $enabled = []; foreach ($plugins as $plugin) { if (self::is_plugin_enabled($plugin)) { $enabled[$plugin] = $plugin; } } return $enabled; } /** * Check if a provider plugin is enabled in config. * * @param string $plugin The plugin to check. * @return bool Return true if enabled. */ public static function is_plugin_enabled(string $plugin): bool { $config = get_config("aiplacement_$plugin", 'enabled'); return $config == 1; } } qformat.php000064400000002110152267646420006736 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for question types */ class qformat extends base { public function is_uninstall_allowed() { return true; } } cachestore.php000064400000002443152267646420007416 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for cache store plugins */ class cachestore extends base { public function is_uninstall_allowed() { $instance = \cache_config::instance(); foreach ($instance->get_all_stores() as $store) { if ($store['plugin'] == $this->name) { return false; } } return true; } } mlbackend.php000064400000005575152267646420007227 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2017 David Monllao * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for analytics machine learning backend plugins * * @package core * @copyright 2017 David Monllao * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class mlbackend extends base { /** * Is uninstall allowed or not. * * @return bool */ public function is_uninstall_allowed() { return !\core_analytics\manager::is_mlbackend_used('mlbackend_' . $this->name); } /** * Returns the node name used in admin settings menu for this plugin settings (if applicable). * * @return null|string node name or null if plugin does not create settings node (default) */ public function get_settings_section_name() { return 'mlbackendsettings' . $this->name; } /** * Load the global settings for a particular availability plugin (if there are any) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig * @return void */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } } theme.php000064400000005607152267646420006405 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url; defined('MOODLE_INTERNAL') || die(); /** * Class for themes */ class theme extends base { public function is_uninstall_allowed() { global $CFG; if ($this->name === 'boost') { // All of these are protected for now. return false; } if (!empty($CFG->theme) and $CFG->theme === $this->name) { // Cannot uninstall default theme. return false; } return true; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $DB; $DB->set_field('course', 'theme', '', array('theme'=>$this->name)); $DB->set_field('course_categories', 'theme', '', array('theme'=>$this->name)); $DB->set_field('user', 'theme', '', array('theme'=>$this->name)); $DB->set_field('mnet_host', 'theme', '', array('theme'=>$this->name)); if (get_config('core', 'thememobile') === $this->name) { unset_config('thememobile'); } if (get_config('core', 'themetablet') === $this->name) { unset_config('themetablet'); } if (get_config('core', 'themelegacy') === $this->name) { unset_config('themelegacy'); } $themelist = get_config('core', 'themelist'); if (!empty($themelist)) { $themes = explode(',', $themelist); $key = array_search($this->name, $themes); if ($key !== false) { unset($themes[$key]); set_config('themelist', implode(',', $themes)); } } parent::uninstall_cleanup(); } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/themeselector.php'); } } smsgateway.php000064400000005705152267646420007466 0ustar00. namespace core\plugininfo; use core_plugin_manager; use moodle_url; /** * SMS gateway subplugin info class. * * @package core * @copyright 2024 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class smsgateway extends base { #[\Override] public function is_uninstall_allowed(): bool { return true; } #[\Override] public function get_settings_section_name(): string { return "smsgateway{$this->name}"; } #[\Override] public function load_settings( \part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig, ): void { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } #[\Override] public static function get_manage_url(): moodle_url { return new moodle_url('/sms/sms_gateways.php'); } #[\Override] public static function get_enabled_plugins(): ?array { $pluginmanager = core_plugin_manager::instance(); $plugins = $pluginmanager->get_installed_plugins('smsgateway'); if (!$plugins) { return []; } $plugins = array_keys($plugins); // Filter to return only enabled plugins. $enabled = []; foreach ($plugins as $plugin) { $disabled = get_config('smsgateway_' . $plugin, 'disabled'); if (empty($disabled)) { $enabled[$plugin] = $plugin; } } return $enabled; } } auth.php000064400000012760152267646420006242 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_settingpage; use moodle_url; use part_of_admin_tree; /** * Class for authentication plugins */ class auth extends base { public static function plugintype_supports_disabling(): bool { return true; } public function is_uninstall_allowed() { global $DB; if (in_array($this->name, array('manual', 'nologin', 'webservice', 'mnet'))) { return false; } return !$DB->record_exists('user', array('auth'=>$this->name)); } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $CFG; // These two are always enabled and can't be disabled. $enabled = array('nologin'=>'nologin', 'manual'=>'manual'); foreach (explode(',', $CFG->auth) as $auth) { $enabled[$auth] = $auth; } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { global $CFG; $haschanged = false; $plugins = []; if (!empty($CFG->auth)) { $plugins = array_flip(explode(',', $CFG->auth)); } // Only set visibility if it's different from the current value. if ($enabled && !array_key_exists($pluginname, $plugins)) { $plugins[$pluginname] = $pluginname; $haschanged = true; } else if (!$enabled && array_key_exists($pluginname, $plugins)) { unset($plugins[$pluginname]); $haschanged = true; if ($pluginname == $CFG->registerauth) { set_config('registerauth', ''); } } if ($haschanged) { $new = implode(',', array_flip($plugins)); add_to_config_log('auth', $CFG->auth, $new, 'core'); set_config('auth', $new); \core\session\manager::destroy_by_auth_plugin($pluginname); // Remove stale sessions. \core\session\manager::gc(); // Reset caches. \core_plugin_manager::reset_caches(); } return $haschanged; } public function get_settings_section_name() { return 'authsetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $auth = $this; // Also to be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } $section = $this->get_settings_section_name(); $settings = null; if (file_exists($this->full_path('settings.php'))) { // TODO: finish implementation of common settings - locking, etc. $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. } if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/settings.php', array('section'=>'manageauths')); } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $CFG; if (!empty($CFG->auth)) { $auths = explode(',', $CFG->auth); $auths = array_unique($auths); } else { $auths = array(); } if (($key = array_search($this->name, $auths)) !== false) { unset($auths[$key]); $value = implode(',', $auths); add_to_config_log('auth', $CFG->auth, $value, 'core'); set_config('auth', $value); \core\session\manager::destroy_by_auth_plugin($this->name); } if (!empty($CFG->registerauth) and $CFG->registerauth === $this->name) { unset_config('registerauth'); } parent::uninstall_cleanup(); } } format.php000064400000016007152267646420006567 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url, part_of_admin_tree, admin_settingpage, core_plugin_manager; defined('MOODLE_INTERNAL') || die(); /** * Class for course formats */ class format extends base { /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB; $plugins = core_plugin_manager::instance()->get_installed_plugins('format'); if (!$plugins) { return array(); } $installed = array(); foreach ($plugins as $plugin => $version) { $installed[] = 'format_'.$plugin; } list($installed, $params) = $DB->get_in_or_equal($installed, SQL_PARAMS_NAMED); $disabled = $DB->get_records_select('config_plugins', "plugin $installed AND name = 'disabled'", $params, 'plugin ASC'); foreach ($disabled as $conf) { if (empty($conf->value)) { continue; } list($type, $name) = explode('_', $conf->plugin, 2); unset($plugins[$name]); } $enabled = array(); foreach ($plugins as $plugin => $version) { $enabled[$plugin] = $plugin; } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugin = 'format_' . $pluginname; $oldvalue = get_config($plugin, 'disabled'); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { if (get_config('moodlecourse', 'format') === $pluginname) { // The default course format can't be disabled. throw new \moodle_exception('cannotdisableformat', 'error'); } set_config('disabled', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('disabled', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('disabled', $oldvalue, $disabled, $plugin); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Gathers and returns the information about all plugins of the given type * * @param string $type the name of the plugintype, eg. mod, auth or workshopform * @param string $typerootdir full path to the location of the plugin dir * @param string $typeclass the name of the actually called class * @param core_plugin_manager $pluginman the plugin manager calling this method * @return array of plugintype classes, indexed by the plugin name */ public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) { global $CFG; require_once($CFG->dirroot.'/course/lib.php'); $formats = parent::get_plugins($type, $typerootdir, $typeclass, $pluginman); $order = get_sorted_course_formats(); $sortedformats = array(); foreach ($order as $formatname) { $sortedformats[$formatname] = $formats[$formatname]; } return $sortedformats; } public function get_settings_section_name() { return 'formatsetting' . $this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig or !file_exists($this->full_path('settings.php'))) { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($this->full_path('settings.php')); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } public function is_uninstall_allowed() { if ($this->name !== get_config('moodlecourse', 'format') && $this->name !== 'site') { return true; } else { return false; } } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/settings.php', array('section'=>'manageformats')); } public function get_uninstall_extra_warning() { global $DB; $coursecount = $DB->count_records('course', array('format' => $this->name)); if (!$coursecount) { return ''; } $defaultformat = $this->pluginman->plugin_name('format_'.get_config('moodlecourse', 'format')); $message = get_string( 'formatuninstallwithcourses', 'core_admin', (object)array('count' => $coursecount, 'format' => $this->displayname, 'defaultformat' => $defaultformat)); return $message; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { global $DB; if (($defaultformat = get_config('moodlecourse', 'format')) && $defaultformat !== $this->name) { $courses = $DB->get_records('course', array('format' => $this->name), 'id'); $data = (object)array('id' => null, 'format' => $defaultformat); foreach ($courses as $record) { $data->id = $record->id; update_course($data); } } $DB->delete_records('course_format_options', array('format' => $this->name)); parent::uninstall_cleanup(); } } tool.php000064400000005075152267646420006257 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class tool extends base { public function is_uninstall_allowed() { // Some mobile settings are used by the core. if ($this->name === 'mobile') { return false; } else { return true; } } /** * Tools cannot be disabled. * * @return boolean */ public function is_enabled() { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/settings.php', ['section' => 'toolsmanagement']); } /** * Loads plugin settings to the settings tree * * This function usually includes settings.php file in plugins folder. * Alternatively it can create a link to some settings page (instance of admin_externalpage) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (file_exists($this->full_path('settings.php'))) { include($this->full_path('settings.php')); } } } gradingform.php000064400000004451152267646420007576 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Class for admin tool plugins */ class gradingform extends base { public function is_uninstall_allowed() { return true; } /** * Pre-uninstall hook. * This is intended for disabling of plugin, some DB table purging, etc. */ public function uninstall_cleanup() { global $DB; // Find all definitions and templates. $definitions = $DB->get_fieldset_select('grading_definitions', 'id', 'method = ?', [$this->name]); if ($definitions) { // Delete instances and definitions. Deleting instance will not delete grades because they were // already pushed to the module and gradebook. list($sqld, $paramsd) = $DB->get_in_or_equal($definitions); $DB->delete_records_select('grading_instances', 'definitionid ' . $sqld, $paramsd); $DB->delete_records_select('grading_definitions', 'id ' . $sqld, $paramsd); } // Delete templates for this grading method. $DB->delete_records_select('grading_areas', 'component = ? AND activemethod = ?', array('core_grading', $this->name)); // Update the remaining grading areas to use simple grading method instead of this grading method. $DB->execute('UPDATE {grading_areas} SET activemethod = NULL WHERE activemethod = ?', [$this->name]); parent::uninstall_cleanup(); } } dataformat.php000064400000016130152267646420007416 0ustar00. /** * Defines classes used for plugin info. * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @copyright 2016 Brendan Heywood (brendan@catalyst-au.net) * @package core */ namespace core\plugininfo; use admin_settingpage; use core_plugin_manager; use moodle_url; use part_of_admin_tree; /** * Class for dataformats * * @package core * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @copyright 2016 Brendan Heywood (brendan@catalyst-au.net) */ class dataformat extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Display name */ public function init_display_name() { if (!get_string_manager()->string_exists('dataformat', $this->component)) { $this->displayname = '[dataformat,' . $this->component . ']'; } else { $this->displayname = get_string('dataformat', $this->component); } } /** * Given a list of dataformat types, return them sorted according to site configuration (if set) * * @param string[] $formats List of formats, ['csv', 'pdf', etc] * @return string[] List of formats according to configured sort, ['csv', 'odf', etc] */ private static function get_plugins_sortorder(array $formats): array { global $CFG; if (!empty($CFG->dataformat_plugins_sortorder)) { $order = explode(',', $CFG->dataformat_plugins_sortorder); $order = array_merge(array_intersect($order, $formats), array_diff($formats, $order)); } else { $order = $formats; } return $order; } /** * Gathers and returns the information about all plugins of the given type * * @param string $type the name of the plugintype, eg. mod, auth or workshopform * @param string $typerootdir full path to the location of the plugin dir * @param string $typeclass the name of the actually called class * @param core_plugin_manager $pluginman the plugin manager calling this method * @return array of plugintype classes, indexed by the plugin name */ public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) { $formats = parent::get_plugins($type, $typerootdir, $typeclass, $pluginman); $order = static::get_plugins_sortorder(array_keys($formats)); $sortedformats = array(); foreach ($order as $formatname) { $sortedformats[$formatname] = $formats[$formatname]; } return $sortedformats; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { $plugins = core_plugin_manager::instance()->get_installed_plugins('dataformat'); if (!$plugins) { return array(); } $order = static::get_plugins_sortorder(array_keys($plugins)); $enabled = array(); foreach ($order as $formatname) { $disabled = get_config('dataformat_' . $formatname, 'disabled'); if (empty($disabled)) { $enabled[$formatname] = $formatname; } } return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { $haschanged = false; $plugin = 'dataformat_' . $pluginname; $oldvalue = get_config($plugin, 'disabled'); $disabled = !$enabled; // Only set value if there is no config setting or if the value is different from the previous one. if ($oldvalue == false && $disabled) { set_config('disabled', $disabled, $plugin); $haschanged = true; } else if ($oldvalue != false && !$disabled) { unset_config('disabled', $plugin); $haschanged = true; } if ($haschanged) { add_to_config_log('disabled', $oldvalue, $disabled, $plugin); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Returns the node name used in admin settings menu for this plugin settings (if applicable) * * @return null|string node name or null if plugin does not create settings node (default) */ public function get_settings_section_name() { return 'dataformatsetting' . $this->name; } /** * Loads plugin settings to the settings tree * * This function usually includes settings.php file in plugins folder. * Alternatively it can create a link to some settings page (instance of admin_externalpage) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $dataformat = $this; // Also can be used inside settings.php. if (!$this->is_installed_and_upgraded()) { return; } if (!$hassiteconfig) { return; } if (file_exists($this->full_path('settings.php'))) { $fullpath = $this->full_path('settings.php'); } else if (file_exists($this->full_path('dataformatsettings.php'))) { $fullpath = $this->full_path('dataformatsettings.php'); } else { return; } $section = $this->get_settings_section_name(); $settings = new admin_settingpage($section, $this->displayname, 'moodle/site:config', $this->is_enabled() === false); include($fullpath); // This may also set $settings to null. if ($settings) { $ADMIN->add($parentnodename, $settings); } } /** * dataformats can be uninstalled * * @return bool */ public function is_uninstall_allowed() { return true; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/settings.php?section=managedataformats'); } } base.php000064400000064231152267646420006213 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use coding_exception; use core_component; use core_plugin_manager; use moodle_url; /** * Base class providing access to the information about a plugin */ abstract class base { /** @var string the plugintype name, eg. mod, auth or workshopform */ public $type; /** @var string full path to the location of all the plugins of this type */ public $typerootdir; /** @var string the plugin name, eg. assignment, ldap */ public $name; /** @var string the localized plugin name */ public $displayname; /** @var string the plugin source, one of core_plugin_manager::PLUGIN_SOURCE_xxx constants */ public $source; /** @var string fullpath to the location of this plugin */ public $rootdir; /** @var int|string the version of the plugin's source code */ public $versiondisk; /** @var int|string the version of the installed plugin */ public $versiondb; /** @var int|float|string required version of Moodle core */ public $versionrequires; /** @var array explicitly supported branches of Moodle core */ public $pluginsupported; /** @var int first incompatible branch of Moodle core */ public $pluginincompatible; /** @var mixed human-readable release information */ public $release; /** @var array other plugins that this one depends on, lazy-loaded by {@link get_other_required_plugins()} */ public $dependencies; /** @var int number of instances of the plugin - not supported yet */ public $instances; /** @var int order of the plugin among other plugins of the same type - not supported yet */ public $sortorder; /** @var core_plugin_manager the plugin manager this plugin info is part of */ public $pluginman; /** @var array|null array of {@link \core\update\info} for this plugin */ protected $availableupdates; /** @var int Move a plugin up in the plugin order */ public const MOVE_UP = -1; /** @var int Move a plugin down in the plugin order */ public const MOVE_DOWN = 1; /** @var array hold $plugin->supported in version.php */ public $supported; /** @var int hold $plugin->incompatible in version.php */ public $incompatible; /** @var string Name of the plugin */ public $component = ''; /** @var bool whether the plugin is that of a phase 1 deprecated type or subplugin type. */ public $deprecatedtype = false; /** @var bool whether the plugin is that of a phase 2 deprecated (deleted) type or subplugin type. */ public $deletedtype = false; /** * Whether this plugintype supports its plugins being disabled. * * @return bool */ public static function plugintype_supports_disabling(): bool { return false; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { return null; } /** * Enable or disable a plugin. * When possible, the change will be stored into the config_log table, to let admins check when/who has modified it. * * @param string $pluginname The plugin name to enable/disable. * @param int $enabled Whether the pluginname should be enabled (1) or not (0). This is an integer because some plugins, such * as filters or repositories, might support more statuses than just enabled/disabled. * * @return bool Whether $pluginname has been updated or not. */ public static function enable_plugin(string $pluginname, int $enabled): bool { return false; } /** * Returns current status for a pluginname. * * @param string $pluginname The plugin name to check. * @return int The current status (enabled, disabled...) of $pluginname. */ public static function get_enabled_plugin(string $pluginname): int { $enabledplugins = static::get_enabled_plugins(); $value = $enabledplugins && array_key_exists($pluginname, $enabledplugins); return (int) $value; } /** * Gathers and returns the information about all plugins of the given type, * either on disk or previously installed. * * This is supposed to be used exclusively by the plugin manager when it is * populating its tree of plugins. * * @param string $type the name of the plugintype, eg. mod, auth or workshopform * @param string $typerootdir full path to the location of the plugin dir * @param string $typeclass the name of the actually called class * @param core_plugin_manager $pluginman the plugin manager calling this method * @return array of plugintype classes, indexed by the plugin name */ public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) { // Get the information about plugins at the disk, including deprecated plugins. $plugins = core_component::get_all_plugins_list($type); // Also included deleted plugins. $return = array(); foreach ($plugins as $pluginname => $pluginrootdir) { $return[$pluginname] = self::make_plugin_instance($type, $typerootdir, $pluginname, $pluginrootdir, $typeclass, $pluginman); } // Fetch missing incorrectly uninstalled plugins, including deprecated plugins which are not included above. $plugins = $pluginman->get_installed_plugins($type); foreach ($plugins as $name => $version) { if (isset($return[$name])) { continue; } $plugin = new $typeclass(); $plugin->type = $type; $plugin->typerootdir = $typerootdir; $plugin->name = $name; $plugin->component = $plugin->type.'_'.$plugin->name; $plugin->rootdir = null; $plugin->displayname = $name; $plugin->versiondb = $version; $plugin->pluginman = $pluginman; $plugin->init_is_standard(); $plugin->init_is_deprecated(); $return[$name] = $plugin; } return $return; } /** * Makes a new instance of the plugininfo class * * @param string $type the plugin type, eg. 'mod' * @param string $typerootdir full path to the location of all the plugins of this type * @param string $name the plugin name, eg. 'workshop' * @param string $namerootdir full path to the location of the plugin * @param string $typeclass the name of class that holds the info about the plugin * @param core_plugin_manager $pluginman the plugin manager of the new instance * @return base the instance of $typeclass */ protected static function make_plugin_instance($type, $typerootdir, $name, $namerootdir, $typeclass, $pluginman) { $plugin = new $typeclass(); $plugin->type = $type; $plugin->typerootdir = $typerootdir; $plugin->name = $name; $plugin->rootdir = $namerootdir; $plugin->pluginman = $pluginman; $plugin->component = $plugin->type.'_'.$plugin->name; $plugin->init_display_name(); $plugin->load_disk_version(); $plugin->load_db_version(); $plugin->init_is_standard(); $plugin->init_is_deprecated(); return $plugin; } /** * Is this plugin already installed and updated? * @return bool true if plugin installed and upgraded. */ public function is_installed_and_upgraded() { if (!$this->rootdir) { return false; } if ($this->versiondb === null and $this->versiondisk === null) { // There is no version.php or version info inside it. return false; } return ((float)$this->versiondb === (float)$this->versiondisk); } /** * Sets {@link $displayname} property to a localized name of the plugin */ public function init_display_name() { if (!get_string_manager()->string_exists('pluginname', $this->component)) { $this->displayname = '[pluginname,' . $this->component . ']'; } else { $this->displayname = get_string('pluginname', $this->component); } } /** * Magic method getter, redirects to read only values. * * @param string $name * @return mixed */ public function __get($name) { switch ($name) { case 'component': return $this->type . '_' . $this->name; default: debugging('Invalid plugin property accessed! '.$name); return null; } } /** * Return the full path name of a file within the plugin. * * No check is made to see if the file exists. * * @param string $relativepath e.g. 'version.php'. * @return string e.g. $CFG->dirroot . '/mod/quiz/version.php'. */ public function full_path($relativepath) { if (empty($this->rootdir)) { return ''; } return $this->rootdir . '/' . $relativepath; } /** * Sets {@link $versiondisk} property to a numerical value representing the * version of the plugin's source code. * * If the value is null after calling this method, either the plugin * does not use versioning (typically does not have any database * data) or is missing from disk. */ public function load_disk_version() { // Note: this includes deprecated plugins. $versions = $this->pluginman->get_present_plugins($this->type); $this->versiondisk = null; $this->versionrequires = null; $this->pluginsupported = null; $this->pluginincompatible = null; $this->dependencies = array(); if (!isset($versions[$this->name])) { return; } $plugin = $versions[$this->name]; if (isset($plugin->version)) { $this->versiondisk = $plugin->version; } if (isset($plugin->requires)) { $this->versionrequires = $plugin->requires; } if (isset($plugin->release)) { $this->release = $plugin->release; } if (isset($plugin->dependencies)) { $this->dependencies = $plugin->dependencies; } // Check that supports and incompatible are wellformed, exception otherwise. if (isset($plugin->supported)) { // Checks for structure of supported. $isint = (is_int($plugin->supported[0]) && is_int($plugin->supported[1])); $isrange = ($plugin->supported[0] <= $plugin->supported[1] && count($plugin->supported) == 2); if (is_array($plugin->supported) && $isint && $isrange) { $this->pluginsupported = $plugin->supported; } else { throw new coding_exception('Incorrect syntax in plugin supported declaration in '."$this->name"); } } if (isset($plugin->incompatible) && $plugin->incompatible !== null) { if (((is_string($plugin->incompatible) && ctype_digit($plugin->incompatible)) || is_int($plugin->incompatible)) && (int) $plugin->incompatible > 0) { $this->pluginincompatible = intval($plugin->incompatible); } else { throw new coding_exception('Incorrect syntax in plugin incompatible declaration in '."$this->name"); } } } /** * Get the list of other plugins that this plugin requires to be installed. * * @return array with keys the frankenstyle plugin name, and values either * a version string (like '2011101700') or the constant ANY_VERSION. */ public function get_other_required_plugins() { if (is_null($this->dependencies)) { $this->load_disk_version(); } return $this->dependencies; } /** * Is this is a subplugin? * * @return boolean */ public function is_subplugin() { return ($this->get_parent_plugin() !== false); } /** * If I am a subplugin, return the name of my parent plugin. * * @return string|bool false if not a subplugin, name of the parent otherwise */ public function get_parent_plugin() { return $this->pluginman->get_parent_of_subplugin($this->type, true); } /** * Sets {@link $versiondb} property to a numerical value representing the * currently installed version of the plugin. * * If the value is null after calling this method, either the plugin * does not use versioning (typically does not have any database * data) or has not been installed yet. */ public function load_db_version() { $versions = $this->pluginman->get_installed_plugins($this->type); if (isset($versions[$this->name])) { $this->versiondb = $versions[$this->name]; } else { $this->versiondb = null; } } /** * Sets {@link $source} property to one of core_plugin_manager::PLUGIN_SOURCE_xxx * constants. * * If the property's value is null after calling this method, then * the type of the plugin has not been recognized and you should throw * an exception. */ public function init_is_standard() { $pluginman = $this->pluginman; $standard = $pluginman::standard_plugins_list($this->type); if ($standard !== false) { $standard = array_flip($standard); if (isset($standard[$this->name])) { $this->source = core_plugin_manager::PLUGIN_SOURCE_STANDARD; } else if (!is_null($this->versiondb) and is_null($this->versiondisk) and $pluginman::is_deleted_standard_plugin($this->type, $this->name)) { $this->source = core_plugin_manager::PLUGIN_SOURCE_STANDARD; // To be deleted. } else { $this->source = core_plugin_manager::PLUGIN_SOURCE_EXTENSION; } } } /** * Init some instance props denoting the deprecation state of the plugin. * * Sets {@see $deprecatedtype} property, indicating whether the plugintype is phase 1 deprecated. * Sets {@see $deletedtype} property, indicating whether the plugintype is phase 2 deprecated. * Sets {@see $displayname} property to the plugin name phase 2 deprecated plugins since lang string support has then ended. * * @return void */ final public function init_is_deprecated(): void { $this->deprecatedtype = \core_component::is_deprecated_plugin_type($this->type); $this->deletedtype = \core_component::is_deleted_plugin_type($this->type); $this->displayname = $this->deletedtype ? $this->name : $this->displayname; } /** * Returns true if the plugin is shipped with the official distribution * of the current Moodle version, false otherwise. * * @return bool */ public function is_standard() { return $this->source === core_plugin_manager::PLUGIN_SOURCE_STANDARD; } /** * Returns true if the the given Moodle version is enough to run this plugin * * @param string|int|double $moodleversion * @return bool */ public function is_core_dependency_satisfied($moodleversion) { if (empty($this->versionrequires)) { return true; } else { return (double)$this->versionrequires <= (double)$moodleversion; } } /** * Returns true if the the given moodle branch is not stated incompatible with the plugin * * @param int $branch the moodle branch number * @return bool true if not incompatible with moodle branch */ public function is_core_compatible_satisfied(int $branch): bool { if (!empty($this->pluginincompatible) && ($branch >= $this->pluginincompatible)) { return false; } else { return true; } } /** * Returns the status of the plugin * * @return string one of core_plugin_manager::PLUGIN_STATUS_xxx constants */ public function get_status() { $pluginman = $this->pluginman; if (is_null($this->versiondb) and is_null($this->versiondisk)) { return core_plugin_manager::PLUGIN_STATUS_NODB; } else if (is_null($this->versiondb) and !is_null($this->versiondisk)) { return core_plugin_manager::PLUGIN_STATUS_NEW; } else if (!is_null($this->versiondb) and is_null($this->versiondisk)) { if ($pluginman::is_deleted_standard_plugin($this->type, $this->name)) { return core_plugin_manager::PLUGIN_STATUS_DELETE; } else { return core_plugin_manager::PLUGIN_STATUS_MISSING; } } else if ((float)$this->versiondb === (float)$this->versiondisk) { // Note: the float comparison should work fine here // because there are no arithmetic operations with the numbers. return core_plugin_manager::PLUGIN_STATUS_UPTODATE; } else if ($this->versiondb < $this->versiondisk) { return core_plugin_manager::PLUGIN_STATUS_UPGRADE; } else if ($this->versiondb > $this->versiondisk) { return core_plugin_manager::PLUGIN_STATUS_DOWNGRADE; } else { // $version = pi(); and similar funny jokes - hopefully Donald E. Knuth will never contribute to Moodle ;-) throw new coding_exception('Unable to determine plugin state, check the plugin versions'); } } /** * Returns the information about plugin availability * * True means that the plugin is enabled. False means that the plugin is * disabled. Null means that the information is not available, or the * plugin does not support configurable availability or the availability * can not be changed. * * @return null|bool */ public function is_enabled() { if (!$this->rootdir) { // Plugin missing. return false; } $enabled = $this->pluginman->get_enabled_plugins($this->type); if (!is_array($enabled)) { return null; } return isset($enabled[$this->name]); } /** * Return whether this plugin is deprecated (i.e. the plugin type to which it belongs is deprecated). * * @return bool */ public function is_deprecated(): bool { return $this->deprecatedtype; } /** * Return whether this plugin is deleted (i.e. the plugin type to which it belongs is deleted). * * @return bool */ public function is_deleted(): bool { return $this->deletedtype; } /** * If there are updates for this plugin available, returns them. * * Returns array of {@link \core\update\info} objects, if some update * is available. Returns null if there is no update available or if the update * availability is unknown. * * Populates the property {@link $availableupdates} on first call (lazy * loading). * * @return array|null */ public function available_updates() { if ($this->availableupdates === null) { // Lazy load the information about available updates. $this->availableupdates = $this->pluginman->load_available_updates_for_plugin($this->component); } if (empty($this->availableupdates) or !is_array($this->availableupdates)) { $this->availableupdates = array(); return null; } $updates = array(); foreach ($this->availableupdates as $availableupdate) { if ($availableupdate->version > $this->versiondisk) { $updates[] = $availableupdate; } } if (empty($updates)) { return null; } return $updates; } /** * Returns the node name used in admin settings menu for this plugin settings (if applicable) * * @return null|string node name or null if plugin does not create settings node (default) */ public function get_settings_section_name() { return null; } /** * Returns the URL of the plugin settings screen * * Null value means that the plugin either does not have the settings screen * or its location is not available via this library. * * @return null|moodle_url */ public function get_settings_url(): ?moodle_url { $section = $this->get_settings_section_name(); if ($section === null) { return null; } $settings = admin_get_root()->locate($section); if ($settings && $settings instanceof \core_admin\local\settings\linkable_settings_page) { return $settings->get_settings_page_url(); } return null; } /** * Loads plugin settings to the settings tree * * This function usually includes settings.php file in plugins folder. * Alternatively it can create a link to some settings page (instance of admin_externalpage) * * @param \part_of_admin_tree $adminroot * @param string $parentnodename * @param bool $hassiteconfig whether the current user has moodle/site:config capability */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { } /** * Should there be a way to uninstall the plugin via the administration UI. * * By default uninstallation is not allowed, plugin developers must enable it explicitly! * * @return bool */ public function is_uninstall_allowed() { return false; } /** * Optional extra warning before uninstallation, for example number of uses in courses. * * @return string */ public function get_uninstall_extra_warning() { return ''; } /** * Pre-uninstall hook. * * This is intended for disabling of plugin, some DB table purging, etc. * * NOTE: to be called from uninstall_plugin() only. * @private */ public function uninstall_cleanup() { // Override when extending class, // do not forget to call parent::pre_uninstall_cleanup() at the end. } /** * Returns relative directory of the plugin with heading '/' * * @return string */ public function get_dir() { global $CFG; if (!isset($this->rootdir)) { return ''; } return substr($this->rootdir, strlen($CFG->dirroot)); } /** * Hook method to implement certain steps when uninstalling the plugin. * * This hook is called by {@link core_plugin_manager::uninstall_plugin()} so * it is basically usable only for those plugin types that use the default * uninstall tool provided by {@link self::get_default_uninstall_url()}. * * @param \progress_trace $progress traces the process * @return bool true on success, false on failure */ public function uninstall(\progress_trace $progress) { return true; } /** * Where should we return after plugin of this type is uninstalled? * @param string $return * @return moodle_url */ public function get_return_url_after_uninstall($return) { if ($return === 'manage') { if ($url = $this->get_manage_url()) { return $url; } } return new moodle_url('/admin/plugins.php#plugin_type_cell_'.$this->type); } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return null; } /** * Returns URL to a script that handles common plugin uninstall procedure. * * This URL is intended for all plugin uninstallations. * * @param string $return either 'overview' or 'manage' * @return moodle_url */ final public function get_default_uninstall_url($return = 'overview') { return new moodle_url('/admin/plugins.php', array( 'uninstall' => $this->component, 'confirm' => 0, 'return' => $return, )); } /** * Whether this plugintype supports ordering of plugins using native functionality. * * Please note that plugintypes which pre-date this native functionality may still support ordering * but will not use the built-in functionality. * * @return bool */ public static function plugintype_supports_ordering(): bool { return false; } /** * Finds all enabled plugins, the result may include missing plugins. * * @param bool $enabledonly Show all plugins, or only those which are enabled * @return array|null of sorted plugins $pluginname => $pluginname, null means unknown */ public static function get_sorted_plugins(bool $enabledonly = false): ?array { return null; } /** * Change the order of the plugin relative to other plugins in the plugintype. * * When possible, the change will be stored into the config_log table, to let admins check when/who has modified it. * * @param string $pluginname The plugin name to enable/disable. * @param int $direction The direction to move the plugin. Negative numbers mean up, Positive mean down. * @return bool Whether $pluginname has been updated or not. */ public static function change_plugin_order(string $pluginname, int $direction): bool { return false; } } repository.php000064400000015506152267646420007521 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use admin_externalpage; use moodle_url; use part_of_admin_tree; defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/repository/lib.php'); /** * Class for repositories */ class repository extends base { /** @var int Repository state, when it's enabled and visible. */ public const REPOSITORY_ON = 1; /** @var int Repository state, when it's enabled but hidden. */ public const REPOSITORY_OFF = 0; /** @var int Repository state, when it's disabled. */ public const REPOSITORY_DISABLED = -1; public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB; return $DB->get_records_menu('repository', null, 'type ASC', 'type, type AS val'); } /** * Returns current status for a pluginname. * * Repositories needs to be calculated in a different way than the default method in the base class because they need to take * into account the value of the visible column too. * * @param string $pluginname The plugin name to check. * @return int The current status (enabled, disabled...) of $pluginname. */ public static function get_enabled_plugin(string $pluginname): int { global $DB; $repository = $DB->get_record('repository', ['type' => $pluginname]); if ($repository) { switch ($repository->visible) { case 1: $value = self::REPOSITORY_ON; break; default: $value = self::REPOSITORY_OFF; } } else { $value = self::REPOSITORY_DISABLED; } return $value; } /** * Enable or disable a plugin. * When possible, the change will be stored into the config_log table, to let admins check when/who has modified it. * * @param string $pluginname The plugin name to enable/disable. * @param int $enabled Whether the pluginname should be enabled and visible (1), enabled but hidden (0) or disabled (-1). * * @return bool Whether $pluginname has been updated or not. */ public static function enable_plugin(string $pluginname, int $enabled): bool { global $DB; $haschanged = false; // Enabled repositories exist in 'repository' table. // Visible = REPOSITORY_ON ==> Enabled and visible. // Visible = REPOSITORY_OFF ==> Enabled but hidden. // Disabled repositories don't exist in 'repository' table. if ($plugin = $DB->get_record('repository', ['type' => $pluginname])) { // The plugin is enabled. $oldvalue = $plugin->visible; $repositorytype = \repository::get_type_by_typename($pluginname); if ($enabled == self::REPOSITORY_DISABLED) { $haschanged = $repositorytype->delete(); $enabled = ''; } else if ($oldvalue != $enabled) { $haschanged = $repositorytype->update_visibility($enabled); } } else { // Not all repositories have their own 'repository' record created. Disabled repositories don't have one. // Make changes only when we want to enable repository. $oldvalue = ''; if ($enabled == self::REPOSITORY_ON || $enabled == self::REPOSITORY_OFF) { $type = new \repository_type($pluginname, [], $enabled); if (!$haschanged = $type->create()) { throw new \moodle_exception('invalidplugin', 'repository', '', $pluginname); } } } if ($haschanged) { // Include this information into config changes table. add_to_config_log('repository_visibility', $oldvalue, $enabled, $pluginname); \core_plugin_manager::reset_caches(); } return $haschanged; } public function get_settings_section_name() { return 'repositorysettings'.$this->name; } public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { if (!$this->is_installed_and_upgraded()) { return; } if ($hassiteconfig && $this->is_enabled()) { // Completely no access to repository setting when it is not enabled. $sectionname = $this->get_settings_section_name(); $settings = new admin_externalpage($sectionname, $this->displayname, new moodle_url('/admin/repository.php', ['action' => 'edit', 'repos' => $this->name]), 'moodle/site:config', false); $adminroot->add($parentnodename, $settings); } } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/repository.php'); } /** * Defines if there should be a way to uninstall the plugin via the administration UI. * @return boolean */ public function is_uninstall_allowed() { if ($this->name === 'upload' || $this->name === 'coursefiles' || $this->name === 'user' || $this->name === 'recent') { return false; } else { return true; } } /** * Pre-uninstall hook. * This is intended for disabling of plugin, some DB table purging, etc. * Converts all linked files to standard files when repository is removed * and cleans up all records in the DB for that repository. */ public function uninstall_cleanup() { global $CFG; require_once($CFG->dirroot.'/repository/lib.php'); $repo = \repository::get_type_by_typename($this->name); if ($repo) { $repo->delete(true); } parent::uninstall_cleanup(); } } portfolio.php000064400000011112152267646420007304 0ustar00. /** * Defines classes used for plugin info. * * @package core * @copyright 2011 David Mudrak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; use moodle_url; /** * Class for portfolios */ class portfolio extends base { public static function plugintype_supports_disabling(): bool { return true; } /** * Finds all enabled plugins, the result may include missing plugins. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { global $DB; $enabled = array(); $rs = $DB->get_recordset('portfolio_instance', array('visible'=>1), 'plugin ASC', 'plugin'); foreach ($rs as $repository) { $enabled[$repository->plugin] = $repository->plugin; } $rs->close(); return $enabled; } public static function enable_plugin(string $pluginname, int $enabled): bool { global $DB, $CFG; require_once($CFG->libdir . '/portfoliolib.php'); $haschanged = false; $oldvalue = null; $data = ['visible' => $enabled]; if ($plugin = $DB->get_record('portfolio_instance', ['plugin' => $pluginname])) { $instance = portfolio_instance($plugin->id); $oldvalue = $instance->get('visible'); if (empty($oldvalue) && $instance->instance_sanity_check()) { throw new \moodle_exception('cannotsetvisible', 'portfolio'); } // Only set visibility if it's different from the current value. if ($oldvalue != $enabled) { $haschanged = true; $instance->set('visible', $enabled); $instance->save(); } } else { $haschanged = true; portfolio_static_function($pluginname, 'create_instance', $pluginname, $pluginname, $data); } if ($haschanged) { // Include this information into config changes table. add_to_config_log('portfolio_visibility', $oldvalue, $enabled, $pluginname); \core_plugin_manager::reset_caches(); } return $haschanged; } /** * Return URL used for management of plugins of this type. * @return moodle_url */ public static function get_manage_url() { return new moodle_url('/admin/portfolio.php'); } /** * Defines if there should be a way to uninstall the plugin via the administration UI. * @return boolean */ public function is_uninstall_allowed() { return true; } /** * Pre-uninstall hook. * This is intended for disabling of plugin, some DB table purging, etc. */ public function uninstall_cleanup() { global $DB; // Get all instances of this portfolio. $count = $DB->count_records('portfolio_instance', array('plugin' => $this->name)); if ($count > 0) { // This portfolio is in use, get the it's ID. $rec = $DB->get_record('portfolio_instance', array('plugin' => $this->name)); // Remove all records from portfolio_instance_config. $DB->delete_records('portfolio_instance_config', array('instance' => $rec->id)); // Remove all records from portfolio_instance_user. $DB->delete_records('portfolio_instance_user', array('instance' => $rec->id)); // Remove all records from portfolio_log. $DB->delete_records('portfolio_log', array('portfolio' => $rec->id)); // Remove all records from portfolio_tempdata. $DB->delete_records('portfolio_tempdata', array('instance' => $rec->id)); // Remove the record from the portfolio_instance table. $DB->delete_records('portfolio_instance', array('id' => $rec->id)); } parent::uninstall_cleanup(); } } orphaned.php000064400000005507152267646420007102 0ustar00. /** * Defines class used for orphaned subplugins. * * @package core * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core\plugininfo; defined('MOODLE_INTERNAL') || die(); /** * Orphaned subplugins class. */ class orphaned extends base { public function is_uninstall_allowed() { return true; } /** * We do not know if orphaned subplugins are enabled. * @return bool */ public function is_enabled() { return null; } /** * No lang strings are present. */ public function init_display_name() { $this->displayname = $this->component; } /** * Oprhaned plugins can not be enabled. * @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown */ public static function get_enabled_plugins() { return null; } /** * Gathers and returns the information about all plugins of the given type, * either on disk or previously installed. * * @param string $type the name of the plugintype, eg. mod, auth or workshopform * @param string $typerootdir full path to the location of the plugin dir * @param string $typeclass the name of the actually called class * @param \core_plugin_manager $pluginman the plugin manager calling this method * @return array of plugintype classes, indexed by the plugin name */ public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) { $return = array(); $plugins = $pluginman->get_installed_plugins($type); foreach ($plugins as $name => $version) { $plugin = new $typeclass(); $plugin->type = $type; $plugin->typerootdir = $typerootdir; $plugin->name = $name; $plugin->rootdir = null; $plugin->displayname = $name; $plugin->versiondb = $version; $plugin->pluginman = $pluginman; $plugin->init_is_standard(); $return[$name] = $plugin; } return $return; } } repository_test.php000064400000011132152270020020010517 0ustar00. /** * Unit tests for repository plugin manager class. * * @package core * @copyright 2021 Amaia Anabitarte * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ declare(strict_types = 1); namespace core\plugininfo; /** * Tests of the repository plugin manager. */ final class repository_test extends \advanced_testcase { /** * Test the enable_plugin function to check that it enables and disables repository plugins properly. * * @dataProvider enable_plugin_provider * @param string $pluginname Repository to enable. * @param int|null $initialvisibility Initialvalue for visibility field. * @param int $newstatus New enabled status for the plugin. * @param bool $result Wether the repository is part of enabled plugin list or not. */ public function test_enable_plugin(string $pluginname, ?int $initialvisibility, int $newstatus, bool $result): void { global $DB; $this->resetAfterTest(); $DB->set_field('repository', 'visible', $initialvisibility, ['type' => $pluginname]); repository::enable_plugin($pluginname, $newstatus); $enableplugins = repository::get_enabled_plugins(); $this->assertSame($result, in_array($pluginname, $enableplugins)); } /** * Data provider for the load_disk_version tests for testing with invalid supported fields. * * @return array */ public static function enable_plugin_provider(): array { return [ 'Disable an enable and visible repository' => [ 'pluginname' => 'contentbank', 'initialvisibility' => repository::REPOSITORY_ON, 'newstatus' => repository::REPOSITORY_DISABLED, 'result' => false, ], 'Disable an enable and hidden repository' => [ 'pluginname' => 'contentbank', 'initialvisibility' => repository::REPOSITORY_OFF, 'newstatus' => repository::REPOSITORY_DISABLED, 'result' => false, ], 'Disable a disabled repository' => [ 'pluginname' => 'coursefiles', 'initialvisibility' => null, 'newstatus' => repository::REPOSITORY_DISABLED, 'result' => false ], 'Enable an enable and visible repository' => [ 'pluginname' => 'contentbank', 'initialvisibility' => repository::REPOSITORY_ON, 'newstatus' => repository::REPOSITORY_ON, 'result' => true, ], 'Enable an enable and hidden repository' => [ 'pluginname' => 'contentbank', 'initialvisibility' => repository::REPOSITORY_OFF, 'newstatus' => repository::REPOSITORY_ON, 'result' => true, ], 'Enable a disabled repository' => [ 'pluginname' => 'coursefiles', 'initialvisibility' => null, 'newstatus' => repository::REPOSITORY_ON, 'result' => true, ], 'Enable but hide an enable and visible repository' => [ 'pluginname' => 'contentbank', 'initialvisibility' => repository::REPOSITORY_ON, 'newstatus' => repository::REPOSITORY_OFF, 'result' => true, ], 'Enable but hide an enable and hidden repository' => [ 'pluginname' => 'contentbank', 'initialvisibility' => repository::REPOSITORY_OFF, 'newstatus' => repository::REPOSITORY_OFF, 'result' => true, ], 'Enable but hide a disabled repository' => [ 'pluginname' => 'coursefiles', 'initialvisibility' => null, 'newstatus' => repository::REPOSITORY_OFF, 'result' => true, ], ]; } } block_test.php000064400000005375152270020020007406 0ustar00. declare(strict_types=1); namespace core\plugininfo; use advanced_testcase; /** * Unit tests for the mod plugininfo class * * @package core * @covers \core\plugininfo\block * @copyright 2023 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class block_test extends advanced_testcase { /** * Test the get_enabled_plugins method. */ public function test_get_enabled_plugins(): void { $this->resetAfterTest(); // The bigbluebuttonbn plugin is disabled by default. // Check all default formats. $plugins = block::get_enabled_plugins(); $this->assertArrayHasKey('badges', $plugins); $this->assertArrayHasKey('timeline', $plugins); $this->assertArrayHasKey('admin_bookmarks', $plugins); // Disable a plugin. block::enable_plugin('timeline', 0); $plugins = block::get_enabled_plugins(); $this->assertArrayHasKey('badges', $plugins); $this->assertArrayNotHasKey('timeline', $plugins); $this->assertArrayHasKey('admin_bookmarks', $plugins); } /** * Test the is_uninstall_allowed method. * * @dataProvider is_uninstall_allowed_provider * @param string $plugin * @param bool $expected */ public function test_is_uninstall_allowed( string $plugin, bool $expected, ): void { $pluginmanager = \core_plugin_manager::instance(); $plugininfo = $pluginmanager->get_plugin_info("block_{$plugin}"); $this->assertEquals($expected, $plugininfo->is_uninstall_allowed()); } public static function is_uninstall_allowed_provider(): array { $plugins = block::get_enabled_plugins(); return array_map(function ($plugin) { $expected = true; if ($plugin === 'settings' || $plugin === 'navigation') { $expected = false; } return [ 'plugin' => $plugin, 'expected' => $expected, ]; }, array_keys($plugins)); } } dataformat_test.php000064400000005717152270020020010436 0ustar00. declare(strict_types=1); namespace core\plugininfo; use advanced_testcase; /** * Unit tests for the dataformat plugininfo class * * @package core * @covers \core\plugininfo\dataformat * @copyright 2022 Paul Holden * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class dataformat_test extends advanced_testcase { /** * Helper method, to allow easy filtering of default formats in order to perform assertions without any third-party * formats affecting expected results * * @param string $format * @return bool */ private function filter_default_plugins(string $format): bool { $defaultformats = ['csv', 'excel', 'html', 'json', 'ods', 'pdf']; return in_array($format, $defaultformats); } /** * Test getting enabled plugins */ public function test_get_enabled_plugins(): void { $this->resetAfterTest(); // Check all default formats. $plugins = array_filter(dataformat::get_enabled_plugins(), [$this, 'filter_default_plugins']); $this->assertEquals([ 'csv' => 'csv', 'excel' => 'excel', 'html' => 'html', 'json' => 'json', 'ods' => 'ods', 'pdf' => 'pdf', ], $plugins); // Disable excel & html. dataformat::enable_plugin('excel', 0); dataformat::enable_plugin('html', 0); $plugins = array_filter(dataformat::get_enabled_plugins(), [$this, 'filter_default_plugins']); $this->assertEquals([ 'csv' => 'csv', 'json' => 'json', 'ods' => 'ods', 'pdf' => 'pdf', ], $plugins); } /** * Test getting enabled plugins obeys configured sortorder */ public function test_get_enabled_plugins_sorted(): void { $this->resetAfterTest(); set_config('dataformat_plugins_sortorder', 'csv,pdf,excel,json,html,ods'); $plugins = array_filter(dataformat::get_enabled_plugins(), [$this, 'filter_default_plugins']); $this->assertEquals([ 'csv' => 'csv', 'pdf' => 'pdf', 'excel' => 'excel', 'json' => 'json', 'html' => 'html', 'ods' => 'ods', ], $plugins); } } media_test.php000064400000014157152270020020007371 0ustar00. declare(strict_types=1); namespace core\plugininfo; use advanced_testcase; /** * Unit tests for the media plugininfo class. * * @package core * @covers \core\plugininfo\media * @copyright 2023 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class media_test extends advanced_testcase { /** * Test the get_enabled_plugins method. */ public function test_get_enabled_plugins(): void { $this->resetAfterTest(); $plugins = media::get_enabled_plugins(); $this->assertArrayHasKey('videojs', $plugins); $this->assertArrayHasKey('youtube', $plugins); // Disable a plugin. media::enable_plugin('youtube', 0); $plugins = media::get_enabled_plugins(); $this->assertArrayNotHasKey('youtube', $plugins); $this->assertArrayHasKey('videojs', $plugins); } /** * Test the is_uninstall_allowed method. * * @dataProvider is_uninstall_allowed_provider * @param string $plugin */ public function test_is_uninstall_allowed( string $plugin, ): void { $pluginmanager = \core_plugin_manager::instance(); $plugininfo = $pluginmanager->get_plugin_info("media_{$plugin}"); $this->assertTrue($plugininfo->is_uninstall_allowed()); } /** * Data provider for the is_uninstall_allowed tests. * * @return array */ public static function is_uninstall_allowed_provider(): array { $plugins = media::get_enabled_plugins(); return array_map(function ($plugin) { return [ 'plugin' => $plugin, ]; }, array_keys($plugins)); } /** * Ensure that change_plugin_order() changes the order of the plugins. * * @dataProvider change_plugin_order_provider * @param string $initialorder * @param string $pluginname * @param int $direction * @param array $expected */ public function test_change_plugin_order( array $initialorder, string $pluginname, int $direction, array $expected, ): void { $this->resetAfterTest(true); media::set_enabled_plugins($initialorder); media::change_plugin_order($pluginname, $direction); $this->assertSame( $expected, array_keys(media::get_sorted_plugins()), ); } public static function change_plugin_order_provider(): array { $pluginmanager = \core_plugin_manager::instance(); $allplugins = $pluginmanager->get_plugins_of_type('media'); \core_collator::asort_objects_by_method($allplugins, 'get_rank', \core_collator::SORT_NUMERIC); $getorder = function (array $plugins) use ($allplugins) { return array_merge( $plugins, array_diff(array_reverse(array_keys($allplugins)), array_values($plugins)), ); }; return [ 'Top item down one' => [ 'initialorder' => [ 'videojs', 'html5audio', 'html5video', 'youtube', ], 'pluginname' => 'videojs', 'direction' => base::MOVE_DOWN, 'expected' => $getorder([ 'html5audio', 'videojs', 'html5video', 'youtube', ]), ], 'Bottom item down one' => [ 'initialorder' => [ 'videojs', 'html5audio', 'html5video', 'youtube', ], 'pluginname' => 'youtube', 'direction' => base::MOVE_DOWN, 'expected' => $getorder([ 'videojs', 'html5audio', 'html5video', 'youtube', ]), ], 'Top item up' => [ 'initialorder' => [ 'videojs', 'html5audio', 'html5video', 'youtube', ], 'pluginname' => 'videojs', 'direction' => base::MOVE_UP, 'expected' => $getorder([ 'videojs', 'html5audio', 'html5video', 'youtube', ]), ], 'Disabled plugin' => [ 'initialorder' => [ 'videojs', 'html5audio', 'html5video', ], 'pluginname' => 'youtube', 'direction' => base::MOVE_UP, 'expected' => $getorder([ 'videojs', 'html5audio', 'html5video', ]), ], 'Non-existent plugin' => [ 'initialorder' => [ 'videojs', 'html5audio', 'html5video', 'youtube', ], 'pluginname' => 'moodletube', 'direction' => base::MOVE_UP, 'expected' => $getorder([ 'videojs', 'html5audio', 'html5video', 'youtube', ]), ], ]; } } editor_test.php000064400000022136152270020020007574 0ustar00. declare(strict_types=1); namespace core\plugininfo; use advanced_testcase; /** * Unit tests for the editor plugininfo class * * @package core * @covers \core\plugininfo\editor * @copyright 2023 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class editor_test extends advanced_testcase { /** * Test that editor::get_enabled_plugins() returns the correct list of enabled plugins. */ public function test_get_enabled_plugins(): void { $this->resetAfterTest(); // All plugins are enabled by default. $plugins = editor::get_enabled_plugins(); $this->assertArrayHasKey('tiny', $plugins); $this->assertArrayHasKey('textarea', $plugins); // Disable tiny. editor::enable_plugin('textarea', 0); $plugins = editor::get_enabled_plugins(); $this->assertArrayHasKey('tiny', $plugins); $this->assertArrayNotHasKey('textarea', $plugins); } /** * Test that editor::enable_plugin set to disable all plugins will leave the textarea enabled. */ public function test_enable_plugin_all(): void { $this->resetAfterTest(); // All plugins are enabled by default. $plugins = editor::get_enabled_plugins(); foreach ($plugins as $plugin) { editor::enable_plugin($plugin, 0); } $plugins = editor::get_enabled_plugins(); $this->assertCount(1, $plugins); $this->assertArrayHasKey('textarea', $plugins); } /** * Ensure that plugintype_supports_ordering() returns true. */ public function test_plugintype_supports_ordering(): void { $this->assertTrue(editor::plugintype_supports_ordering()); } /** * Ensure that get_sorted_plugins() returns the correct list of plugins. * * @dataProvider get_sorted_plugins_provider * @param string $texteditors The $CFG->texteditors value to use as a base * @param bool $enabledonly * @param array $expected The expected order */ public function test_get_sorted_plugins( string $texteditors, bool $enabledonly, array $expected, ): void { global $CFG; $this->resetAfterTest(true); $CFG->texteditors = $texteditors; $this->assertSame( $expected, array_keys(editor::get_sorted_plugins($enabledonly)), ); } /** * Data provider for the get_sorted_plugins tests. * * @return array */ public static function get_sorted_plugins_provider(): array { $pluginmanager = \core_plugin_manager::instance(); $allplugins = array_keys($pluginmanager->get_plugins_of_type('editor')); // Disabled editors are listed alphabetically at the end. $getorder = function (array $plugins) use ($allplugins) { return array_merge( $plugins, array_diff($allplugins, array_values($plugins)), ); }; return [ [ 'texteditors' => 'textarea,tiny', 'enabledonly' => true, 'expected' => [ 'textarea', 'tiny', ], ], [ 'texteditors' => 'tiny,textarea', 'enabledonly' => true, 'expected' => [ 'tiny', 'textarea', ], ], [ 'texteditors' => 'tiny', 'enabledonly' => true, 'expected' => [ 'tiny', ], ], 'Phantom values are removed from the list' => [ 'texteditors' => 'fakeeditor', 'enabledonly' => true, 'expected' => [ ], ], [ 'texteditors' => 'textarea,tiny', 'enabledonly' => false, 'expected' => $getorder([ 'textarea', 'tiny', ]), ], [ 'texteditors' => 'tiny', 'enabledonly' => false, 'expected' => $getorder([ 'tiny', ]), ], ]; } /** * Ensure that change_plugin_order() changes the order of the plugins. * * @dataProvider change_plugin_order_provider * @param string $texteditors * @param string $pluginname * @param int $direction * @param array $expected * @param string $newtexteditors */ public function test_change_plugin_order( string $texteditors, string $pluginname, int $direction, array $expected, string $newtexteditors, ): void { global $CFG; $this->resetAfterTest(true); $CFG->texteditors = $texteditors; editor::change_plugin_order($pluginname, $direction); $this->assertSame( $expected, array_keys(editor::get_sorted_plugins()), ); $this->assertSame($newtexteditors, $CFG->texteditors); } /** * Data provider fro the change_plugin_order() tests. * * @return array */ public static function change_plugin_order_provider(): array { $pluginmanager = \core_plugin_manager::instance(); $allplugins = array_keys($pluginmanager->get_plugins_of_type('editor')); // Disabled editors are listed alphabetically at the end. $getorder = function (array $plugins) use ($allplugins) { return array_merge( $plugins, array_diff($allplugins, array_values($plugins)), ); }; return [ [ 'texteditors' => 'textarea,tiny', 'pluginname' => 'textarea', 'direction' => base::MOVE_DOWN, 'expected' => $getorder([ 'tiny', 'textarea', ]), 'newtexteditors' => 'tiny,textarea', ], [ 'texteditors' => 'textarea,tiny', 'pluginname' => 'tiny', 'direction' => base::MOVE_DOWN, // Tiny is already at the bottom of the enabled plugins. 'expected' => $getorder([ 'textarea', 'tiny', ]), 'newtexteditors' => 'textarea,tiny', ], [ 'texteditors' => 'textarea,tiny', 'pluginname' => 'atto', 'direction' => base::MOVE_DOWN, // Atto is not available. No change expected. 'expected' => $getorder([ 'textarea', 'tiny', ]), 'newtexteditors' => 'textarea,tiny', ], [ 'texteditors' => 'textarea,tiny', 'pluginname' => 'tiny', 'direction' => base::MOVE_UP, 'expected' => $getorder([ 'tiny', 'textarea', ]), 'newtexteditors' => 'tiny,textarea', ], [ 'texteditors' => 'textarea,tiny', 'pluginname' => 'tiny', 'direction' => base::MOVE_UP, // Tiny is already at the top of the enabled plugins. 'expected' => $getorder([ 'tiny', 'textarea', ]), 'newtexteditors' => 'tiny,textarea', ], [ 'texteditors' => 'textarea,tiny', 'pluginname' => 'atto', 'direction' => base::MOVE_UP, // Atto is not available. No change expected. 'expected' => $getorder([ 'textarea', 'tiny', ]), 'newtexteditors' => 'textarea,tiny', ], [ 'texteditors' => 'textarea,tiny', 'pluginname' => 'fakeeditor', 'direction' => base::MOVE_UP, // The fakeeditor plugin does not exist. No change expected. 'expected' => $getorder([ 'textarea', 'tiny', ]), 'newtexteditors' => 'textarea,tiny', ], ]; } } base_test.php000064400000026226152270020020007224 0ustar00. declare(strict_types=1); namespace core\plugininfo; use testable_core_plugin_manager; use testable_plugininfo_base; /** * Unit tests for plugin base class. * * @package core * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core\plugininfo\base */ final class base_test extends \advanced_testcase { /** * Setup to ensure that fixtures are loaded. */ public static function setUpBeforeClass(): void { global $CFG; require_once($CFG->dirroot.'/lib/tests/fixtures/testable_plugin_manager.php'); require_once($CFG->dirroot.'/lib/tests/fixtures/testable_plugininfo_base.php'); parent::setUpBeforeClass(); } /** * Tear down the testable plugin manager singleton between tests. */ public function tearDown(): void { // The caches of the testable singleton must be reset explicitly. It is // safer to kill the whole testable singleton at the end of every test. testable_core_plugin_manager::reset_caches(); parent::tearDown(); } /** * Test the load_disk_version function to check that it handles a variety of invalid supported fields. * * @dataProvider load_disk_version_invalid_supported_version_provider * @param array|null $supported Supported versions to inject * @param string|int|null $incompatible Incompatible version to inject. * @param int $version Version to test */ public function test_load_disk_version_invalid_supported_version($supported, $incompatible, $version): void { $pluginman = testable_core_plugin_manager::instance(); // Prepare a fake plugininfo instance. $plugininfo = new testable_plugininfo_base(); $plugininfo->type = 'fake'; $plugininfo->typerootdir = '/dev/null'; $plugininfo->name = 'example'; $plugininfo->rootdir = '/dev/null/fake'; $plugininfo->pluginman = $pluginman; $plugininfo->versiondisk = 2015060600; $plugininfo->supported = $supported; $plugininfo->incompatible = $incompatible; $pluginman->add_fake_plugin_info($plugininfo); $this->expectException(\coding_exception::class); $this->expectExceptionMessage('Incorrect syntax in plugin supported declaration in example'); $plugininfo->load_disk_version(); } /** * Data provider for the load_disk_version tests for testing with invalid supported fields. * * @return array */ public static function load_disk_version_invalid_supported_version_provider(): array { return [ 'Invalid supported range.' => [ 'supported' => [31, 29], 'incompatible' => null, 'version' => 32, ], 'Explicit list, low' => [ 'supported' => [29, 30, 31, 32], 'incompatible' => null, 'version' => 28, ], 'Explicit list, high' => [ 'supported' => [29, 30, 31, 32], 'incompatible' => null, 'version' => 33, ], 'Explicit list, in list' => [ 'supported' => [29, 30, 31, 32, 33], 'incompatible' => null, 'version' => 31, ], 'Explicit list, missing value, unsupported' => [ 'supported' => [29, 30, 32], 'incompatible' => null, 'version' => 31, ], 'Explicit list, missing value, supported' => [ 'supported' => [29, 30, 32], 'incompatible' => null, 'version' => 30, ], ]; } /** * Test the load_disk_version function to check that it handles a variety of invalid incompatible fields. * * @dataProvider load_disk_version_invalid_incompatible_version_provider * @param mixed $incompatible */ public function test_load_disk_version_invalid_incompatible_version($incompatible): void { $pluginman = testable_core_plugin_manager::instance(); // Prepare a fake plugininfo instance. $plugininfo = new testable_plugininfo_base(); $plugininfo->type = 'fake'; $plugininfo->typerootdir = '/dev/null'; $plugininfo->name = 'example'; $plugininfo->rootdir = '/dev/null/fake'; $plugininfo->pluginman = $pluginman; $plugininfo->versiondisk = 2015060600; $plugininfo->incompatible = $incompatible; $pluginman->add_fake_plugin_info($plugininfo); $this->expectException(\coding_exception::class); $this->expectExceptionMessage('Incorrect syntax in plugin incompatible declaration in example'); $plugininfo->load_disk_version(); } /** * Data provider for the load_disk_version tests for testing with invalid incompatible fields. * * @return array */ public static function load_disk_version_invalid_incompatible_version_provider(): array { return [ [[38]], [['38']], [3.8], ['3.8'], [''], ['somestring'], ]; } /** * Test the load_disk_version function to check that it handles a range of correct supported and incompatible field * definitions. * * @dataProvider load_disk_version_branch_supports_provider * @param array|null $supported Supported versions to inject * @param string|int|null $incompatible Incompatible version to inject. * @param int $version Version to test */ public function test_load_disk_version_branch_supports($supported, $incompatible, $version): void { $pluginman = testable_core_plugin_manager::instance(); // Prepare a fake plugininfo instance. $plugininfo = new testable_plugininfo_base(); $plugininfo->type = 'fake'; $plugininfo->typerootdir = '/dev/null'; $plugininfo->name = 'example'; $plugininfo->rootdir = '/dev/null/fake'; $plugininfo->pluginman = $pluginman; $plugininfo->versiondisk = 2015060600; $plugininfo->supported = $supported; $plugininfo->incompatible = $incompatible; $pluginman->add_fake_plugin_info($plugininfo); $plugininfo->load_disk_version(); $this->assertEquals($supported, $plugininfo->supported); $this->assertEquals($incompatible, $plugininfo->incompatible); } /** * Test cases for tests of load_disk_version for testing the supported/incompatible fields. * * @return array */ public static function load_disk_version_branch_supports_provider(): array { return [ 'Range, branch in support, lowest' => [ 'supported' => [29, 31], 'incompatible' => null, 'version' => 29, ], 'Range, branch in support, mid' => [ 'supported' => [29, 31], 'incompatible' => null, 'version' => 30, ], 'Range, branch in support, highest' => [ 'supported' => [29, 31], 'incompatible' => null, 'version' => 31, ], 'Range, branch not in support, high' => [ 'supported' => [29, 31], 'incompatible' => null, 'version' => 32, ], 'Range, branch not in support, low' => [ 'supported' => [29, 31], 'incompatible' => null, 'version' => 28, ], 'Range, incompatible, high.' => [ 'supported' => [29, 31], 'incompatible' => 32, 'version' => 33, ], 'Range, incompatible, low.' => [ 'supported' => [29, 31], 'incompatible' => 32, 'version' => 31, ], 'Range, incompatible, equal.' => [ 'supported' => [29, 31], 'incompatible' => 32, 'version' => 32, ], 'No supports' => [ 'supported' => null, 'incompatible' => null, 'version' => 32, ], 'No supports, but incompatible, older' => [ 'supported' => null, 'incompatible' => 30, 'version' => 32, ], 'No supports, but incompatible, equal' => [ 'supported' => null, 'incompatible' => 32, 'version' => 32, ], 'No supports, but incompatible, newer' => [ 'supported' => null, 'incompatible' => 34, 'version' => 32, ], 'String incompatible' => [ 'supported' => null, 'incompatible' => '34', 'version' => 32, ], 'Empty incompatible' => [ 'supported' => null, 'incompatible' => null, 'version' => 32, ], ]; } /** * Ensure that plugintype_supports_ordering() returns true. */ public function test_plugintype_supports_ordering(): void { $this->assertFalse(base::plugintype_supports_ordering()); } /** * Ensure that the base implementation is used for plugins not supporting ordering. * * @dataProvider plugins_not_supporting_ordering * @param string $plugin * @coversNothing * * Note: This test cannot declare coverage because it covers the various plugin implementations. */ public function test_get_sorted_plugins( string $plugin, ): void { [$plugintype, $pluginname] = explode('_', $plugin, 2); $classname = \core_plugin_manager::resolve_plugininfo_class($plugintype); $this->assertFalse($classname::plugintype_supports_ordering()); $this->assertNull($classname::get_sorted_plugins()); $this->assertNull($classname::get_sorted_plugins(true)); $this->assertNull($classname::get_sorted_plugins(false)); $this->assertFalse($classname::change_plugin_order($pluginname, base::MOVE_UP)); $this->assertFalse($classname::change_plugin_order($pluginname, base::MOVE_DOWN)); } /** * Data provider for plugins_not_supporting_ordering. * * @return string[] */ public static function plugins_not_supporting_ordering(): array { return [ ['mod_assign'], ['block_login'], ]; } } mod_test.php000064400000003345152270020020007066 0ustar00. declare(strict_types=1); namespace core\plugininfo; use advanced_testcase; /** * Unit tests for the mod plugininfo class * * @package core * @covers \core\plugininfo\mod * @copyright 2023 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class mod_test extends advanced_testcase { public function test_get_enabled_plugins(): void { $this->resetAfterTest(); // The bigbluebuttonbn is disabled by default. // Check all default formats. $plugins = mod::get_enabled_plugins(); $this->assertArrayHasKey('assign', $plugins); $this->assertArrayHasKey('forum', $plugins); $this->assertArrayNotHasKey('bigbluebuttonbn', $plugins); // Disable assignment. mod::enable_plugin('assign', 0); $plugins = mod::get_enabled_plugins(); $this->assertArrayHasKey('forum', $plugins); $this->assertArrayNotHasKey('assign', $plugins); $this->assertArrayNotHasKey('bigbluebuttonbn', $plugins); } } tiny_test.php000064400000005660152274744000007313 0ustar00. declare(strict_types=1); namespace editor_tiny\plugininfo; use advanced_testcase; /** * Unit tests for the editor_tiny\tiny plugininfo class. * * @package editor_tiny * @covers \editor_tiny\plugininfo\tiny * @copyright 2023 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class tiny_test extends advanced_testcase { /** * Uninstall is allowed of TinyMCE plugins. * * @covers ::is_uninstall_allowed */ public function test_is_uninstall_allowed(): void { $instance = new tiny(); $this->assertTrue($instance->is_uninstall_allowed()); } /** * Check the manage URL. * * @covers ::get_manage_url */ public function test_get_manage_url(): void { $this->assertInstanceOf(\moodle_url::class, tiny::get_manage_url()); } /** * Test the get_enabled_plugins method. * * @covers ::get_enabled_plugin */ public function test_get_enabled_plugins(): void { $this->resetAfterTest(); $plugins = tiny::get_enabled_plugins(); $this->assertArrayHasKey('recordrtc', $plugins); $this->assertArrayHasKey('media', $plugins); $this->assertArrayHasKey('autosave', $plugins); $this->assertArrayHasKey('h5p', $plugins); // Disable a plugin. tiny::enable_plugin('h5p', 0); $plugins = tiny::get_enabled_plugins(); $this->assertArrayHasKey('recordrtc', $plugins); $this->assertArrayHasKey('media', $plugins); $this->assertArrayHasKey('autosave', $plugins); $this->assertArrayNotHasKey('h5p', $plugins); } /** * Ensure that the base implementation is used for plugins not supporting ordering. */ public function test_sorting_not_supported(): void { $this->assertFalse(tiny::plugintype_supports_ordering()); $this->assertNull(tiny::get_sorted_plugins()); $this->assertNull(tiny::get_sorted_plugins(true)); $this->assertNull(tiny::get_sorted_plugins(false)); $this->assertFalse(tiny::change_plugin_order('tiny_h5p', \core\plugininfo\base::MOVE_UP)); $this->assertFalse(tiny::change_plugin_order('tiny_h5p', \core\plugininfo\base::MOVE_DOWN)); } }