Proyectos de Subversion Moodle

Rev

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