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\local\aggregation;
20
 
21
use core_badges_generator;
22
use core_badges\reportbuilder\datasource\badges;
23
use core_reportbuilder_generator;
24
use core_reportbuilder\manager;
1441 ariadna 25
use core_reportbuilder\tests\core_reportbuilder_testcase;
1 efrain 26
use core_user\reportbuilder\datasource\users;
27
use stdClass;
28
 
29
/**
30
 * Unit tests for group concatenation aggregation
31
 *
32
 * @package     core_reportbuilder
33
 * @covers      \core_reportbuilder\local\aggregation\base
34
 * @covers      \core_reportbuilder\local\aggregation\groupconcat
35
 * @copyright   2021 Paul Holden <paulh@moodle.com>
36
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37
 */
1441 ariadna 38
final class groupconcat_test extends core_reportbuilder_testcase {
1 efrain 39
 
40
    /**
41
     * Test aggregation when applied to column
42
     */
43
    public function test_column_aggregation(): void {
44
        $this->resetAfterTest();
45
 
46
        // Test subjects.
47
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Banana']);
48
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Apple']);
49
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Banana']);
50
 
51
        /** @var core_reportbuilder_generator $generator */
52
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
53
        $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
54
 
55
        // Report columns, aggregated/sorted by user lastname.
56
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']);
57
        $generator->create_column([
58
            'reportid' => $report->get('id'),
59
            'uniqueidentifier' => 'user:lastname',
60
            'aggregation' => groupconcat::get_class_name(),
61
            'sortenabled' => 1,
62
            'sortdirection' => SORT_ASC,
63
        ]);
64
 
65
        // Assert lastname column was aggregated, and itself also sorted predictably.
66
        $content = $this->get_custom_report_content($report->get('id'));
67
        $this->assertEquals([
68
            ['Bob', 'Apple, Banana, Banana'],
69
            ['Admin', 'User'],
70
        ], array_map('array_values', $content));
71
    }
72
 
73
    /**
1441 ariadna 74
     * Test aggregation with custom separator option when applied to column
75
     */
76
    public function test_column_aggregation_separator_option(): void {
77
        $this->resetAfterTest();
78
 
79
        // Test subjects.
80
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Banana']);
81
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Apple']);
82
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'lastname' => 'Banana']);
83
 
84
        /** @var core_reportbuilder_generator $generator */
85
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
86
        $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
87
 
88
        // Report columns, aggregated/sorted by user lastname.
89
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']);
90
        $generator->create_column([
91
            'reportid' => $report->get('id'),
92
            'uniqueidentifier' => 'user:lastname',
93
            'aggregation' => groupconcat::get_class_name(),
94
            'sortenabled' => 1,
95
            'sortdirection' => SORT_ASC,
96
        ]);
97
 
98
        // Set aggregation option for separator.
99
        $instance = manager::get_report_from_persistent($report);
100
        $instance->get_column('user:lastname')
101
            ->set_aggregation_options(groupconcat::get_class_name(), ['separator' => '<br />']);
102
 
103
        // Assert lastname column was aggregated, with defined separator between each item.
104
        $content = $this->get_custom_report_content($report->get('id'));
105
        $this->assertEquals([
106
            ['Bob', 'Apple<br />Banana<br />Banana'],
107
            ['Admin', 'User'],
108
        ], array_map('array_values', $content));
109
    }
110
 
111
    /**
1 efrain 112
     * Test aggregation when applied to column with multiple fields
113
     */
114
    public function test_column_aggregation_multiple_fields(): void {
115
        $this->resetAfterTest();
116
 
117
        $user = $this->getDataGenerator()->create_user(['firstname' => 'Adam', 'lastname' => 'Apple']);
118
 
119
        /** @var core_reportbuilder_generator $generator */
120
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
121
        $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
122
 
123
        // This is the column we'll aggregate.
124
        $generator->create_column([
125
            'reportid' => $report->get('id'),
126
            'uniqueidentifier' => 'user:fullnamewithlink',
127
            'aggregation' => groupconcat::get_class_name(),
128
        ]);
129
 
130
        $content = $this->get_custom_report_content($report->get('id'));
131
        $this->assertCount(1, $content);
132
 
133
        // Ensure users are sorted predictably (Adam -> Admin).
134
        [$userone, $usertwo] = explode(', ', reset($content[0]));
135
        $this->assertStringContainsString(fullname($user, true), $userone);
136
        $this->assertStringContainsString(fullname(get_admin(), true), $usertwo);
137
    }
