░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/var/www/moodle/public/reportbuilder/tests/local/report
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: column_test.php
<?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. declare(strict_types=1); namespace core_reportbuilder\local\report; use advanced_testcase; use core\exception\coding_exception; use core\lang_string; use core_reportbuilder\local\aggregation\{count, groupconcat}; use core_reportbuilder\local\helpers\{aggregation, database}; use stdClass; /** * Unit tests for a report column * * @package core_reportbuilder * @covers \core_reportbuilder\local\report\column * @copyright 2020 Paul Holden <paulh@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class column_test extends advanced_testcase { /** * Test column name getter/setter */ public function test_name(): void { $column = $this->create_column('test'); $this->assertEquals('test', $column->get_name()); $this->assertEquals('another', $column ->set_name('another') ->get_name() ); } /** * Test column title getter/setter */ public function test_title(): void { $column = $this->create_column('test', new lang_string('show')); $this->assertEquals('Show', $column->get_title()); $this->assertFalse($column->has_custom_title()); $this->assertEquals('Hide', $column ->set_title(new lang_string('hide')) ->get_title() ); $this->assertTrue($column->has_custom_title()); // Column titles can also be empty. $this->assertEmpty($column ->set_title(null) ->get_title()); } /** * Test entity name getter */ public function test_get_entity_name(): void { $column = $this->create_column('test', null, 'entityname'); $this->assertEquals('entityname', $column->get_entity_name()); } /** * Test getting unique identifier */ public function test_get_unique_identifier(): void { $column = $this->create_column('test', null, 'entityname'); $this->assertEquals('entityname:test', $column->get_unique_identifier()); } /** * Test column type getter/setter */ public function test_get_type(): void { $column = $this->create_column('test'); $this->assertEquals(column::TYPE_INTEGER, $column ->set_type(column::TYPE_INTEGER) ->get_type()); } /** * Test column default type */ public function test_get_type_default(): void { $column = $this->create_column('test'); $this->assertEquals(column::TYPE_TEXT, $column->get_type()); } /** * Test column type with invalid value */ public function test_set_type_invalid(): void { $column = $this->create_column('test'); $this->expectException(coding_exception::class); $this->expectExceptionMessage('Invalid column type'); $column->set_type(-1); } /** * Data provider for {@see test_get_effective_type} * * @return array[] */ public static function get_effective_type_provider(): array { return [ [column::TYPE_TEXT, null, column::TYPE_TEXT], [column::TYPE_TEXT, count::get_class_name(), column::TYPE_INTEGER], [column::TYPE_INTEGER, null, column::TYPE_INTEGER], [column::TYPE_INTEGER, groupconcat::get_class_name(), column::TYPE_TEXT], ]; } /** * Test effective column type * * @param int $columntype * @param string|null $aggregation * @param int $expectedtype * * @dataProvider get_effective_type_provider */ public function test_get_effective_type(int $columntype, ?string $aggregation, int $expectedtype): void { $column = $this->create_column('test') ->set_type($columntype) ->set_aggregation($aggregation); $this->assertEquals($expectedtype, $column->get_effective_type()); } /** * Data provider for {@see test_add_field} * * @return array[] */ public static function add_field_provider(): array { return [ ['foo', '', ['foo AS c1_foo']], ['foo', 'bar', ['foo AS c1_bar']], ['t.foo', '', ['t.foo AS c1_foo']], ['t.foo', 'bar', ['t.foo AS c1_bar']], ]; } /** * Test adding single field, and retrieving it * * @param string $sql * @param string $alias * @param array $expectedselect * * @dataProvider add_field_provider */ public function test_add_field(string $sql, string $alias, array $expectedselect): void { $column = $this->create_column('test') ->set_index(1) ->add_field($sql, $alias); $this->assertEquals($expectedselect, $column->get_fields()); } /** * Test adding params to field, and retrieving them */ public function test_add_field_with_params(): void { [$param0, $param1] = database::generate_param_names(2); $column = $this->create_column('test') ->set_index(1) ->add_field(":{$param0}", 'foo', [$param0 => 'foo']) ->add_field(":{$param1}", 'bar', [$param1 => 'bar']); // Select will look like the following: "p<index>_rbparam<counter>", where index is the column index and counter is // a static value of the report helper class. $fields = $column->get_fields(); $this->assertCount(2, $fields); preg_match('/:(?<paramname>p1_rbparam[\d]+) AS c1_foo/', $fields[0], $matches); $this->assertArrayHasKey('paramname', $matches); $fieldparam0 = $matches['paramname']; preg_match('/:(?<paramname>p1_rbparam[\d]+) AS c1_bar/', $fields[1], $matches); $this->assertArrayHasKey('paramname', $matches); $fieldparam1 = $matches['paramname']; // Ensure column parameters have been renamed appropriately. $this->assertEquals([ $fieldparam0 => 'foo', $fieldparam1 => 'bar', ], $column->get_params()); } /** * Test adding field with alias as part of SQL throws an exception */ public function test_add_field_alias_in_sql(): void { $column = $this->create_column('test') ->set_index(1); $this->expectException(coding_exception::class); $this->expectExceptionMessage('Column alias must be passed as a separate argument'); $column->add_field('foo AS bar'); } /** * Test adding field with complex SQL without an alias throws an exception */ public function test_add_field_complex_without_alias(): void { global $DB; $column = $this->create_column('test') ->set_index(1); $this->expectException(coding_exception::class); $this->expectExceptionMessage('Complex columns must have an alias'); $column->add_field($DB->sql_concat('foo', 'bar')); } /** * Data provider for {@see test_add_fields} * * @return array[] */ public static function add_fields_provider(): array { return [ ['t.foo', ['t.foo AS c1_foo']], ['t.foo bar', ['t.foo AS c1_bar']], ['t.foo AS bar', ['t.foo AS c1_bar']], ['t.foo1, t.foo2 bar, t.foo3 AS baz', ['t.foo1 AS c1_foo1', 't.foo2 AS c1_bar', 't.foo3 AS c1_baz']], ]; } /** * Test adding fields to a column, and retrieving them * * @param string $sql * @param array $expectedselect * * @dataProvider add_fields_provider */ public function test_add_fields(string $sql, array $expectedselect): void { $column = $this->create_column('test') ->set_index(1) ->add_fields($sql); $this->assertEquals($expectedselect, $column->get_fields()); } /** * Test column alias */ public function test_column_alias(): void { $column = $this->create_column('test') ->set_index(1) ->add_fields('t.foo, t.bar'); $this->assertEquals('c1_foo', $column->get_column_alias()); } /** * Test column alias with a field containing an alias */ public function test_column_alias_with_field_alias(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('COALESCE(t.foo, t.bar)', 'lionel'); $this->assertEquals('c1_lionel', $column->get_column_alias()); } /** * Test alias of column without any fields throws exception */ public function test_column_alias_no_fields(): void { $column = $this->create_column('test'); $this->expectException(coding_exception::class); $this->expectExceptionMessage('Column ' . $column->get_unique_identifier() . ' contains no fields'); $column->add_field($column->get_column_alias()); } /** * Test setting column group by SQL */ public function test_set_groupby_sql(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('COALESCE(t.foo, t.bar)', 'lionel') ->set_groupby_sql('t.id'); $this->assertEquals(['t.id'], $column->get_groupby_sql()); } /** * Test getting default column group by SQL */ public function test_get_groupby_sql(): void { global $DB; $column = $this->create_column('test') ->set_index(1) ->add_fields('t.foo, t.bar'); // The behaviour of this method differs due to DB limitations. $usealias = in_array($DB->get_dbfamily(), ['mysql', 'postgres']); if ($usealias) { $expected = ['c1_foo', 'c1_bar']; } else { $expected = ['t.foo', 't.bar']; } $this->assertEquals($expected, $column->get_groupby_sql()); } /** * Data provider for {@see test_get_default_value} and {@see test_format_value} * * @return array[] */ public static function column_type_provider(): array { return [ [column::TYPE_INTEGER, 42], [column::TYPE_TEXT, 'Hello'], [column::TYPE_TIMESTAMP, HOURSECS], [column::TYPE_BOOLEAN, 1, true], [column::TYPE_FLOAT, 1.23], [column::TYPE_LONGTEXT, 'Amigos'], ]; } /** * Test default value is returned from selected values, with correct type * * @param int $columntype * @param mixed $value * @param mixed|null $expected Expected value, or null to indicate it should be identical to value * * @dataProvider column_type_provider */ public function test_get_default_value(int $columntype, $value, $expected = null): void { $defaultvalue = column::get_default_value([ 'value' => $value, 'foo' => 'bar', ], $columntype); $this->assertSame($expected ?? $value, $defaultvalue); } /** * Test that column value is returned correctly, with correct type * * @param int $columntype * @param mixed $value * @param mixed|null $expected Expected value, or null to indicate it should be identical to value * * @dataProvider column_type_provider */ public function test_format_value(int $columntype, $value, $expected = null): void { $column = $this->create_column('test') ->set_index(1) ->set_type($columntype) ->add_field('t.foo'); $this->assertSame($expected ?? $value, $column->format_value([ 'c1_foo' => $value, ])); } /** * Test that column value with callback is returned */ public function test_format_value_callback(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('t.foo') ->set_type(column::TYPE_INTEGER) ->add_callback(static function(int $value, stdClass $values) { return $value * 2; }); $this->assertEquals(84, $column->format_value([ 'c1_bar' => 10, 'c1_foo' => 42, ])); } /** * Test that column value with callback (using all fields) is returned */ public function test_format_value_callback_fields(): void { $column = $this->create_column('test') ->set_index(1) ->add_fields('t.foo, t.baz') ->set_type(column::TYPE_INTEGER) ->add_callback(static function(int $value, stdClass $values) { return $values->foo + $values->baz; }); $this->assertEquals(60, $column->format_value([ 'c1_bar' => 10, 'c1_foo' => 42, 'c1_baz' => 18, ])); } /** * Test that column value with callback (using arguments) is returned */ public function test_format_value_callback_arguments(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('t.foo') ->set_type(column::TYPE_INTEGER) ->add_callback(static function(int $value, stdClass $values, int $argument) { return $value - $argument; }, 10); $this->assertEquals(32, $column->format_value([ 'c1_bar' => 10, 'c1_foo' => 42, ])); } /** * Test that column value with callback (where aggregation is not set) is returned */ public function test_format_value_callback_aggregation(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('t.foo') ->set_type(column::TYPE_INTEGER) ->add_callback(static function(int $value, stdClass $values, $argument, ?string $aggregation): string { // Simple callback to return the given value, and append type of aggregation parameter. return "{$value} " . gettype($aggregation); }); $this->assertEquals("42 NULL", $column->format_value(['c1_foo' => 42])); } /** * Test adding multiple callbacks to a column */ public function test_add_multiple_callback(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('t.foo') ->set_type(column::TYPE_TEXT) ->add_callback(static function(string $value): string { return strrev($value); }) ->add_callback(static function(string $value): string { return strtoupper($value); }); $this->assertEquals('LIONEL', $column->format_value([ 'c1_foo' => 'lenoil', ])); } /** * Test that setting column callback overwrites previous callbacks */ public function test_set_callback(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('t.foo') ->set_type(column::TYPE_TEXT) ->add_callback(static function(string $value): string { return strrev($value); }) ->set_callback(static function(string $value): string { return strtoupper($value); }); $this->assertEquals('LENOIL', $column->format_value([ 'c1_foo' => 'lenoil', ])); } /** * Test setting column aggregation */ public function test_set_aggregation(): void { $column = $this->create_column('test'); $this->assertNull($column->get_aggregation()); $column->set_aggregation(count::get_class_name()); $this->assertInstanceOf(count::class, $column->get_aggregation()); } /** * Test setting invalid column aggregation */ public function test_set_aggregation_invalid(): void { $column = $this->create_column('test'); $this->expectException(coding_exception::class); $this->expectExceptionMessage('Invalid column aggregation'); $column->set_aggregation('invalid'); } /** * Test setting column aggregation options */ public function test_set_aggregation_options(): void { $column = $this->create_column('test'); $this->assertEquals([], $column->get_aggregation_options(count::get_class_name())); $column->set_aggregation_options(count::get_class_name(), ['foo' => 'bar']); $this->assertEquals(['foo' => 'bar'], $column->get_aggregation_options(count::get_class_name())); } /** * Test disabling column aggregation */ public function test_set_disabled_aggregation(): void { $column = $this->create_column('test'); $this->assertEquals([], $column->get_disabled_aggregation()); $column->set_disabled_aggregation([count::get_class_name()]); $this->assertEquals([count::get_class_name()], $column->get_disabled_aggregation()); } /** * Test disabling all column aggregation */ public function test_set_disabled_aggregation_all(): void { $column = $this->create_column('test') ->set_disabled_aggregation_all(); $this->assertEquals(array_map( fn($aggregation) => $aggregation::get_class_name(), aggregation::get_aggregations(), ), $column->get_disabled_aggregation()); } /** * Test is sortable */ public function test_is_sortable(): void { $column = $this->create_column('test'); $this->assertFalse($column->get_is_sortable()); $column->set_is_sortable(true); $this->assertTrue($column->get_is_sortable()); } /** * Test retrieving sort fields */ public function test_get_sort_fields(): void { $column = $this->create_column('test') ->set_index(1) ->add_fields('t.foo, t.bar, t.baz') ->set_is_sortable(true, ['t.baz', 't.bar']); $this->assertEquals(['c1_baz', 'c1_bar'], $column->get_sort_fields()); } /** * Test retrieving sort fields when an aliased field is set as sortable */ public function test_get_sort_fields_with_field_alias(): void { $column = $this->create_column('test') ->set_index(1) ->add_field('t.foo') ->add_field('COALESCE(t.foo, t.bar)', 'lionel') ->set_is_sortable(true, ['lionel']); $this->assertEquals(['c1_lionel'], $column->get_sort_fields()); } /** * Test retrieving sort fields that contain references to fields within complex snippet */ public function test_get_sort_fields_complex(): void { $column = $this->create_column('test') ->set_index(1) ->add_fields('t.foo, t.bar') ->set_is_sortable(true, ['CASE WHEN 1=1 THEN t.foo ELSE t.bar END']); $this->assertEquals(['CASE WHEN 1=1 THEN c1_foo ELSE c1_bar END'], $column->get_sort_fields()); } /** * Test retrieving sort fields when an unknown field is set as sortable */ public function test_get_sort_fields_unknown_field(): void { $column = $this->create_column('test') ->set_index(1) ->add_fields('t.foo') ->set_is_sortable(true, ['t.baz']); $this->assertEquals(['t.baz'], $column->get_sort_fields()); } /** * Test is available */ public function test_is_available(): void { $column = $this->create_column('test'); $this->assertTrue($column->get_is_available()); $column->set_is_available(true); $this->assertTrue($column->get_is_available()); } /** * Helper method to create a column instance * * @param string $name * @param lang_string|null $title * @param string $entityname * @return column */ private function create_column(string $name, ?lang_string $title = null, string $entityname = 'column_testcase'): column { return new column($name, $title, $entityname); } }
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 action_test.php
PHP
4.6 KB
2026-02-11 01:44
EDIT
📄 base_test.php
PHP
10.6 KB
2026-02-11 01:44
EDIT
📄 column_test.php
PHP
20.2 KB
2026-02-11 01:44
EDIT
📄 filter_test.php
PHP
6.5 KB
2026-02-11 01:44
EDIT