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
/**
18
 * Unit tests for base datasource
19
 *
20
 * @package     core_reportbuilder
21
 * @copyright   2023 Paul Holden <paulh@moodle.com>
22
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
declare(strict_types=1);
26
 
27
namespace core_reportbuilder;
28
 
29
use advanced_testcase;
30
use core_reportbuilder_generator;
31
use core_reportbuilder\local\entities\base;
32
use core_reportbuilder\local\filters\text;
33
use core_reportbuilder\local\report\{column, filter};
34
use lang_string;
35
use ReflectionClass;
36
 
37
defined('MOODLE_INTERNAL') || die();
38
 
39
/**
40
 * Unit tests for base datasource
41
 *
42
 * @package     core_reportbuilder
43
 * @coversDefaultClass \core_reportbuilder\datasource
44
 * @copyright   2023 Paul Holden <paulh@moodle.com>
45
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46
 */
47
final class datasource_test extends advanced_testcase {
48
 
49
    /**
50
     * Data provider for {@see test_add_columns_from_entity}
51
     *
52
     * @return array[]
53
     */
54
    public static function add_columns_from_entity_provider(): array {
55
        return [
56
            'All columns' => [
57
                [],
58
                [],
59
                4,
60
            ],
61
            'Include columns (first, extra1, extra2)' => [
62
                ['first', 'extra*'],
63
                [],
64
                3,
65
            ],
66
            'Exclude columns (first, extra1, extra2)' => [
67
                [],
68
                ['first', 'extra*'],
69
                1,
70
            ],
71
        ];
72
    }
73
 
74
    /**
75
     * Test adding columns from entity
76
     *
77
     * @param string[] $include
78
     * @param string[] $exclude
79
     * @param int $expectedcount
80
     *
81
     * @covers ::add_columns_from_entity
82
     *
83
     * @dataProvider add_columns_from_entity_provider
84
     */
85
    public function test_add_columns_from_entity(
86
        array $include,
87
        array $exclude,
88
        int $expectedcount,
89
    ): void {
90
        $instance = $this->get_datasource_test_source();
91
 
92
        $method = (new ReflectionClass($instance))->getMethod('add_columns_from_entity');
93
        $method->invoke($instance, 'datasource_test_entity', $include, $exclude);
94
 
95
        // Get all our entity columns.
96
        $columns = array_filter(
97
            $instance->get_columns(),
98
            fn(string $columnname) => strpos($columnname, 'datasource_test_entity:') === 0,
99
            ARRAY_FILTER_USE_KEY,
100
        );
101
 
102
        $this->assertCount($expectedcount, $columns);
103
    }
104
 
105
    /**
106
     * Data provider for {@see test_add_filters_from_entity}
107
     *
108
     * @return array[]
109
     */
110
    public static function add_filters_from_entity_provider(): array {
111
        return [
112
            'All filters' => [
113
                [],
114
                [],
115
                4,
116
            ],
117
            'Include filters (first, extra1, extra2)' => [
118
                ['first', 'extra*'],
119
                [],
120
                3,
121
            ],
122
            'Exclude filters (first, extra1, extra2)' => [
123
                [],
124
                ['first', 'extra*'],
125
                1,
126
            ],
127
        ];
128
    }
129
 
130
    /**
131
     * Test adding filters from entity
132
     *
133
     * @param string[] $include
134
     * @param string[] $exclude
135
     * @param int $expectedcount
136
     *
137
     * @covers ::add_filters_from_entity
138
     *
139
     * @dataProvider add_filters_from_entity_provider
140
     */
141
    public function test_add_filters_from_entity(
142
        array $include,
143
        array $exclude,
144
        int $expectedcount,
145
    ): void {
146
        $instance = $this->get_datasource_test_source();
147
 
148
        $method = (new ReflectionClass($instance))->getMethod('add_filters_from_entity');
149
        $method->invoke($instance, 'datasource_test_entity', $include, $exclude);
150
 
151
        // Get all our entity filters.
152
        $filters = array_filter(
153
            $instance->get_filters(),
154
            fn(string $filtername) => strpos($filtername, 'datasource_test_entity:') === 0,
155
            ARRAY_FILTER_USE_KEY,
156
        );
157
 
158
        $this->assertCount($expectedcount, $filters);
159
    }
160
 
161
    /**
162
     * Data provider for {@see test_add_conditions_from_entity}
163
     *
164
     * @return array[]
165
     */
166
    public static function add_conditions_from_entity_provider(): array {
167
        return [
168
            'All conditions' => [
169
                [],
170
                [],
171
                4,
172
            ],
173
            'Include conditions (first, extra1, extra2)' => [
174
                ['first', 'extra*'],
175
                [],
176
                3,
177
            ],
178
            'Exclude conditions (first, extra1, extra2)' => [
179
                [],
180
                ['first', 'extra*'],
181
                1,
182
            ],
183
        ];
184
    }
185
 
186
    /**
187
     * Test adding conditions from entity
188
     *
189
     * @param string[] $include
190
     * @param string[] $exclude
191
     * @param int $expectedcount
192
     *
193
     * @covers ::add_conditions_from_entity
194
     *
195
     * @dataProvider add_conditions_from_entity_provider
196
     */
197
    public function test_add_conditions_from_entity(
198
        array $include,
199
        array $exclude,
200
        int $expectedcount,
201
    ): void {
202
        $instance = $this->get_datasource_test_source();
203
 
204
        $method = (new ReflectionClass($instance))->getMethod('add_conditions_from_entity');
205
        $method->invoke($instance, 'datasource_test_entity', $include, $exclude);
206
 
207
        // Get all our entity conditions.
208
        $conditions = array_filter(
209
            $instance->get_conditions(),
210
            fn(string $conditionname) => strpos($conditionname, 'datasource_test_entity:') === 0,
211
            ARRAY_FILTER_USE_KEY,
212
        );
213
 
214
        $this->assertCount($expectedcount, $conditions);
215
    }
216
 
217
    /**
218
     * Test adding all from entity
219
     *
220
     * @covers ::add_all_from_entity
221
     */
222
    public function test_add_all_from_entity(): void {
223
        $instance = $this->get_datasource_test_source();
224
 
225
        $method = (new ReflectionClass($instance))->getMethod('add_all_from_entity');
226
        $method->invoke($instance, 'datasource_test_entity', ['first'], ['second'], ['extra1']);
227
 
228
        // Assert the column we added (plus one we didn't).
229
        $this->assertInstanceOf(column::class, $instance->get_column('datasource_test_entity:first'));
230
        $this->assertNull($instance->get_column('datasource_test_entity:second'));
231
 
232
        // Assert the filter we added (plus one we didn't).
233
        $this->assertInstanceOf(filter::class, $instance->get_filter('datasource_test_entity:second'));
234
        $this->assertNull($instance->get_filter('datasource_test_entity:first'));
235
 
236
        // Assert the condition we added (plus one we didn't).
237
        $this->assertInstanceOf(filter::class, $instance->get_condition('datasource_test_entity:extra1'));
238
        $this->assertNull($instance->get_condition('datasource_test_entity:extra2'));
239
    }
240
 
241
    /**
1441 ariadna 242
     * Data provider for {@see get_datasource_test_source}
243
     *
244
     * @return array[]
245
     */
246
    public static function add_all_from_entities_provider(): array {
247
        return [
248
            'All' => [
249
                [],
250
                9,
251
                8,
252
                8,
253
            ],
254
            'Entity' => [
255
                ['datasource_test_entity'],
256
                5,
257
                4,
258
                4,
259
            ],
260
        ];
261
    }
262
 
263
    /**
264
     * Test adding from all entities
265
     *
266
     * @param string[] $entitynames
267
     * @param int $expectedcountcolumns
268
     * @param int $expectedcountfilters
269
     * @param int $expectedcountconditions
270
     *
271
     * @covers ::add_all_from_entities
272
     *
273
     * @dataProvider add_all_from_entities_provider
274
     */
275
    public function test_add_all_from_entities(
276
        array $entitynames,
277
        int $expectedcountcolumns,
278
        int $expectedcountfilters,
279
        int $expectedcountconditions,
280
    ): void {
281
        $instance = $this->get_datasource_test_source();
282
 
283
        $method = (new ReflectionClass($instance))->getMethod('add_all_from_entities');
284
        $method->invoke($instance, $entitynames);
285
 
286
        $this->assertCount($expectedcountcolumns, $instance->get_columns());
287
        $this->assertCount($expectedcountfilters, $instance->get_filters());
288
        $this->assertCount($expectedcountconditions, $instance->get_conditions());
289
    }
290
 
291
    /**
292
     * Test getting active conditions
293
     *
294
     * @covers ::get_active_conditions
295
     */
296
    public function test_get_active_conditions(): void {
297
        $instance = $this->get_datasource_test_source();
298
 
299
        $method = (new ReflectionClass($instance))->getMethod('add_conditions_from_entity');
300
        $method->invoke($instance, 'datasource_test_entity');
301
 
302
        /** @var core_reportbuilder_generator $generator */
303
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
304
 
305
        $reportid = $instance->get_report_persistent()->get('id');
306
        $generator->create_condition(['reportid' => $reportid, 'uniqueidentifier' => 'datasource_test_entity:first']);
307
        $generator->create_condition(['reportid' => $reportid, 'uniqueidentifier' => 'datasource_test_entity:second']);
308
 
309
        // Set the second condition as unavailable.
310
        $instance->get_condition('datasource_test_entity:second')->set_is_available(false);
311
 
312
        $this->assertEquals([
313
            'datasource_test_entity:first',
314
        ], array_keys($instance->get_active_conditions(true)));
315
 
316
        // Ensure report elements are reloaded.
317
        $instance::report_elements_modified($reportid);
318
 
319
        $this->assertEquals([
320
            'datasource_test_entity:first',
321
            'datasource_test_entity:second',
322
        ], array_keys($instance->get_active_conditions(false)));
323
    }
324
 
325
    /**
1 efrain 326
     * Create and return our test datasource instance
327
     *
328
     * @return datasource_test_source
329
     */
330
    protected function get_datasource_test_source(): datasource_test_source {
331
        $this->resetAfterTest();
332
 
333
        /** @var core_reportbuilder_generator $generator */
334
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
335
        $report = $generator->create_report(['name' => 'Test', 'source' => datasource_test_source::class, 'default' => 0]);
336
 
337
        /** @var datasource_test_source $instance */
338
        $instance = manager::get_report_from_persistent($report);
339
        return $instance;
340
    }
341
}
342
 
