Merge branch 'patch/MDL-85666-404' of https://github.com/skodak/moodle into MOODLE_404_STABLE
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace tool_capability;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Detect common problems in capability definitions of plugins.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @package tool_capability
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class plugin_checks_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Verify contents of plugin db/access.php file.
|
||||
*
|
||||
* @dataProvider all_plugins_provider
|
||||
* @coversNothing
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $plugintype
|
||||
* @param string $pluginname
|
||||
* @param string $dir
|
||||
*/
|
||||
public function test_db_access_file(string $component, string $plugintype, string $pluginname, string $dir): void {
|
||||
global $CFG;
|
||||
|
||||
$stringmanager = get_string_manager();
|
||||
$corerolefile = "$CFG->dirroot/lang/en/role.php";
|
||||
$langfile = "$dir/lang/en/$component.php";
|
||||
|
||||
$file = "$dir/db/access.php";
|
||||
$capabilities = $this->fetch_array_from_file($file, 'capabilities');
|
||||
if (!$capabilities) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($capabilities as $capname => $capability) {
|
||||
if ($plugintype === 'qbank' && str_starts_with($capname, 'moodle/question:')) {
|
||||
// Question bank capabilities are irregular.
|
||||
$strname = explode('/', $capname, 2)[1];
|
||||
$this->assertTrue($stringmanager->string_exists($strname, 'core_role'),
|
||||
"Missing capability name string '$strname' in $corerolefile");
|
||||
continue;
|
||||
}
|
||||
$this->assertMatchesRegularExpression("|^$plugintype/$pluginname:[a-z0-9_]+$|", $capname);
|
||||
$strname = substr($capname, strlen($plugintype) + 1);
|
||||
$this->assertTrue($stringmanager->string_exists($strname, $component),
|
||||
"Missing capability name string '$strname' in $langfile");
|
||||
$this->assertSame($capname, clean_param($capname, PARAM_CAPABILITY));
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -391,6 +391,7 @@ final class external_api_test extends \advanced_testcase {
|
||||
/**
|
||||
* Test \core_external\external_api::external_function_info.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @runInSeparateProcess
|
||||
* @dataProvider all_external_info_provider
|
||||
* @covers \core_external\external_api::external_function_info
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_external;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Detect common problems in plugin external API.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @package core_external
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class plugin_checks_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Verify plugin external API definition files.
|
||||
*
|
||||
* @dataProvider all_plugins_provider
|
||||
* @coversNothing
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $plugintype
|
||||
* @param string $pluginname
|
||||
* @param string $dir
|
||||
*/
|
||||
public function test_db_services_file(string $component, string $plugintype, string $pluginname, string $dir): void {
|
||||
$file = "$dir/db/services.php";
|
||||
$functions = $this->fetch_array_from_file($file, 'functions');
|
||||
if (!$functions) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($functions as $wsname => $definition) {
|
||||
$this->assertStringStartsWith($component . '_', $wsname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\tests;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Base class for general testing of plugin features and APIs.
|
||||
* The test must not modify database or any global state.
|
||||
*
|
||||
* Following is required to allow filtering of test by Frankenstyle plugin name:
|
||||
* - all providers used in the tests must use components as keys of provider data
|
||||
* - all tests must include group "plugin_checks"
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class plugin_checks_testcase extends \basic_testcase {
|
||||
/**
|
||||
* Data provider for testing of all available plugins.
|
||||
*
|
||||
* @return array as array of [component, plugintype, pluginname, dir]
|
||||
*/
|
||||
public static function all_plugins_provider(): array {
|
||||
$result = [];
|
||||
foreach (\core_component::get_plugin_types() as $plugintype => $unused) {
|
||||
foreach (\core_component::get_plugin_list($plugintype) as $pluginname => $dir) {
|
||||
$component = $plugintype . '_' . $pluginname;
|
||||
$result[$component] = [$component, $plugintype, $pluginname, $dir];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include file and return an array variable defined in its global scope.
|
||||
* This is intended primarily for files inside plugin /db/ subdirectory.
|
||||
*
|
||||
* @param string $phpfile
|
||||
* @param string $variablename
|
||||
* @return array|null NULL means file does not exist
|
||||
*/
|
||||
protected function fetch_array_from_file(string $phpfile, string $variablename): ?array {
|
||||
if (!file_exists($phpfile)) {
|
||||
return null;
|
||||
}
|
||||
require($phpfile);
|
||||
return $$variablename;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\db;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Detect common problems in plugin database structures.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @package core
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class plugin_checks_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Verify plugin db/install.xml file.
|
||||
*
|
||||
* @dataProvider all_plugins_provider
|
||||
* @coversNothing
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $plugintype
|
||||
* @param string $pluginname
|
||||
* @param string $dir
|
||||
*/
|
||||
public function test_db_install_file(string $component, string $plugintype, string $pluginname, string $dir): void {
|
||||
global $DB;
|
||||
$DB->get_manager(); // Preload XMLDB classes.
|
||||
|
||||
$file = "$dir/db/install.xml";
|
||||
if (!file_exists($file)) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
|
||||
$rawcontents = file_get_contents($file);
|
||||
$xmldb = new \xmldb_file($file);
|
||||
$xmldb->loadXMLStructure();
|
||||
$xmlcontents = $xmldb->getStructure()->xmlOutput();
|
||||
$this->assertSame($xmlcontents, $rawcontents,
|
||||
"Unexpected install.xml format detected, reconciliation needed in $file");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\event;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Detect common problems in plugin events.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @package core
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class plugin_checks_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Verify all plugin events.
|
||||
*
|
||||
* @dataProvider all_plugins_provider
|
||||
* @coversNothing
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $plugintype
|
||||
* @param string $pluginname
|
||||
* @param string $dir
|
||||
*/
|
||||
public function test_event_classes(string $component, string $plugintype, string $pluginname, string $dir): void {
|
||||
$events = \core_component::get_component_classes_in_namespace($component, 'event');
|
||||
if (!$events) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($events as $eventclassname => $unused) {
|
||||
$rc = new \ReflectionClass($eventclassname);
|
||||
if ($rc->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
if (!is_subclass_of($eventclassname, \core\event\base::class)) {
|
||||
// Most likely an observer in irregular location, ignore for now.
|
||||
continue;
|
||||
}
|
||||
$this->assertIsString($eventclassname::get_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\output;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Detect common problems in plugin output and them related code.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @package core
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class plugin_checks_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Verify plugin defines FA icon fallbacks.
|
||||
*
|
||||
* @dataProvider all_plugins_provider
|
||||
* @coversNothing
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $plugintype
|
||||
* @param string $pluginname
|
||||
* @param string $dir
|
||||
*/
|
||||
public function test_get_fontawesome_icon_map(string $component, string $plugintype, string $pluginname, string $dir): void {
|
||||
$iconmap = component_callback($component, 'get_fontawesome_icon_map');
|
||||
if (!$iconmap) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($iconmap as $componenticon => $fa) {
|
||||
list($iconcomponent, $iconname) = explode(':', $componenticon, 2);
|
||||
$svgfile = "$dir/pix/$iconname.svg";
|
||||
$this->assertFileExists($svgfile, "No SVG equivalent found for icon '$componenticon'");
|
||||
$this->assertSame($component, $iconcomponent,
|
||||
"Unexpected icon component found in {$component}_get_fontawesome_icon_map() function");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core\task;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Detect common problems in plugin tasks.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @package core
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class plugin_checks_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Verify plugin all plugin tasks.
|
||||
*
|
||||
* @dataProvider all_plugins_provider
|
||||
* @coversNothing
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $plugintype
|
||||
* @param string $pluginname
|
||||
* @param string $dir
|
||||
*/
|
||||
public function test_db_tasks_file(string $component, string $plugintype, string $pluginname, string $dir): void {
|
||||
$file = "$dir/db/tasks.php";
|
||||
$tasks = $this->fetch_array_from_file($file, 'tasks');
|
||||
if (!$tasks) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($tasks as $task) {
|
||||
/** @var class-string<\core\task\task_base> $taskclassname */
|
||||
$taskclassname = $task['classname'];
|
||||
$t = new $taskclassname();
|
||||
$this->assertIsString($t->get_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
// This file is part of Moodle - https://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_message;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Detect common problems in message provider definitions of plugins.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @package core_message
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class plugin_checks_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Verify contents of plugin db/message.php file.
|
||||
*
|
||||
* @dataProvider all_plugins_provider
|
||||
* @coversNothing
|
||||
*
|
||||
* @param string $component
|
||||
* @param string $plugintype
|
||||
* @param string $pluginname
|
||||
* @param string $dir
|
||||
*/
|
||||
public function test_db_messages_file(string $component, string $plugintype, string $pluginname, string $dir): void {
|
||||
$stringmanager = get_string_manager();
|
||||
$langfile = "$dir/lang/en/$component.php";
|
||||
|
||||
$file = "$dir/db/messages.php";
|
||||
$messageproviders = $this->fetch_array_from_file($file, 'messageproviders');
|
||||
if (!$messageproviders) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($messageproviders as $providername => $provider) {
|
||||
$strname = 'messageprovider:' . $providername;
|
||||
$this->assertTrue($stringmanager->string_exists($strname, $component),
|
||||
"Missing capability name string '$strname' in $langfile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,6 @@ namespace mod_lesson\event;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
debugging('mod_lesson\event\highscore_added has been deprecated. Since the functionality no longer resides in the lesson module.',
|
||||
DEBUG_DEVELOPER);
|
||||
/**
|
||||
* The mod_lesson highscore added event class.
|
||||
*
|
||||
@@ -51,6 +49,10 @@ class highscore_added extends \core\event\base {
|
||||
* Set basic properties for the event.
|
||||
*/
|
||||
protected function init() {
|
||||
// phpcs:ignore moodle.Files.LineLength.TooLong
|
||||
debugging('mod_lesson\event\highscore_added has been deprecated. Since the functionality no longer resides in the lesson module.',
|
||||
DEBUG_DEVELOPER);
|
||||
|
||||
$this->data['objecttable'] = 'lesson_high_scores';
|
||||
$this->data['crud'] = 'c';
|
||||
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
|
||||
|
||||
@@ -27,8 +27,6 @@ namespace mod_lesson\event;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
debugging('mod_lesson\event\highscores_viewed has been deprecated. Since the functionality no longer resides in the lesson module.',
|
||||
DEBUG_DEVELOPER);
|
||||
/**
|
||||
* The mod_lesson highscores viewed class.
|
||||
*
|
||||
@@ -43,6 +41,10 @@ class highscores_viewed extends \core\event\base {
|
||||
* Set basic properties for the event.
|
||||
*/
|
||||
protected function init() {
|
||||
// phpcs:ignore moodle.Files.LineLength.TooLong
|
||||
debugging('mod_lesson\event\highscores_viewed has been deprecated. Since the functionality no longer resides in the lesson module.',
|
||||
DEBUG_DEVELOPER);
|
||||
|
||||
$this->data['objecttable'] = 'lesson';
|
||||
$this->data['crud'] = 'r';
|
||||
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_privacy\privacy;
|
||||
|
||||
use core_privacy\manager;
|
||||
|
||||
/**
|
||||
* Slow unit tests for all Privacy Providers that require database modifications.
|
||||
*
|
||||
* @package core_privacy
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @copyright 2025 Petr Skoda
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class provider_advanced_test extends \advanced_testcase {
|
||||
/**
|
||||
* Returns a list of frankenstyle names of core components (plugins and subsystems).
|
||||
*
|
||||
* @return array the array of frankenstyle component names with the relevant class name.
|
||||
*/
|
||||
public static function get_component_list(): array {
|
||||
$components = ['core' => [
|
||||
'component' => 'core',
|
||||
'classname' => manager::get_provider_classname_for_component('core'),
|
||||
]];
|
||||
// Get all plugins.
|
||||
$plugintypes = \core_component::get_plugin_types();
|
||||
foreach ($plugintypes as $plugintype => $typedir) {
|
||||
$plugins = \core_component::get_plugin_list($plugintype);
|
||||
foreach ($plugins as $pluginname => $plugindir) {
|
||||
$frankenstyle = $plugintype . '_' . $pluginname;
|
||||
$components[$frankenstyle] = [
|
||||
'component' => $frankenstyle,
|
||||
'classname' => manager::get_provider_classname_for_component($frankenstyle),
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
// Get all subsystems.
|
||||
foreach (\core_component::get_core_subsystems() as $name => $path) {
|
||||
if (isset($path)) {
|
||||
$frankenstyle = 'core_' . $name;
|
||||
$components[$frankenstyle] = [
|
||||
'component' => $frankenstyle,
|
||||
'classname' => manager::get_provider_classname_for_component($frankenstyle),
|
||||
];
|
||||
}
|
||||
}
|
||||
return $components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that providers do not throw an error when processing a deleted user.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @dataProvider is_user_data_provider
|
||||
* @coversNothing
|
||||
* @param string $component
|
||||
*/
|
||||
public function test_component_understands_deleted_users($component): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a user.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Delete the user and their context.
|
||||
delete_user($user);
|
||||
$usercontext = \context_user::instance($user->id);
|
||||
$usercontext->delete();
|
||||
|
||||
$contextlist = manager::component_class_callback($component, \core_privacy\local\request\core_user_data_provider::class,
|
||||
'get_contexts_for_userid', [$user->id]);
|
||||
|
||||
$this->assertInstanceOf(\core_privacy\local\request\contextlist::class, $contextlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of providers which implement the core_user_data_provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function is_user_data_provider(): array {
|
||||
return array_filter(self::get_component_list(), function($component): bool {
|
||||
return static::component_implements(
|
||||
$component['classname'],
|
||||
\core_privacy\local\request\core_user_data_provider::class
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the component's provider class implements the specified interface, either directly or as a grandchild.
|
||||
*
|
||||
* @param string $providerclass The name of the class to test.
|
||||
* @param string $interface the name of the interface we want to check.
|
||||
* @return bool Whether the class implements the interface.
|
||||
*/
|
||||
protected static function component_implements($providerclass, $interface) {
|
||||
if (class_exists($providerclass) && interface_exists($interface)) {
|
||||
return is_subclass_of($providerclass, $interface);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,13 @@
|
||||
*/
|
||||
namespace core_privacy\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_privacy\manager;
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\metadata\types\type;
|
||||
use core_privacy\local\metadata\types\database_table;
|
||||
use core_privacy\local\metadata\types\external_location;
|
||||
use core_privacy\local\metadata\types\plugin_type_link;
|
||||
use core_privacy\local\metadata\types\subsystem_link;
|
||||
use core_privacy\local\metadata\types\user_preference;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseProvider.dataProviderSyntaxMethodNotFound
|
||||
|
||||
/**
|
||||
* Unit tests for all Privacy Providers.
|
||||
@@ -40,7 +37,7 @@ use core_privacy\local\metadata\types\user_preference;
|
||||
* @copyright 2018 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class provider_test extends \advanced_testcase {
|
||||
final class provider_test extends \core\tests\plugin_checks_testcase {
|
||||
/**
|
||||
* Returns a list of frankenstyle names of core components (plugins and subsystems).
|
||||
*
|
||||
@@ -49,7 +46,7 @@ final class provider_test extends \advanced_testcase {
|
||||
public static function get_component_list(): array {
|
||||
$components = ['core' => [
|
||||
'component' => 'core',
|
||||
'classname' => manager::get_provider_classname_for_component('core')
|
||||
'classname' => manager::get_provider_classname_for_component('core'),
|
||||
]];
|
||||
// Get all plugins.
|
||||
$plugintypes = \core_component::get_plugin_types();
|
||||
@@ -80,6 +77,7 @@ final class provider_test extends \advanced_testcase {
|
||||
/**
|
||||
* Test that the specified null_provider works as expected.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @dataProvider null_provider_provider
|
||||
* @param string $component The name of the component.
|
||||
* @param string $classname The name of the class for privacy
|
||||
@@ -89,7 +87,6 @@ final class provider_test extends \advanced_testcase {
|
||||
$this->assertIsString($reason);
|
||||
|
||||
$this->assertIsString(get_string($reason, $component));
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,6 +106,7 @@ final class provider_test extends \advanced_testcase {
|
||||
/**
|
||||
* Test that the specified metadata_provider works as expected.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @dataProvider metadata_provider_provider
|
||||
* @param string $component The name of the component.
|
||||
* @param string $classname The name of the class for privacy
|
||||
@@ -150,7 +148,6 @@ final class provider_test extends \advanced_testcase {
|
||||
|
||||
// Check that the string is also correctly defined.
|
||||
$this->assertIsString(get_string($summary, $component));
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
|
||||
if ($fields = $item->get_privacy_fields()) {
|
||||
@@ -161,7 +158,6 @@ final class provider_test extends \advanced_testcase {
|
||||
|
||||
// Check that the string is also correctly defined.
|
||||
$this->assertIsString(get_string($identifier, $component));
|
||||
$this->assertDebuggingNotCalled();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,6 +166,7 @@ final class provider_test extends \advanced_testcase {
|
||||
/**
|
||||
* Test that all providers implement some form of compliant provider.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @dataProvider get_component_list
|
||||
* @param string $component frankenstyle component name, e.g. 'mod_assign'
|
||||
* @param string $classname the fully qualified provider classname
|
||||
@@ -182,29 +179,7 @@ final class provider_test extends \advanced_testcase {
|
||||
/**
|
||||
* Ensure that providers do not throw an error when processing a deleted user.
|
||||
*
|
||||
* @dataProvider is_user_data_provider
|
||||
* @param string $component
|
||||
*/
|
||||
public function test_component_understands_deleted_users($component): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create a user.
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Delete the user and their context.
|
||||
delete_user($user);
|
||||
$usercontext = \context_user::instance($user->id);
|
||||
$usercontext->delete();
|
||||
|
||||
$contextlist = manager::component_class_callback($component, \core_privacy\local\request\core_user_data_provider::class,
|
||||
'get_contexts_for_userid', [$user->id]);
|
||||
|
||||
$this->assertInstanceOf(\core_privacy\local\request\contextlist::class, $contextlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that providers do not throw an error when processing a deleted user.
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @dataProvider is_user_data_provider
|
||||
* @param string $component
|
||||
*/
|
||||
@@ -289,24 +264,32 @@ final class provider_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test that all tables with user fields are covered by metadata providers
|
||||
*
|
||||
* @group plugin_checks
|
||||
* @dataProvider get_component_list
|
||||
* @coversNothing
|
||||
* @param string $component frankenstyle component name, e.g. 'mod_assign'
|
||||
* @param string $classname the fully qualified provider classname
|
||||
*/
|
||||
public function test_table_coverage(): void {
|
||||
public function test_table_coverage(string $component, string $classname): void {
|
||||
global $DB;
|
||||
$dbman = $DB->get_manager();
|
||||
$dbman = $DB->get_manager(); // Load DDL classes.
|
||||
$tables = [];
|
||||
|
||||
foreach ($dbman->get_install_xml_files() as $filename) {
|
||||
$xmldbfile = new \xmldb_file($filename);
|
||||
if (!$xmldbfile->loadXMLStructure()) {
|
||||
continue;
|
||||
}
|
||||
$structure = $xmldbfile->getStructure();
|
||||
$tablelist = $structure->getTables();
|
||||
$filename = \core_component::get_component_directory($component) . '/db/install.xml';
|
||||
if (!file_exists($filename)) {
|
||||
$this->expectNotToPerformAssertions();
|
||||
return;
|
||||
}
|
||||
$xmldbfile = new \xmldb_file($filename);
|
||||
$this->assertTrue($xmldbfile->loadXMLStructure());;
|
||||
|
||||
foreach ($tablelist as $table) {
|
||||
if ($fields = $this->get_userid_fields($table)) {
|
||||
$tables[$table->getName()] = ' - ' . $table->getName() . ' (' . join(', ', $fields) . ')';
|
||||
}
|
||||
$structure = $xmldbfile->getStructure();
|
||||
$tablelist = $structure->getTables();
|
||||
|
||||
foreach ($tablelist as $table) {
|
||||
if ($fields = $this->get_userid_fields($table)) {
|
||||
$tables[$table->getName()] = ' - ' . $table->getName() . ' (' . join(', ', $fields) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user