Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   1  <?php
   2  // This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
  16  
  17  namespace core;
  18  
  19  /**
  20   * Standard hook discovery agent for Moodle which lists
  21   * all non-abstract classes in hooks namespace of core and all plugins
  22   * unless there is a hook discovery agent in a plugin.
  23   *
  24   * @package   core
  25   * @copyright Andrew Lyons <andrew@nicols.co.uk>
  26   * @license   https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  final class hooks implements \core\hook\discovery_agent {
  29      /**
  30       * Returns all Moodle hooks in standard hook namespace.
  31       *
  32       * @return array list of hook classes
  33       */
  34      public static function discover_hooks(): array {
  35          // Look for hooks in hook namespace in core and all components.
  36          $hooks = [];
  37  
  38          $hooks = array_merge($hooks, self::discover_hooks_in_namespace('core', 'hook'));
  39  
  40          foreach (\core_component::get_component_names() as $component) {
  41              $agent = "$component\\hooks";
  42              if (class_exists($agent) && is_subclass_of($agent, hook\discovery_agent::class)) {
  43                  // Let the plugin supply the list of hooks instead.
  44                  continue;
  45              }
  46              $hooks = array_merge($hooks, self::discover_hooks_in_namespace($component, 'hook'));
  47          }
  48  
  49          return $hooks;
  50      }
  51  
  52      /**
  53       * Look up all non-abstract classes in "$component\$namespace" namespace.
  54       *
  55       * @param string $component
  56       * @param string $namespace
  57       * @return array list of hook classes
  58       */
  59      public static function discover_hooks_in_namespace(string $component, string $namespace): array {
  60          $classes = \core_component::get_component_classes_in_namespace($component, $namespace);
  61  
  62          $hooks = [];
  63          foreach (array_keys($classes) as $classname) {
  64              $rc = new \ReflectionClass($classname);
  65              if ($rc->isAbstract()) {
  66                  // Skip abstract classes.
  67                  continue;
  68              }
  69  
  70              if ($classname === \core\hook\manager::class) {
  71                  // Skip the manager in core.
  72                  continue;
  73              }
  74  
  75              $hooks[$classname] = [
  76                  'class' => $classname,
  77                  'description' => '',
  78                  'tags' => [],
  79              ];
  80  
  81              if (is_subclass_of($classname, \core\hook\described_hook::class)) {
  82                  $hooks[$classname]['description'] = $classname::get_hook_description();
  83                  $hooks[$classname]['tags'] = $classname::get_hook_tags();
  84              }
  85          }
  86  
  87          return $hooks;
  88      }
  89  }