343
/**
344
 * Simple implementation of the base datasource
345
 */
346
class datasource_test_source extends datasource {
347
 
348
    protected function initialise(): void {
349
        $this->set_main_table('user', 'u');
1441 ariadna 350
 
351
        // Because we must have at least one column in the report.
1 efrain 352
        $this->annotate_entity('dummy', new lang_string('yes'));
353
        $this->add_column(new column('test', null, 'dummy'));
354
 
1441 ariadna 355
        // These are the entities from which we'll add additional report elements.
1 efrain 356
        $this->add_entity(new datasource_test_entity());
1441 ariadna 357
        $this->add_entity((new datasource_test_entity())->set_entity_name('datasource_test_entity_second'));
1 efrain 358
    }
359
 
360
    public static function get_name(): string {
361
        return self::class;
362
    }
363
 
364
    public function get_default_columns(): array {
365
        return [];
366
    }
367
 
368
    public function get_default_filters(): array {
369
        return [];
370
    }
371
 
372
    public function get_default_conditions(): array {
373
        return [];
374
    }
375
}
376
 
377
/**
378
 * Simple implementation of the base entity
379
 */
380
class datasource_test_entity extends base {
381
 
382
    protected function get_default_tables(): array {
383
        return ['course'];
384
    }
385
 
386
    protected function get_default_entity_title(): lang_string {
387
        return new lang_string('course');
388
    }
389
 
390
    /**
391
     * We're going to add multiple columns/filters/conditions, each named as following:
392
     *
393
     * [first, second, extra1, extra2]
394
     *
395
     * @return base
396
     */
397
    public function initialise(): base {
398
        foreach (['first', 'second', 'extra1', 'extra2'] as $field) {
399
            $name = new lang_string('customfieldcolumn', 'core_reportbuilder', $field);
400
 
401
            $this->add_column(new column($field, $name, $this->get_entity_name()));
402
            $this->add_filter(new filter(text::class, $field, $name, $this->get_entity_name()));
403
            $this->add_condition(new filter(text::class, $field, $name, $this->get_entity_name()));
404
        }
405
 
406
        return $this;
407
    }
408
}