mirror of
https://github.com/moodle/moodle.git
synced 2025-04-20 07:56:06 +02:00
Merge branch 'MDL-81063-main' of https://github.com/andrewnicols/moodle
This commit is contained in:
commit
a7d9658d55
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -43,8 +43,8 @@ const findMatchingTour = (tourDetails, filters) => {
|
||||
*/
|
||||
export const init = async(tourDetails, filters) => {
|
||||
const requirements = [];
|
||||
filters.forEach(filter => {
|
||||
requirements.push(import(`tool_usertours/filter_${filter}`));
|
||||
filters.forEach((filter) => {
|
||||
requirements.push(import(filter));
|
||||
});
|
||||
|
||||
const filterPlugins = await Promise.all(requirements);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
use coding_exception;
|
||||
use core\output\inplace_editable;
|
||||
|
||||
/**
|
||||
@ -534,10 +535,7 @@ class helper {
|
||||
];
|
||||
}, $tours);
|
||||
|
||||
$filternames = [];
|
||||
foreach ($filters as $filter) {
|
||||
$filternames[] = $filter::get_filter_name();
|
||||
}
|
||||
$filternames = self::get_clientside_filter_module_names($filters);
|
||||
|
||||
$PAGE->requires->js_call_amd('tool_usertours/usertours', 'init', [
|
||||
$tourdetails,
|
||||
@ -546,19 +544,48 @@ class helper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JS module names for the filters.
|
||||
*
|
||||
* @param array $filters
|
||||
* @return array
|
||||
* @throws coding_exception
|
||||
*/
|
||||
public static function get_clientside_filter_module_names(array $filters): array {
|
||||
$filternames = [];
|
||||
foreach ($filters as $filter) {
|
||||
if ($component = \core_component::get_component_from_classname($filter)) {
|
||||
$filternames[] = sprintf(
|
||||
"%s/filter_%s",
|
||||
$component,
|
||||
$filter::get_filter_name(),
|
||||
);
|
||||
} else {
|
||||
throw new \coding_exception("Could not determine component for filter class {$filter}");
|
||||
}
|
||||
}
|
||||
|
||||
return $filternames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all possible filters.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_all_filters() {
|
||||
$filters = \core_component::get_component_classes_in_namespace('tool_usertours', 'local\filter');
|
||||
$filters = array_keys($filters);
|
||||
$hook = new hook\before_serverside_filter_fetch(array_keys(
|
||||
\core_component::get_component_classes_in_namespace('tool_usertours', 'local\filter')
|
||||
));
|
||||
\core\di::get(\core\hook\manager::class)->dispatch($hook);
|
||||
|
||||
$filters = array_filter($filters, function ($filterclass) {
|
||||
$rc = new \ReflectionClass($filterclass);
|
||||
return $rc->isInstantiable();
|
||||
});
|
||||
$filters = array_filter(
|
||||
$hook->get_filter_list(),
|
||||
function ($filterclass) {
|
||||
$rc = new \ReflectionClass($filterclass);
|
||||
return $rc->isInstantiable();
|
||||
}
|
||||
);
|
||||
|
||||
$filters = array_merge($filters, static::get_all_clientside_filters());
|
||||
|
||||
@ -571,13 +598,18 @@ class helper {
|
||||
* @return array
|
||||
*/
|
||||
public static function get_all_clientside_filters() {
|
||||
$filters = \core_component::get_component_classes_in_namespace('tool_usertours', 'local\clientside_filter');
|
||||
$filters = array_keys($filters);
|
||||
$hook = new hook\before_clientside_filter_fetch(array_keys(
|
||||
\core_component::get_component_classes_in_namespace('tool_usertours', 'local\clientside_filter')
|
||||
));
|
||||
\core\di::get(\core\hook\manager::class)->dispatch($hook);
|
||||
|
||||
$filters = array_filter($filters, function ($filterclass) {
|
||||
$rc = new \ReflectionClass($filterclass);
|
||||
return $rc->isInstantiable();
|
||||
});
|
||||
$filters = array_filter(
|
||||
$hook->get_filter_list(),
|
||||
function ($filterclass) {
|
||||
$rc = new \ReflectionClass($filterclass);
|
||||
return $rc->isInstantiable();
|
||||
}
|
||||
);
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
<?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 tool_usertours\hook;
|
||||
|
||||
/**
|
||||
* Provides the ability to add and remove custom client-side filters to the user tour filter list.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
#[\core\attribute\label('Provides the ability to add and remove custom client-side filters to the user tour filter list.')]
|
||||
#[\core\attribute\tags('tool_usertours')]
|
||||
class before_clientside_filter_fetch {
|
||||
/**
|
||||
* Create a new instance of the hook.
|
||||
*
|
||||
* @param array $filters
|
||||
*/
|
||||
public function __construct(
|
||||
/** @var array The list of filters applied */
|
||||
protected array $filters,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter classname to the list of filters to be processed.
|
||||
*
|
||||
* @param string $classname
|
||||
* @return self
|
||||
*/
|
||||
public function add_filter_by_classname(string $classname): self {
|
||||
if (!\is_a($classname, \tool_usertours\local\clientside_filter\clientside_filter::class, true)) {
|
||||
throw new \coding_exception("Invalid clientside filter class {$classname}");
|
||||
}
|
||||
$this->filters[] = $classname;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a filter classname from the list of filters to be processed.
|
||||
*
|
||||
* @param string $classname
|
||||
* @return self
|
||||
*/
|
||||
public function remove_filter_by_classname(string $classname): self {
|
||||
$this->filters = array_filter($this->filters, fn($filter) => $filter !== $classname);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of filters to be processed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_filter_list(): array {
|
||||
return $this->filters;
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?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 tool_usertours\hook;
|
||||
|
||||
/**
|
||||
* Provides the ability to add and remove custom server-side filters to the user tour filter list.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
#[\core\attribute\label('Provides the ability to add and remove custom server-side filters to the user tour filter list.')]
|
||||
#[\core\attribute\tags('tool_usertours')]
|
||||
class before_serverside_filter_fetch {
|
||||
/**
|
||||
* Create a new instance of the hook.
|
||||
*
|
||||
* @param array $filters
|
||||
*/
|
||||
public function __construct(
|
||||
/** @var array The list of filters applied */
|
||||
protected array $filters,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter classname to the list of filters to be processed.
|
||||
*
|
||||
* @param string $classname
|
||||
* @return self
|
||||
*/
|
||||
public function add_filter_by_classname(string $classname): self {
|
||||
if (!\is_a($classname, \tool_usertours\local\filter\base::class, true)) {
|
||||
throw new \coding_exception("Invalid filter class {$classname}");
|
||||
}
|
||||
|
||||
if (\is_a($classname, \tool_usertours\local\clientside_filter\clientside_filter::class, true)) {
|
||||
throw new \coding_exception("Invalid filter class {$classname} (client-side filter for server-side hook)");
|
||||
}
|
||||
|
||||
$this->filters[] = $classname;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a filter classname from the list of filters to be processed.
|
||||
*
|
||||
* @param string $classname
|
||||
* @return self
|
||||
*/
|
||||
public function remove_filter_by_classname(string $classname): self {
|
||||
$this->filters = array_filter($this->filters, fn($filter) => $filter !== $classname);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of filters to be processed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_filter_list(): array {
|
||||
return $this->filters;
|
||||
}
|
||||
}
|
45
admin/tool/usertours/tests/fixtures/clientside_filter_for_serverside_hook.php
vendored
Normal file
45
admin/tool/usertours/tests/fixtures/clientside_filter_for_serverside_hook.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Hook fixtures for testing of hooks.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\test\hook\clientside_filter_for_serverside_hook;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
final class filter_class extends \tool_usertours\local\clientside_filter\clientside_filter {
|
||||
}
|
||||
|
||||
final class callback {
|
||||
public static function callme(
|
||||
\tool_usertours\hook\before_serverside_filter_fetch $hook
|
||||
): void {
|
||||
$hook->add_filter_by_classname(filter_class::class);
|
||||
}
|
||||
}
|
||||
|
||||
$callbacks = [
|
||||
[
|
||||
'hook' => \tool_usertours\hook\before_serverside_filter_fetch::class,
|
||||
'callback' => callback::class . '::callme',
|
||||
],
|
||||
];
|
61
admin/tool/usertours/tests/fixtures/hook_fixtures.php
vendored
Normal file
61
admin/tool/usertours/tests/fixtures/hook_fixtures.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Hook fixtures for testing of hooks.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\test\hook;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
final class serverside_filter_fixture extends \tool_usertours\local\filter\base {
|
||||
}
|
||||
|
||||
final class clientside_filter_fixture extends \tool_usertours\local\clientside_filter\clientside_filter {
|
||||
}
|
||||
|
||||
final class hook_fixtures {
|
||||
public static function example_serverside_hook(
|
||||
\tool_usertours\hook\before_serverside_filter_fetch $hook
|
||||
): void {
|
||||
// Add a valid serverside and an invalid clientside filter.
|
||||
$hook->add_filter_by_classname(\tool_usertours\test\hook\serverside_filter_fixture::class);
|
||||
$hook->remove_filter_by_classname(\tool_usertours\local\filter\accessdate::class);
|
||||
}
|
||||
|
||||
public static function example_clientside_hook(
|
||||
\tool_usertours\hook\before_clientside_filter_fetch $hook
|
||||
): void {
|
||||
$hook->add_filter_by_classname(\tool_usertours\test\hook\clientside_filter_fixture::class);
|
||||
$hook->remove_filter_by_classname(\tool_usertours\local\clientside_filter\cssselector::class);
|
||||
}
|
||||
}
|
||||
|
||||
$callbacks = [
|
||||
[
|
||||
'hook' => \tool_usertours\hook\before_serverside_filter_fetch::class,
|
||||
'callback' => \tool_usertours\test\hook\hook_fixtures::class . '::example_serverside_hook',
|
||||
],
|
||||
[
|
||||
'hook' => \tool_usertours\hook\before_clientside_filter_fetch::class,
|
||||
'callback' => \tool_usertours\test\hook\hook_fixtures::class . '::example_clientside_hook',
|
||||
],
|
||||
];
|
43
admin/tool/usertours/tests/fixtures/invalid_clientside_hook_fixture.php
vendored
Normal file
43
admin/tool/usertours/tests/fixtures/invalid_clientside_hook_fixture.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Hook fixtures for testing of hooks.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
final class nocomponent_clientside_filter_fixture extends \tool_usertours\local\clientside_filter\clientside_filter {
|
||||
}
|
||||
|
||||
final class nocomponent_clientside_hook_fixtures {
|
||||
public static function example_clientside_hook(
|
||||
\tool_usertours\hook\before_clientside_filter_fetch $hook
|
||||
): void {
|
||||
$hook->add_filter_by_classname(\nocomponent_clientside_filter_fixture::class);
|
||||
}
|
||||
}
|
||||
|
||||
$callbacks = [
|
||||
[
|
||||
'hook' => \tool_usertours\hook\before_clientside_filter_fetch::class,
|
||||
'callback' => \nocomponent_clientside_hook_fixtures::class . '::example_clientside_hook',
|
||||
],
|
||||
];
|
43
admin/tool/usertours/tests/fixtures/invalid_serverside_hook_fixture.php
vendored
Normal file
43
admin/tool/usertours/tests/fixtures/invalid_serverside_hook_fixture.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Hook fixtures for testing of hooks.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
final class nocomponent_serverside_filter_fixture {
|
||||
}
|
||||
|
||||
final class nocomponent_serverside_hook_fixtures {
|
||||
public static function example_serverside_hook(
|
||||
\tool_usertours\hook\before_serverside_filter_fetch $hook
|
||||
): void {
|
||||
$hook->add_filter_by_classname(\nocomponent_serverside_filter_fixture::class);
|
||||
}
|
||||
}
|
||||
|
||||
$callbacks = [
|
||||
[
|
||||
'hook' => \tool_usertours\hook\before_serverside_filter_fetch::class,
|
||||
'callback' => \nocomponent_serverside_hook_fixtures::class . '::example_serverside_hook',
|
||||
],
|
||||
];
|
45
admin/tool/usertours/tests/fixtures/serverside_filter_for_clientside_hook.php
vendored
Normal file
45
admin/tool/usertours/tests/fixtures/serverside_filter_for_clientside_hook.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Hook fixtures for testing of hooks.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2024 Andrew Lyons <andrew@nicols.co.uk>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\test\hook\serverside_filter_for_clientside_hook;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
final class filter_class extends \tool_usertours\local\filter\base {
|
||||
}
|
||||
|
||||
final class callback {
|
||||
public static function callme(
|
||||
\tool_usertours\hook\before_clientside_filter_fetch $hook
|
||||
): void {
|
||||
$hook->add_filter_by_classname(filter_class::class);
|
||||
}
|
||||
}
|
||||
|
||||
$callbacks = [
|
||||
[
|
||||
'hook' => \tool_usertours\hook\before_clientside_filter_fetch::class,
|
||||
'callback' => callback::class . '::callme',
|
||||
],
|
||||
];
|
@ -16,17 +16,18 @@
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
use advanced_testcase;
|
||||
|
||||
/**
|
||||
* Tests for helper.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @category test
|
||||
* @copyright 2022 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \tool_usertours\helper
|
||||
* @covers \tool_usertours\helper
|
||||
* @covers \tool_usertours\hook\before_serverside_filter_fetch
|
||||
* @covers \tool_usertours\hook\before_clientside_filter_fetch
|
||||
*/
|
||||
class helper_test extends advanced_testcase {
|
||||
final class helper_test extends \advanced_testcase {
|
||||
/**
|
||||
* Data Provider for get_string_from_input.
|
||||
*
|
||||
@ -71,4 +72,117 @@ class helper_test extends advanced_testcase {
|
||||
public function test_get_string_from_input($string, $expected): void {
|
||||
$this->assertEquals($expected, helper::get_string_from_input($string));
|
||||
}
|
||||
|
||||
public function test_get_all_filters(): void {
|
||||
$filters = helper::get_all_filters();
|
||||
$this->assertIsArray($filters);
|
||||
|
||||
array_map(
|
||||
function ($filter) {
|
||||
$this->assertIsString($filter);
|
||||
$this->assertTrue(class_exists($filter));
|
||||
$this->assertTrue(is_a($filter, \tool_usertours\local\filter\base::class, true));
|
||||
$rc = new \ReflectionClass($filter);
|
||||
$this->assertTrue($rc->isInstantiable());
|
||||
},
|
||||
$filters,
|
||||
);
|
||||
|
||||
$this->assertNotContains(\tool_usertours\test\hook\serverside_filter_fixture::class, $filters);
|
||||
$this->assertNotContains(\tool_usertours\test\hook\clientside_filter_fixture::class, $filters);
|
||||
$this->assertContains(\tool_usertours\local\filter\accessdate::class, $filters);
|
||||
$this->assertContains(\tool_usertours\local\clientside_filter\cssselector::class, $filters);
|
||||
|
||||
$filters = helper::get_all_clientside_filters();
|
||||
array_map(
|
||||
function ($filter) {
|
||||
$this->assertIsString($filter);
|
||||
},
|
||||
$filters,
|
||||
);
|
||||
}
|
||||
|
||||
public function test_get_invalid_server_filter(): void {
|
||||
\core\di::set(
|
||||
\core\hook\manager::class,
|
||||
\core\hook\manager::phpunit_get_instance([
|
||||
'test_plugin1' => __DIR__ . '/fixtures/invalid_serverside_hook_fixture.php',
|
||||
]),
|
||||
);
|
||||
|
||||
$this->expectException(\coding_exception::class);
|
||||
helper::get_all_filters();
|
||||
}
|
||||
|
||||
public function test_clientside_filter_for_serverside_hook(): void {
|
||||
\core\di::set(
|
||||
\core\hook\manager::class,
|
||||
\core\hook\manager::phpunit_get_instance([
|
||||
'test_plugin1' => __DIR__ . '/fixtures/clientside_filter_for_serverside_hook.php',
|
||||
]),
|
||||
);
|
||||
|
||||
$this->expectException(\coding_exception::class);
|
||||
helper::get_all_filters();
|
||||
}
|
||||
|
||||
public function test_serverside_filter_for_clientside_hook(): void {
|
||||
\core\di::set(
|
||||
\core\hook\manager::class,
|
||||
\core\hook\manager::phpunit_get_instance([
|
||||
'test_plugin1' => __DIR__ . '/fixtures/serverside_filter_for_clientside_hook.php',
|
||||
]),
|
||||
);
|
||||
|
||||
$this->expectException(\coding_exception::class);
|
||||
helper::get_all_clientside_filters();
|
||||
}
|
||||
|
||||
public function test_filter_hooks(): void {
|
||||
\core\di::set(
|
||||
\core\hook\manager::class,
|
||||
\core\hook\manager::phpunit_get_instance([
|
||||
'test_plugin1' => __DIR__ . '/fixtures/hook_fixtures.php',
|
||||
]),
|
||||
);
|
||||
|
||||
$filters = helper::get_all_filters();
|
||||
$this->assertIsArray($filters);
|
||||
|
||||
// Check the modifications from the serverside hook.
|
||||
$this->assertContains(\tool_usertours\test\hook\serverside_filter_fixture::class, $filters);
|
||||
$this->assertNotContains(\tool_usertours\test\hook\another_clientside_filter_fixture::class, $filters);
|
||||
$this->assertNotContains(\tool_usertours\local\filter\accessdate::class, $filters);
|
||||
|
||||
// Check the modifications from the clientside hook.
|
||||
$this->assertContains(\tool_usertours\test\hook\clientside_filter_fixture::class, $filters);
|
||||
$this->assertNotContains(\tool_usertours\test\hook\another_serverside_filter_fixture::class, $filters);
|
||||
$this->assertNotContains(\tool_usertours\local\clientside_filter\cssselector::class, $filters);
|
||||
|
||||
array_map(
|
||||
function ($filter) {
|
||||
$this->assertIsString($filter);
|
||||
$this->assertTrue(class_exists($filter));
|
||||
$this->assertTrue(is_a($filter, \tool_usertours\local\filter\base::class, true));
|
||||
$rc = new \ReflectionClass($filter);
|
||||
$this->assertTrue($rc->isInstantiable());
|
||||
},
|
||||
$filters,
|
||||
);
|
||||
}
|
||||
|
||||
public function test_get_clientside_filter_module_names(): void {
|
||||
\core\di::set(
|
||||
\core\hook\manager::class,
|
||||
\core\hook\manager::phpunit_get_instance([
|
||||
'test_plugin1' => __DIR__ . '/fixtures/invalid_clientside_hook_fixture.php',
|
||||
]),
|
||||
);
|
||||
|
||||
$filters = helper::get_all_clientside_filters();
|
||||
|
||||
$this->expectException(\coding_exception::class);
|
||||
$this->expectExceptionMessageMatches('/Could not determine component/');
|
||||
helper::get_clientside_filter_module_names($filters);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,12 @@
|
||||
This files describes API changes in the tool_usertours code.
|
||||
|
||||
=== 4.4 ===
|
||||
* New hooks have been provided to allow plugins to define their own server-side, and client-side user tour filters.
|
||||
The new hooks are named:
|
||||
- \tool_usertours\hook\before_serverside_filter_fetch
|
||||
- \tool_usertours\hook\before_clientside_filter_fetch
|
||||
These hooks allow addition, and removal, of filters.
|
||||
|
||||
=== 4.0 ===
|
||||
* The `tourconfig` property returned by the `tool_usertours_fetch_and_start_tour`
|
||||
external method has also an `endtourlabel` property that contains the label to be used
|
||||
|
@ -1090,6 +1090,35 @@ $cache = ' . var_export($cache, true) . ';
|
||||
return [$type, $plugin];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the component name from a Moodle PSR-like namespace.
|
||||
*
|
||||
* Note: Classnames in the flat underscore_class_name_format are not supported.
|
||||
*
|
||||
* @param string $classname
|
||||
* @return null|string The component name, or null if a matching component was not found
|
||||
*/
|
||||
public static function get_component_from_classname(string $classname): ?string {
|
||||
$components = static::get_component_names(true);
|
||||
|
||||
$classname = ltrim($classname, '\\');
|
||||
|
||||
// Prefer PSR-4 classnames.
|
||||
$parts = explode('\\', $classname);
|
||||
if ($parts) {
|
||||
$component = array_shift($parts);
|
||||
if (array_search($component, $components) !== false) {
|
||||
return $component;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Frankenstyle classnames are not supported as they lead to false positives, for example:
|
||||
// \core_typo\example => \core instead of \core_typo because it does not exist
|
||||
// Please *do not* add support for Frankenstyle classnames. They will break other things.
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return exact absolute path to a plugin directory.
|
||||
*
|
||||
@ -1407,18 +1436,16 @@ $cache = ' . var_export($cache, true) . ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of frankenstyle component names.
|
||||
* Returns a list of frankenstyle component names, including all plugins, subplugins, and subsystems.
|
||||
*
|
||||
* E.g.
|
||||
* [
|
||||
* 'core_course',
|
||||
* 'core_message',
|
||||
* 'mod_assign',
|
||||
* ...
|
||||
* ]
|
||||
* @return array the list of frankenstyle component names.
|
||||
* Note: By default the 'core' subsystem is not included.
|
||||
*
|
||||
* @param bool $includecore Whether to include the 'core' subsystem
|
||||
* @return string[] the list of frankenstyle component names.
|
||||
*/
|
||||
public static function get_component_names(): array {
|
||||
public static function get_component_names(
|
||||
bool $includecore = false,
|
||||
): array {
|
||||
$componentnames = [];
|
||||
// Get all plugins.
|
||||
foreach (self::get_plugin_types() as $plugintype => $typedir) {
|
||||
@ -1430,6 +1457,11 @@ $cache = ' . var_export($cache, true) . ';
|
||||
foreach (self::get_core_subsystems() as $subsystemname => $subsystempath) {
|
||||
$componentnames[] = 'core_' . $subsystemname;
|
||||
}
|
||||
|
||||
if ($includecore) {
|
||||
$componentnames[] = 'core';
|
||||
}
|
||||
|
||||
return $componentnames;
|
||||
}
|
||||
|
||||
|
@ -411,6 +411,73 @@ class component_test extends advanced_testcase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit tests for get_component_from_classname.
|
||||
*
|
||||
* @dataProvider get_component_from_classname_provider
|
||||
* @param string $classname The class name to test
|
||||
* @param string|null $expected The expected component
|
||||
* @covers \core_component::get_component_from_classname
|
||||
*/
|
||||
public function test_get_component_from_classname(
|
||||
string $classname,
|
||||
string|null $expected,
|
||||
): void {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
\core_component::get_component_from_classname($classname),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for get_component_from_classname tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_component_from_classname_provider(): array {
|
||||
// Start off with testcases which have the leading \.
|
||||
$testcases = [
|
||||
// Core.
|
||||
[\core\example::class, 'core'],
|
||||
|
||||
// A core subsystem.
|
||||
[\core_message\example::class, 'core_message'],
|
||||
|
||||
// A fake core subsystem.
|
||||
[\core_fake\example::class, null],
|
||||
|
||||
// A plugin.
|
||||
[\mod_forum\example::class, 'mod_forum'],
|
||||
|
||||
// A plugin in the old style is not supported.
|
||||
[\mod_forum_example::class, null],
|
||||
|
||||
// A fake plugin.
|
||||
[\mod_fake\example::class, null],
|
||||
|
||||
// A subplugin.
|
||||
[\tiny_link\example::class, 'tiny_link'],
|
||||
];
|
||||
|
||||
// Duplicate the testcases, adding a nested namespace.
|
||||
$testcases = array_merge(
|
||||
$testcases,
|
||||
array_map(
|
||||
fn ($testcase) => [$testcase[0] . '\\in\\sub\\directory', $testcase[1]],
|
||||
$testcases,
|
||||
),
|
||||
);
|
||||
|
||||
// Duplicate the testcases, removing the leading \.
|
||||
return array_merge(
|
||||
$testcases,
|
||||
array_map(
|
||||
fn ($testcase) => [ltrim($testcase[0], '\\'), $testcase[1]],
|
||||
$testcases,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function test_deprecated_get_component_directory(): void {
|
||||
$plugintypes = core_component::get_plugin_types();
|
||||
foreach ($plugintypes as $plugintype => $fulldir) {
|
||||
@ -873,22 +940,31 @@ class component_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the get_component_names() method.
|
||||
*
|
||||
* @dataProvider get_component_names_provider
|
||||
* @param bool $includecore Whether to include core in the list.
|
||||
* @param bool $coreexpected Whether core is expected to be in the list.
|
||||
*/
|
||||
public function test_get_component_names(): void {
|
||||
public function test_get_component_names(
|
||||
bool $includecore,
|
||||
bool $coreexpected,
|
||||
): void {
|
||||
global $CFG;
|
||||
$componentnames = \core_component::get_component_names();
|
||||
$componentnames = \core_component::get_component_names($includecore);
|
||||
|
||||
// We should have an entry for each plugin type.
|
||||
$plugintypes = \core_component::get_plugin_types();
|
||||
$numplugintypes = 0;
|
||||
foreach ($plugintypes as $type => $typedir) {
|
||||
foreach (\core_component::get_plugin_list($type) as $plugin) {
|
||||
$numplugintypes++;
|
||||
}
|
||||
foreach (array_keys($plugintypes) as $type) {
|
||||
$numplugintypes += count(\core_component::get_plugin_list($type));
|
||||
}
|
||||
// And an entry for each core subsystem.
|
||||
$numcomponents = $numplugintypes + count(\core_component::get_core_subsystems());
|
||||
|
||||
if ($coreexpected) {
|
||||
// Add one for core.
|
||||
$numcomponents++;
|
||||
}
|
||||
$this->assertEquals($numcomponents, count($componentnames));
|
||||
|
||||
// Check a few of the known plugin types to confirm their presence at their respective type index.
|
||||
@ -896,6 +972,23 @@ class component_test extends advanced_testcase {
|
||||
$this->assertContains('mod_forum', $componentnames);
|
||||
$this->assertContains('tool_usertours', $componentnames);
|
||||
$this->assertContains('core_favourites', $componentnames);
|
||||
if ($coreexpected) {
|
||||
$this->assertContains('core', $componentnames);
|
||||
} else {
|
||||
$this->assertNotContains('core', $componentnames);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for get_component_names() test.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_component_names_provider(): array {
|
||||
return [
|
||||
[false, false],
|
||||
[true, true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user