Skip to content

Commit 7acb211

Browse files
committed
Add hook for certificate element classes discovery
1 parent 20395db commit 7acb211

File tree

4 files changed

+126
-21
lines changed

4 files changed

+126
-21
lines changed

classes/element.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,19 @@ public static function instance(int $id = 0, ?\stdClass $obj = null): element {
6969
* Helper method to create an instance from persistent
7070
*
7171
* @param \tool_certificate\persistent\element $persistent
72-
* @return element
72+
* @return element|null
7373
*/
7474
protected static function instance_from_persistent(\tool_certificate\persistent\element $persistent): ?element {
75-
// Get the class name.
76-
$classname = '\\certificateelement_' . $persistent->get('element') . '\\element';
75+
$elementclasses = element_helper::get_element_classes();
7776

78-
// Ensure the necessary class exists.
79-
if (!class_exists($classname) || !is_subclass_of($classname, self::class)) {
77+
$shortname = $persistent->get('element');
78+
if (!isset($elementclasses[$shortname])) {
8079
return null;
8180
}
8281

83-
/** @var self $el */
82+
/** @var class-string<element> $classname */
83+
$classname = $elementclasses[$shortname];
84+
8485
$el = new $classname($persistent);
8586
$el->persistent = $persistent;
8687
return $el;

classes/element_helper.php

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -446,29 +446,58 @@ public static function get_element_sequence($pageid) {
446446
return $sequence;
447447
}
448448

449+
/**
450+
* Returns all enabled element classes.
451+
*
452+
* @return array<string, class-string<\tool_certificate\element>>
453+
*/
454+
public static function get_element_classes(): array {
455+
$plugins = self::get_enabled_plugins();
456+
457+
if (!class_exists(\core\hook\manager::class)) {
458+
// Legacy code for 4.2.x and older.
459+
$options = [];
460+
foreach ($plugins as $plugin) {
461+
/** @var element $classname */
462+
$classname = '\\certificateelement_' . $plugin. '\\element';
463+
// Ensure the necessary class exists.
464+
if (class_exists($classname) && is_subclass_of($classname, element::class)) {
465+
$options[$plugin] = $classname;
466+
}
467+
}
468+
return $options;
469+
}
470+
471+
$hook = new hook\element_classes();
472+
473+
// Loop through the enabled plugins.
474+
foreach ($plugins as $plugin) {
475+
$classname = 'certificateelement_' . $plugin. '\\element';
476+
$hook->add_class($plugin, $classname);
477+
}
478+
479+
// Ask other plugins if they define more elements.
480+
\core\hook\manager::get_instance()->dispatch($hook);
481+
482+
return $hook->get_classes();
483+
}
484+
449485
/**
450486
* Return the list of possible elements to add.
451487
*
452488
* @return array the list of element types that can be used.
453489
*/
454-
public static function get_available_element_types() {
455-
global $CFG;
456-
490+
public static function get_available_element_types(): array {
457491
// Array to store the element types.
458492
$options = [];
459493

460-
$plugins = self::get_enabled_plugins();
494+
$classes = self::get_element_classes();
461495

462496
// Loop through the enabled plugins.
463-
foreach ($plugins as $plugin) {
464-
/** @var element $classname */
465-
$classname = '\\certificateelement_' . $plugin. '\\element';
466-
// Ensure the necessary class exists.
467-
if (class_exists($classname) && is_subclass_of($classname, element::class)) {
468-
// Additionally, check if the user is allowed to add the element at all.
469-
if ($classname::can_add()) {
470-
$options[$plugin] = $classname::get_element_type_name();
471-
}
497+
foreach ($classes as $shortname => $classname) {
498+
// Additionally, check if the user is allowed to add the element at all.
499+
if ($classname::can_add()) {
500+
$options[$shortname] = $classname::get_element_type_name();
472501
}
473502
}
474503

classes/hook/element_classes.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
// This file is part of the tool_certificate plugin for 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 tool_certificate\hook;
18+
19+
/**
20+
* Certification element classes discovery hook.
21+
*
22+
* @package tool_certificate
23+
* @copyright 2024 Petr Skoda
24+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25+
*/
26+
final class element_classes implements \core\hook\described_hook {
27+
/**
28+
* @var array<string, class-string<\tool_certificate\element>>
29+
*/
30+
protected $classes = [];
31+
32+
/**
33+
* Add known enabled element class.
34+
*
35+
* @param string $shortname name of certificateelement sub-plugin or other unique name
36+
* @param class-string<\tool_certificate\element> $classname
37+
*/
38+
public function add_class(string $shortname, string $classname): void {
39+
if (!class_exists($classname) || !is_subclass_of($classname, \tool_certificate\element::class)) {
40+
debugging('Invalid certificate element class: ' . $classname, DEBUG_DEVELOPER);
41+
return;
42+
}
43+
if (isset($this->classes[$shortname])) {
44+
debugging('Duplicate certificate element short name detected: ' . $shortname, DEBUG_DEVELOPER);
45+
// Override previous in case admins forgot to uninstall element add-on.
46+
}
47+
$this->classes[$shortname] = $classname;
48+
}
49+
50+
/**
51+
* Returns known enabled element classes indexed with their short names.
52+
*
53+
* @return array<string, class-string<\tool_certificate\element>>
54+
*/
55+
public function get_classes(): array {
56+
return $this->classes;
57+
}
58+
59+
/**
60+
* Hook description.
61+
*
62+
* @return string
63+
*/
64+
public static function get_hook_description(): string {
65+
return 'Certificate element class discovery';
66+
}
67+
68+
/**
69+
* Hook tags.
70+
*
71+
* @return array
72+
*/
73+
public static function get_hook_tags(): array {
74+
return [];
75+
}
76+
}

classes/output/element.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,10 @@ protected static function define_other_properties(): array {
8989
*/
9090
protected function get_other_values(\renderer_base $output): array {
9191
$element = $this->get_element();
92-
$pluginname = 'certificateelement_' . $this->persistent->get('element');
9392
return [
9493
'displayname' => $element->get_display_name(),
9594
'editablename' => $element->get_inplace_editable()->export_for_template($output),
96-
'elementtype' => get_string('pluginname', $pluginname),
95+
'elementtype' => $element::get_element_type_name(),
9796
'movetitle' => get_string('changeelementsequence', 'tool_certificate'),
9897
'icon' => $output->render($this->get_element()->get_element_type_image(true)),
9998
'html' => $this->get_element()->render_html(),

0 commit comments

Comments
 (0)