| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 3 | //
 | 
        
           |  |  | 4 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 5 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 6 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 7 | // (at your option) any later version.
 | 
        
           |  |  | 8 | //
 | 
        
           |  |  | 9 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 12 | // GNU General Public License for more details.
 | 
        
           |  |  | 13 | //
 | 
        
           |  |  | 14 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 15 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 16 |   | 
        
           |  |  | 17 | namespace core;
 | 
        
           |  |  | 18 |   | 
        
           | 1441 | ariadna | 19 | use core\plugininfo\base;
 | 
        
           |  |  | 20 | use core\tests\fake_plugins_test_trait;
 | 
        
           | 1 | efrain | 21 | use core_plugin_manager;
 | 
        
           |  |  | 22 | use testable_core_plugin_manager;
 | 
        
           |  |  | 23 | use testable_plugininfo_base;
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | /**
 | 
        
           |  |  | 26 |  * Unit tests for plugin manager class.
 | 
        
           |  |  | 27 |  *
 | 
        
           |  |  | 28 |  * @package   core
 | 
        
           |  |  | 29 |  * @category  test
 | 
        
           |  |  | 30 |  * @copyright 2013 Petr Skoda {@link http://skodak.org}
 | 
        
           |  |  | 31 |  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 32 |  * @covers \core_plugin_manager
 | 
        
           |  |  | 33 |  */
 | 
        
           |  |  | 34 | final class plugin_manager_test extends \advanced_testcase {
 | 
        
           | 1441 | ariadna | 35 |   | 
        
           |  |  | 36 |     use fake_plugins_test_trait;
 | 
        
           |  |  | 37 |   | 
        
           | 1 | efrain | 38 |     public static function setUpBeforeClass(): void {
 | 
        
           |  |  | 39 |         global $CFG;
 | 
        
           |  |  | 40 |         require_once($CFG->dirroot . '/lib/tests/fixtures/testable_plugin_manager.php');
 | 
        
           |  |  | 41 |         require_once($CFG->dirroot . '/lib/tests/fixtures/testable_plugininfo_base.php');
 | 
        
           | 1441 | ariadna | 42 |         parent::setUpBeforeClass();
 | 
        
           | 1 | efrain | 43 |     }
 | 
        
           |  |  | 44 |   | 
        
           |  |  | 45 |     public function tearDown(): void {
 | 
        
           |  |  | 46 |         // The caches of the testable singleton must be reset explicitly. It is
 | 
        
           |  |  | 47 |         // safer to kill the whole testable singleton at the end of every test.
 | 
        
           |  |  | 48 |         testable_core_plugin_manager::reset_caches();
 | 
        
           | 1441 | ariadna | 49 |         parent::tearDown();
 | 
        
           | 1 | efrain | 50 |     }
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 |     public function test_instance(): void {
 | 
        
           |  |  | 53 |         $pluginman1 = core_plugin_manager::instance();
 | 
        
           |  |  | 54 |         $this->assertInstanceOf('core_plugin_manager', $pluginman1);
 | 
        
           |  |  | 55 |         $pluginman2 = core_plugin_manager::instance();
 | 
        
           |  |  | 56 |         $this->assertSame($pluginman1, $pluginman2);
 | 
        
           |  |  | 57 |         $pluginman3 = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 58 |         $this->assertInstanceOf('core_plugin_manager', $pluginman3);
 | 
        
           |  |  | 59 |         $this->assertInstanceOf('testable_core_plugin_manager', $pluginman3);
 | 
        
           |  |  | 60 |         $pluginman4 = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 61 |         $this->assertSame($pluginman3, $pluginman4);
 | 
        
           |  |  | 62 |         $this->assertNotSame($pluginman1, $pluginman3);
 | 
        
           |  |  | 63 |     }
 | 
        
           |  |  | 64 |   | 
        
           |  |  | 65 |     public function test_reset_caches(): void {
 | 
        
           |  |  | 66 |         // Make sure there are no warnings or errors.
 | 
        
           |  |  | 67 |         core_plugin_manager::reset_caches();
 | 
        
           |  |  | 68 |         testable_core_plugin_manager::reset_caches();
 | 
        
           |  |  | 69 |     }
 | 
        
           |  |  | 70 |   | 
        
           |  |  | 71 |     /**
 | 
        
           |  |  | 72 |      * Make sure that the tearDown() really kills the singleton after this test.
 | 
        
           |  |  | 73 |      */
 | 
        
           |  |  | 74 |     public function test_teardown_works_precheck(): void {
 | 
        
           |  |  | 75 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 76 |         $pluginfo = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 77 |             'fake',
 | 
        
           |  |  | 78 |             '/dev/null',
 | 
        
           |  |  | 79 |             'one',
 | 
        
           |  |  | 80 |             '/dev/null/fake',
 | 
        
           |  |  | 81 |             'testable_plugininfo_base',
 | 
        
           |  |  | 82 |             $pluginman
 | 
        
           |  |  | 83 |         );
 | 
        
           |  |  | 84 |         $pluginman->inject_testable_plugininfo('fake', 'one', $pluginfo);
 | 
        
           |  |  | 85 |   | 
        
           |  |  | 86 |         $this->assertInstanceOf('\core\plugininfo\base', $pluginman->get_plugin_info('fake_one'));
 | 
        
           |  |  | 87 |         $this->assertNull($pluginman->get_plugin_info('fake_two'));
 | 
        
           |  |  | 88 |     }
 | 
        
           |  |  | 89 |   | 
        
           |  |  | 90 |     public function test_teardown_works_postcheck(): void {
 | 
        
           |  |  | 91 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 92 |         $this->assertNull($pluginman->get_plugin_info('fake_one'));
 | 
        
           |  |  | 93 |         $this->assertNull($pluginman->get_plugin_info('fake_two'));
 | 
        
           |  |  | 94 |     }
 | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 |     public function test_get_plugin_types(): void {
 | 
        
           |  |  | 97 |         // Make sure there are no warnings or errors.
 | 
        
           |  |  | 98 |         $types = core_plugin_manager::instance()->get_plugin_types();
 | 
        
           |  |  | 99 |         $this->assertIsArray($types);
 | 
        
           |  |  | 100 |         foreach ($types as $type => $fulldir) {
 | 
        
           |  |  | 101 |             $this->assertFileExists($fulldir);
 | 
        
           |  |  | 102 |         }
 | 
        
           |  |  | 103 |     }
 | 
        
           |  |  | 104 |   | 
        
           |  |  | 105 |     public function test_get_installed_plugins(): void {
 | 
        
           |  |  | 106 |         $types = core_plugin_manager::instance()->get_plugin_types();
 | 
        
           |  |  | 107 |         foreach ($types as $type => $fulldir) {
 | 
        
           |  |  | 108 |             $installed = core_plugin_manager::instance()->get_installed_plugins($type);
 | 
        
           |  |  | 109 |             foreach ($installed as $plugin => $version) {
 | 
        
           |  |  | 110 |                 $this->assertMatchesRegularExpression('/^[a-z]+[a-z0-9_]*$/', $plugin);
 | 
        
           |  |  | 111 |                 $this->assertTrue(
 | 
        
           |  |  | 112 |                     is_numeric($version),
 | 
        
           |  |  | 113 |                     'All plugins should have a version, plugin ' . $type . '_' . $plugin . ' does not have version info.'
 | 
        
           |  |  | 114 |                 );
 | 
        
           |  |  | 115 |             }
 | 
        
           |  |  | 116 |         }
 | 
        
           |  |  | 117 |     }
 | 
        
           |  |  | 118 |   | 
        
           |  |  | 119 |     public function test_get_enabled_plugins(): void {
 | 
        
           |  |  | 120 |         $types = core_plugin_manager::instance()->get_plugin_types();
 | 
        
           |  |  | 121 |         foreach ($types as $type => $fulldir) {
 | 
        
           |  |  | 122 |             $enabled = core_plugin_manager::instance()->get_enabled_plugins($type);
 | 
        
           |  |  | 123 |             if (is_array($enabled)) {
 | 
        
           |  |  | 124 |                 foreach ($enabled as $key => $val) {
 | 
        
           |  |  | 125 |                     $this->assertMatchesRegularExpression('/^[a-z]+[a-z0-9_]*$/', $key);
 | 
        
           |  |  | 126 |                     $this->assertSame($key, $val);
 | 
        
           |  |  | 127 |                 }
 | 
        
           |  |  | 128 |             } else {
 | 
        
           |  |  | 129 |                 $this->assertNull($enabled);
 | 
        
           |  |  | 130 |             }
 | 
        
           |  |  | 131 |         }
 | 
        
           |  |  | 132 |     }
 | 
        
           |  |  | 133 |   | 
        
           |  |  | 134 |     public function test_get_present_plugins(): void {
 | 
        
           |  |  | 135 |         $types = core_plugin_manager::instance()->get_plugin_types();
 | 
        
           |  |  | 136 |         foreach ($types as $type => $fulldir) {
 | 
        
           |  |  | 137 |             $present = core_plugin_manager::instance()->get_present_plugins($type);
 | 
        
           |  |  | 138 |             if (is_array($present)) {
 | 
        
           |  |  | 139 |                 foreach ($present as $plugin => $version) {
 | 
        
           |  |  | 140 |                     $this->assertMatchesRegularExpression(
 | 
        
           |  |  | 141 |                         '/^[a-z]+[a-z0-9_]*$/',
 | 
        
           |  |  | 142 |                         $plugin,
 | 
        
           |  |  | 143 |                         'All plugins are supposed to have version.php file.'
 | 
        
           |  |  | 144 |                     );
 | 
        
           |  |  | 145 |                     $this->assertIsObject($version);
 | 
        
           |  |  | 146 |                     $this->assertTrue(
 | 
        
           |  |  | 147 |                         is_numeric($version->version),
 | 
        
           |  |  | 148 |                         'All plugins should have a version, plugin ' . $type . '_' . $plugin . ' does not have version info.'
 | 
        
           |  |  | 149 |                     );
 | 
        
           |  |  | 150 |                 }
 | 
        
           |  |  | 151 |             } else {
 | 
        
           |  |  | 152 |                 // No plugins of this type exist.
 | 
        
           |  |  | 153 |                 $this->assertNull($present);
 | 
        
           |  |  | 154 |             }
 | 
        
           |  |  | 155 |         }
 | 
        
           |  |  | 156 |     }
 | 
        
           |  |  | 157 |   | 
        
           |  |  | 158 |     public function test_get_plugins(): void {
 | 
        
           |  |  | 159 |         $plugininfos1 = core_plugin_manager::instance()->get_plugins();
 | 
        
           |  |  | 160 |         foreach ($plugininfos1 as $type => $infos) {
 | 
        
           |  |  | 161 |             foreach ($infos as $name => $info) {
 | 
        
           |  |  | 162 |                 $this->assertInstanceOf('\core\plugininfo\base', $info);
 | 
        
           |  |  | 163 |             }
 | 
        
           |  |  | 164 |         }
 | 
        
           |  |  | 165 |   | 
        
           |  |  | 166 |         // The testable variant of the manager holds its own tree of the
 | 
        
           |  |  | 167 |         // plugininfo objects.
 | 
        
           |  |  | 168 |         $plugininfos2 = testable_core_plugin_manager::instance()->get_plugins();
 | 
        
           |  |  | 169 |         $this->assertNotSame($plugininfos1['mod']['forum'], $plugininfos2['mod']['forum']);
 | 
        
           |  |  | 170 |   | 
        
           |  |  | 171 |         // Singletons of each manager class share the same tree.
 | 
        
           |  |  | 172 |         $plugininfos3 = core_plugin_manager::instance()->get_plugins();
 | 
        
           |  |  | 173 |         $this->assertSame($plugininfos1['mod']['forum'], $plugininfos3['mod']['forum']);
 | 
        
           |  |  | 174 |         $plugininfos4 = testable_core_plugin_manager::instance()->get_plugins();
 | 
        
           |  |  | 175 |         $this->assertSame($plugininfos2['mod']['forum'], $plugininfos4['mod']['forum']);
 | 
        
           |  |  | 176 |     }
 | 
        
           |  |  | 177 |   | 
        
           |  |  | 178 |     public function test_plugininfo_back_reference_to_the_plugin_manager(): void {
 | 
        
           |  |  | 179 |         $plugman1 = core_plugin_manager::instance();
 | 
        
           |  |  | 180 |         $plugman2 = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 181 |   | 
        
           |  |  | 182 |         foreach ($plugman1->get_plugins() as $type => $infos) {
 | 
        
           |  |  | 183 |             foreach ($infos as $info) {
 | 
        
           |  |  | 184 |                 $this->assertSame($info->pluginman, $plugman1);
 | 
        
           |  |  | 185 |             }
 | 
        
           |  |  | 186 |         }
 | 
        
           |  |  | 187 |   | 
        
           |  |  | 188 |         foreach ($plugman2->get_plugins() as $type => $infos) {
 | 
        
           |  |  | 189 |             foreach ($infos as $info) {
 | 
        
           |  |  | 190 |                 $this->assertSame($info->pluginman, $plugman2);
 | 
        
           |  |  | 191 |             }
 | 
        
           |  |  | 192 |         }
 | 
        
           |  |  | 193 |     }
 | 
        
           |  |  | 194 |   | 
        
           |  |  | 195 |     public function test_get_plugins_of_type(): void {
 | 
        
           |  |  | 196 |         $plugininfos = core_plugin_manager::instance()->get_plugins();
 | 
        
           |  |  | 197 |         foreach ($plugininfos as $type => $infos) {
 | 
        
           |  |  | 198 |             $this->assertSame($infos, core_plugin_manager::instance()->get_plugins_of_type($type));
 | 
        
           |  |  | 199 |         }
 | 
        
           |  |  | 200 |     }
 | 
        
           |  |  | 201 |   | 
        
           |  |  | 202 |     public function test_get_subplugins_of_plugin(): void {
 | 
        
           |  |  | 203 |         global $CFG;
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 |         // Any standard plugin with subplugins is suitable.
 | 
        
           |  |  | 206 |         $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
 | 
        
           |  |  | 207 |   | 
        
           |  |  | 208 |         $subplugins = core_plugin_manager::instance()->get_subplugins_of_plugin('editor_tiny');
 | 
        
           |  |  | 209 |         foreach ($subplugins as $component => $info) {
 | 
        
           |  |  | 210 |             $this->assertInstanceOf('\core\plugininfo\base', $info);
 | 
        
           |  |  | 211 |         }
 | 
        
           |  |  | 212 |     }
 | 
        
           |  |  | 213 |   | 
        
           |  |  | 214 |     public function test_get_subplugins(): void {
 | 
        
           |  |  | 215 |         // Tested already indirectly from test_get_subplugins_of_plugin().
 | 
        
           |  |  | 216 |         $subplugins = core_plugin_manager::instance()->get_subplugins();
 | 
        
           |  |  | 217 |         $this->assertIsArray($subplugins);
 | 
        
           |  |  | 218 |     }
 | 
        
           |  |  | 219 |   | 
        
           |  |  | 220 |     public function test_get_parent_of_subplugin(): void {
 | 
        
           |  |  | 221 |         global $CFG;
 | 
        
           |  |  | 222 |   | 
        
           |  |  | 223 |         // Any standard plugin with subplugins is suitable.
 | 
        
           |  |  | 224 |         $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
 | 
        
           |  |  | 225 |   | 
        
           |  |  | 226 |         $parent = core_plugin_manager::instance()->get_parent_of_subplugin('tiny');
 | 
        
           |  |  | 227 |         $this->assertSame('editor_tiny', $parent);
 | 
        
           |  |  | 228 |     }
 | 
        
           |  |  | 229 |   | 
        
           |  |  | 230 |     public function test_plugin_name(): void {
 | 
        
           |  |  | 231 |         global $CFG;
 | 
        
           |  |  | 232 |   | 
        
           |  |  | 233 |         // Any standard plugin is suitable.
 | 
        
           |  |  | 234 |         $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
 | 
        
           |  |  | 235 |   | 
        
           |  |  | 236 |         $name = core_plugin_manager::instance()->plugin_name('editor_tiny');
 | 
        
           |  |  | 237 |         $this->assertSame(get_string('pluginname', 'editor_tiny'), $name);
 | 
        
           |  |  | 238 |     }
 | 
        
           |  |  | 239 |   | 
        
           |  |  | 240 |     public function test_plugintype_name(): void {
 | 
        
           |  |  | 241 |         $name = core_plugin_manager::instance()->plugintype_name('editor');
 | 
        
           |  |  | 242 |         $this->assertSame(get_string('type_editor', 'core_plugin'), $name);
 | 
        
           |  |  | 243 |     }
 | 
        
           |  |  | 244 |   | 
        
           |  |  | 245 |     public function test_plugintype_name_plural(): void {
 | 
        
           |  |  | 246 |         $name = core_plugin_manager::instance()->plugintype_name_plural('editor');
 | 
        
           |  |  | 247 |         $this->assertSame(get_string('type_editor_plural', 'core_plugin'), $name);
 | 
        
           |  |  | 248 |     }
 | 
        
           |  |  | 249 |   | 
        
           |  |  | 250 |     public function test_get_plugin_info(): void {
 | 
        
           |  |  | 251 |         global $CFG;
 | 
        
           |  |  | 252 |   | 
        
           |  |  | 253 |         // Any standard plugin is suitable.
 | 
        
           |  |  | 254 |         $this->assertFileExists("$CFG->dirroot/lib/editor/tiny", 'TinyMCE is not present.');
 | 
        
           |  |  | 255 |   | 
        
           |  |  | 256 |         $info = core_plugin_manager::instance()->get_plugin_info('editor_tiny');
 | 
        
           |  |  | 257 |         $this->assertInstanceOf('\core\plugininfo\editor', $info);
 | 
        
           |  |  | 258 |     }
 | 
        
           |  |  | 259 |   | 
        
           |  |  | 260 |     public function test_can_uninstall_plugin(): void {
 | 
        
           |  |  | 261 |         global $CFG;
 | 
        
           |  |  | 262 |   | 
        
           |  |  | 263 |         // Any standard plugin that is required by some other standard plugin is ok.
 | 
        
           |  |  | 264 |         $this->assertFileExists("$CFG->dirroot/report/competency", 'competency report is not present');
 | 
        
           |  |  | 265 |         $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/lp", 'tool lp is not present');
 | 
        
           |  |  | 266 |   | 
        
           |  |  | 267 |         $this->assertFalse(core_plugin_manager::instance()->can_uninstall_plugin('tool_lp'));
 | 
        
           |  |  | 268 |         $this->assertTrue(core_plugin_manager::instance()->can_uninstall_plugin('report_competency'));
 | 
        
           |  |  | 269 |     }
 | 
        
           |  |  | 270 |   | 
        
           |  |  | 271 |     public function test_plugin_states(): void {
 | 
        
           |  |  | 272 |         global $CFG;
 | 
        
           |  |  | 273 |         $this->resetAfterTest();
 | 
        
           |  |  | 274 |   | 
        
           |  |  | 275 |         // Any standard plugin that is ok.
 | 
        
           |  |  | 276 |         $this->assertFileExists("$CFG->dirroot/mod/assign", 'assign module is not present');
 | 
        
           |  |  | 277 |         $this->assertFileExists("$CFG->dirroot/mod/forum", 'forum module is not present');
 | 
        
           |  |  | 278 |         $this->assertFileExists("$CFG->dirroot/$CFG->admin/tool/phpunit", 'phpunit tool is not present');
 | 
        
           |  |  | 279 |         $this->assertFileDoesNotExist("$CFG->dirroot/mod/xxxxxxx");
 | 
        
           |  |  | 280 |         $this->assertFileDoesNotExist("$CFG->dirroot/enrol/autorize");
 | 
        
           |  |  | 281 |   | 
        
           |  |  | 282 |         // Ready for upgrade.
 | 
        
           |  |  | 283 |         $assignversion = get_config('mod_assign', 'version');
 | 
        
           |  |  | 284 |         set_config('version', $assignversion - 1, 'mod_assign');
 | 
        
           |  |  | 285 |         // Downgrade problem.
 | 
        
           |  |  | 286 |         $forumversion = get_config('mod_forum', 'version');
 | 
        
           |  |  | 287 |         set_config('version', $forumversion + 1, 'mod_forum');
 | 
        
           |  |  | 288 |         // Not installed yet.
 | 
        
           |  |  | 289 |         unset_config('version', 'tool_phpunit');
 | 
        
           |  |  | 290 |         // Missing already installed.
 | 
        
           |  |  | 291 |         set_config('version', 2013091300, 'mod_xxxxxxx');
 | 
        
           |  |  | 292 |         // Deleted present.
 | 
        
           |  |  | 293 |         set_config('version', 2013091300, 'enrol_authorize');
 | 
        
           |  |  | 294 |   | 
        
           |  |  | 295 |         core_plugin_manager::reset_caches();
 | 
        
           |  |  | 296 |   | 
        
           |  |  | 297 |         $plugininfos = core_plugin_manager::instance()->get_plugins();
 | 
        
           |  |  | 298 |         foreach ($plugininfos as $type => $infos) {
 | 
        
           |  |  | 299 |             /** @var \core\plugininfo\base $info */
 | 
        
           |  |  | 300 |             foreach ($infos as $info) {
 | 
        
           |  |  | 301 |                 if ($info->component === 'mod_assign') {
 | 
        
           |  |  | 302 |                     $this->assertSame(
 | 
        
           |  |  | 303 |                         core_plugin_manager::PLUGIN_STATUS_UPGRADE,
 | 
        
           |  |  | 304 |                         $info->get_status(),
 | 
        
           |  |  | 305 |                         'Invalid ' . $info->component . ' state'
 | 
        
           |  |  | 306 |                     );
 | 
        
           |  |  | 307 |                 } else if ($info->component === 'mod_forum') {
 | 
        
           |  |  | 308 |                     $this->assertSame(
 | 
        
           |  |  | 309 |                         core_plugin_manager::PLUGIN_STATUS_DOWNGRADE,
 | 
        
           |  |  | 310 |                         $info->get_status(),
 | 
        
           |  |  | 311 |                         'Invalid ' . $info->component . ' state'
 | 
        
           |  |  | 312 |                     );
 | 
        
           |  |  | 313 |                 } else if ($info->component === 'tool_phpunit') {
 | 
        
           |  |  | 314 |                     $this->assertSame(
 | 
        
           |  |  | 315 |                         core_plugin_manager::PLUGIN_STATUS_NEW,
 | 
        
           |  |  | 316 |                         $info->get_status(),
 | 
        
           |  |  | 317 |                         'Invalid ' . $info->component . ' state'
 | 
        
           |  |  | 318 |                     );
 | 
        
           |  |  | 319 |                 } else if ($info->component === 'mod_xxxxxxx') {
 | 
        
           |  |  | 320 |                     $this->assertSame(
 | 
        
           |  |  | 321 |                         core_plugin_manager::PLUGIN_STATUS_MISSING,
 | 
        
           |  |  | 322 |                         $info->get_status(),
 | 
        
           |  |  | 323 |                         'Invalid ' . $info->component . ' state'
 | 
        
           |  |  | 324 |                     );
 | 
        
           |  |  | 325 |                 } else if ($info->component === 'enrol_authorize') {
 | 
        
           |  |  | 326 |                     $this->assertSame(
 | 
        
           |  |  | 327 |                         core_plugin_manager::PLUGIN_STATUS_DELETE,
 | 
        
           |  |  | 328 |                         $info->get_status(),
 | 
        
           |  |  | 329 |                         'Invalid ' . $info->component . ' state'
 | 
        
           |  |  | 330 |                     );
 | 
        
           |  |  | 331 |                 } else {
 | 
        
           |  |  | 332 |                     $this->assertSame(
 | 
        
           |  |  | 333 |                         core_plugin_manager::PLUGIN_STATUS_UPTODATE,
 | 
        
           |  |  | 334 |                         $info->get_status(),
 | 
        
           |  |  | 335 |                         'Invalid ' . $info->component . ' state'
 | 
        
           |  |  | 336 |                     );
 | 
        
           |  |  | 337 |                 }
 | 
        
           |  |  | 338 |             }
 | 
        
           |  |  | 339 |         }
 | 
        
           |  |  | 340 |     }
 | 
        
           |  |  | 341 |   | 
        
           |  |  | 342 |     public function test_plugin_available_updates(): void {
 | 
        
           |  |  | 343 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 344 |   | 
        
           |  |  | 345 |         $foobar = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 346 |             'foo',
 | 
        
           |  |  | 347 |             '/dev/null',
 | 
        
           |  |  | 348 |             'bar',
 | 
        
           |  |  | 349 |             '/dev/null/fake',
 | 
        
           |  |  | 350 |             'testable_plugininfo_base',
 | 
        
           |  |  | 351 |             $pluginman
 | 
        
           |  |  | 352 |         );
 | 
        
           |  |  | 353 |         $foobar->versiondb = 2015092900;
 | 
        
           |  |  | 354 |         $foobar->versiondisk = 2015092900;
 | 
        
           |  |  | 355 |         $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
 | 
        
           |  |  | 356 |   | 
        
           |  |  | 357 |         $washere = false;
 | 
        
           |  |  | 358 |         foreach ($pluginman->get_plugins() as $type => $infos) {
 | 
        
           |  |  | 359 |             foreach ($infos as $name => $plugin) {
 | 
        
           |  |  | 360 |                 $updates = $plugin->available_updates();
 | 
        
           |  |  | 361 |                 if ($plugin->component != 'foo_bar') {
 | 
        
           |  |  | 362 |                     $this->assertNull($updates);
 | 
        
           |  |  | 363 |                 } else {
 | 
        
           |  |  | 364 |                     $this->assertTrue(is_array($updates));
 | 
        
           |  |  | 365 |                     $this->assertEquals(3, count($updates));
 | 
        
           |  |  | 366 |                     foreach ($updates as $update) {
 | 
        
           |  |  | 367 |                         $washere = true;
 | 
        
           |  |  | 368 |                         $this->assertInstanceOf('\core\update\info', $update);
 | 
        
           |  |  | 369 |                         $this->assertEquals($update->component, $plugin->component);
 | 
        
           |  |  | 370 |                         $this->assertTrue($update->version > $plugin->versiondb);
 | 
        
           |  |  | 371 |                     }
 | 
        
           |  |  | 372 |                 }
 | 
        
           |  |  | 373 |             }
 | 
        
           |  |  | 374 |         }
 | 
        
           |  |  | 375 |         $this->assertTrue($washere);
 | 
        
           |  |  | 376 |     }
 | 
        
           |  |  | 377 |   | 
        
           |  |  | 378 |     public function test_some_plugins_updatable_none(): void {
 | 
        
           |  |  | 379 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 380 |         $this->assertFalse($pluginman->some_plugins_updatable());
 | 
        
           |  |  | 381 |     }
 | 
        
           |  |  | 382 |   | 
        
           |  |  | 383 |     public function test_some_plugins_updatable_some(): void {
 | 
        
           |  |  | 384 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 385 |   | 
        
           |  |  | 386 |         $foobar = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 387 |             'foo',
 | 
        
           |  |  | 388 |             '/dev/null',
 | 
        
           |  |  | 389 |             'bar',
 | 
        
           |  |  | 390 |             '/dev/null/fake',
 | 
        
           |  |  | 391 |             'testable_plugininfo_base',
 | 
        
           |  |  | 392 |             $pluginman
 | 
        
           |  |  | 393 |         );
 | 
        
           |  |  | 394 |         $foobar->versiondb = 2015092900;
 | 
        
           |  |  | 395 |         $foobar->versiondisk = 2015092900;
 | 
        
           |  |  | 396 |         $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
 | 
        
           |  |  | 397 |   | 
        
           |  |  | 398 |         $this->assertTrue($pluginman->some_plugins_updatable());
 | 
        
           |  |  | 399 |     }
 | 
        
           |  |  | 400 |   | 
        
           |  |  | 401 |     public function test_available_updates(): void {
 | 
        
           |  |  | 402 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 403 |   | 
        
           |  |  | 404 |         $foobar = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 405 |             'foo',
 | 
        
           |  |  | 406 |             '/dev/null',
 | 
        
           |  |  | 407 |             'bar',
 | 
        
           |  |  | 408 |             '/dev/null/fake',
 | 
        
           |  |  | 409 |             'testable_plugininfo_base',
 | 
        
           |  |  | 410 |             $pluginman
 | 
        
           |  |  | 411 |         );
 | 
        
           |  |  | 412 |         $foobar->versiondb = 2015092900;
 | 
        
           |  |  | 413 |         $foobar->versiondisk = 2015092900;
 | 
        
           |  |  | 414 |         $pluginman->inject_testable_plugininfo('foo', 'bar', $foobar);
 | 
        
           |  |  | 415 |   | 
        
           |  |  | 416 |         $updates = $pluginman->available_updates();
 | 
        
           |  |  | 417 |   | 
        
           |  |  | 418 |         $this->assertTrue(is_array($updates));
 | 
        
           |  |  | 419 |         $this->assertEquals(1, count($updates));
 | 
        
           |  |  | 420 |         $update = $updates['foo_bar'];
 | 
        
           |  |  | 421 |         $this->assertInstanceOf('\core\update\remote_info', $update);
 | 
        
           |  |  | 422 |         $this->assertEquals('foo_bar', $update->component);
 | 
        
           |  |  | 423 |         $this->assertEquals(2015100400, $update->version->version);
 | 
        
           |  |  | 424 |     }
 | 
        
           |  |  | 425 |   | 
        
           |  |  | 426 |     public function test_get_remote_plugin_info(): void {
 | 
        
           |  |  | 427 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 428 |   | 
        
           |  |  | 429 |         $this->assertFalse($pluginman->get_remote_plugin_info('not_exists', ANY_VERSION, false));
 | 
        
           |  |  | 430 |   | 
        
           |  |  | 431 |         $info = $pluginman->get_remote_plugin_info('foo_bar', 2015093000, true);
 | 
        
           |  |  | 432 |         $this->assertEquals(2015093000, $info->version->version);
 | 
        
           |  |  | 433 |   | 
        
           |  |  | 434 |         $info = $pluginman->get_remote_plugin_info('foo_bar', 2015093000, false);
 | 
        
           |  |  | 435 |         $this->assertEquals(2015100400, $info->version->version);
 | 
        
           |  |  | 436 |     }
 | 
        
           |  |  | 437 |   | 
        
           |  |  | 438 |     /**
 | 
        
           |  |  | 439 |      * The combination of ANY_VERSION + $exactmatch is illegal.
 | 
        
           |  |  | 440 |      */
 | 
        
           |  |  | 441 |     public function test_get_remote_plugin_info_exception(): void {
 | 
        
           |  |  | 442 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 443 |         $this->expectException(\moodle_exception::class);
 | 
        
           |  |  | 444 |         $pluginman->get_remote_plugin_info('any_thing', ANY_VERSION, true);
 | 
        
           |  |  | 445 |     }
 | 
        
           |  |  | 446 |   | 
        
           |  |  | 447 |     public function test_is_remote_plugin_available(): void {
 | 
        
           |  |  | 448 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 449 |   | 
        
           |  |  | 450 |         $this->assertFalse($pluginman->is_remote_plugin_available('not_exists', ANY_VERSION, false));
 | 
        
           |  |  | 451 |         $this->assertTrue($pluginman->is_remote_plugin_available('foo_bar', 2013131313, false));
 | 
        
           |  |  | 452 |         $this->assertFalse($pluginman->is_remote_plugin_available('foo_bar', 2013131313, true));
 | 
        
           |  |  | 453 |     }
 | 
        
           |  |  | 454 |   | 
        
           |  |  | 455 |     public function test_resolve_requirements(): void {
 | 
        
           |  |  | 456 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 457 |   | 
        
           |  |  | 458 |         // Prepare a fake pluginfo instance.
 | 
        
           |  |  | 459 |         $pluginfo = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 460 |             'fake',
 | 
        
           |  |  | 461 |             '/dev/null',
 | 
        
           |  |  | 462 |             'one',
 | 
        
           |  |  | 463 |             '/dev/null/fake',
 | 
        
           |  |  | 464 |             'testable_plugininfo_base',
 | 
        
           |  |  | 465 |             $pluginman
 | 
        
           |  |  | 466 |         );
 | 
        
           |  |  | 467 |         $pluginfo->versiondisk = 2015060600;
 | 
        
           |  |  | 468 |   | 
        
           |  |  | 469 |         // Test no $plugin->requires is specified in version.php.
 | 
        
           |  |  | 470 |         $pluginfo->versionrequires = null;
 | 
        
           |  |  | 471 |         $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015100100));
 | 
        
           |  |  | 472 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
 | 
        
           |  |  | 473 |         $this->assertEquals(2015100100, $reqs['core']->hasver);
 | 
        
           |  |  | 474 |         $this->assertEquals(ANY_VERSION, $reqs['core']->reqver);
 | 
        
           |  |  | 475 |         $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
 | 
        
           |  |  | 476 |   | 
        
           |  |  | 477 |         // Test plugin requires higher core version.
 | 
        
           |  |  | 478 |         $pluginfo->versionrequires = 2015110900;
 | 
        
           |  |  | 479 |         $this->assertFalse($pluginfo->is_core_dependency_satisfied(2015100100));
 | 
        
           |  |  | 480 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
 | 
        
           |  |  | 481 |         $this->assertEquals(2015100100, $reqs['core']->hasver);
 | 
        
           |  |  | 482 |         $this->assertEquals(2015110900, $reqs['core']->reqver);
 | 
        
           |  |  | 483 |         $this->assertEquals($pluginman::REQUIREMENT_STATUS_OUTDATED, $reqs['core']->status);
 | 
        
           |  |  | 484 |   | 
        
           |  |  | 485 |         // Test plugin requires current core version.
 | 
        
           |  |  | 486 |         $pluginfo->versionrequires = 2015110900;
 | 
        
           |  |  | 487 |         $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015110900));
 | 
        
           |  |  | 488 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
 | 
        
           |  |  | 489 |         $this->assertEquals(2015110900, $reqs['core']->hasver);
 | 
        
           |  |  | 490 |         $this->assertEquals(2015110900, $reqs['core']->reqver);
 | 
        
           |  |  | 491 |         $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
 | 
        
           |  |  | 492 |   | 
        
           |  |  | 493 |         // Test plugin requires lower core version.
 | 
        
           |  |  | 494 |         $pluginfo->versionrequires = 2014122400;
 | 
        
           |  |  | 495 |         $this->assertTrue($pluginfo->is_core_dependency_satisfied(2015100100));
 | 
        
           |  |  | 496 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015100100, 29);
 | 
        
           |  |  | 497 |         $this->assertEquals(2015100100, $reqs['core']->hasver);
 | 
        
           |  |  | 498 |         $this->assertEquals(2014122400, $reqs['core']->reqver);
 | 
        
           |  |  | 499 |         $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
 | 
        
           |  |  | 500 |   | 
        
           |  |  | 501 |         // Test plugin dependencies and their availability.
 | 
        
           |  |  | 502 |         // See {@link \core\update\testable_api} class.
 | 
        
           |  |  | 503 |   | 
        
           |  |  | 504 |         $pluginfo->dependencies = ['foo_bar' => ANY_VERSION, 'not_exists' => ANY_VERSION];
 | 
        
           |  |  | 505 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
 | 
        
           |  |  | 506 |         $this->assertNull($reqs['foo_bar']->hasver);
 | 
        
           |  |  | 507 |         $this->assertEquals(ANY_VERSION, $reqs['foo_bar']->reqver);
 | 
        
           |  |  | 508 |         $this->assertEquals($pluginman::REQUIREMENT_STATUS_MISSING, $reqs['foo_bar']->status);
 | 
        
           |  |  | 509 |         $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
 | 
        
           |  |  | 510 |         $this->assertEquals($pluginman::REQUIREMENT_UNAVAILABLE, $reqs['not_exists']->availability);
 | 
        
           |  |  | 511 |   | 
        
           |  |  | 512 |         $pluginfo->dependencies = ['foo_bar' => 2013122400];
 | 
        
           |  |  | 513 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
 | 
        
           |  |  | 514 |         $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
 | 
        
           |  |  | 515 |   | 
        
           |  |  | 516 |         $pluginfo->dependencies = ['foo_bar' => 2015093000];
 | 
        
           |  |  | 517 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
 | 
        
           |  |  | 518 |         $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
 | 
        
           |  |  | 519 |   | 
        
           |  |  | 520 |         $pluginfo->dependencies = ['foo_bar' => 2015100500];
 | 
        
           |  |  | 521 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
 | 
        
           |  |  | 522 |         $this->assertEquals($pluginman::REQUIREMENT_AVAILABLE, $reqs['foo_bar']->availability);
 | 
        
           |  |  | 523 |   | 
        
           |  |  | 524 |         $pluginfo->dependencies = ['foo_bar' => 2025010100];
 | 
        
           |  |  | 525 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
 | 
        
           |  |  | 526 |         $this->assertEquals($pluginman::REQUIREMENT_UNAVAILABLE, $reqs['foo_bar']->availability);
 | 
        
           |  |  | 527 |   | 
        
           |  |  | 528 |         // Plugin missing from disk - no version.php available.
 | 
        
           |  |  | 529 |         $pluginfo = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 530 |             'fake',
 | 
        
           |  |  | 531 |             '/dev/null',
 | 
        
           |  |  | 532 |             'missing',
 | 
        
           |  |  | 533 |             '/dev/null/fake',
 | 
        
           |  |  | 534 |             'testable_plugininfo_base',
 | 
        
           |  |  | 535 |             $pluginman
 | 
        
           |  |  | 536 |         );
 | 
        
           |  |  | 537 |         $pluginfo->versiondisk = null;
 | 
        
           |  |  | 538 |         $this->assertEmpty($pluginman->resolve_requirements($pluginfo, 2015110900, 30));
 | 
        
           |  |  | 539 |   | 
        
           |  |  | 540 |         // Test plugin fails for incompatible version.
 | 
        
           |  |  | 541 |         $pluginfo = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 542 |             'fake',
 | 
        
           |  |  | 543 |             '/dev/null',
 | 
        
           |  |  | 544 |             'two',
 | 
        
           |  |  | 545 |             '/dev/null/fake',
 | 
        
           |  |  | 546 |             'testable_plugininfo_base',
 | 
        
           |  |  | 547 |             $pluginman
 | 
        
           |  |  | 548 |         );
 | 
        
           |  |  | 549 |         $pluginfo->versiondisk = 2015060600;
 | 
        
           |  |  | 550 |         $pluginfo->pluginincompatible = 30;
 | 
        
           |  |  | 551 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 30);
 | 
        
           |  |  | 552 |         $this->assertEquals($pluginman::REQUIREMENT_STATUS_NEWER, $reqs['core']->status);
 | 
        
           |  |  | 553 |   | 
        
           |  |  | 554 |         // Test no failure for no incompatible version.
 | 
        
           |  |  | 555 |         $pluginfo->pluginincompatible = 30;
 | 
        
           |  |  | 556 |         $reqs = $pluginman->resolve_requirements($pluginfo, 2015110900, 29);
 | 
        
           |  |  | 557 |         $this->assertEquals($pluginman::REQUIREMENT_STATUS_OK, $reqs['core']->status);
 | 
        
           |  |  | 558 |     }
 | 
        
           |  |  | 559 |   | 
        
           |  |  | 560 |     public function test_missing_dependencies(): void {
 | 
        
           |  |  | 561 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 562 |   | 
        
           |  |  | 563 |         $one = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 564 |             'fake',
 | 
        
           |  |  | 565 |             '/dev/null',
 | 
        
           |  |  | 566 |             'one',
 | 
        
           |  |  | 567 |             '/dev/null/fake',
 | 
        
           |  |  | 568 |             'testable_plugininfo_base',
 | 
        
           |  |  | 569 |             $pluginman
 | 
        
           |  |  | 570 |         );
 | 
        
           |  |  | 571 |         $one->versiondisk = 2015070800;
 | 
        
           |  |  | 572 |   | 
        
           |  |  | 573 |         $two = testable_plugininfo_base::fake_plugin_instance(
 | 
        
           |  |  | 574 |             'fake',
 | 
        
           |  |  | 575 |             '/dev/null',
 | 
        
           |  |  | 576 |             'two',
 | 
        
           |  |  | 577 |             '/dev/null/fake',
 | 
        
           |  |  | 578 |             'testable_plugininfo_base',
 | 
        
           |  |  | 579 |             $pluginman
 | 
        
           |  |  | 580 |         );
 | 
        
           |  |  | 581 |         $two->versiondisk = 2015070900;
 | 
        
           |  |  | 582 |   | 
        
           |  |  | 583 |         $pluginman->inject_testable_plugininfo('fake', 'one', $one);
 | 
        
           |  |  | 584 |         $pluginman->inject_testable_plugininfo('fake', 'two', $two);
 | 
        
           |  |  | 585 |   | 
        
           |  |  | 586 |         $this->assertEmpty($pluginman->missing_dependencies());
 | 
        
           |  |  | 587 |   | 
        
           |  |  | 588 |         $one->dependencies = ['foo_bar' => ANY_VERSION];
 | 
        
           |  |  | 589 |         $misdeps = $pluginman->missing_dependencies();
 | 
        
           |  |  | 590 |         $this->assertInstanceOf('\core\update\remote_info', $misdeps['foo_bar']);
 | 
        
           |  |  | 591 |         $this->assertEquals(2015100400, $misdeps['foo_bar']->version->version);
 | 
        
           |  |  | 592 |   | 
        
           |  |  | 593 |         $two->dependencies = ['foo_bar' => 2015100500];
 | 
        
           |  |  | 594 |         $misdeps = $pluginman->missing_dependencies();
 | 
        
           |  |  | 595 |         $this->assertInstanceOf('\core\update\remote_info', $misdeps['foo_bar']);
 | 
        
           |  |  | 596 |         $this->assertEquals(2015100500, $misdeps['foo_bar']->version->version);
 | 
        
           |  |  | 597 |     }
 | 
        
           |  |  | 598 |   | 
        
           |  |  | 599 |     /**
 | 
        
           |  |  | 600 |      * Tests for check_explicitly_supported function to ensure that versions are correctly reported.
 | 
        
           |  |  | 601 |      *
 | 
        
           |  |  | 602 |      * @dataProvider check_explicitly_supported_provider
 | 
        
           |  |  | 603 |      * @param array|null $supported Supported versions to inject
 | 
        
           |  |  | 604 |      * @param string|int|null $incompatible Incompatible version to inject.
 | 
        
           |  |  | 605 |      * @param int $version Version to test
 | 
        
           |  |  | 606 |      * @param int $expected
 | 
        
           |  |  | 607 |      * @return void
 | 
        
           |  |  | 608 |      */
 | 
        
           |  |  | 609 |     public function test_explicitly_supported($supported, $incompatible, $version, $expected): void {
 | 
        
           |  |  | 610 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 611 |   | 
        
           |  |  | 612 |         // Prepare a fake pluginfo instance.
 | 
        
           |  |  | 613 |         $plugininfo = new testable_plugininfo_base();
 | 
        
           |  |  | 614 |         $plugininfo->type = 'fake';
 | 
        
           |  |  | 615 |         $plugininfo->typerootdir = '/dev/null';
 | 
        
           |  |  | 616 |         $plugininfo->name = 'example';
 | 
        
           |  |  | 617 |         $plugininfo->rootdir = '/dev/null/fake';
 | 
        
           |  |  | 618 |         $plugininfo->pluginman = $pluginman;
 | 
        
           |  |  | 619 |         $plugininfo->versiondisk = 2015060600;
 | 
        
           |  |  | 620 |         $plugininfo->supported = $supported;
 | 
        
           |  |  | 621 |         $plugininfo->incompatible = $incompatible;
 | 
        
           |  |  | 622 |   | 
        
           |  |  | 623 |         $pluginman->add_fake_plugin_info($plugininfo);
 | 
        
           |  |  | 624 |   | 
        
           |  |  | 625 |         $plugininfo->load_disk_version();
 | 
        
           |  |  | 626 |   | 
        
           |  |  | 627 |         $this->assertEquals($expected, $pluginman->check_explicitly_supported($plugininfo, $version));
 | 
        
           |  |  | 628 |     }
 | 
        
           |  |  | 629 |   | 
        
           |  |  | 630 |     /**
 | 
        
           |  |  | 631 |      * Data provider for check_explicitly_supported with a range of correctly defined version support values.
 | 
        
           |  |  | 632 |      *
 | 
        
           |  |  | 633 |      * @return array
 | 
        
           |  |  | 634 |      */
 | 
        
           |  |  | 635 |     public static function check_explicitly_supported_provider(): array {
 | 
        
           |  |  | 636 |         return [
 | 
        
           |  |  | 637 |             'Range, branch in support, lowest' => [
 | 
        
           |  |  | 638 |                 'supported' => [29, 31],
 | 
        
           |  |  | 639 |                 'incompatible' => null,
 | 
        
           |  |  | 640 |                 'version' => 29,
 | 
        
           |  |  | 641 |                 'expected' => core_plugin_manager::VERSION_SUPPORTED,
 | 
        
           |  |  | 642 |             ],
 | 
        
           |  |  | 643 |             'Range, branch in support, mid' => [
 | 
        
           |  |  | 644 |                 'supported' => [29, 31],
 | 
        
           |  |  | 645 |                 'incompatible' => null,
 | 
        
           |  |  | 646 |                 'version' => 30,
 | 
        
           |  |  | 647 |                 'expected' => core_plugin_manager::VERSION_SUPPORTED,
 | 
        
           |  |  | 648 |             ],
 | 
        
           |  |  | 649 |             'Range, branch in support, highest' => [
 | 
        
           |  |  | 650 |                 'supported' => [29, 31],
 | 
        
           |  |  | 651 |                 'incompatible' => null,
 | 
        
           |  |  | 652 |                 'version' => 31,
 | 
        
           |  |  | 653 |                 'expected' => core_plugin_manager::VERSION_SUPPORTED,
 | 
        
           |  |  | 654 |             ],
 | 
        
           |  |  | 655 |   | 
        
           |  |  | 656 |             'Range, branch not in support, high' => [
 | 
        
           |  |  | 657 |                 'supported' => [29, 31],
 | 
        
           |  |  | 658 |                 'incompatible' => null,
 | 
        
           |  |  | 659 |                 'version' => 32,
 | 
        
           |  |  | 660 |                 'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
 | 
        
           |  |  | 661 |             ],
 | 
        
           |  |  | 662 |             'Range, branch not in support, low' => [
 | 
        
           |  |  | 663 |                 'supported' => [29, 31],
 | 
        
           |  |  | 664 |                 'incompatible' => null,
 | 
        
           |  |  | 665 |                 'version' => 28,
 | 
        
           |  |  | 666 |                 'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
 | 
        
           |  |  | 667 |             ],
 | 
        
           |  |  | 668 |             'Range, incompatible, high.' => [
 | 
        
           |  |  | 669 |                 'supported' => [29, 31],
 | 
        
           |  |  | 670 |                 'incompatible' => 32,
 | 
        
           |  |  | 671 |                 'version' => 33,
 | 
        
           |  |  | 672 |                 'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
 | 
        
           |  |  | 673 |             ],
 | 
        
           |  |  | 674 |             'Range, incompatible, low.' => [
 | 
        
           |  |  | 675 |                 'supported' => [29, 31],
 | 
        
           |  |  | 676 |                 'incompatible' => 32,
 | 
        
           |  |  | 677 |                 'version' => 31,
 | 
        
           |  |  | 678 |                 'expected' => core_plugin_manager::VERSION_SUPPORTED,
 | 
        
           |  |  | 679 |             ],
 | 
        
           |  |  | 680 |             'Range, incompatible, equal.' => [
 | 
        
           |  |  | 681 |                 'supported' => [29, 31],
 | 
        
           |  |  | 682 |                 'incompatible' => 32,
 | 
        
           |  |  | 683 |                 'version' => 32,
 | 
        
           |  |  | 684 |                 'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
 | 
        
           |  |  | 685 |             ],
 | 
        
           |  |  | 686 |             'No supports' => [
 | 
        
           |  |  | 687 |                 'supported' => null,
 | 
        
           |  |  | 688 |                 'incompatible' => null,
 | 
        
           |  |  | 689 |                 'version' => 32,
 | 
        
           |  |  | 690 |                 'expected' => core_plugin_manager::VERSION_NO_SUPPORTS,
 | 
        
           |  |  | 691 |             ],
 | 
        
           |  |  | 692 |             'No supports, but incompatible, older' => [
 | 
        
           |  |  | 693 |                 'supported' => null,
 | 
        
           |  |  | 694 |                 'incompatible' => 30,
 | 
        
           |  |  | 695 |                 'version' => 32,
 | 
        
           |  |  | 696 |                 'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
 | 
        
           |  |  | 697 |             ],
 | 
        
           |  |  | 698 |             'No supports, but incompatible, equal' => [
 | 
        
           |  |  | 699 |                 'supported' => null,
 | 
        
           |  |  | 700 |                 'incompatible' => 32,
 | 
        
           |  |  | 701 |                 'version' => 32,
 | 
        
           |  |  | 702 |                 'expected' => core_plugin_manager::VERSION_NOT_SUPPORTED,
 | 
        
           |  |  | 703 |             ],
 | 
        
           |  |  | 704 |             'No supports, but incompatible, newer' => [
 | 
        
           |  |  | 705 |                 'supported' => null,
 | 
        
           |  |  | 706 |                 'incompatible' => 34,
 | 
        
           |  |  | 707 |                 'version' => 32,
 | 
        
           |  |  | 708 |                 'expected' => core_plugin_manager::VERSION_NO_SUPPORTS,
 | 
        
           |  |  | 709 |             ],
 | 
        
           |  |  | 710 |         ];
 | 
        
           |  |  | 711 |     }
 | 
        
           |  |  | 712 |   | 
        
           |  |  | 713 |     /**
 | 
        
           |  |  | 714 |      * @dataProvider is_deleted_standard_plugin_provider
 | 
        
           |  |  | 715 |      */
 | 
        
           |  |  | 716 |     public function test_is_deleted_standard_plugin(
 | 
        
           |  |  | 717 |         mixed $type,
 | 
        
           |  |  | 718 |         mixed $name,
 | 
        
           |  |  | 719 |         bool $expected,
 | 
        
           |  |  | 720 |     ): void {
 | 
        
           |  |  | 721 |         $this->assertEquals(
 | 
        
           |  |  | 722 |             $expected,
 | 
        
           |  |  | 723 |             \core_plugin_manager::is_deleted_standard_plugin($type, $name),
 | 
        
           |  |  | 724 |         );
 | 
        
           |  |  | 725 |     }
 | 
        
           |  |  | 726 |   | 
        
           |  |  | 727 |     public static function is_deleted_standard_plugin_provider(): array {
 | 
        
           |  |  | 728 |         return [
 | 
        
           |  |  | 729 |             // Valid deleted plugin.
 | 
        
           |  |  | 730 |             ['h5plib', 'v124', true],
 | 
        
           |  |  | 731 |             // Valid type, but not a valid plugin.
 | 
        
           |  |  | 732 |             ['h5plib', 'v99', false],
 | 
        
           |  |  | 733 |             // Invalid type.
 | 
        
           |  |  | 734 |             ['marmelade', 'paddington', false],
 | 
        
           |  |  | 735 |         ];
 | 
        
           |  |  | 736 |     }
 | 
        
           |  |  | 737 |   | 
        
           |  |  | 738 |     public function test_get_deleted_plugins(): void {
 | 
        
           |  |  | 739 |         $plugins = core_plugin_manager::get_deleted_plugins();
 | 
        
           |  |  | 740 |         $this->assertIsArray($plugins);
 | 
        
           |  |  | 741 |   | 
        
           |  |  | 742 |         // Pick a couple we know should be there.
 | 
        
           |  |  | 743 |         $this->assertContains('h5plib_v124', $plugins);
 | 
        
           |  |  | 744 |         $this->assertNotContains('h5plib_v99', $plugins);
 | 
        
           |  |  | 745 |   | 
        
           |  |  | 746 |         $this->assertContains('editor_tinymce', $plugins);
 | 
        
           |  |  | 747 |         $this->assertNotContains('editor_tiny', $plugins);
 | 
        
           |  |  | 748 |     }
 | 
        
           |  |  | 749 |   | 
        
           |  |  | 750 |     public function test_standard_plugins_list_no_type(): void {
 | 
        
           |  |  | 751 |         $plugins = core_plugin_manager::standard_plugins_list('typo');
 | 
        
           |  |  | 752 |         $this->assertFalse($plugins);
 | 
        
           |  |  | 753 |     }
 | 
        
           |  |  | 754 |   | 
        
           |  |  | 755 |     /**
 | 
        
           |  |  | 756 |      * @dataProvider standard_plugins_list_provider
 | 
        
           |  |  | 757 |      */
 | 
        
           |  |  | 758 |     public function test_standard_plugins_list(
 | 
        
           |  |  | 759 |         string $type,
 | 
        
           |  |  | 760 |         array $expectedplugins,
 | 
        
           |  |  | 761 |     ): void {
 | 
        
           |  |  | 762 |         $plugins = core_plugin_manager::standard_plugins_list($type);
 | 
        
           |  |  | 763 |         $this->assertIsArray($plugins);
 | 
        
           |  |  | 764 |         foreach ($expectedplugins as $expected) {
 | 
        
           |  |  | 765 |             $this->assertContains($expected, $plugins);
 | 
        
           |  |  | 766 |         }
 | 
        
           |  |  | 767 |     }
 | 
        
           |  |  | 768 |   | 
        
           |  |  | 769 |     public static function standard_plugins_list_provider(): array {
 | 
        
           |  |  | 770 |         return [
 | 
        
           |  |  | 771 |             [
 | 
        
           |  |  | 772 |                 'mod',
 | 
        
           |  |  | 773 |                 ['forum', 'assign', 'book', 'choice'],
 | 
        
           |  |  | 774 |             ],
 | 
        
           |  |  | 775 |             [
 | 
        
           |  |  | 776 |                 'block',
 | 
        
           |  |  | 777 |                 ['starredcourses', 'badges'],
 | 
        
           |  |  | 778 |             ],
 | 
        
           |  |  | 779 |             [
 | 
        
           |  |  | 780 |                 'tiny',
 | 
        
           |  |  | 781 |                 ['autosave', 'h5p'],
 | 
        
           |  |  | 782 |             ],
 | 
        
           |  |  | 783 |         ];
 | 
        
           |  |  | 784 |     }
 | 
        
           |  |  | 785 |   | 
        
           |  |  | 786 |     public function test_get_standard_plugins(): void {
 | 
        
           |  |  | 787 |         $plugins = core_plugin_manager::get_standard_plugins();
 | 
        
           |  |  | 788 |         $this->assertIsArray($plugins);
 | 
        
           |  |  | 789 |   | 
        
           |  |  | 790 |         $this->assertContains('mod_forum', $plugins);
 | 
        
           |  |  | 791 |         $this->assertContains('block_badges', $plugins);
 | 
        
           |  |  | 792 |         $this->assertNotContains('marmelade_paddington', $plugins);
 | 
        
           |  |  | 793 |     }
 | 
        
           | 1441 | ariadna | 794 |   | 
        
           |  |  | 795 |     /**
 | 
        
           |  |  | 796 |      * Test core_plugin_manager when dealing with deprecated plugin (not subplugin) types.
 | 
        
           |  |  | 797 |      *
 | 
        
           |  |  | 798 |      * @runInSeparateProcess
 | 
        
           |  |  | 799 |      * @return void
 | 
        
           |  |  | 800 |      */
 | 
        
           |  |  | 801 |     public function test_plugin_manager_deprecated_plugintype(): void {
 | 
        
           |  |  | 802 |         $this->resetAfterTest();
 | 
        
           |  |  | 803 |   | 
        
           |  |  | 804 |         // Inject the mock plugin 'fake_fullfeatured' and deprecate it.
 | 
        
           |  |  | 805 |         $this->add_full_mocked_plugintype(
 | 
        
           |  |  | 806 |             plugintype: 'fake',
 | 
        
           |  |  | 807 |             path: 'lib/tests/fixtures/fakeplugins/fake',
 | 
        
           |  |  | 808 |         );
 | 
        
           |  |  | 809 |         $this->deprecate_full_mocked_plugintype('fake');
 | 
        
           |  |  | 810 |   | 
        
           |  |  | 811 |         // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
 | 
        
           |  |  | 812 |         // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
 | 
        
           |  |  | 813 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 814 |   | 
        
           |  |  | 815 |         // Deprecated plugin type are excluded from the following for B/C.
 | 
        
           |  |  | 816 |         $this->assertArrayNotHasKey('fake', $pluginman->get_plugin_types());
 | 
        
           |  |  | 817 |         $this->assertNull($pluginman->get_enabled_plugins('fake'));
 | 
        
           |  |  | 818 |   | 
        
           |  |  | 819 |         // Deprecated plugins excluded by default for B/C, but can be included by request.
 | 
        
           |  |  | 820 |         $this->assertArrayNotHasKey('fake', $pluginman->get_plugins());
 | 
        
           |  |  | 821 |         $plugins = $pluginman->get_plugins(true);
 | 
        
           |  |  | 822 |         $this->assertArrayHasKey('fake', $plugins);
 | 
        
           |  |  | 823 |   | 
        
           |  |  | 824 |         /** @var base $plugininfo */
 | 
        
           |  |  | 825 |         $plugininfo = $plugins['fake']['fullfeatured'];
 | 
        
           |  |  | 826 |         $this->assertNull($plugininfo->is_enabled());
 | 
        
           |  |  | 827 |         $this->assertTrue($plugininfo->is_deprecated());
 | 
        
           |  |  | 828 |         $this->assertFalse($plugininfo->is_deleted());
 | 
        
           |  |  | 829 |         $this->assertTrue($plugininfo->is_uninstall_allowed());
 | 
        
           |  |  | 830 |         $this->assertIsString($plugininfo->full_path('version.php'));
 | 
        
           |  |  | 831 |         $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
 | 
        
           |  |  | 832 |         $this->assertFalse($plugininfo->get_parent_plugin());
 | 
        
           |  |  | 833 |         $this->assertNotEmpty($plugininfo->versiondisk);
 | 
        
           |  |  | 834 |         $this->assertStringContainsString('/fake/', $plugininfo->get_dir());
 | 
        
           |  |  | 835 |   | 
        
           |  |  | 836 |         $this->assertArrayNotHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake'));
 | 
        
           |  |  | 837 |         $this->assertArrayHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake', true));
 | 
        
           |  |  | 838 |   | 
        
           |  |  | 839 |         // Deprecated plugins included in the following.
 | 
        
           |  |  | 840 |         $this->assertArrayHasKey('fullfeatured', $pluginman->get_present_plugins('fake')); // Plugins on disk.
 | 
        
           |  |  | 841 |         $this->assertArrayHasKey('fullfeatured', $pluginman->get_installed_plugins('fake')); // Plugins with DB config.
 | 
        
           |  |  | 842 |         $this->assertInstanceOf(\fake_plugininfo::class, $pluginman->get_plugin_info('fake_fullfeatured'));
 | 
        
           |  |  | 843 |         $this->assertIsString($pluginman->get_plugintype_root('fake'));
 | 
        
           |  |  | 844 |         $this->assertTrue($pluginman->can_uninstall_plugin('fake_fullfeatured'));
 | 
        
           |  |  | 845 |         $uninstallurl = $pluginman->get_uninstall_url('fake_fullfeatured');
 | 
        
           |  |  | 846 |         $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
 | 
        
           |  |  | 847 |         $this->assertEquals('fake_fullfeatured', $uninstallurl->param('uninstall'));
 | 
        
           |  |  | 848 |   | 
        
           |  |  | 849 |         // Strings are supported for deprecated plugins.
 | 
        
           |  |  | 850 |         $this->assertEquals('Fake full featured plugin', $pluginman->plugin_name('fake_fullfeatured'));
 | 
        
           |  |  | 851 |         $this->assertEquals('fake', $pluginman->plugintype_name('fake'));
 | 
        
           |  |  | 852 |         $this->assertEquals('fake', $pluginman->plugintype_name_plural('fake'));
 | 
        
           |  |  | 853 |     }
 | 
        
           |  |  | 854 |   | 
        
           |  |  | 855 |     /**
 | 
        
           |  |  | 856 |      * Test core_plugin_manager when dealing with deprecated subplugin types.
 | 
        
           |  |  | 857 |      *
 | 
        
           |  |  | 858 |      * @runInSeparateProcess
 | 
        
           |  |  | 859 |      * @return void
 | 
        
           |  |  | 860 |      */
 | 
        
           |  |  | 861 |     public function test_plugin_manager_deprecated_subplugintype(): void {
 | 
        
           |  |  | 862 |         $this->resetAfterTest();
 | 
        
           |  |  | 863 |   | 
        
           |  |  | 864 |         // Inject the 'fake' plugin type. This includes three mock subplugins:
 | 
        
           |  |  | 865 |         // 1. fullsubtype_example: a regular plugin type, not deprecated, nor deleted.
 | 
        
           |  |  | 866 |         // 2. fulldeprecatedsubtype_test: a deprecated subplugin type.
 | 
        
           |  |  | 867 |         // 3. fulldeletedsubtype_demo: a deleted subplugin type.
 | 
        
           |  |  | 868 |         $this->add_full_mocked_plugintype(
 | 
        
           |  |  | 869 |             plugintype: 'fake',
 | 
        
           |  |  | 870 |             path: 'lib/tests/fixtures/fakeplugins/fake',
 | 
        
           |  |  | 871 |             subpluginsupport: true
 | 
        
           |  |  | 872 |         );
 | 
        
           |  |  | 873 |   | 
        
           |  |  | 874 |         // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
 | 
        
           |  |  | 875 |         // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
 | 
        
           |  |  | 876 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 877 |   | 
        
           |  |  | 878 |         // Deprecated plugin type are excluded from the following for B/C.
 | 
        
           |  |  | 879 |         $this->assertArrayNotHasKey('fulldeprecatedsubtype', $pluginman->get_plugin_types());
 | 
        
           |  |  | 880 |         $this->assertNull($pluginman->get_enabled_plugins('fulldeprecatedsubtype'));
 | 
        
           |  |  | 881 |         $subplugins = $pluginman->get_subplugins();
 | 
        
           |  |  | 882 |         $this->assertArrayHasKey('fake_fullfeatured', $subplugins);
 | 
        
           |  |  | 883 |         $fullfeaturedplug = $subplugins['fake_fullfeatured'];
 | 
        
           |  |  | 884 |         $this->assertArrayHasKey('fullsubtype', $fullfeaturedplug);
 | 
        
           |  |  | 885 |         $this->assertArrayNotHasKey('fulldeprecatedsubtype', $fullfeaturedplug);
 | 
        
           |  |  | 886 |         $this->assertArrayHasKey('fullsubtype_example', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
 | 
        
           |  |  | 887 |         $this->assertArrayNotHasKey('fulldeprecatedsubtype_test', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
 | 
        
           |  |  | 888 |   | 
        
           |  |  | 889 |         // Deprecated plugins excluded by default for B/C, but can be included by request.
 | 
        
           |  |  | 890 |         $this->assertArrayNotHasKey('fulldeprecatedsubtype', $pluginman->get_plugins());
 | 
        
           |  |  | 891 |         $plugins = $pluginman->get_plugins(true);
 | 
        
           |  |  | 892 |         $this->assertArrayHasKey('fulldeprecatedsubtype', $plugins);
 | 
        
           |  |  | 893 |   | 
        
           |  |  | 894 |         /** @var base $plugininfo */
 | 
        
           |  |  | 895 |         $plugininfo = $plugins['fulldeprecatedsubtype']['test'];
 | 
        
           |  |  | 896 |         $this->assertNull($plugininfo->is_enabled());
 | 
        
           |  |  | 897 |         $this->assertTrue($plugininfo->is_deprecated());
 | 
        
           |  |  | 898 |         $this->assertFalse($plugininfo->is_deleted());
 | 
        
           |  |  | 899 |         $this->assertTrue($plugininfo->is_uninstall_allowed());
 | 
        
           |  |  | 900 |         $this->assertIsString($plugininfo->full_path('version.php'));
 | 
        
           |  |  | 901 |         $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
 | 
        
           |  |  | 902 |         $this->assertEquals('fake_fullfeatured', $plugininfo->get_parent_plugin());
 | 
        
           |  |  | 903 |         $this->assertNotEmpty($plugininfo->versiondisk);
 | 
        
           |  |  | 904 |         $this->assertStringContainsString('/fulldeprecatedsubtype/', $plugininfo->get_dir());
 | 
        
           |  |  | 905 |   | 
        
           |  |  | 906 |         $this->assertArrayNotHasKey('test', $pluginman->get_plugins_of_type('fulldeprecatedsubtype'));
 | 
        
           |  |  | 907 |         $this->assertArrayHasKey('test', $pluginman->get_plugins_of_type('fulldeprecatedsubtype', true));
 | 
        
           |  |  | 908 |   | 
        
           |  |  | 909 |         $this->assertFalse($pluginman->get_parent_of_subplugin('fulldeprecatedsubtype'));
 | 
        
           |  |  | 910 |         $this->assertEquals('fake_fullfeatured', $pluginman->get_parent_of_subplugin('fulldeprecatedsubtype', true));
 | 
        
           |  |  | 911 |   | 
        
           |  |  | 912 |         // Deprecated plugins included in the following.
 | 
        
           |  |  | 913 |         $this->assertArrayHasKey('test', $pluginman->get_present_plugins('fulldeprecatedsubtype')); // Plugins on disk.
 | 
        
           |  |  | 914 |         $this->assertArrayHasKey('test', $pluginman->get_installed_plugins('fulldeprecatedsubtype')); // Plugins with DB config.
 | 
        
           |  |  | 915 |         $this->assertInstanceOf(\fake_fullfeatured\plugininfo\fulldeprecatedsubtype::class,
 | 
        
           |  |  | 916 |             $pluginman->get_plugin_info('fulldeprecatedsubtype_test'));
 | 
        
           |  |  | 917 |         $this->assertEquals('Full deprecated subtype test', $pluginman->plugin_name('fulldeprecatedsubtype_test'));
 | 
        
           |  |  | 918 |         $this->assertIsString($pluginman->get_plugintype_root('fulldeprecatedsubtype'));
 | 
        
           |  |  | 919 |         $this->assertTrue($pluginman->can_uninstall_plugin('fulldeprecatedsubtype_test'));
 | 
        
           |  |  | 920 |         $uninstallurl = $pluginman->get_uninstall_url('fulldeprecatedsubtype_test');
 | 
        
           |  |  | 921 |         $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
 | 
        
           |  |  | 922 |         $this->assertEquals('fulldeprecatedsubtype_test', $uninstallurl->param('uninstall'));
 | 
        
           |  |  | 923 |     }
 | 
        
           |  |  | 924 |   | 
        
           |  |  | 925 |     /**
 | 
        
           |  |  | 926 |      * Test core_plugin_manager when dealing with deleted plugin (not subplugin) types.
 | 
        
           |  |  | 927 |      *
 | 
        
           |  |  | 928 |      * @runInSeparateProcess
 | 
        
           |  |  | 929 |      * @return void
 | 
        
           |  |  | 930 |      */
 | 
        
           |  |  | 931 |     public function test_plugin_manager_deleted_plugintype(): void {
 | 
        
           |  |  | 932 |         $this->resetAfterTest();
 | 
        
           |  |  | 933 |   | 
        
           |  |  | 934 |         // Inject the mock plugin 'fake_fullfeatured', and deprecate it.
 | 
        
           |  |  | 935 |         $this->add_full_mocked_plugintype(
 | 
        
           |  |  | 936 |             plugintype: 'fake',
 | 
        
           |  |  | 937 |             path: 'lib/tests/fixtures/fakeplugins/fake',
 | 
        
           |  |  | 938 |         );
 | 
        
           |  |  | 939 |         $this->delete_full_mocked_plugintype('fake');
 | 
        
           |  |  | 940 |   | 
        
           |  |  | 941 |         // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
 | 
        
           |  |  | 942 |         // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
 | 
        
           |  |  | 943 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 944 |   | 
        
           |  |  | 945 |         // Deleted plugins are excluded from the following for B/C.
 | 
        
           |  |  | 946 |         $this->assertArrayNotHasKey('fake', $pluginman->get_plugin_types());
 | 
        
           |  |  | 947 |         $this->assertNull($pluginman->get_enabled_plugins('fake'));
 | 
        
           |  |  | 948 |   | 
        
           |  |  | 949 |         // Deleted plugins excluded by default for B/C, but can be included by request.
 | 
        
           |  |  | 950 |         $this->assertArrayNotHasKey('fake', $pluginman->get_plugins());
 | 
        
           |  |  | 951 |         $plugins = $pluginman->get_plugins(true);
 | 
        
           |  |  | 952 |         $this->assertArrayHasKey('fake', $plugins);
 | 
        
           |  |  | 953 |   | 
        
           |  |  | 954 |         /** @var base $plugininfo */
 | 
        
           |  |  | 955 |         $plugininfo = $plugins['fake']['fullfeatured'];
 | 
        
           |  |  | 956 |         $this->assertNull($plugininfo->is_enabled());
 | 
        
           |  |  | 957 |         $this->assertFalse($plugininfo->is_deprecated());
 | 
        
           |  |  | 958 |         $this->assertTrue($plugininfo->is_deleted());
 | 
        
           |  |  | 959 |         $this->assertTrue($plugininfo->is_uninstall_allowed());
 | 
        
           |  |  | 960 |         $this->assertIsString($plugininfo->full_path('version.php'));
 | 
        
           |  |  | 961 |         $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
 | 
        
           |  |  | 962 |         $this->assertFalse($plugininfo->get_parent_plugin());
 | 
        
           |  |  | 963 |         $this->assertNotEmpty($plugininfo->versiondisk);
 | 
        
           |  |  | 964 |         $this->assertStringContainsString('/fake/', $plugininfo->get_dir());
 | 
        
           |  |  | 965 |   | 
        
           |  |  | 966 |         $this->assertArrayNotHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake'));
 | 
        
           |  |  | 967 |         $this->assertArrayHasKey('fullfeatured', $pluginman->get_plugins_of_type('fake', true));
 | 
        
           |  |  | 968 |   | 
        
           |  |  | 969 |         // Deleted plugins included in the following.
 | 
        
           |  |  | 970 |         $this->assertArrayHasKey('fullfeatured', $pluginman->get_present_plugins('fake')); // Plugins on disk.
 | 
        
           |  |  | 971 |         $this->assertArrayHasKey('fullfeatured', $pluginman->get_installed_plugins('fake')); // Plugins with DB config.
 | 
        
           |  |  | 972 |         $this->assertInstanceOf(\fake_plugininfo::class, $pluginman->get_plugin_info('fake_fullfeatured'));
 | 
        
           |  |  | 973 |         $this->assertIsString($pluginman->get_plugintype_root('fake'));
 | 
        
           |  |  | 974 |         $this->assertTrue($pluginman->can_uninstall_plugin('fake_fullfeatured'));
 | 
        
           |  |  | 975 |         $uninstallurl = $pluginman->get_uninstall_url('fake_fullfeatured');
 | 
        
           |  |  | 976 |         $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
 | 
        
           |  |  | 977 |         $this->assertEquals('fake_fullfeatured', $uninstallurl->param('uninstall'));
 | 
        
           |  |  | 978 |   | 
        
           |  |  | 979 |         // Included, but there is no string support for deleted plugin types.
 | 
        
           |  |  | 980 |         // Without string support, the type name defaults to the plugin type,
 | 
        
           |  |  | 981 |         // while plugin name is set in \core\plugininfo\base::init_is_deprecated().
 | 
        
           |  |  | 982 |         $this->assertEquals('fullfeatured', $pluginman->plugin_name('fake_fullfeatured'));
 | 
        
           |  |  | 983 |         $this->assertEquals('fake', $pluginman->plugintype_name('fake'));
 | 
        
           |  |  | 984 |         $this->assertEquals('fake', $pluginman->plugintype_name_plural('fake'));
 | 
        
           |  |  | 985 |     }
 | 
        
           |  |  | 986 |   | 
        
           |  |  | 987 |     /**
 | 
        
           |  |  | 988 |      * Test core_plugin_manager when dealing with deleted subplugin types.
 | 
        
           |  |  | 989 |      *
 | 
        
           |  |  | 990 |      * @runInSeparateProcess
 | 
        
           |  |  | 991 |      * @return void
 | 
        
           |  |  | 992 |      */
 | 
        
           |  |  | 993 |     public function test_plugin_manager_deleted_subplugintype(): void {
 | 
        
           |  |  | 994 |         $this->resetAfterTest();
 | 
        
           |  |  | 995 |   | 
        
           |  |  | 996 |         // Inject the 'fake' plugin type. This includes three mock subplugins:
 | 
        
           |  |  | 997 |         // 1. fullsubtype_example: a regular plugin type, not deprecated, nor deleted.
 | 
        
           |  |  | 998 |         // 2. fulldeprecatedsubtype_test: a deprecated subplugin type.
 | 
        
           |  |  | 999 |         // 3. fulldeletedsubtype_demo: a deleted subplugin type.
 | 
        
           |  |  | 1000 |         $this->add_full_mocked_plugintype(
 | 
        
           |  |  | 1001 |             plugintype: 'fake',
 | 
        
           |  |  | 1002 |             path: 'lib/tests/fixtures/fakeplugins/fake',
 | 
        
           |  |  | 1003 |             subpluginsupport: true
 | 
        
           |  |  | 1004 |         );
 | 
        
           |  |  | 1005 |   | 
        
           |  |  | 1006 |         // Use testable_plugin_manager, as this properly loads the mocked fake_plugininfo class, meaning the fake plugins are
 | 
        
           |  |  | 1007 |         // recognised by the plugin manager. See testable_plugin_manager::resolve_plugininfo_class().
 | 
        
           |  |  | 1008 |         $pluginman = testable_core_plugin_manager::instance();
 | 
        
           |  |  | 1009 |   | 
        
           |  |  | 1010 |         // Deleted plugin type are excluded from the following for B/C.
 | 
        
           |  |  | 1011 |         $this->assertArrayNotHasKey('fulldeletedsubtype', $pluginman->get_plugin_types());
 | 
        
           |  |  | 1012 |         $this->assertNull($pluginman->get_enabled_plugins('fulldeletedsubtype'));
 | 
        
           |  |  | 1013 |         $subplugins = $pluginman->get_subplugins();
 | 
        
           |  |  | 1014 |         $this->assertArrayHasKey('fake_fullfeatured', $subplugins);
 | 
        
           |  |  | 1015 |         $fullfeaturedplug = $subplugins['fake_fullfeatured'];
 | 
        
           |  |  | 1016 |         $this->assertArrayHasKey('fullsubtype', $fullfeaturedplug);
 | 
        
           |  |  | 1017 |         $this->assertArrayNotHasKey('fulldeletedsubtype', $fullfeaturedplug);
 | 
        
           |  |  | 1018 |         $this->assertArrayHasKey('fullsubtype_example', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
 | 
        
           |  |  | 1019 |         $this->assertArrayNotHasKey('fulldeletedsubtype_demo', $pluginman->get_subplugins_of_plugin('fake_fullfeatured'));
 | 
        
           |  |  | 1020 |   | 
        
           |  |  | 1021 |         // Deleted plugins excluded by default for B/C, but can be included by request.
 | 
        
           |  |  | 1022 |         $this->assertArrayNotHasKey('fulldeletedsubtype', $pluginman->get_plugins());
 | 
        
           |  |  | 1023 |         $plugins = $pluginman->get_plugins(true);
 | 
        
           |  |  | 1024 |         $this->assertArrayHasKey('fulldeletedsubtype', $plugins);
 | 
        
           |  |  | 1025 |   | 
        
           |  |  | 1026 |         /** @var base $plugininfo */
 | 
        
           |  |  | 1027 |         $plugininfo = $plugins['fulldeletedsubtype']['demo'];
 | 
        
           |  |  | 1028 |         $this->assertNull($plugininfo->is_enabled());
 | 
        
           |  |  | 1029 |         $this->assertFalse($plugininfo->is_deprecated());
 | 
        
           |  |  | 1030 |         $this->assertTrue($plugininfo->is_deleted());
 | 
        
           |  |  | 1031 |         $this->assertTrue($plugininfo->is_uninstall_allowed());
 | 
        
           |  |  | 1032 |         $this->assertIsString($plugininfo->full_path('version.php'));
 | 
        
           |  |  | 1033 |         $this->assertEquals(\core_plugin_manager::PLUGIN_STATUS_UPTODATE, $plugininfo->get_status());
 | 
        
           |  |  | 1034 |         $this->assertEquals('fake_fullfeatured', $plugininfo->get_parent_plugin());
 | 
        
           |  |  | 1035 |         $this->assertNotEmpty($plugininfo->versiondisk);
 | 
        
           |  |  | 1036 |         $this->assertStringContainsString('/fulldeletedsubtype/', $plugininfo->get_dir());
 | 
        
           |  |  | 1037 |   | 
        
           |  |  | 1038 |         $this->assertArrayNotHasKey('demo', $pluginman->get_plugins_of_type('fulldeletedsubtype'));
 | 
        
           |  |  | 1039 |         $this->assertArrayHasKey('demo', $pluginman->get_plugins_of_type('fulldeletedsubtype', true));
 | 
        
           |  |  | 1040 |   | 
        
           |  |  | 1041 |         $this->assertFalse($pluginman->get_parent_of_subplugin('fulldeletedsubtype'));
 | 
        
           |  |  | 1042 |         $this->assertEquals('fake_fullfeatured', $pluginman->get_parent_of_subplugin('fulldeletedsubtype', true));
 | 
        
           |  |  | 1043 |   | 
        
           |  |  | 1044 |         // Deprecated plugins included in the following.
 | 
        
           |  |  | 1045 |         $this->assertArrayHasKey('demo', $pluginman->get_present_plugins('fulldeletedsubtype')); // Plugins on disk.
 | 
        
           |  |  | 1046 |         $this->assertArrayHasKey('demo', $pluginman->get_installed_plugins('fulldeletedsubtype')); // Plugins with DB config.
 | 
        
           |  |  | 1047 |         $this->assertInstanceOf(\fake_fullfeatured\plugininfo\fulldeletedsubtype::class,
 | 
        
           |  |  | 1048 |             $pluginman->get_plugin_info('fulldeletedsubtype_demo'));
 | 
        
           |  |  | 1049 |         $this->assertIsString($pluginman->get_plugintype_root('fulldeletedsubtype'));
 | 
        
           |  |  | 1050 |         $this->assertTrue($pluginman->can_uninstall_plugin('fulldeletedsubtype_demo'));
 | 
        
           |  |  | 1051 |         $uninstallurl = $pluginman->get_uninstall_url('fulldeletedsubtype_demo');
 | 
        
           |  |  | 1052 |         $this->assertInstanceOf(\moodle_url::class, $uninstallurl);
 | 
        
           |  |  | 1053 |         $this->assertEquals('fulldeletedsubtype_demo', $uninstallurl->param('uninstall'));
 | 
        
           |  |  | 1054 |   | 
        
           |  |  | 1055 |         // Included, but there is no string support for deleted plugin types.
 | 
        
           |  |  | 1056 |         // Without string support, the type name defaults to the plugin type,
 | 
        
           |  |  | 1057 |         // while plugin name is set in \core\plugininfo\base::init_is_deprecated().
 | 
        
           |  |  | 1058 |         $this->assertEquals('demo', $pluginman->plugin_name('fulldeletedsubtype_demo'));
 | 
        
           |  |  | 1059 |         $this->assertEquals('fulldeletedsubtype', $pluginman->plugintype_name('fulldeletedsubtype'));
 | 
        
           |  |  | 1060 |         $this->assertEquals('fulldeletedsubtype', $pluginman->plugintype_name_plural('fulldeletedsubtype'));
 | 
        
           |  |  | 1061 |     }
 | 
        
           | 1 | efrain | 1062 | }
 |