Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of 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
declare(strict_types=1);
18
 
19
namespace core_reportbuilder;
20
 
21
use core_collator;
22
use core_component;
23
use core_plugin_manager;
24
use stdClass;
25
use core_reportbuilder\local\models\report;
26
use core_reportbuilder\local\report\base;
27
 
28
/**
29
 * Report management class
30
 *
31
 * @package     core_reportbuilder
32
 * @copyright   2020 Paul Holden <paulh@moodle.com>
33
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class manager {
36
 
37
    /** @var base $instances */
38
    private static $instances = [];
39
 
40
    /**
41
     * Return an instance of a report class from the given report persistent
42
     *
43
     * We statically cache the list of loaded reports per user during request lifecycle, to allow this method to be called
44
     * repeatedly without potential performance problems initialising the same report multiple times
45
     *
46
     * @param report $report
47
     * @param array $parameters
48
     * @return base
49
     * @throws source_invalid_exception
50
     * @throws source_unavailable_exception
51
     */
52
    public static function get_report_from_persistent(report $report, array $parameters = []): base {
53
        global $USER;
54
 
55
        // Cached instance per report/user, to account for initialization dependent on current user.
56
        $instancekey = $report->get('id') . ':' . ($USER->id ?? 0);
57
 
58
        if (!array_key_exists($instancekey, static::$instances)) {
59
            $source = $report->get('source');
60
 
61
            // Throw exception for invalid or unavailable report source.
62
            if (!self::report_source_exists($source)) {
63
                throw new source_invalid_exception($source);
64
            } else if (!self::report_source_available($source)) {
65
                throw new source_unavailable_exception($source);
66
            }
67
 
68
            static::$instances[$instancekey] = new $source($report, $parameters);
69
        }
70
 
71
        return static::$instances[$instancekey];
72
    }
73
 
74
    /**
75
     * Run reset code after tests to reset the instance cache
76
     */
77
    public static function reset_caches(): void {
78
        if (PHPUNIT_TEST || defined('BEHAT_TEST')) {
79
            static::$instances = [];
80
        }
81
    }
82
 
83
    /**
84
     * Return an instance of a report class from the given report ID
85
     *
86
     * @param int $reportid
87
     * @param array $parameters
88
     * @return base
89
     */
90
    public static function get_report_from_id(int $reportid, array $parameters = []): base {
91
        $report = new report($reportid);
92
 
93
        return self::get_report_from_persistent($report, $parameters);
94
    }
95
 
96
    /**
97
     * Verify that report source exists and extends appropriate base classes
98
     *
99
     * @param string $source Full namespaced path to report definition
100
     * @param string $additionalbaseclass Specify addition base class that given classname should extend
101
     * @return bool
102
     */
103
    public static function report_source_exists(string $source, string $additionalbaseclass = ''): bool {
104
        return (class_exists($source) && is_subclass_of($source, base::class) &&
105
            (empty($additionalbaseclass) || is_subclass_of($source, $additionalbaseclass)));
106
    }
107
 
108
    /**
109
     * Verify given report source is available. Note that it is assumed caller has already checked that it exists
110
     *
111
     * @param string $source
112
     * @return bool
113
     */
114
    public static function report_source_available(string $source): bool {
115
        return call_user_func([$source, 'is_available']);
116
    }
117
 
118
    /**
119
     * Create new report persistent
120
     *
121
     * @param stdClass $reportdata
122
     * @return report
123
     */
124
    public static function create_report_persistent(stdClass $reportdata): report {
125
        return (new report(0, $reportdata))->create();
126
    }
127
 
128
    /**
129
     * Return an array of all valid report sources across the site
130
     *
131
     * @return array[][] Indexed by [component => [class => name]]
132
     */
133
    public static function get_report_datasources(): array {
134
        $sources = array();
135
 
136
        $datasources = core_component::get_component_classes_in_namespace(null, 'reportbuilder\\datasource');
137
        foreach ($datasources as $class => $path) {
138
            if (self::report_source_exists($class, datasource::class) && self::report_source_available($class)) {
139
 
140
                // Group each report source by the component that it belongs to.
141
                [$component] = explode('\\', $class);
142
                if ($plugininfo = core_plugin_manager::instance()->get_plugin_info($component)) {
143
                    $componentname = $plugininfo->displayname;
144
                } else {
145
                    $componentname = get_string('site');
146
                }
147
 
148
                $sources[$componentname][$class] = call_user_func([$class, 'get_name']);
149
            }
150
        }
151
 
152
        // Order source for each component alphabetically.
153
        array_walk($sources, static function(array &$componentsources): void {
154
            core_collator::asort($componentsources);
155
        });
156
 
157
        return $sources;
158
    }
159
 
160
    /**
161
     * Configured site limit for number of custom reports threshold has been reached
162
     *
163
     * @return bool
164
     */
165
    public static function report_limit_reached(): bool {
166
        global $CFG;
167
 
168
        return (!empty($CFG->customreportslimit) &&
169
            (int) $CFG->customreportslimit <= report::count_records(['type' => base::TYPE_CUSTOM_REPORT]));
170
    }
171
}