2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
17 declare(strict_types
=1);
19 namespace core_reportbuilder
;
22 use core_plugin_manager
;
24 use core_reportbuilder\local\models\report
;
25 use core_reportbuilder\local\report\base
;
28 * Report management class
30 * @package core_reportbuilder
31 * @copyright 2020 Paul Holden <paulh@moodle.com>
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 /** @var base $instances */
37 private static $instances = [];
40 * Return an instance of a report class from the given report persistent
42 * We statically cache the list of loaded reports during request lifecycle, to allow this method to be called
43 * repeatedly without potential performance problems initialising the same report multiple times
45 * @param report $report
46 * @param array $parameters
48 * @throws source_invalid_exception
49 * @throws source_unavailable_exception
51 public static function get_report_from_persistent(report
$report, array $parameters = []): base
{
52 $instancekey = $report->get('id');
53 if (!array_key_exists($instancekey, static::$instances)) {
54 $source = $report->get('source');
56 // Throw exception for invalid or unavailable report source.
57 if (!self
::report_source_exists($source)) {
58 throw new source_invalid_exception($source);
59 } else if (!self
::report_source_available($source)) {
60 throw new source_unavailable_exception($source);
63 static::$instances[$instancekey] = new $source($report, $parameters);
66 return static::$instances[$instancekey];
70 * Run reset code after tests to reset the instance cache
72 public static function reset_caches(): void
{
73 if (PHPUNIT_TEST ||
defined('BEHAT_TEST')) {
74 static::$instances = [];
79 * Return an instance of a report class from the given report ID
81 * @param int $reportid
82 * @param array $parameters
85 public static function get_report_from_id(int $reportid, array $parameters = []): base
{
86 $report = new report($reportid);
88 return self
::get_report_from_persistent($report, $parameters);
92 * Verify that report source exists and extends appropriate base classes
94 * @param string $source Full namespaced path to report definition
95 * @param string $additionalbaseclass Specify addition base class that given classname should extend
98 public static function report_source_exists(string $source, string $additionalbaseclass = ''): bool {
99 return (class_exists($source) && is_subclass_of($source, base
::class) &&
100 (empty($additionalbaseclass) ||
is_subclass_of($source, $additionalbaseclass)));
104 * Verify given report source is available. Note that it is assumed caller has already checked that it exists
106 * @param string $source
109 public static function report_source_available(string $source): bool {
110 return call_user_func([$source, 'is_available']);
114 * Create new report persistent
116 * @param stdClass $reportdata
119 public static function create_report_persistent(stdClass
$reportdata): report
{
120 return (new report(0, $reportdata))->create();
124 * Return an array of all valid report sources across the site
126 * @return array[][] Indexed by [component => [class => name]]
128 public static function get_report_datasources(): array {
131 $datasources = core_component
::get_component_classes_in_namespace(null, 'reportbuilder\\datasource');
132 foreach ($datasources as $class => $path) {
133 if (self
::report_source_exists($class, datasource
::class) && self
::report_source_available($class)) {
134 [$component] = explode('\\', $class);
136 if ($plugininfo = core_plugin_manager
::instance()->get_plugin_info($component)) {
137 $componentname = $plugininfo->displayname
;
139 $componentname = get_string('site');
142 $sources[$componentname][$class] = call_user_func([$class, 'get_name']);