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