138
 
139
    /**
140
     * Test aggregation when applied to column with callback
141
     */
142
    public function test_column_aggregation_with_callback(): void {
143
        $this->resetAfterTest();
144
 
145
        // Test subjects.
146
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'confirmed' => 1]);
147
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'confirmed' => 0]);
148
        $this->getDataGenerator()->create_user(['firstname' => 'Bob', 'confirmed' => 1]);
149
 
150
        /** @var core_reportbuilder_generator $generator */
151
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
152
        $report = $generator->create_report(['name' => 'Users', 'source' => users::class, 'default' => 0]);
153
 
154
        // First column, sorted.
155
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname', 'sortenabled' => 1]);
156
 
157
        // This is the column we'll aggregate.
158
        $generator->create_column([
159
            'reportid' => $report->get('id'),
160
            'uniqueidentifier' => 'user:confirmed',
161
            'aggregation' => groupconcat::get_class_name(),
162
        ]);
163
 
164
        // Add callback to format the column.
165
        $instance = manager::get_report_from_persistent($report);
166
        $instance->get_column('user:confirmed')
167
            ->add_callback(static function(string $value, stdClass $row, $arguments, ?string $aggregation): string {
168
                // Simple callback to return the given value, and append aggregation type.
169
                return "{$value} ({$aggregation})";
170
            });
171
 
172
        // Assert confirmed column was aggregated, and sorted predictably with callback applied.
173
        $content = $this->get_custom_report_content($report->get('id'));
174
        $this->assertEquals([
1441 ariadna 175
            ['Admin', 'Yes (groupconcat)'],
176
            ['Bob', 'No (groupconcat), Yes (groupconcat), Yes (groupconcat)'],
177
        ], array_map('array_values', $content));
1 efrain 178
    }
179
 
180
    /**
181
     * Test aggregation when applied to column with callback that expects/handles null values
182
     */
183
    public function test_datasource_aggregate_column_callback_with_null(): void {
184
        $this->resetAfterTest();
185
        $this->setAdminUser();
186
 
187
        $userone = $this->getDataGenerator()->create_user(['description' => 'First user']);
188
        $usertwo = $this->getDataGenerator()->create_user(['description' => 'Second user']);
189
 
190
        /** @var core_badges_generator $generator */
191
        $generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
192
 
193
        // Create course badge, issue to both users.
194
        $badgeone = $generator->create_badge(['name' => 'First badge']);
195
        $badgeone->issue($userone->id, true);
196
        $badgeone->issue($usertwo->id, true);
197
 
198
        // Create second badge, without issuing to anyone.
199
        $badgetwo = $generator->create_badge(['name' => 'Second badge']);
200
 
201
        /** @var core_reportbuilder_generator $generator */
202
        $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
203
        $report = $generator->create_report(['name' => 'Badges', 'source' => badges::class, 'default' => 0]);
204
 
205
        // First column, sorted.
206
        $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'badge:name', 'sortenabled' => 1]);
207
 
208
        // This is the column we'll aggregate.
209
        $generator->create_column([
210
            'reportid' => $report->get('id'),
211
            'uniqueidentifier' => 'user:description',
212
            'aggregation' => groupconcat::get_class_name(),
213
        ]);
214
 
215
        // Assert description column was aggregated, with callbacks accounting for null values.
216
        $content = $this->get_custom_report_content($report->get('id'));
217
        $this->assertEquals([
1441 ariadna 218
            [$badgeone->name, "{$userone->description}, {$usertwo->description}"],
219
            [$badgetwo->name, ''],
220
        ], array_map('array_values', $content));
1 efrain 221
    }
222
}