See Release Notes
Long Term Support Release
Differences Between: [Versions 400 and 401]
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\helpers; 20 21 use core_customfield_generator; 22 use core_reportbuilder_generator; 23 use core_reportbuilder_testcase; 24 use core_reportbuilder\local\entities\course; 25 use core_reportbuilder\local\filters\boolean_select; 26 use core_reportbuilder\local\filters\date; 27 use core_reportbuilder\local\filters\select; 28 use core_reportbuilder\local\filters\text; 29 use core_reportbuilder\local\report\column; 30 use core_reportbuilder\local\report\filter; 31 use core_course\reportbuilder\datasource\courses; 32 33 defined('MOODLE_INTERNAL') || die(); 34 35 global $CFG; 36 require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); 37 38 /** 39 * Unit tests for custom fields helper 40 * 41 * @package core_reportbuilder 42 * @covers \core_reportbuilder\local\helpers\custom_fields 43 * @copyright 2021 David Matamoros <davidmc@moodle.com> 44 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 45 */ 46 class custom_fields_test extends core_reportbuilder_testcase { 47 48 /** 49 * Generate custom fields, one of each type 50 * 51 * @return custom_fields 52 */ 53 private function generate_customfields(): custom_fields { 54 55 /** @var core_customfield_generator $generator */ 56 $generator = $this->getDataGenerator()->get_plugin_generator('core_customfield'); 57 $category = $generator->create_category([ 58 'component' => 'core_course', 59 'area' => 'course', 60 'itemid' => 0, 61 'contextid' => \context_system::instance()->id 62 ]); 63 64 $generator->create_field( 65 ['categoryid' => $category->get('id'), 'type' => 'text', 'name' => 'Text', 'shortname' => 'text']); 66 67 $generator->create_field( 68 ['categoryid' => $category->get('id'), 'type' => 'textarea', 'name' => 'Textarea', 'shortname' => 'textarea']); 69 70 $generator->create_field( 71 ['categoryid' => $category->get('id'), 'type' => 'checkbox', 'name' => 'Checkbox', 'shortname' => 'checkbox']); 72 73 $generator->create_field( 74 ['categoryid' => $category->get('id'), 'type' => 'date', 'name' => 'Date', 'shortname' => 'date']); 75 76 $generator->create_field( 77 ['categoryid' => $category->get('id'), 'type' => 'select', 'name' => 'Select', 'shortname' => 'select', 78 'configdata' => ['options' => "Cat\nDog", 'defaultvalue' => 'Cat']]); 79 80 $courseentity = new course(); 81 $coursealias = $courseentity->get_table_alias('course'); 82 83 // Create an instance of the customfields helper. 84 return new custom_fields($coursealias . '.id', $courseentity->get_entity_name(), 85 'core_course', 'course'); 86 } 87 88 /** 89 * Test for get_columns 90 */ 91 public function test_get_columns(): void { 92 $this->resetAfterTest(); 93 94 $customfields = $this->generate_customfields(); 95 $columns = $customfields->get_columns(); 96 97 $this->assertCount(5, $columns); 98 $this->assertContainsOnlyInstancesOf(column::class, $columns); 99 100 [$column0, $column1, $column2, $column3, $column4] = $columns; 101 $this->assertEqualsCanonicalizing(['Text', 'Textarea', 'Checkbox', 'Date', 'Select'], [ 102 $column0->get_title(), $column1->get_title(), $column2->get_title(), $column3->get_title(), $column4->get_title() 103 ]); 104 105 $this->assertEquals(column::TYPE_TEXT, $column0->get_type()); 106 $this->assertEquals('course', $column0->get_entity_name()); 107 $this->assertStringStartsWith('LEFT JOIN {customfield_data}', $column0->get_joins()[0]); 108 // Column of type TEXT is sortable. 109 $this->assertTrue($column0->get_is_sortable()); 110 } 111 112 /** 113 * Test for add_join 114 */ 115 public function test_add_join(): void { 116 $this->resetAfterTest(); 117 118 $customfields = $this->generate_customfields(); 119 $columns = $customfields->get_columns(); 120 $this->assertCount(1, ($columns[0])->get_joins()); 121 122 $customfields->add_join('JOIN {test} t ON t.id = id'); 123 $columns = $customfields->get_columns(); 124 $this->assertCount(2, ($columns[0])->get_joins()); 125 } 126 127 /** 128 * Test for add_joins 129 */ 130 public function test_add_joins(): void { 131 $this->resetAfterTest(); 132 133 $customfields = $this->generate_customfields(); 134 $columns = $customfields->get_columns(); 135 $this->assertCount(1, ($columns[0])->get_joins()); 136 137 $customfields->add_joins(['JOIN {test} t ON t.id = id', 'JOIN {test2} t2 ON t2.id = id']); 138 $columns = $customfields->get_columns(); 139 $this->assertCount(3, ($columns[0])->get_joins()); 140 } 141 142 /** 143 * Test for get_filters 144 */ 145 public function test_get_filters(): void { 146 $this->resetAfterTest(); 147 148 $customfields = $this->generate_customfields(); 149 $filters = $customfields->get_filters(); 150 151 $this->assertCount(5, $filters); 152 $this->assertContainsOnlyInstancesOf(filter::class, $filters); 153 154 [$filter0, $filter1, $filter2, $filter3, $filter4] = $filters; 155 $this->assertEqualsCanonicalizing(['Text', 'Textarea', 'Checkbox', 'Date', 'Select'], [ 156 $filter0->get_header(), $filter1->get_header(), $filter2->get_header(), $filter3->get_header(), $filter4->get_header() 157 ]); 158 } 159 160 /** 161 * Test that adding custom field columns to a report returns expected values 162 */ 163 public function test_custom_report_content(): void { 164 $this->resetAfterTest(); 165 166 $this->generate_customfields(); 167 168 $course = $this->getDataGenerator()->create_course(['customfields' => [ 169 ['shortname' => 'text', 'value' => 'Hello'], 170 ['shortname' => 'textarea_editor', 'value' => ['text' => 'Goodbye', 'format' => FORMAT_MOODLE]], 171 ['shortname' => 'checkbox', 'value' => true], 172 ['shortname' => 'date', 'value' => 1669852800], 173 ['shortname' => 'select', 'value' => 2], 174 ]]); 175 176 /** @var core_reportbuilder_generator $generator */ 177 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 178 $report = $generator->create_report(['name' => 'Courses', 'source' => courses::class, 'default' => 0]); 179 180 // Add user profile field columns to the report. 181 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']); 182 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_text']); 183 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_textarea']); 184 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_checkbox']); 185 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_date']); 186 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:customfield_select']); 187 188 $content = $this->get_custom_report_content($report->get('id')); 189 190 $this->assertEquals([ 191 $course->fullname, 192 'Hello', 193 '<div class="text_to_html">Goodbye</div>', 194 'Yes', 195 userdate(1669852800), 196 'Dog' 197 ], array_values($content[0])); 198 } 199 200 /** 201 * Data provider for {@see test_custom_report_filter} 202 * 203 * @return array[] 204 */ 205 public function custom_report_filter_provider(): array { 206 return [ 207 'Filter by text custom field' => ['course:customfield_text', [ 208 'course:customfield_text_operator' => text::IS_EQUAL_TO, 209 'course:customfield_text_value' => 'Hello', 210 ], true], 211 'Filter by text custom field (no match)' => ['course:customfield_text', [ 212 'course:customfield_text_operator' => text::IS_EQUAL_TO, 213 'course:customfield_text_value' => 'Goodbye', 214 ], false], 215 'Filter by textarea custom field' => ['course:customfield_textarea', [ 216 'course:customfield_textarea_operator' => text::IS_EQUAL_TO, 217 'course:customfield_textarea_value' => 'Goodbye', 218 ], true], 219 'Filter by textarea custom field (no match)' => ['course:customfield_textarea', [ 220 'course:customfield_textarea_operator' => text::IS_EQUAL_TO, 221 'course:customfield_textarea_value' => 'Hello', 222 ], false], 223 'Filter by checkbox custom field' => ['course:customfield_checkbox', [ 224 'course:customfield_checkbox_operator' => boolean_select::CHECKED, 225 ], true], 226 'Filter by checkbox custom field (no match)' => ['course:customfield_checkbox', [ 227 'course:customfield_checkbox_operator' => boolean_select::NOT_CHECKED, 228 ], false], 229 'Filter by date custom field' => ['course:customfield_date', [ 230 'course:customfield_date_operator' => date::DATE_RANGE, 231 'course:customfield_date_from' => 1622502000, 232 ], true], 233 'Filter by date custom field (no match)' => ['course:customfield_date', [ 234 'course:customfield_date_operator' => date::DATE_RANGE, 235 'course:customfield_date_to' => 1622502000, 236 ], false], 237 'Filter by select custom field' => ['course:customfield_select', [ 238 'course:customfield_select_operator' => select::EQUAL_TO, 239 'course:customfield_select_value' => 2, 240 ], true], 241 'Filter by select custom field (no match)' => ['course:customfield_select', [ 242 'course:customfield_select_operator' => select::EQUAL_TO, 243 'course:customfield_select_value' => 1, 244 ], false], 245 ]; 246 } 247 248 /** 249 * Test filtering report by custom fields 250 * 251 * @param string $filtername 252 * @param array $filtervalues 253 * @param bool $expectmatch 254 * 255 * @dataProvider custom_report_filter_provider 256 */ 257 public function test_custom_report_filter(string $filtername, array $filtervalues, bool $expectmatch): void { 258 $this->resetAfterTest(); 259 260 $this->generate_customfields(); 261 262 $course = $this->getDataGenerator()->create_course(['customfields' => [ 263 ['shortname' => 'text', 'value' => 'Hello'], 264 ['shortname' => 'textarea_editor', 'value' => ['text' => 'Goodbye', 'format' => FORMAT_MOODLE]], 265 ['shortname' => 'checkbox', 'value' => true], 266 ['shortname' => 'date', 'value' => 1669852800], 267 ['shortname' => 'select', 'value' => 2], 268 ]]); 269 270 /** @var core_reportbuilder_generator $generator */ 271 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 272 273 // Create report containing single column, and given filter. 274 $report = $generator->create_report(['name' => 'Users', 'source' => courses::class, 'default' => 0]); 275 $generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course:fullname']); 276 277 // Add filter, set it's values. 278 $generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]); 279 $content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues); 280 281 if ($expectmatch) { 282 $this->assertCount(1, $content); 283 $this->assertEquals($course->fullname, reset($content[0])); 284 } else { 285 $this->assertEmpty($content); 286 } 287 } 288 289 /** 290 * Stress test course datasource using custom fields 291 * 292 * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php 293 */ 294 public function test_stress_datasource(): void { 295 if (!PHPUNIT_LONGTEST) { 296 $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); 297 } 298 299 $this->resetAfterTest(); 300 301 $this->generate_customfields(); 302 $course = $this->getDataGenerator()->create_course(['customfields' => [ 303 ['shortname' => 'text', 'value' => 'Hello'], 304 ['shortname' => 'textarea_editor', 'value' => ['text' => 'Goodbye', 'format' => FORMAT_MOODLE]], 305 ['shortname' => 'checkbox', 'value' => true], 306 ['shortname' => 'date', 'value' => 1669852800], 307 ['shortname' => 'select', 'value' => 2], 308 ]]); 309 310 $this->datasource_stress_test_columns(courses::class); 311 $this->datasource_stress_test_columns_aggregation(courses::class); 312 $this->datasource_stress_test_conditions(courses::class, 'course:idnumber'); 313 } 314 } 315
title
Description
Body
title
Description
Body
title
Description
Body
title
Body