From 3e4d6657c31767997956c451373502fd4aee1b43 Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Wed, 20 Nov 2024 14:17:58 +0000 Subject: [PATCH 1/9] Report builder deprecated get_default_table_aliases in Moodle 4.4 --- docs/apis/core/reportbuilder/index.md | 6 +++--- versioned_docs/version-4.3/apis/core/reportbuilder/index.md | 6 +++--- versioned_docs/version-4.4/apis/core/reportbuilder/index.md | 6 +++--- versioned_docs/version-4.5/apis/core/reportbuilder/index.md | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/apis/core/reportbuilder/index.md b/docs/apis/core/reportbuilder/index.md index a9117b1795..3c4f634f0a 100644 --- a/docs/apis/core/reportbuilder/index.md +++ b/docs/apis/core/reportbuilder/index.md @@ -128,14 +128,14 @@ All report elements can be defined within the reports themselves - but entities To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/base.php)** class and must include these methods: ```php -get_default_table_aliases() +get_default_tables() get_default_entity_title() initialise() ``` -##### get_default_table_aliases() +##### get_default_tables() -Defines the SQL alias for the database tables the entity uses. +Defines all the database tables that must be present in the main SQL or joins added to the entity. ##### get_default_entity_title() diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index a9117b1795..c4a720d6e8 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -125,7 +125,7 @@ All report elements can be defined within the reports themselves - but entities #### Create an entity -To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/base.php)** class and must include these methods: +To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php](https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/entities/base.php)** class and must include these methods: ```php get_default_table_aliases() @@ -149,8 +149,8 @@ This is where we **add** the entity columns and filters. Check out these two entities as an example to start building reports: -- **User entity**: [reportbuilder/classes/local/entities/user.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/user.php) -- **Course entity**: [reportbuilder/classes/local/entities/course.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/course.php) +- **User entity**: [reportbuilder/classes/local/entities/user.php](https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/entities/user.php) +- **Course entity**: [reportbuilder/classes/local/entities/course.php](https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/entities/course.php) ### Actions diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index a9117b1795..3c4f634f0a 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -128,14 +128,14 @@ All report elements can be defined within the reports themselves - but entities To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/base.php)** class and must include these methods: ```php -get_default_table_aliases() +get_default_tables() get_default_entity_title() initialise() ``` -##### get_default_table_aliases() +##### get_default_tables() -Defines the SQL alias for the database tables the entity uses. +Defines all the database tables that must be present in the main SQL or joins added to the entity. ##### get_default_entity_title() diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index a9117b1795..3c4f634f0a 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -128,14 +128,14 @@ All report elements can be defined within the reports themselves - but entities To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/base.php)** class and must include these methods: ```php -get_default_table_aliases() +get_default_tables() get_default_entity_title() initialise() ``` -##### get_default_table_aliases() +##### get_default_tables() -Defines the SQL alias for the database tables the entity uses. +Defines all the database tables that must be present in the main SQL or joins added to the entity. ##### get_default_entity_title() From 4e606be3b646e9ca29285bd02b7632f1a9054398 Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Tue, 26 Nov 2024 08:52:01 +0000 Subject: [PATCH 2/9] Reformat Report API headers The first part seems to be more of an overview of how the report builder API is structured, and how those parts should be used, before talking about how to specifically use it in system reports. --- docs/apis/core/reportbuilder/index.md | 16 ++++++++-------- .../version-4.3/apis/core/reportbuilder/index.md | 16 ++++++++-------- .../version-4.4/apis/core/reportbuilder/index.md | 16 ++++++++-------- .../version-4.5/apis/core/reportbuilder/index.md | 16 ++++++++-------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/docs/apis/core/reportbuilder/index.md b/docs/apis/core/reportbuilder/index.md index 3c4f634f0a..cc5aecf441 100644 --- a/docs/apis/core/reportbuilder/index.md +++ b/docs/apis/core/reportbuilder/index.md @@ -5,11 +5,11 @@ tags: - reports --- -## System Reports +## Overview ### Introduction -System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. +The report builder API is a way of providing reporting data, with paging, filtering, exporting standardized across them in both system and custom reports. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. ### Column @@ -168,11 +168,11 @@ Report actions can be defined in system reports to provide CTA links for each ro ))); ``` -### System reports +## System reports System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them -#### Create a new system report using entities +### Create a new system report using entities To create a new system report just create a new class extending [reportbuilder/classes/system_report.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/system_report.php). @@ -261,9 +261,9 @@ Once the whole report has been defined, is possible to set if the report will be $this->set_downloadable(true); ``` -#### Use an entity +### Use an entity -#### Override display name for a column +### Override display name for a column It's possible to override the display name of a column, if you don't want to use the value provided by the entity. @@ -273,7 +273,7 @@ if ($column = $this->get_column('user:fullname')) { } ``` -#### Set a default initial sort direction +### Set a default initial sort direction It's possible to set a default initial sort direction for one column. @@ -281,7 +281,7 @@ It's possible to set a default initial sort direction for one column. $this->set_initial_sort_column('task_log:starttime', SORT_DESC); ``` -#### Examples +### Examples Check out these two system reports as an example: diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index c4a720d6e8..4eba4f1ec8 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -5,11 +5,11 @@ tags: - reports --- -## System Reports +## Overview ### Introduction -System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. +The report builder API is a way of providing reporting data, with paging, filtering, exporting standardized across them in both system and custom reports. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. ### Column @@ -168,11 +168,11 @@ Report actions can be defined in system reports to provide CTA links for each ro ))); ``` -### System reports +## System reports System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them -#### Create a new system report using entities +### Create a new system report using entities To create a new system report just create a new class extending [reportbuilder/classes/system_report.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/system_report.php). @@ -261,9 +261,9 @@ Once the whole report has been defined, is possible to set if the report will be $this->set_downloadable(true); ``` -#### Use an entity +### Use an entity -#### Override display name for a column +### Override display name for a column It's possible to override the display name of a column, if you don't want to use the value provided by the entity. @@ -273,7 +273,7 @@ if ($column = $this->get_column('user:fullname')) { } ``` -#### Set a default initial sort direction +### Set a default initial sort direction It's possible to set a default initial sort direction for one column. @@ -281,7 +281,7 @@ It's possible to set a default initial sort direction for one column. $this->set_initial_sort_column('task_log:starttime', SORT_DESC); ``` -#### Examples +### Examples Check out these two system reports as an example: diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index 3c4f634f0a..cc5aecf441 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -5,11 +5,11 @@ tags: - reports --- -## System Reports +## Overview ### Introduction -System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. +The report builder API is a way of providing reporting data, with paging, filtering, exporting standardized across them in both system and custom reports. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. ### Column @@ -168,11 +168,11 @@ Report actions can be defined in system reports to provide CTA links for each ro ))); ``` -### System reports +## System reports System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them -#### Create a new system report using entities +### Create a new system report using entities To create a new system report just create a new class extending [reportbuilder/classes/system_report.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/system_report.php). @@ -261,9 +261,9 @@ Once the whole report has been defined, is possible to set if the report will be $this->set_downloadable(true); ``` -#### Use an entity +### Use an entity -#### Override display name for a column +### Override display name for a column It's possible to override the display name of a column, if you don't want to use the value provided by the entity. @@ -273,7 +273,7 @@ if ($column = $this->get_column('user:fullname')) { } ``` -#### Set a default initial sort direction +### Set a default initial sort direction It's possible to set a default initial sort direction for one column. @@ -281,7 +281,7 @@ It's possible to set a default initial sort direction for one column. $this->set_initial_sort_column('task_log:starttime', SORT_DESC); ``` -#### Examples +### Examples Check out these two system reports as an example: diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index 3c4f634f0a..cc5aecf441 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -5,11 +5,11 @@ tags: - reports --- -## System Reports +## Overview ### Introduction -System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. +The report builder API is a way of providing reporting data, with paging, filtering, exporting standardized across them in both system and custom reports. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them. ### Column @@ -168,11 +168,11 @@ Report actions can be defined in system reports to provide CTA links for each ro ))); ``` -### System reports +## System reports System reports are a consistent way of providing reporting data, with paging, filtering, exporting standardized across them. Once the groundwork is done in defining the report elements in entities, it's possible to implement them with minimal code just by adding entities to the report, and defining which elements you want to use from them -#### Create a new system report using entities +### Create a new system report using entities To create a new system report just create a new class extending [reportbuilder/classes/system_report.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/system_report.php). @@ -261,9 +261,9 @@ Once the whole report has been defined, is possible to set if the report will be $this->set_downloadable(true); ``` -#### Use an entity +### Use an entity -#### Override display name for a column +### Override display name for a column It's possible to override the display name of a column, if you don't want to use the value provided by the entity. @@ -273,7 +273,7 @@ if ($column = $this->get_column('user:fullname')) { } ``` -#### Set a default initial sort direction +### Set a default initial sort direction It's possible to set a default initial sort direction for one column. @@ -281,7 +281,7 @@ It's possible to set a default initial sort direction for one column. $this->set_initial_sort_column('task_log:starttime', SORT_DESC); ``` -#### Examples +### Examples Check out these two system reports as an example: From b1900b2e48ffbd37060911a405bd253bd5e88270 Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Tue, 26 Nov 2024 09:44:44 +0000 Subject: [PATCH 3/9] Columns and filters always require all the joins from their entity --- docs/apis/core/reportbuilder/index.md | 29 ++++++++++++++++ .../apis/core/reportbuilder/index.md | 17 ++++++++++ .../apis/core/reportbuilder/index.md | 34 +++++++++++++++++++ .../apis/core/reportbuilder/index.md | 17 ++++++++++ 4 files changed, 97 insertions(+) diff --git a/docs/apis/core/reportbuilder/index.md b/docs/apis/core/reportbuilder/index.md index cc5aecf441..bf06a3bc99 100644 --- a/docs/apis/core/reportbuilder/index.md +++ b/docs/apis/core/reportbuilder/index.md @@ -133,6 +133,18 @@ get_default_entity_title() initialise() ``` +If creating an entity for core Moodle data it should be located in one of the following namespaces: + +- `\core_reportbuilder\local\entities\` +- `reportbuilder\local\entities` sub namespace of the subsystem the data is from, for example [`core_course\reportbuilder\local\entities\course_category`](https://github.com/moodle/moodle/blob/main/course/classes/reportbuilder/local/entities/course_category.php) + +When creating one for your own plugin you could technically put it anywhere, however to make it easy to find you should probably use a sub namespace like: + +- `reportbuilder\local\entities` +- `reportbuilder\entities` + +For example if you were building a entity to show assignments you might make it's full namespace `\mod_assign\reportbuilder\entities\assignments`. + ##### get_default_tables() Defines all the database tables that must be present in the main SQL or joins added to the entity. @@ -145,6 +157,23 @@ Defines the default title for this entity. This is where we **add** the entity columns and filters. +#### Tips + +Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. + +```php title="Adding entity joins to a column" +$column->add_joins($this->get_joins()) +``` + +When writing any SQL snippets you should always use the alias table aliases that are returned by the `get_table_alias()` method, this is because reports using the column can change the alias used by a table. + +```php title="Example of getting the alias for a table" +$logalias = $this->get_table_alias('logstore_standard_log'); +$useralias = $this->get_table_alias('user'); +$fildname = "{$useralias).lastname"; +$join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" +``` + #### Examples Check out these two entities as an example to start building reports: diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index 4eba4f1ec8..7b08aa285c 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -145,6 +145,23 @@ Defines the default title for this entity. This is where we **add** the entity columns and filters. +#### Tips + +Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. + +```php title="Adding entity joins to a column" +$column->add_joins($this->get_joins()) +``` + +When writing any SQL snippets you should always use the alias table aliases that are returned by the `get_table_alias()` method, this is because reports using the column can change the alias used by a table. + +```php title="Example of getting the alias for a table" +$logalias = $this->get_table_alias('logstore_standard_log'); +$useralias = $this->get_table_alias('user'); +$fildname = "{$useralias).lastname"; +$join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" +``` + #### Examples Check out these two entities as an example to start building reports: diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index cc5aecf441..fd783eda3f 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -145,6 +145,23 @@ Defines the default title for this entity. This is where we **add** the entity columns and filters. +#### Tips + +Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. + +```php title="Adding entity joins to a column" +$column->add_joins($this->get_joins()) +``` + +When writing any SQL snippets you should always use the alias table aliases that are returned by the `get_table_alias()` method, this is because reports using the column can change the alias used by a table. + +```php title="Example of getting the alias for a table" +$logalias = $this->get_table_alias('logstore_standard_log'); +$useralias = $this->get_table_alias('user'); +$fildname = "{$useralias).lastname"; +$join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" +``` + #### Examples Check out these two entities as an example to start building reports: @@ -281,6 +298,23 @@ It's possible to set a default initial sort direction for one column. $this->set_initial_sort_column('task_log:starttime', SORT_DESC); ``` +#### Tips + +Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. + +```php title="Adding entity joins to a column" +$column->add_joins($this->get_joins()) +``` + +When writing any SQL snippets you should always use the alias table aliases that are returned by the `get_table_alias()` method, this is because reports using the column can change the alias used by a table. + +```php title="Example of getting the alias for a table" +$logalias = $this->get_table_alias('logstore_standard_log'); +$useralias = $this->get_table_alias('user'); +$fildname = "{$useralias).lastname"; +$join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" +``` + ### Examples Check out these two system reports as an example: diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index cc5aecf441..7862aba7fd 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -145,6 +145,23 @@ Defines the default title for this entity. This is where we **add** the entity columns and filters. +#### Tips + +Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. + +```php title="Adding entity joins to a column" +$column->add_joins($this->get_joins()) +``` + +When writing any SQL snippets you should always use the alias table aliases that are returned by the `get_table_alias()` method, this is because reports using the column can change the alias used by a table. + +```php title="Example of getting the alias for a table" +$logalias = $this->get_table_alias('logstore_standard_log'); +$useralias = $this->get_table_alias('user'); +$fildname = "{$useralias).lastname"; +$join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" +``` + #### Examples Check out these two entities as an example to start building reports: From 41feecefde827ea9027be253372b3bea440efad1 Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Tue, 26 Nov 2024 11:30:43 +0000 Subject: [PATCH 4/9] Add some information about creating data sources for custom reports We are also detqailing how to write unit tests for them so that any errors can be found before they go into production --- docs/apis/core/reportbuilder/index.md | 311 +++++++++++++++++- .../apis/core/reportbuilder/index.md | 311 +++++++++++++++++- .../apis/core/reportbuilder/index.md | 311 +++++++++++++++++- .../apis/core/reportbuilder/index.md | 311 +++++++++++++++++- 4 files changed, 1240 insertions(+), 4 deletions(-) diff --git a/docs/apis/core/reportbuilder/index.md b/docs/apis/core/reportbuilder/index.md index bf06a3bc99..004cd80330 100644 --- a/docs/apis/core/reportbuilder/index.md +++ b/docs/apis/core/reportbuilder/index.md @@ -159,7 +159,11 @@ This is where we **add** the entity columns and filters. #### Tips -Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. +Always add all the entities joins to each of its columns and filters; also ensure you add them before any other joins. + +If you do not do add these joins when the entity is not being used as the main one there will be SQL errors when they are used. + +If you do not add them before other joins when the entity is not the main one in a report, you may find that any references to the primary table of the entity in your additional joins break. ```php title="Adding entity joins to a column" $column->add_joins($this->get_joins()) @@ -316,3 +320,308 @@ Check out these two system reports as an example: - **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`](https://github.com/moodle/moodle/blob/main/admin/classes/reportbuilder/local/systemreports/task_logs.php) - **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`](https://github.com/moodle/moodle/blob/main/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) + +## Custom reports + +The custom reporting interface allows reports to be built with a custom view for users, Moodle and plugins can define data sources that provide the basis for the reports that users can make using the system. + +### Create a new data source using entities + +To create a data source you need to extend [`\core_reportbuilder\datasource`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. + +The first method you need to build is `initialise()` + +```php +/** +* Initialise report, we need to set the main table, load our entities and set columns/filters +*/ +protected function initialise(): void { +``` + +The initialise method needs to get the main entity, set the main table it needs to use and add the entity to the report: + +```php +// Our main entity, it contains all of the column definitions that we need. +$entitymain = new task_log(); +$entitymainalias = $entitymain->get_table_alias('task_log'); + +$this->set_main_table('task_log', $entitymainalias); +$this->add_entity($entitymain); +``` + +Now, after adding our first entity, the report can use the columns and filters from it OR more entities can be added to the report using SQL joins: + +```php +$entityuser = new user(); +$entityuseralias = $entityuser->get_table_alias('user'); +$entityuser->add_join( + "LEFT JOIN {user} {$entityuseralias} ON {$entityuseralias}.id = {$entitymainalias}.userid" +); +$this->add_entity($entityuser); +``` + +If you are adding an entity that does not directly join to the entity containing the main table you will need to add the joins to all the intermediate entities to it, without this if a user adds a column from the table to a custom report and has not also added a column from the intermediate table there will be an error. + +```php +$entitycourse = new course(); +$entitycoursealias = $entityuser->get_table_alias('course'); +$entitycourse->add_join("JOIN {course} {$entitycoursealias} ON {$entitycoursealias}.id = {$entityactivity}.course"); + +$entitycategory = new course_category(); +$entitycategoryalias = $entityuser->get_table_alias('course_category'); +$entitycategory->add_joins($entitycourse->get_joins()); +$entitycategory->add_join("JOIN {course_category} {$entitycategoryalias} ON {$entitycategoryalias}.id = {$entitycoursealias}.category"); +``` + +If you are using the same sort of entity twice, or they happen to have clashing aliases in another entity, you can set the alias for a table in an entity: + +```php +$entityuser2 = new user(); +$entityuser2->set_table_alias('user', 'u2'); +``` + +Next you need to add the columns, filters and conditions that a user can add to the custom report. If you want everything you can use: + +```php +$this->add_all_from_entities(); +``` + +### Setup default columns + +Once all entities have been added you need to define which columns it will show by default **they will be displayed in the order you define them**, by implementing the `get_default_columns()` method: + +```php +/** + * Return the columns that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_columns(): array { + return [ + 'task_log:name', + 'task_log:starttime', + 'task_log:duration', + 'task_log:result', + ]; +} +``` + +You may also optionally define the sorting that will be applied to the default report, **it must only use default columns** by overriding the `get_default_column_sorting()` method: + +```php +/** + * Return the column sorting that will be added to the report upon creation + * + * @return int[] + */ +public function get_default_column_sorting(): array { + return [ + 'task_log:starttime' => SORT_DESC, + ]; +} +``` + +### Setup default filters + +The filters allow the end user of the report to only see a subset of the data the report will normally show. You need to define the default setup for this using the `get_default_filters()` method. + +```php +/** + * Return the filters that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_filters(): array { + return [ + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +### Setup conditions + +The conditions allow the user creating the report to define which data it will return. You need to define the default setup for this using the `get_default_conditions()` method. + +```php +/** + * Return the conditions that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_conditions(): array { + return [ + 'task_log:type', + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +You may also optionally define the [initial values for any of the default conditions](\docs\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. + +```php +/** + * Return the condition values that will be set for the report upon creation + * + * @return array + */ +public function get_default_condition_values(): array { + return [ + 'task_log:type_operator' => select::EQUAL_TO, + 'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED, + ]; +} +``` + +### Adding unit tests + +Data sources have a specific type of testcase `\core_reportbuilder_testcase` that provides several useful utility methods that will help you ensure that the data source and it's entities are working correctly. + +```php +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); + +/** + * Unit tests for course categories datasource + * + * @package core_course + * @covers \core_course\reportbuilder\datasource\categories + * @copyright 2023 Paul Holden + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class categories_test extends core_reportbuilder_testcase { +``` + +The `core_reportbuilder_testcase` will not autoload so we first ensure that it is loaded with the `require_once`. After this there are a few things you should look to test: + +1. That the default report setup works properly +2. That you can add all the columns that are not defined in the default report +3. That the filters work +4. Add the stress tests + +#### Testing the default report + +For this you want a step that sets up will return enough data allows you test all the ordering you have configured for the report. + +```php + /** + * Test default datasource + */ + public function test_datasource_default(): void { + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'Zoo', 'idnumber' => 'Z01']); + $course = $this->getDataGenerator()->create_course(['category' => $category->id]); + + /** @var core_reportbuilder_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); + $report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 1]); + + $content = $this->get_custom_report_content($report->get('id')); + $this->assertCount(2, $content); + + // Default columns are name, idnumber, coursecount. Sorted by name ascending. + $this->assertEquals([ + [get_string('defaultcategoryname'), '', 0], + [$category->get_formatted_name(), $category->idnumber, 1], + ], array_map('array_values', $content)); + } +``` + +In this example an additional category has been added to Moodle, the category has had a course added to it so that the count of courses in the category can also be tested. + +It then creates a custom report and gets it's data before testing: + +- It has the expected number of rows +- Testing after stripping out the array keys that the data returned is in the correct order and formatted correctly + +#### Testing the non-default columns and filtering + +You can create blank report can be created by passing `'default' => 0` to the `create_report()` method of the `core_reportbuilder` data generator: + +```php +$report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 0]); +``` + +to add columns of data to the report you would use the `create_column()` method: + +```php +$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:path']); +``` + +it is possible to add sorting to the column by passing additional data in the array, for example: + +```php +$generator->create_column( + [ + 'reportid' => $report->get('id'), + 'uniqueidentifier' => 'course_category:path' + 'sortenabled' => true, + 'sortdirection' => SORT_ASC, + 'sortorder' => 1, + ] +); +``` + +This would cause the column to be sorted ascending. You need to use `sortorder` to decide on the priority it is given in the sorting, with lower numbers being given priority. + +To add a filter to the report you would use the `create_filter()` method of the `core_reportbuilder` data generator: + +```php +$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']); +``` + +This will add the filter for the user's firstname. When you generate the report you will need to pass an array of conditions as the third parameter: + +```php +$filtervalues = [ + 'user:firstname_operator' => text::IS_EQUAL_TO, + 'user:firstname_value' => 'Pedro', +]; +$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues); +``` + +This would cause the report to return results for users with the first name of _Pedro_ only. + +#### The stress test + +The stress test uses helper methods which: + +- Add and remove every colum individually from a report and ensures that is still returns data without error. +- Individually aggregates a report on each column +- Individually applies each filter + +None of these tests checks that the data is what you want, but will ensure that all your joins are setup correctly for the `datasource` to work without errors when manipulating it via the custom report interface. + +```php + /** + * Stress test datasource + * + * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php + */ + public function test_stress_datasource(): void { + if (!PHPUNIT_LONGTEST) { + $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); + } + + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'My category']); + + $this->datasource_stress_test_columns(categories::class); + $this->datasource_stress_test_columns_aggregation(categories::class); + $this->datasource_stress_test_conditions(categories::class, 'course_category:idnumber'); + } +``` + +The test first sets up some data that the data source can return, it then uses three helper methods provided by `core_reportbuilder_testcase` + +The first parameter for each method is the fully qualified class name of the `datasource` that should be tested. `datasource_stress_test_conditions()` has a second parameter that must be the name of a column from the `datasource`. + +#### Unit test examples + +- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/main/course/tests/reportbuilder/datasource/categories_test.php) +- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/main/badges/tests/reportbuilder/datasource/badges_test.php) diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index 7b08aa285c..31e6fd8aad 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -147,7 +147,11 @@ This is where we **add** the entity columns and filters. #### Tips -Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. +Always add all the entities joins to each of its columns and filters; also ensure you add them before any other joins. + +If you do not do add these joins when the entity is not being used as the main one there will be SQL errors when they are used. + +If you do not add them before other joins when the entity is not the main one in a report, you may find that any references to the primary table of the entity in your additional joins break. ```php title="Adding entity joins to a column" $column->add_joins($this->get_joins()) @@ -304,3 +308,308 @@ Check out these two system reports as an example: - **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`](https://github.com/moodle/moodle/blob/main/admin/classes/reportbuilder/local/systemreports/task_logs.php) - **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`](https://github.com/moodle/moodle/blob/main/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) + +## Custom reports + +The custom reporting interface allows reports to be built with a custom view for users, Moodle and plugins can define data sources that provide the basis for the reports that users can make using the system. + +### Create a new data source using entities + +To create a data source you need to extend [`\core_reportbuilder\datasource`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. + +The first method you need to build is `initialise()` + +```php +/** +* Initialise report, we need to set the main table, load our entities and set columns/filters +*/ +protected function initialise(): void { +``` + +The initialise method needs to get the main entity, set the main table it needs to use and add the entity to the report: + +```php +// Our main entity, it contains all of the column definitions that we need. +$entitymain = new task_log(); +$entitymainalias = $entitymain->get_table_alias('task_log'); + +$this->set_main_table('task_log', $entitymainalias); +$this->add_entity($entitymain); +``` + +Now, after adding our first entity, the report can use the columns and filters from it OR more entities can be added to the report using SQL joins: + +```php +$entityuser = new user(); +$entityuseralias = $entityuser->get_table_alias('user'); +$entityuser->add_join( + "LEFT JOIN {user} {$entityuseralias} ON {$entityuseralias}.id = {$entitymainalias}.userid" +); +$this->add_entity($entityuser); +``` + +If you are adding an entity that does not directly join to the entity containing the main table you will need to add the joins to all the intermediate entities to it, without this if a user adds a column from the table to a custom report and has not also added a column from the intermediate table there will be an error. + +```php +$entitycourse = new course(); +$entitycoursealias = $entityuser->get_table_alias('course'); +$entitycourse->add_join("JOIN {course} {$entitycoursealias} ON {$entitycoursealias}.id = {$entityactivity}.course"); + +$entitycategory = new course_category(); +$entitycategoryalias = $entityuser->get_table_alias('course_category'); +$entitycategory->add_joins($entitycourse->get_joins()); +$entitycategory->add_join("JOIN {course_category} {$entitycategoryalias} ON {$entitycategoryalias}.id = {$entitycoursealias}.category"); +``` + +If you are using the same sort of entity twice, or they happen to have clashing aliases in another entity, you can set the alias for a table in an entity: + +```php +$entityuser2 = new user(); +$entityuser2->set_table_alias('user', 'u2'); +``` + +Next you need to add the columns, filters, and conditions that a user can add to the custom report. If you want everything you can use: + +```php +$this->add_all_from_entities(); +``` + +### Setup default columns + +Once all entities have been added you need to define which columns it will show by default **they will be displayed in the order you define them**, by implementing the `get_default_columns()` method: + +```php +/** + * Return the columns that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_columns(): array { + return [ + 'task_log:name', + 'task_log:starttime', + 'task_log:duration', + 'task_log:result', + ]; +} +``` + +You may also optionally define the sorting that will be applied to the default report, **it must only use default columns** by overriding the `get_default_column_sorting()` method: + +```php +/** + * Return the column sorting that will be added to the report upon creation + * + * @return int[] + */ +public function get_default_column_sorting(): array { + return [ + 'task_log:starttime' => SORT_DESC, + ]; +} +``` + +### Setup default filters + +The filters allow the end user of the report to only see a subset of the data the report will normally show. We need to define the default setup for this using the `get_default_filters()` method. + +```php +/** + * Return the filters that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_filters(): array { + return [ + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +### Setup conditions + +The conditions allow the user creating the report to define which data it will return. You need to define the default setup for this using the `get_default_conditions()` method. + +```php +/** + * Return the conditions that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_conditions(): array { + return [ + 'task_log:type', + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +You may also optionally define the [initial values for any of the default conditions](\versioned_docs\version-4.3\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. + +```php +/** + * Return the condition values that will be set for the report upon creation + * + * @return array + */ +public function get_default_condition_values(): array { + return [ + 'task_log:type_operator' => select::EQUAL_TO, + 'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED, + ]; +} +``` + +### Adding unit tests + +Data sources have a specific type of testcase `\core_reportbuilder_testcase` that provides several useful utility methods that will help you ensure that the data source and it's entities are working correctly. + +```php +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); + +/** + * Unit tests for course categories datasource + * + * @package core_course + * @covers \core_course\reportbuilder\datasource\categories + * @copyright 2023 Paul Holden + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class categories_test extends core_reportbuilder_testcase { +``` + +The `core_reportbuilder_testcase` will not autoload so we first ensure that it is loaded with the `require_once`. After this there are a few things you should look to test: + +1. That the default report setup works properly +2. That you can add all the columns that are not defined in the default report +3. That the filters work +4. Add the stress tests + +#### Testing the default report + +For this you want a step that sets up will return enough data allows you test all the ordering you have configured for the report. + +```php + /** + * Test default datasource + */ + public function test_datasource_default(): void { + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'Zoo', 'idnumber' => 'Z01']); + $course = $this->getDataGenerator()->create_course(['category' => $category->id]); + + /** @var core_reportbuilder_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); + $report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 1]); + + $content = $this->get_custom_report_content($report->get('id')); + $this->assertCount(2, $content); + + // Default columns are name, idnumber, coursecount. Sorted by name ascending. + $this->assertEquals([ + [get_string('defaultcategoryname'), '', 0], + [$category->get_formatted_name(), $category->idnumber, 1], + ], array_map('array_values', $content)); + } +``` + +In this example an additional category has been added to Moodle, the category has had a course added to it so that the count of courses in the category can also be tested. + +It then creates a custom report and gets it's data before testing: + +- It has the expected number of rows +- Testing after stripping out the array keys that the data returned is in the correct order and formatted correctly + +#### Testing the non-default columns and filtering + +You can create blank report can be created by passing `'default' => 0` to the `create_report()` method of the `core_reportbuilder` data generator: + +```php +$report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 0]); +``` + +to add columns of data to the report you would use the `create_column()` method: + +```php +$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:path']); +``` + +it is possible to add sorting to the column by passing additional data in the array, for example: + +```php +$generator->create_column( + [ + 'reportid' => $report->get('id'), + 'uniqueidentifier' => 'course_category:path' + 'sortenabled' => true, + 'sortdirection' => SORT_ASC, + 'sortorder' => 1, + ] +); +``` + +This would cause the column to be sorted ascending. You need to use `sortorder` to decide on the priority it is given in the sorting, with lower numbers being given priority. + +To add a filter to the report you would use the `create_filter()` method of the `core_reportbuilder` data generator: + +```php +$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']); +``` + +This will add the filter for the user's firstname. When you generate the report you will need to pass an array of conditions as the third parameter: + +```php +$filtervalues = [ + 'user:firstname_operator' => text::IS_EQUAL_TO, + 'user:firstname_value' => 'Pedro', +]; +$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues); +``` + +This would cause the report to return results for users with the first name of _Pedro_ only. + +#### The stress test + +The stress test uses helper methods which: + +- Add and remove every colum individually from a report and ensures that is still returns data without error. +- Individually aggregates a report on each column +- Individually applies each filter + +None of these tests checks that the data is what you want, but will ensure that all your joins are setup correctly for the `datasource` to work without errors when manipulating it via the custom report interface. + +```php + /** + * Stress test datasource + * + * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php + */ + public function test_stress_datasource(): void { + if (!PHPUNIT_LONGTEST) { + $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); + } + + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'My category']); + + $this->datasource_stress_test_columns(categories::class); + $this->datasource_stress_test_columns_aggregation(categories::class); + $this->datasource_stress_test_conditions(categories::class, 'course_category:idnumber'); + } +``` + +The test first sets up some data that the data source can return, it then uses three helper methods provided by `core_reportbuilder_testcase` + +The first parameter for each method is the fully qualified class name of the `datasource` that should be tested. `datasource_stress_test_conditions()` has a second parameter that must be the name of a column from the `datasource`. + +#### Unit test examples + +- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/main/course/tests/reportbuilder/datasource/categories_test.php) +- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/main/badges/tests/reportbuilder/datasource/badges_test.php) diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index fd783eda3f..866c03054e 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -147,7 +147,11 @@ This is where we **add** the entity columns and filters. #### Tips -Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. +Always add all the entities joins to each of its columns and filters; also ensure you add them before any other joins. + +If you do not do add these joins when the entity is not being used as the main one there will be SQL errors when they are used. + +If you do not add them before other joins when the entity is not the main one in a report, you may find that any references to the primary table of the entity in your additional joins break. ```php title="Adding entity joins to a column" $column->add_joins($this->get_joins()) @@ -321,3 +325,308 @@ Check out these two system reports as an example: - **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`](https://github.com/moodle/moodle/blob/main/admin/classes/reportbuilder/local/systemreports/task_logs.php) - **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`](https://github.com/moodle/moodle/blob/main/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) + +## Custom reports + +The custom reporting interface allows reports to be built with a custom view for users, Moodle and plugins can define data sources that provide the basis for the reports that users can make using the system. + +### Create a new data source using entities + +To create a data source you need to extend [`\core_reportbuilder\datasource`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. + +The first method you need to build is `initialise()` + +```php +/** +* Initialise report, we need to set the main table, load our entities and set columns/filters +*/ +protected function initialise(): void { +``` + +The initialise method needs to get the main entity, set the main table it needs to use and add the entity to the report: + +```php +// Our main entity, it contains all of the column definitions that we need. +$entitymain = new task_log(); +$entitymainalias = $entitymain->get_table_alias('task_log'); + +$this->set_main_table('task_log', $entitymainalias); +$this->add_entity($entitymain); +``` + +Now, after adding our first entity, the report can use the columns and filters from it OR more entities can be added to the report using SQL joins: + +```php +$entityuser = new user(); +$entityuseralias = $entityuser->get_table_alias('user'); +$entityuser->add_join( + "LEFT JOIN {user} {$entityuseralias} ON {$entityuseralias}.id = {$entitymainalias}.userid" +); +$this->add_entity($entityuser); +``` + +If you are adding an entity that does not directly join to the entity containing the main table you will need to add the joins to all the intermediate entities to it, without this if a user adds a column from the table to a custom report and has not also added a column from the intermediate table there will be an error. + +```php +$entitycourse = new course(); +$entitycoursealias = $entityuser->get_table_alias('course'); +$entitycourse->add_join("JOIN {course} {$entitycoursealias} ON {$entitycoursealias}.id = {$entityactivity}.course"); + +$entitycategory = new course_category(); +$entitycategoryalias = $entityuser->get_table_alias('course_category'); +$entitycategory->add_joins($entitycourse->get_joins()); +$entitycategory->add_join("JOIN {course_category} {$entitycategoryalias} ON {$entitycategoryalias}.id = {$entitycoursealias}.category"); +``` + +If you are using the same sort of entity twice, or they happen to have clashing aliases in another entity, you can set the alias for a table in an entity: + +```php +$entityuser2 = new user(); +$entityuser2->set_table_alias('user', 'u2'); +``` + +Next you need to add the columns, filters and conditions that a user can add to the custom report. If you want everything you can use: + +```php +$this->add_all_from_entities(); +``` + +### Setup default columns + +Once all entities have been added you need to define which columns it will show by default **they will be displayed in the order you define them**, by implementing the `get_default_columns()` method: + +```php +/** + * Return the columns that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_columns(): array { + return [ + 'task_log:name', + 'task_log:starttime', + 'task_log:duration', + 'task_log:result', + ]; +} +``` + +You may also optionally define the sorting that will be applied to the default report, **it must only use default columns** by overriding the `get_default_column_sorting()` method: + +```php +/** + * Return the column sorting that will be added to the report upon creation + * + * @return int[] + */ +public function get_default_column_sorting(): array { + return [ + 'task_log:starttime' => SORT_DESC, + ]; +} +``` + +### Setup default filters + +The filters allow the end user of the report to only see a subset of the data the report will normally show. You need to define the default setup for this using the `get_default_filters()` method. + +```php +/** + * Return the filters that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_filters(): array { + return [ + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +### Setup conditions + +The conditions allow the user creating the report to define which data it will return. You need to define the default setup for this using the `get_default_conditions()` method. + +```php +/** + * Return the conditions that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_conditions(): array { + return [ + 'task_log:type', + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +You may also optionally define the [initial values for any of the default conditions](\versioned_docs\version-4.4\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. + +```php +/** + * Return the condition values that will be set for the report upon creation + * + * @return array + */ +public function get_default_condition_values(): array { + return [ + 'task_log:type_operator' => select::EQUAL_TO, + 'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED, + ]; +} +``` + +### Adding unit tests + +Data sources have a specific type of testcase `\core_reportbuilder_testcase` that provides several useful utility methods that will help you ensure that the data source and it's entities are working correctly. + +```php +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); + +/** + * Unit tests for course categories datasource + * + * @package core_course + * @covers \core_course\reportbuilder\datasource\categories + * @copyright 2023 Paul Holden + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class categories_test extends core_reportbuilder_testcase { +``` + +The `core_reportbuilder_testcase` will not autoload so we first ensure that it is loaded with the `require_once`. After this there are a few things you should look to test: + +1. That the default report setup works properly +2. That you can add all the columns that are not defined in the default report +3. That the filters work +4. Add the stress tests + +#### Testing the default report + +For this you want a step that sets up will return enough data allows you test all the ordering you have configured for the report. + +```php + /** + * Test default datasource + */ + public function test_datasource_default(): void { + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'Zoo', 'idnumber' => 'Z01']); + $course = $this->getDataGenerator()->create_course(['category' => $category->id]); + + /** @var core_reportbuilder_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); + $report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 1]); + + $content = $this->get_custom_report_content($report->get('id')); + $this->assertCount(2, $content); + + // Default columns are name, idnumber, coursecount. Sorted by name ascending. + $this->assertEquals([ + [get_string('defaultcategoryname'), '', 0], + [$category->get_formatted_name(), $category->idnumber, 1], + ], array_map('array_values', $content)); + } +``` + +In this example an additional category has been added to Moodle, the category has had a course added to it so that the count of courses in the category can also be tested. + +It then creates a custom report and gets it's data before testing: + +- It has the expected number of rows +- Testing after stripping out the array keys that the data returned is in the correct order and formatted correctly + +#### Testing the non-default columns and filtering + +You can create blank report can be created by passing `'default' => 0` to the `create_report()` method of the `core_reportbuilder` data generator: + +```php +$report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 0]); +``` + +to add columns of data to the report you would use the `create_column()` method: + +```php +$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:path']); +``` + +it is possible to add sorting to the column by passing additional data in the array, for example: + +```php +$generator->create_column( + [ + 'reportid' => $report->get('id'), + 'uniqueidentifier' => 'course_category:path' + 'sortenabled' => true, + 'sortdirection' => SORT_ASC, + 'sortorder' => 1, + ] +); +``` + +This would cause the column to be sorted ascending. You need to use `sortorder` to decide on the priority it is given in the sorting, with lower numbers being given priority. + +To add a filter to the report you would use the `create_filter()` method of the `core_reportbuilder` data generator: + +```php +$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']); +``` + +This will add the filter for the user's firstname. When you generate the report you will need to pass an array of conditions as the third parameter: + +```php +$filtervalues = [ + 'user:firstname_operator' => text::IS_EQUAL_TO, + 'user:firstname_value' => 'Pedro', +]; +$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues); +``` + +This would cause the report to return results for users with the first name of _Pedro_ only. + +#### The stress test + +The stress test uses helper methods which: + +- Add and remove every colum individually from a report and ensures that is still returns data without error. +- Individually aggregates a report on each column +- Individually applies each filter + +None of these tests checks that the data is what you want, but will ensure that all your joins are setup correctly for the `datasource` to work without errors when manipulating it via the custom report interface. + +```php + /** + * Stress test datasource + * + * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php + */ + public function test_stress_datasource(): void { + if (!PHPUNIT_LONGTEST) { + $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); + } + + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'My category']); + + $this->datasource_stress_test_columns(categories::class); + $this->datasource_stress_test_columns_aggregation(categories::class); + $this->datasource_stress_test_conditions(categories::class, 'course_category:idnumber'); + } +``` + +The test first sets up some data that the data source can return, it then uses three helper methods provided by `core_reportbuilder_testcase` + +The first parameter for each method is the fully qualified class name of the `datasource` that should be tested. `datasource_stress_test_conditions()` has a second parameter that must be the name of a column from the `datasource`. + +#### Unit test examples + +- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/main/course/tests/reportbuilder/datasource/categories_test.php) +- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/main/badges/tests/reportbuilder/datasource/badges_test.php) diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index 7862aba7fd..b6bcc5e271 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -147,7 +147,11 @@ This is where we **add** the entity columns and filters. #### Tips -Always add all the entities joins to each of its columns and filters, if you do not do this there may be issues when you try to use them in reports. +Always add all the entities joins to each of its columns and filters; also ensure you add them before any other joins. + +If you do not do add these joins when the entity is not being used as the main one there will be SQL errors when they are used. + +If you do not add them before other joins when the entity is not the main one in a report, you may find that any references to the primary table of the entity in your additional joins break. ```php title="Adding entity joins to a column" $column->add_joins($this->get_joins()) @@ -304,3 +308,308 @@ Check out these two system reports as an example: - **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`](https://github.com/moodle/moodle/blob/main/admin/classes/reportbuilder/local/systemreports/task_logs.php) - **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`](https://github.com/moodle/moodle/blob/main/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) + +## Custom reports + +The custom reporting interface allows reports to be built with a custom view for users, Moodle and plugins can define data sources that provide the basis for the reports that users can make using the system. + +### Create a new data source using entities + +To create a data source you need to extend [`\core_reportbuilder\datasource`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. + +The first method you need to build is `initialise()` + +```php +/** +* Initialise report, we need to set the main table, load our entities and set columns/filters +*/ +protected function initialise(): void { +``` + +The initialise method needs to get the main entity, set the main table it needs to use and add the entity to the report: + +```php +// Our main entity, it contains all of the column definitions that we need. +$entitymain = new task_log(); +$entitymainalias = $entitymain->get_table_alias('task_log'); + +$this->set_main_table('task_log', $entitymainalias); +$this->add_entity($entitymain); +``` + +Now, after adding our first entity, the report can use the columns and filters from it OR more entities can be added to the report using SQL joins: + +```php +$entityuser = new user(); +$entityuseralias = $entityuser->get_table_alias('user'); +$entityuser->add_join( + "LEFT JOIN {user} {$entityuseralias} ON {$entityuseralias}.id = {$entitymainalias}.userid" +); +$this->add_entity($entityuser); +``` + +If you are adding an entity that does not directly join to the entity containing the main table you will need to add the joins to all the intermediate entities to it, without this if a user adds a column from the table to a custom report and has not also added a column from the intermediate table there will be an error. + +```php +$entitycourse = new course(); +$entitycoursealias = $entityuser->get_table_alias('course'); +$entitycourse->add_join("JOIN {course} {$entitycoursealias} ON {$entitycoursealias}.id = {$entityactivity}.course"); + +$entitycategory = new course_category(); +$entitycategoryalias = $entityuser->get_table_alias('course_category'); +$entitycategory->add_joins($entitycourse->get_joins()); +$entitycategory->add_join("JOIN {course_category} {$entitycategoryalias} ON {$entitycategoryalias}.id = {$entitycoursealias}.category"); +``` + +If you are using the same sort of entity twice, or they happen to have clashing aliases in another entity, you can set the alias for a table in an entity: + +```php +$entityuser2 = new user(); +$entityuser2->set_table_alias('user', 'u2'); +``` + +Next you need to add the columns, filters and conditions that a user can add to the custom report. If you want everything you can use: + +```php +$this->add_all_from_entities(); +``` + +### Setup default columns + +Once all entities have been added you need to define which columns it will show by default **they will be displayed in the order you define them**, by implementing the `get_default_columns()` method: + +```php +/** + * Return the columns that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_columns(): array { + return [ + 'task_log:name', + 'task_log:starttime', + 'task_log:duration', + 'task_log:result', + ]; +} +``` + +You may also optionally define the sorting that will be applied to the default report, **it must only use default columns** by overriding the `get_default_column_sorting()` method: + +```php +/** + * Return the column sorting that will be added to the report upon creation + * + * @return int[] + */ +public function get_default_column_sorting(): array { + return [ + 'task_log:starttime' => SORT_DESC, + ]; +} +``` + +### Setup default filters + +The filters allow the end user of the report to only see a subset of the data the report will normally show. You need to define the default setup for this using the `get_default_filters()` method. + +```php +/** + * Return the filters that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_filters(): array { + return [ + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +### Setup conditions + +The conditions allow the user creating the report to define which data it will return. You need to define the default setup for this using the `get_default_conditions()` method. + +```php +/** + * Return the conditions that will be added to the report upon creation + * + * @return string[] + */ +public function get_default_conditions(): array { + return [ + 'task_log:type', + 'task_log:timestart', + 'task_log:result', + ]; +} +``` + +You may also optionally define the [initial values for any of the default conditions](\versioned_docs\version-4.5\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. + +```php +/** + * Return the condition values that will be set for the report upon creation + * + * @return array + */ +public function get_default_condition_values(): array { + return [ + 'task_log:type_operator' => select::EQUAL_TO, + 'task_log:type_value' => \core\task\database_logger::TYPE_SCHEDULED, + ]; +} +``` + +### Adding unit tests + +Data sources have a specific type of testcase `\core_reportbuilder_testcase` that provides several useful utility methods that will help you ensure that the data source and it's entities are working correctly. + +```php +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once("{$CFG->dirroot}/reportbuilder/tests/helpers.php"); + +/** + * Unit tests for course categories datasource + * + * @package core_course + * @covers \core_course\reportbuilder\datasource\categories + * @copyright 2023 Paul Holden + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class categories_test extends core_reportbuilder_testcase { +``` + +The `core_reportbuilder_testcase` will not autoload so we first ensure that it is loaded with the `require_once`. After this there are a few things you should look to test: + +1. That the default report setup works properly +2. That you can add all the columns that are not defined in the default report +3. That the filters work +4. Add the stress tests + +#### Testing the default report + +For this you want a step that sets up will return enough data allows you test all the ordering you have configured for the report. + +```php + /** + * Test default datasource + */ + public function test_datasource_default(): void { + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'Zoo', 'idnumber' => 'Z01']); + $course = $this->getDataGenerator()->create_course(['category' => $category->id]); + + /** @var core_reportbuilder_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); + $report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 1]); + + $content = $this->get_custom_report_content($report->get('id')); + $this->assertCount(2, $content); + + // Default columns are name, idnumber, coursecount. Sorted by name ascending. + $this->assertEquals([ + [get_string('defaultcategoryname'), '', 0], + [$category->get_formatted_name(), $category->idnumber, 1], + ], array_map('array_values', $content)); + } +``` + +In this example an additional category has been added to Moodle, the category has had a course added to it so that the count of courses in the category can also be tested. + +It then creates a custom report and gets it's data before testing: + +- It has the expected number of rows +- Testing after stripping out the array keys that the data returned is in the correct order and formatted correctly + +#### Testing the non-default columns and filtering + +You can create blank report can be created by passing `'default' => 0` to the `create_report()` method of the `core_reportbuilder` data generator: + +```php +$report = $generator->create_report(['name' => 'My report', 'source' => categories::class, 'default' => 0]); +``` + +to add columns of data to the report you would use the `create_column()` method: + +```php +$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'course_category:path']); +``` + +it is possible to add sorting to the column by passing additional data in the array, for example: + +```php +$generator->create_column( + [ + 'reportid' => $report->get('id'), + 'uniqueidentifier' => 'course_category:path' + 'sortenabled' => true, + 'sortdirection' => SORT_ASC, + 'sortorder' => 1, + ] +); +``` + +This would cause the column to be sorted ascending. You need to use `sortorder` to decide on the priority it is given in the sorting, with lower numbers being given priority. + +To add a filter to the report you would use the `create_filter()` method of the `core_reportbuilder` data generator: + +```php +$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => 'user:firstname']); +``` + +This will add the filter for the user's firstname. When you generate the report you will need to pass an array of conditions as the third parameter: + +```php +$filtervalues = [ + 'user:firstname_operator' => text::IS_EQUAL_TO, + 'user:firstname_value' => 'Pedro', +]; +$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues); +``` + +This would cause the report to return results for users with the first name of _Pedro_ only. + +#### The stress test + +The stress test uses helper methods which: + +- Add and remove every colum individually from a report and ensures that is still returns data without error. +- Individually aggregates a report on each column +- Individually applies each filter + +None of these tests checks that the data is what you want, but will ensure that all your joins are setup correctly for the `datasource` to work without errors when manipulating it via the custom report interface. + +```php + /** + * Stress test datasource + * + * In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php + */ + public function test_stress_datasource(): void { + if (!PHPUNIT_LONGTEST) { + $this->markTestSkipped('PHPUNIT_LONGTEST is not defined'); + } + + $this->resetAfterTest(); + + $category = $this->getDataGenerator()->create_category(['name' => 'My category']); + + $this->datasource_stress_test_columns(categories::class); + $this->datasource_stress_test_columns_aggregation(categories::class); + $this->datasource_stress_test_conditions(categories::class, 'course_category:idnumber'); + } +``` + +The test first sets up some data that the data source can return, it then uses three helper methods provided by `core_reportbuilder_testcase` + +The first parameter for each method is the fully qualified class name of the `datasource` that should be tested. `datasource_stress_test_conditions()` has a second parameter that must be the name of a column from the `datasource`. + +#### Unit test examples + +- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/main/course/tests/reportbuilder/datasource/categories_test.php) +- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/main/badges/tests/reportbuilder/datasource/badges_test.php) From 40c63cfd4baf5a72f56687abdfec26bd058b1fd1 Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Mon, 2 Dec 2024 12:52:38 +0000 Subject: [PATCH 5/9] Document things that have changed with time --- docs/apis/core/reportbuilder/index.md | 28 +++++++++++++++---- .../apis/core/reportbuilder/index.md | 11 ++++---- .../apis/core/reportbuilder/index.md | 28 +++++++++++++++---- .../apis/core/reportbuilder/index.md | 28 +++++++++++++++---- 4 files changed, 72 insertions(+), 23 deletions(-) diff --git a/docs/apis/core/reportbuilder/index.md b/docs/apis/core/reportbuilder/index.md index 004cd80330..837581d640 100644 --- a/docs/apis/core/reportbuilder/index.md +++ b/docs/apis/core/reportbuilder/index.md @@ -42,11 +42,12 @@ To create a new column, just create a new instance of [`reportbuilder/classes/lo And use: -- **add_joins()** to add any extra SQL joins the column might need -- **set_type()** to add the column type (All constant types are defined within the same column class) -- **set_is_sortable()** to define if column can be sorted (For example we don't want to sort if the column shows just a picture) -- **add_callback()** to format the output of the column -- **add_field()** to add any db fields format callback might need +- `add_joins()` to add any extra SQL joins the column might need +- `set_type()` to add the column type (All constant types are defined within the same column class) +- `set_is_sortable()` to define if column can be sorted (For example we don't want to sort if the column shows just a picture) +- `add_callback()` to format the output of the column +- `add_field()` to add any db fields format callback might need +- `set_is_deprecated()` used to mark a column as deprecated, indicating it will be removed in the future. This is required in core Moodle columns if you want delete or remove one from an entity because plugins may be using the fields. ```php title="Example of code for creating a column" $columns[] = (new column( @@ -386,6 +387,21 @@ Next you need to add the columns, filters and conditions that a user can add to $this->add_all_from_entities(); ``` +### Setup report name + +You will need to specify the name that is displayed to the end user for the data source. + +```php + /** + * Return user friendly name of the report source + * + * @return string + */ + public static function get_name(): string { + return get_string('tasklogs', 'core_admin'); + } +``` + ### Setup default columns Once all entities have been added you need to define which columns it will show by default **they will be displayed in the order you define them**, by implementing the `get_default_columns()` method: @@ -590,7 +606,7 @@ This would cause the report to return results for users with the first name of _ The stress test uses helper methods which: -- Add and remove every colum individually from a report and ensures that is still returns data without error. +- Add and remove every colum individually from a report and ensures that is still returns data without error, it also tests the column can be sorted if that has been enabled. - Individually aggregates a report on each column - Individually applies each filter diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index 31e6fd8aad..1014bb983e 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -42,11 +42,12 @@ To create a new column, just create a new instance of [`reportbuilder/classes/lo And use: -- **add_joins()** to add any extra SQL joins the column might need -- **set_type()** to add the column type (All constant types are defined within the same column class) -- **set_is_sortable()** to define if column can be sorted (For example we don't want to sort if the column shows just a picture) -- **add_callback()** to format the output of the column -- **add_field()** to add any db fields format callback might need +- `add_joins()` to add any extra SQL joins the column might need +- `set_type()` to add the column type (All constant types are defined within the same column class) +- `set_is_sortable()` to define if column can be sorted (For example we don't want to sort if the column shows just a picture) +- `add_callback()` to format the output of the column +- `add_field()` to add any db fields format callback might need +- `set_is_deprecated()` used to mark a column as deprecated, indicating it will be removed in the future. This is required in core Moodle columns if you want delete or remove one from an entity because plugins may be using the fields. ```php title="Example of code for creating a column" $columns[] = (new column( diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index 866c03054e..24388890b4 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -42,11 +42,12 @@ To create a new column, just create a new instance of [`reportbuilder/classes/lo And use: -- **add_joins()** to add any extra SQL joins the column might need -- **set_type()** to add the column type (All constant types are defined within the same column class) -- **set_is_sortable()** to define if column can be sorted (For example we don't want to sort if the column shows just a picture) -- **add_callback()** to format the output of the column -- **add_field()** to add any db fields format callback might need +- `add_joins()` to add any extra SQL joins the column might need +- `set_type()` to add the column type (All constant types are defined within the same column class) +- `set_is_sortable()` to define if column can be sorted (For example we don't want to sort if the column shows just a picture) +- `add_callback()` to format the output of the column +- `add_field()` to add any db fields format callback might need +- `set_is_deprecated()` used to mark a column as deprecated, indicating it will be removed in the future. This is required in core Moodle columns if you want delete or remove one from an entity because plugins may be using the fields. ```php title="Example of code for creating a column" $columns[] = (new column( @@ -391,6 +392,21 @@ Next you need to add the columns, filters and conditions that a user can add to $this->add_all_from_entities(); ``` +### Setup report name + +You will need to specify the name that is displayed to the end user for the data source. + +```php + /** + * Return user friendly name of the report source + * + * @return string + */ + public static function get_name(): string { + return get_string('tasklogs', 'core_admin'); + } +``` + ### Setup default columns Once all entities have been added you need to define which columns it will show by default **they will be displayed in the order you define them**, by implementing the `get_default_columns()` method: @@ -595,7 +611,7 @@ This would cause the report to return results for users with the first name of _ The stress test uses helper methods which: -- Add and remove every colum individually from a report and ensures that is still returns data without error. +- Add and remove every colum individually from a report and ensures that is still returns data without error, it also tests the column can be sorted if that has been enabled. - Individually aggregates a report on each column - Individually applies each filter diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index b6bcc5e271..ed59da5653 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -42,11 +42,12 @@ To create a new column, just create a new instance of [`reportbuilder/classes/lo And use: -- **add_joins()** to add any extra SQL joins the column might need -- **set_type()** to add the column type (All constant types are defined within the same column class) -- **set_is_sortable()** to define if column can be sorted (For example we don't want to sort if the column shows just a picture) -- **add_callback()** to format the output of the column -- **add_field()** to add any db fields format callback might need +- `add_joins()` to add any extra SQL joins the column might need +- `set_type()` to add the column type (All constant types are defined within the same column class) +- `set_is_sortable()` to define if column can be sorted (For example we don't want to sort if the column shows just a picture) +- `add_callback()` to format the output of the column +- `add_field()` to add any db fields format callback might need +- `set_is_deprecated()` used to mark a column as deprecated, indicating it will be removed in the future. This is required in core Moodle columns if you want delete or remove one from an entity because plugins may be using the fields. ```php title="Example of code for creating a column" $columns[] = (new column( @@ -374,6 +375,21 @@ Next you need to add the columns, filters and conditions that a user can add to $this->add_all_from_entities(); ``` +### Setup report name + +You will need to specify the name that is displayed to the end user for the data source. + +```php + /** + * Return user friendly name of the report source + * + * @return string + */ + public static function get_name(): string { + return get_string('tasklogs', 'core_admin'); + } +``` + ### Setup default columns Once all entities have been added you need to define which columns it will show by default **they will be displayed in the order you define them**, by implementing the `get_default_columns()` method: @@ -578,7 +594,7 @@ This would cause the report to return results for users with the first name of _ The stress test uses helper methods which: -- Add and remove every colum individually from a report and ensures that is still returns data without error. +- Add and remove every colum individually from a report and ensures that is still returns data without error, it also tests the column can be sorted if that has been enabled. - Individually aggregates a report on each column - Individually applies each filter From e6196c6d50a39bcaa587dd6c006a13b6cd7ed81e Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Fri, 29 Nov 2024 15:48:41 +0000 Subject: [PATCH 6/9] Add documentation about how to define the filters and conditions in code --- docs/apis/core/reportbuilder/filtering.md | 329 ++++++++++++++++++ .../apis/core/reportbuilder/filtering.md | 291 ++++++++++++++++ .../apis/core/reportbuilder/filtering.md | 329 ++++++++++++++++++ .../apis/core/reportbuilder/filtering.md | 329 ++++++++++++++++++ 4 files changed, 1278 insertions(+) create mode 100644 docs/apis/core/reportbuilder/filtering.md create mode 100644 versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md create mode 100644 versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md create mode 100644 versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md diff --git a/docs/apis/core/reportbuilder/filtering.md b/docs/apis/core/reportbuilder/filtering.md new file mode 100644 index 0000000000..6a83eb1ad2 --- /dev/null +++ b/docs/apis/core/reportbuilder/filtering.md @@ -0,0 +1,329 @@ +--- +title: Setting default conditions +tags: + - Report builder + - reports +--- + +When setting up a `datasource` it is possible to define the default condition values for it using the `get_default_condition_values()` method. + +The method requires that you return an array where the keys are formed in a specific way so it will link to the correct filter and condition form field. The names and number of condition form fields varies depending on both the specific filter type and the operator used. + +The keys used in the array all start with the name of the entity you are querying followed by a colon and the name of the filter, then an underscore followed by the form field you are defining; for example, assuming we are using default names, if you have a `course_category` entity and want to set a value for the `name` filter you would need to start the keys with `course_categotry:name`. + +Most filter types use an `operator` for field to define which of their operators is used, they are defined as constants in each filter type, for example the text filter type has `EQUAL_TO` so you will end up with `'course_categotry:name_operator' => text::EQUAL_TO` + +The operator you have defined will then determine which other form fields you will need to provide values for, in our example so far that would be `value` which would be defined as `'course_categotry:name_value' => 'The name of a category'` this would mean that only a category with that exact name would be returned by default. + +[Core report builder filter types](https://github.com/moodle/moodle/tree/main/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. + +## Text filters + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_EMPTY` +- `IS_NOT_EMPTY` + +## Filtering types with a single value + +A string should be sent in `value` for: + +- `CONTAINS` +- `DOES_NOT_CONTAIN` +- `IS_EQUAL_TO` +- `IS_NOT_EQUAL_TO` +- `STARTS_WITH` +- `ENDS_WITH` + +```php title="Examples of array key and value pairs for single value text filters" +'my:text_operator' => text::CONTAINS, +'my:text_value1' => 'Bob Dylan', +'my:text2_operator' => text::IS_NOT_EQUAL_TO, +'my:text2_value1' => 'This exact thing', +``` + +## Number filter + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_NOT_EMPTY` +- `IS_EMPTY` + +### Operators with a single value + +A number should be passed in `value1` for: + +- `LESS_THAN` +- `GREATER_THAN` +- `EQUAL_TO` +- `EQUAL_OR_LESS_THAN` +- `EQUAL_OR_GREATER_THAN` + +```php title="Examples of array key and value pairs for single value number filters" +'my:number_operator' => number::LESS_THAN, +'my:number_value1' => 42, +'my:number2_operator' => number::EQUAL_OR_GREATER_THAN, +'my:number2_value1' => 15.6, +``` + +### Operators with complex data + +#### RANGE + +- `value1` number for the lower bound +- `value2` number for the upper bound + +```php title="Examples of array key and value pairs for range values text filters" +'my:number_operator' => number::RANGE, +'my:number_value1' => 60, +'my:number_value2' => 600, +``` + +## Date filter + +The date filter has several constants used to define the amount of time: + +- `DATE_UNIT_MINUTE` +- `DATE_UNIT_HOUR` +- `DATE_UNIT_DAY` +- `DATE_UNIT_WEEK` +- `DATE_UNIT_MONTH` +- `DATE_UNIT_YEAR` + +### Operators with no additional data + +- `DATE_ANY` +- `DATE_NOT_EMPTY` +- `DATE_EMPTY` +- `DATE_PAST` +- `DATE_FUTURE` + +### Operators with one value + +The `unit` should be sent defining the amount of time that should be considered. + +- `DATE_CURRENT` + +```php title="Examples of array key and value pairs for single value date filters" +'my:date_operator' => date::DATE_CURRENT, +'my:date_unit' => date::DATE_UNIT_DAY, +``` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0 +2. `unit` - The type of time unit + +- `DATE_LAST` +- `DATE_NEXT` +- `DATE_BEFORE` +- `DATE_AFTER` + +```php title="Examples of array key and value pairs for two value date filters" +'my:date_operator' => date::DATE_NEXT, +'my:date_value' => 5, +'my:date_unit' => date::DATE_UNIT_DAY, +'my:date2_operator' => date::DATE_BEFORE, +'my:date2_value' => 20, +'my:date2_unit' => date::DATE_UNIT_MINUTE, +``` + +### Operators with complex values + +#### DATE_RANGE + +The date range should have a unix timestamp in one or more of the following: + +- `from` +- `to` + +```php title="Examples of array key and value pairs for the range date filters" +'my:date_operator' => date::DATE_RANGE, +'my:date_from' => 1732593669, +'my:date_to' => 1732893669, +``` + +## Select filter + +### Operators with no additional data + +- `ANY_VALUE` + +### Operators with one value + +The value of the select should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value select filters" +'my:select_operator' => select::EQUAL_TO, +'my:select_value' => 10, +'my:select2_operator' => select::NOT_EQUAL_TO, +'my:select2_value' => 'textkey', +``` + +## Boolean select filter + +### Operators with no additional data + +- `ANY_VALUE` +- `CHECKED` +- `NOT_CHECKED` + +## Duration filter + +For units the filter uses the standard Moodle defines: + +- `MINSECS` +- `HOURSECS` +- `DAYSECS` +- `WEEKSECS` + +It also allows the integer value 1 to represent seconds. + +### Operators with no additional data + +- `DURATION_ANY` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0, this should be the number of the units that are included. +2. `unit` - The type of time unit. + +- `DURATION_MAXIMUM` +- `DURATION_MINIMUM` + +```php title="Examples of array key and value pairs for two value duration filters" +'my:duration_operator' => duration::DURATION_MAXIMUM, +'my:duration_value' => 10, +'my:duration_unit' => 1, +'my:duration2_operator' => duration::DURATION_MINIMUM, +'my:duration_value' => 42, +'my:duration_unit' => DAYSECS, +``` + +## Autocomplete filter + +This filter type does not use `operator`, it requires that `values` contains an array of keys that the autocompletion element would return. + +```php title="Examples of array key and value pairs for autocomplete filters" +'my:autocomplete_values' => [1, 4, 6], +'my:autocomplete2_values' => [42], +``` + +## Category filter + +### Operators with complex values + +Both the available operators for this have two values: + +1. `value` The database id of a `course_category` record +2. `subcategories` A boolean to indicate if sub categories of the selected category should also be included. + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for category filters" +'my:category_operator' => category::EQUAL_TO, +'my:category_value' => [142, 4753], +'my:category_subcategories' => true, +'my:category2_operator' => category::NOT_EQUAL_TO, +'my:category2_value' => [1], +'my:category2_subcategories' => false, +``` + +## Course_select filter + +This filter type does not use `operator`, it requires that `values` contains an array of database ids for courses. + +```php title="Examples of array key and value pairs for course filters" +'my:course_values' => [1, 4, 6], +'my:course2_values' => [42], +``` + +## Cohort filter + +This filter type does not use `operator`, it requires that `values` contains an array of database ids for cohorts. + +```php title="Examples of array key and value pairs for cohort filters" +'my:cohort_values' => [1, 4, 6], +'my:cohort2_values' => [42], +``` + +## Filesize filter + +The filter defines several units for filesize as constants: + +- `SIZE_UNIT_KILOBYTE` +- `SIZE_UNIT_MEGABYTE` +- `SIZE_UNIT_GIGABYTE` + +### Operators with no additional data + +- `ANY_VALUE` + +### Operators with two values + +1. `value1` The size of the file in the unit +2. `unit` The type of unit (as defined by the filter constants) + +- `LESS_THAN` +- `GREATER_THAN` + +```php title="Examples of array key and value pairs for two value file size filters" +'my:filesize_operator' => filesize::LESS_THAN, +'my:filesize_value1' => 50, +'my:filesize_unit' => filesize::SIZE_UNIT_KILOBYTE, +'my:filesize2_operator' => filesize::GREATER_THAN, +'my:filesize2_value1' => 1, +'my:filesize2_unit' => filesize::SIZE_UNIT_GIGABYTE, +``` + +## Tags filter + +### Operators with no additional data + +- `ANY_VALUE` +- `NOT_EMPTY` +- `EMPTY` + +### Operators with one value + +An array of tag database ids should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value tag filters" +'my:tags_operator' => tags::EQUAL_TO, +'my:tags_value' => [142, 4753], +'my:tags2_operator' => tags::NOT_EQUAL_TO, +'my:tags2_value' => [1], +``` + +## User filter + +### Operators with no additional data + +- `USER_ANY` +- `USER_CURRENT` + +### Operators with one value + +An array of user database ids should be sent in `value` to: + +- `USER_SELECT` + +```php title="Examples of array key and value pairs for single value user filters" +'my:user_operator' => user::USER_SELECT, +'my:user_value' => [142, 4753], +'my:user2_operator' => user::USER_SELECT, +'my:user2_value' => [1], +``` diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md b/versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md new file mode 100644 index 0000000000..346d00ca0c --- /dev/null +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md @@ -0,0 +1,291 @@ +--- +title: Setting default conditions +tags: + - Report builder + - reports +--- + +When setting up a `datasource` it is possible to define the default condition values for it using the `get_default_condition_values()` method. + +The method requires that you return an array where the keys are formed in a specific way so it will link to the correct filter and condition form field. The names and number of condition form fields varies depending on both the specific filter type and the operator used. + +The keys used in the array all start with the name of the entity you are querying followed by a colon and the name of the filter, then an underscore followed by the form field you are defining; for example, assuming we are using default names, if you have a `course_category` entity and want to set a value for the `name` filter you would need to start the keys with `course_categotry:name`. + +Most filter types use an `operator` for field to define which of their operators is used, they are defined as constants in each filter type, for example the text filter type has `EQUAL_TO` so you will end up with `'course_categotry:name_operator' => text::EQUAL_TO` + +The operator you have defined will then determine which other form fields you will need to provide values for, in our example so far that would be `value` which would be defined as `'course_categotry:name_value' => 'The name of a category'` this would mean that only a category with that exact name would be returned by default. + +[Core report builder filter types](https://github.com/moodle/moodle/tree/main/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. + +## Text filters + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_EMPTY` +- `IS_NOT_EMPTY` + +## Operators with a single value + +A string should be sent in `value` for: + +- `CONTAINS` +- `DOES_NOT_CONTAIN` +- `IS_EQUAL_TO` +- `IS_NOT_EQUAL_TO` +- `STARTS_WITH` +- `ENDS_WITH` + +```php title="Examples of array key and value pairs for single value text filters +'my:text_operator' => text::CONTAINS, +'my:text_value1' => 'Bob Dylan', +'my:text2_operator' => text::IS_NOT_EQUAL_TO, +'my:text2_value1' => 'This exact thing', +``` + +## Number filter + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_NOT_EMPTY` +- `IS_EMPTY` + +### Operators with a single value + +A number should be passed in `value1` for: + +- `LESS_THAN` +- `GREATER_THAN` +- `EQUAL_TO` +- `EQUAL_OR_LESS_THAN` +- `EQUAL_OR_GREATER_THAN` + +```php title="Examples of array key and value pairs for single value number filters" +'my:number_operator' => number::LESS_THAN, +'my:number_value1' => 42, +'my:number2_operator' => number::EQUAL_OR_GREATER_THAN, +'my:number2_value1' => 15.6, +``` + +### Operators with complex data + +#### RANGE + +- `value1` number for the lower bound +- `value2` number for the upper bound + +```php title="Examples of array key and value pairs for range values text filters" +'my:number_operator' => number::RANGE, +'my:number_value1' => 60, +'my:number_value2' => 600, +``` + +## Date filter + +The date filter has several constants used to define the amount of time: + +- `DATE_UNIT_MINUTE` +- `DATE_UNIT_HOUR` +- `DATE_UNIT_DAY` +- `DATE_UNIT_WEEK` +- `DATE_UNIT_MONTH` +- `DATE_UNIT_YEAR` + +### Operators with no additional data + +- `DATE_ANY` +- `DATE_NOT_EMPTY` +- `DATE_EMPTY` +- `DATE_PAST` +- `DATE_FUTURE` + +### Operators with one value + +The `unit` should be sent defining the amount of time that should be considered. + +- `DATE_CURRENT` + +```php title="Examples of array key and value pairs for single value date filters" +'my:date_operator' => date::DATE_CURRENT, +'my:date_unit' => date::DATE_UNIT_DAY, +``` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0 +2. `unit` - The type of time unit + +- `DATE_LAST` +- `DATE_NEXT` +- `DATE_BEFORE` +- `DATE_AFTER` + +```php title="Examples of array key and value pairs for two value date filters" +'my:date_operator' => date::DATE_NEXT, +'my:date_value' => 5, +'my:date_unit' => date::DATE_UNIT_DAY, +'my:date2_operator' => date::DATE_BEFORE, +'my:date2_value' => 20, +'my:date2_unit' => date::DATE_UNIT_MINUTE, +``` + +### Operators with complex values + +#### DATE_RANGE + +The date range should have a unix timestamp in one or more of the following: + +- `from` +- `to` + +```php title="Examples of array key and value pairs for the range date filters" +'my:date_operator' => date::DATE_RANGE, +'my:date_from' => 1732593669, +'my:date_to' => 1732893669, +``` + +## Select filter + +### Operators with no additional data + +- `ANY_VALUE` + +### Operators with one value + +The value of the select should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value select filters" +'my:select_operator' => select::EQUAL_TO, +'my:select_value' => 10, +'my:select2_operator' => select::NOT_EQUAL_TO, +'my:select2_value' => 'textkey', +``` + +## Boolean select filter + +### Operators with no additional data + +- `ANY_VALUE` +- `CHECKED` +- `NOT_CHECKED` + +## Duration filter + +For units the filter uses the standard Moodle defines: + +- `MINSECS` +- `HOURSECS` +- `DAYSECS` +- `WEEKSECS` + +It also allows the integer value 1 to represent seconds. + +### Operators with no additional data + +- `DURATION_ANY` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0, this should be the number of the units that are included. +2. `unit` - The type of time unit. + +- `DURATION_MAXIMUM` +- `DURATION_MINIMUM` + +```php title="Examples of array key and value pairs for two value duration filters" +'my:duration_operator' => duration::DURATION_MAXIMUM, +'my:duration_value' => 10, +'my:duration_unit' => 1, +'my:duration2_operator' => duration::DURATION_MINIMUM, +'my:duration_value' => 42, +'my:duration_unit' => DAYSECS, +``` + +## Autocomplete filter + +This filter type does not use `operator`, it requires that `values` contains an array of keys that the autocompletion element would return. + +```php title="Examples of array key and value pairs for autocomplete filters" +'my:autocomplete_values' => [1, 4, 6], +'my:autocomplete2_values' => [42], +``` + +## Category filter + +### Operators with complex values + +Both the available operators for this have two values: + +1. `value` The database id of a `course_category` record +2. `subcategories` A boolean to indicate if sub categories of the selected category should also be included. + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for category filters" +'my:category_operator' => category::EQUAL_TO, +'my:category_value' => [142, 4753], +'my:category_subcategories' => true, +'my:category2_operator' => category::NOT_EQUAL_TO, +'my:category2_value' => [1], +'my:category2_subcategories' => false, +``` + +## Course_select filter + +This filter type does not use `operator`, it requires that `values` contains an array of database ids for courses. + +```php title="Examples of array key and value pairs for course filters" +'my:course_values' => [1, 4, 6], +'my:course2_values' => [42], +``` + +## Tags filter + +### Operators with no additional data + +- `ANY_VALUE` +- `NOT_EMPTY` +- `EMPTY` + +### Operators with one value + +An array of tag database ids should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value tag filters" +'my:tags_operator' => tags::EQUAL_TO, +'my:tags_value' => [142, 4753], +'my:tags2_operator' => tags::NOT_EQUAL_TO, +'my:tags2_value' => [1], +``` + +## User filter + +### Operators with no additional data + +- `USER_ANY` +- `USER_CURRENT` + +### Operators with one value + +An array of user database ids should be sent in `value` to: + +- `USER_SELECT` + +```php title="Examples of array key and value pairs for single value user filters" +'my:user_operator' => user::USER_SELECT, +'my:user_value' => [142, 4753], +'my:user2_operator' => user::USER_SELECT, +'my:user2_value' => [1], +``` diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md b/versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md new file mode 100644 index 0000000000..c36c2f4a14 --- /dev/null +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md @@ -0,0 +1,329 @@ +--- +title: Setting default conditions +tags: + - Report builder + - reports +--- + +When setting up a `datasource` it is possible to define the default condition values for it using the `get_default_condition_values()` method. + +The method requires that you return an array where the keys are formed in a specific way so it will link to the correct filter and condition form field. The names and number of condition form fields varies depending on both the specific filter type and the operator used. + +The keys used in the array all start with the name of the entity you are querying followed by a colon and the name of the filter, then an underscore followed by the form field you are defining; for example, assuming we are using default names, if you have a `course_category` entity and want to set a value for the `name` filter you would need to start the keys with `course_categotry:name`. + +Most filter types use an `operator` for field to define which of their operators is used, they are defined as constants in each filter type, for example the text filter type has `EQUAL_TO` so you will end up with `'course_categotry:name_operator' => text::EQUAL_TO` + +The operator you have defined will then determine which other form fields you will need to provide values for, in our example so far that would be `value` which would be defined as `'course_categotry:name_value' => 'The name of a category'` this would mean that only a category with that exact name would be returned by default. + +[Core report builder filter types](https://github.com/moodle/moodle/tree/main/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. + +## Text filters + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_EMPTY` +- `IS_NOT_EMPTY` + +## Operators with a single value + +A string should be sent in `value` for: + +- `CONTAINS` +- `DOES_NOT_CONTAIN` +- `IS_EQUAL_TO` +- `IS_NOT_EQUAL_TO` +- `STARTS_WITH` +- `ENDS_WITH` + +```php title="Examples of array key and value pairs for single value text filters +'my:text_operator' => text::CONTAINS, +'my:text_value1' => 'Bob Dylan', +'my:text2_operator' => text::IS_NOT_EQUAL_TO, +'my:text2_value1' => 'This exact thing', +``` + +## Number filter + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_NOT_EMPTY` +- `IS_EMPTY` + +### Operators with a single value + +A number should be passed in `value1` for: + +- `LESS_THAN` +- `GREATER_THAN` +- `EQUAL_TO` +- `EQUAL_OR_LESS_THAN` +- `EQUAL_OR_GREATER_THAN` + +```php title="Examples of array key and value pairs for single value number filters" +'my:number_operator' => number::LESS_THAN, +'my:number_value1' => 42, +'my:number2_operator' => number::EQUAL_OR_GREATER_THAN, +'my:number2_value1' => 15.6, +``` + +### Operators with complex data + +#### RANGE + +- `value1` number for the lower bound +- `value2` number for the upper bound + +```php title="Examples of array key and value pairs for range values text filters" +'my:number_operator' => number::RANGE, +'my:number_value1' => 60, +'my:number_value2' => 600, +``` + +## Date filter + +The date filter has several constants used to define the amount of time: + +- `DATE_UNIT_MINUTE` +- `DATE_UNIT_HOUR` +- `DATE_UNIT_DAY` +- `DATE_UNIT_WEEK` +- `DATE_UNIT_MONTH` +- `DATE_UNIT_YEAR` + +### Operators with no additional data + +- `DATE_ANY` +- `DATE_NOT_EMPTY` +- `DATE_EMPTY` +- `DATE_PAST` +- `DATE_FUTURE` + +### Operators with one value + +The `unit` should be sent defining the amount of time that should be considered. + +- `DATE_CURRENT` + +```php title="Examples of array key and value pairs for single value date filters" +'my:date_operator' => date::DATE_CURRENT, +'my:date_unit' => date::DATE_UNIT_DAY, +``` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0 +2. `unit` - The type of time unit + +- `DATE_LAST` +- `DATE_NEXT` +- `DATE_BEFORE` +- `DATE_AFTER` + +```php title="Examples of array key and value pairs for two value date filters" +'my:date_operator' => date::DATE_NEXT, +'my:date_value' => 5, +'my:date_unit' => date::DATE_UNIT_DAY, +'my:date2_operator' => date::DATE_BEFORE, +'my:date2_value' => 20, +'my:date2_unit' => date::DATE_UNIT_MINUTE, +``` + +### Operators with complex values + +#### DATE_RANGE + +The date range should have a unix timestamp in one or more of the following: + +- `from` +- `to` + +```php title="Examples of array key and value pairs for the range date filters" +'my:date_operator' => date::DATE_RANGE, +'my:date_from' => 1732593669, +'my:date_to' => 1732893669, +``` + +## Select filter + +### Operators with no additional data + +- `ANY_VALUE` + +### Operators with one value + +The value of the select should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value select filters" +'my:select_operator' => select::EQUAL_TO, +'my:select_value' => 10, +'my:select2_operator' => select::NOT_EQUAL_TO, +'my:select2_value' => 'textkey', +``` + +## Boolean select filter + +### Operators with no additional data + +- `ANY_VALUE` +- `CHECKED` +- `NOT_CHECKED` + +## Duration filter + +For units the filter uses the standard Moodle defines: + +- `MINSECS` +- `HOURSECS` +- `DAYSECS` +- `WEEKSECS` + +It also allows the integer value 1 to represent seconds. + +### Operators with no additional data + +- `DURATION_ANY` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0, this should be the number of the units that are included. +2. `unit` - The type of time unit. + +- `DURATION_MAXIMUM` +- `DURATION_MINIMUM` + +```php title="Examples of array key and value pairs for two value duration filters" +'my:duration_operator' => duration::DURATION_MAXIMUM, +'my:duration_value' => 10, +'my:duration_unit' => 1, +'my:duration2_operator' => duration::DURATION_MINIMUM, +'my:duration_value' => 42, +'my:duration_unit' => DAYSECS, +``` + +## Autocomplete filter + +This filter type does not use `operator`, it requires that `values` contains an array of keys that the autocompletion element would return. + +```php title="Examples of array key and value pairs for autocomplete filters" +'my:autocomplete_values' => [1, 4, 6], +'my:autocomplete2_values' => [42], +``` + +## Category filter + +### Operators with complex values + +Both the available operators for this have two values: + +1. `value` The database id of a `course_category` record +2. `subcategories` A boolean to indicate if sub categories of the selected category should also be included. + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for category filters" +'my:category_operator' => category::EQUAL_TO, +'my:category_value' => [142, 4753], +'my:category_subcategories' => true, +'my:category2_operator' => category::NOT_EQUAL_TO, +'my:category2_value' => [1], +'my:category2_subcategories' => false, +``` + +## Course_select filter + +This filter type does not use `operator`, it requires that `values` contains an array of database ids for courses. + +```php title="Examples of array key and value pairs for course filters" +'my:course_values' => [1, 4, 6], +'my:course2_values' => [42], +``` + +## Cohort filter + +This filter type does not use `operator`, it requires that `values` contains an array of database ids for cohorts. + +```php title="Examples of array key and value pairs for cohort filters" +'my:cohort_values' => [1, 4, 6], +'my:cohort2_values' => [42], +``` + +## Filesize filter + +The filter defines several units for filesize as constants: + +- `SIZE_UNIT_KILOBYTE` +- `SIZE_UNIT_MEGABYTE` +- `SIZE_UNIT_GIGABYTE` + +### Operators with no additional data + +- `ANY_VALUE` + +### Operators with two values + +1. `value1` The size of the file in the unit +2. `unit` The type of unit (as defined by the filter constants) + +- `LESS_THAN` +- `GREATER_THAN` + +```php title="Examples of array key and value pairs for two value file size filters" +'my:filesize_operator' => filesize::LESS_THAN, +'my:filesize_value1' => 50, +'my:filesize_unit' => filesize::SIZE_UNIT_KILOBYTE, +'my:filesize2_operator' => filesize::GREATER_THAN, +'my:filesize2_value1' => 1, +'my:filesize2_unit' => filesize::SIZE_UNIT_GIGABYTE, +``` + +## Tags filter + +### Operators with no additional data + +- `ANY_VALUE` +- `NOT_EMPTY` +- `EMPTY` + +### Operators with one value + +An array of tag database ids should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value tag filters" +'my:tags_operator' => tags::EQUAL_TO, +'my:tags_value' => [142, 4753], +'my:tags2_operator' => tags::NOT_EQUAL_TO, +'my:tags2_value' => [1], +``` + +## User filter + +### Operators with no additional data + +- `USER_ANY` +- `USER_CURRENT` + +### Operators with one value + +An array of user database ids should be sent in `value` to: + +- `USER_SELECT` + +```php title="Examples of array key and value pairs for single value user filters" +'my:user_operator' => user::USER_SELECT, +'my:user_value' => [142, 4753], +'my:user2_operator' => user::USER_SELECT, +'my:user2_value' => [1], +``` diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md b/versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md new file mode 100644 index 0000000000..a12024d1c2 --- /dev/null +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md @@ -0,0 +1,329 @@ +--- +title: Setting default conditions +tags: + - Report builder + - reports +--- + +When setting up a `datasource` it is possible to define the default condition values for it using the `get_default_condition_values()` method. + +The method requires that you return an array where the keys are formed in a specific way so it will link to the correct filter and condition form field. The names and number of condition form fields varies depending on both the specific filter type and the operator used. + +The keys used in the array all start with the name of the entity you are querying followed by a colon and the name of the filter, then an underscore followed by the form field you are defining; for example, assuming we are using default names, if you have a `course_category` entity and want to set a value for the `name` filter you would need to start the keys with `course_categotry:name`. + +Most filter types use an `operator` for field to define which of their operators is used, they are defined as constants in each filter type, for example the text filter type has `EQUAL_TO` so you will end up with `'course_categotry:name_operator' => text::EQUAL_TO` + +The operator you have defined will then determine which other form fields you will need to provide values for, in our example so far that would be `value` which would be defined as `'course_categotry:name_value' => 'The name of a category'` this would mean that only a category with that exact name would be returned by default. + +[Core report builder filter types](https://github.com/moodle/moodle/tree/main/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. + +## Text filters + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_EMPTY` +- `IS_NOT_EMPTY` + +## Operators with a single value + +A string should be sent in `value` for: + +- `CONTAINS` +- `DOES_NOT_CONTAIN` +- `IS_EQUAL_TO` +- `IS_NOT_EQUAL_TO` +- `STARTS_WITH` +- `ENDS_WITH` + +```php title="Examples of array key and value pairs for single value text filters +'my:text_operator' => text::CONTAINS, +'my:text_value1' => 'Bob Dylan', +'my:text2_operator' => text::IS_NOT_EQUAL_TO, +'my:text2_value1' => 'This exact thing', +``` + +## Number filter + +### Operators with no additional data + +- `ANY_VALUE` +- `IS_NOT_EMPTY` +- `IS_EMPTY` + +### Operators with a single value + +A number should be passed in `value1` for: + +- `LESS_THAN` +- `GREATER_THAN` +- `EQUAL_TO` +- `EQUAL_OR_LESS_THAN` +- `EQUAL_OR_GREATER_THAN` + +```php title="Examples of array key and value pairs for single value number filters +'my:number_operator' => number::LESS_THAN, +'my:number_value1' => 42, +'my:number2_operator' => number::EQUAL_OR_GREATER_THAN, +'my:number2_value1' => 15.6, +``` + +### Operators with complex data + +#### RANGE + +- `value1` number for the lower bound +- `value2` number for the upper bound + +```php title="Examples of array key and value pairs for range values text filters" +'my:number_operator' => number::RANGE, +'my:number_value1' => 60, +'my:number_value2' => 600, +``` + +## Date filter + +The date filter has several constants used to define the amount of time: + +- `DATE_UNIT_MINUTE` +- `DATE_UNIT_HOUR` +- `DATE_UNIT_DAY` +- `DATE_UNIT_WEEK` +- `DATE_UNIT_MONTH` +- `DATE_UNIT_YEAR` + +### Operators with no additional data + +- `DATE_ANY` +- `DATE_NOT_EMPTY` +- `DATE_EMPTY` +- `DATE_PAST` +- `DATE_FUTURE` + +### Operators with one value + +The `unit` should be sent defining the amount of time that should be considered. + +- `DATE_CURRENT` + +```php title="Examples of array key and value pairs for single value date filters" +'my:date_operator' => date::DATE_CURRENT, +'my:date_unit' => date::DATE_UNIT_DAY, +``` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0 +2. `unit` - The type of time unit + +- `DATE_LAST` +- `DATE_NEXT` +- `DATE_BEFORE` +- `DATE_AFTER` + +```php title="Examples of array key and value pairs for two value date filters" +'my:date_operator' => date::DATE_NEXT, +'my:date_value' => 5, +'my:date_unit' => date::DATE_UNIT_DAY, +'my:date2_operator' => date::DATE_BEFORE, +'my:date2_value' => 20, +'my:date2_unit' => date::DATE_UNIT_MINUTE, +``` + +### Operators with complex values + +#### DATE_RANGE + +The date range should have a unix timestamp in one or more of the following: + +- `from` +- `to` + +```php title="Examples of array key and value pairs for the range date filters" +'my:date_operator' => date::DATE_RANGE, +'my:date_from' => 1732593669, +'my:date_to' => 1732893669, +``` + +## Select filter + +### Operators with no additional data + +- `ANY_VALUE` + +### Operators with one value + +The value of the select should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value select filters" +'my:select_operator' => select::EQUAL_TO, +'my:select_value' => 10, +'my:select2_operator' => select::NOT_EQUAL_TO, +'my:select2_value' => 'textkey', +``` + +## Boolean select filter + +### Operators with no additional data + +- `ANY_VALUE` +- `CHECKED` +- `NOT_CHECKED` + +## Duration filter + +For units the filter uses the standard Moodle defines: + +- `MINSECS` +- `HOURSECS` +- `DAYSECS` +- `WEEKSECS` + +It also allows the integer value 1 to represent seconds. + +### Operators with no additional data + +- `DURATION_ANY` + +### Operators with two values + +These operators can all accept two values: + +1. `value` - A integer greater than 0, this should be the number of the units that are included. +2. `unit` - The type of time unit. + +- `DURATION_MAXIMUM` +- `DURATION_MINIMUM` + +```php title="Examples of array key and value pairs for two value duration filters" +'my:duration_operator' => duration::DURATION_MAXIMUM, +'my:duration_value' => 10, +'my:duration_unit' => 1, +'my:duration2_operator' => duration::DURATION_MINIMUM, +'my:duration_value' => 42, +'my:duration_unit' => DAYSECS, +``` + +## Autocomplete filter + +This filter type does not use `operator`, it requires that `values` contains an array of keys that the autocompletion element would return. + +```php title="Examples of array key and value pairs for autocomplete filters" +'my:autocomplete_values' => [1, 4, 6], +'my:autocomplete2_values' => [42], +``` + +## Category filter + +### Operators with complex values + +Both the available operators for this have two values: + +1. `value` The database id of a `course_category` record +2. `subcategories` A boolean to indicate if sub categories of the selected category should also be included. + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for category filters" +'my:category_operator' => category::EQUAL_TO, +'my:category_value' => [142, 4753], +'my:category_subcategories' => true, +'my:category2_operator' => category::NOT_EQUAL_TO, +'my:category2_value' => [1], +'my:category2_subcategories' => false, +``` + +## Course_select filter + +This filter type does not use `operator`, it requires that `values` contains an array of database ids for courses. + +```php title="Examples of array key and value pairs for course filters" +'my:course_values' => [1, 4, 6], +'my:course2_values' => [42], +``` + +## Cohort filter + +This filter type does not use `operator`, it requires that `values` contains an array of database ids for cohorts. + +```php title="Examples of array key and value pairs for cohort filters" +'my:cohort_values' => [1, 4, 6], +'my:cohort2_values' => [42], +``` + +## Filesize filter + +The filter defines several units for filesize as constants: + +- `SIZE_UNIT_KILOBYTE` +- `SIZE_UNIT_MEGABYTE` +- `SIZE_UNIT_GIGABYTE` + +### Operators with no additional data + +- `ANY_VALUE` + +### Operators with two values + +1. `value1` The size of the file in the unit +2. `unit` The type of unit (as defined by the filter constants) + +- `LESS_THAN` +- `GREATER_THAN` + +```php title="Examples of array key and value pairs for two value file size filters" +'my:filesize_operator' => filesize::LESS_THAN, +'my:filesize_value1' => 50, +'my:filesize_unit' => filesize::SIZE_UNIT_KILOBYTE, +'my:filesize2_operator' => filesize::GREATER_THAN, +'my:filesize2_value1' => 1, +'my:filesize2_unit' => filesize::SIZE_UNIT_GIGABYTE, +``` + +## Tags filter + +### Operators with no additional data + +- `ANY_VALUE` +- `NOT_EMPTY` +- `EMPTY` + +### Operators with one value + +An array of tag database ids should be sent in `value` to: + +- `EQUAL_TO` +- `NOT_EQUAL_TO` + +```php title="Examples of array key and value pairs for single value tag filters" +'my:tags_operator' => tags::EQUAL_TO, +'my:tags_value' => [142, 4753], +'my:tags2_operator' => tags::NOT_EQUAL_TO, +'my:tags2_value' => [1], +``` + +## User filter + +### Operators with no additional data + +- `USER_ANY` +- `USER_CURRENT` + +### Operators with one value + +An array of user database ids should be sent in `value` to: + +- `USER_SELECT` + +```php title="Examples of array key and value pairs for single value user filters" +'my:user_operator' => user::USER_SELECT, +'my:user_value' => [142, 4753], +'my:user2_operator' => user::USER_SELECT, +'my:user2_value' => [1], +``` From ad66b69e73fb348f53fce0ecb4914d121123d3e2 Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Mon, 2 Dec 2024 13:05:12 +0000 Subject: [PATCH 7/9] Link to code examples for correct version of Moodle If we do not do this users may see and use features that are not part of the Moodle version they are coding for --- .../apis/core/reportbuilder/filtering.md | 2 +- .../apis/core/reportbuilder/index.md | 36 ++++++++-------- .../apis/core/reportbuilder/filtering.md | 2 +- .../apis/core/reportbuilder/index.md | 42 +++++++++---------- .../apis/core/reportbuilder/filtering.md | 2 +- .../apis/core/reportbuilder/index.md | 42 +++++++++---------- 6 files changed, 63 insertions(+), 63 deletions(-) diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md b/versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md index 346d00ca0c..6d5d364c56 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/filtering.md @@ -15,7 +15,7 @@ Most filter types use an `operator` for field to define which of their operators The operator you have defined will then determine which other form fields you will need to provide values for, in our example so far that would be `value` which would be defined as `'course_categotry:name_value' => 'The name of a category'` this would mean that only a category with that exact name would be returned by default. -[Core report builder filter types](https://github.com/moodle/moodle/tree/main/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. +[Core report builder filter types](https://github.com/moodle/moodle/tree/MOODLE_403_STABLE/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. ## Text filters diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index 1014bb983e..a718de95cb 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -32,7 +32,7 @@ Column instances define the data captured/displayed within a report column typic #### Creating columns -To create a new column, just create a new instance of [`reportbuilder/classes/local/report/column.php`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/report/column.php) class with: +To create a new column, just create a new instance of [`reportbuilder/classes/local/report/column.php`]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/report/column.php) class with: ```php * string $name @@ -81,20 +81,20 @@ Filters & columns are entirely separate concepts in the report, and each can be #### Filter types -- **Text** ([reportbuilder/classes/local/filters/text.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/text.php)) -- **Date** ([reportbuilder/classes/local/filters/date.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/date.php)) -- **Number** ([reportbuilder/classes/local/filters/number.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/number.php)) -- **Boolean Select** ([reportbuilder/classes/local/filters/boolean_select.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/boolean_select.php)) -- **Select** ([reportbuilder/classes/local/filters/select.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/select.php)) -- **Course selector** ([reportbuilder/classes/local/filters/course_selector.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/course_selector.php)) -- **Duration** ([reportbuilder/classes/local/filters/duration.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/duration.php)) -- **Tags** ([reportbuilder/classes/local/filters/tags.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/tags.php)) -- **Autocomplete** ([reportbuilder/classes/local/filters/autocomplete.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/autocomplete.php)) -- **Category** ([reportbuilder/classes/local/filters/category.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/category.php)) +- **Text** ([reportbuilder/classes/local/filters/text.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/text.php)) +- **Date** ([reportbuilder/classes/local/filters/date.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/date.php)) +- **Number** ([reportbuilder/classes/local/filters/number.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/number.php)) +- **Boolean Select** ([reportbuilder/classes/local/filters/boolean_select.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/boolean_select.php)) +- **Select** ([reportbuilder/classes/local/filters/select.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/select.php)) +- **Course selector** ([reportbuilder/classes/local/filters/course_selector.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/course_selector.php)) +- **Duration** ([reportbuilder/classes/local/filters/duration.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/duration.php)) +- **Tags** ([reportbuilder/classes/local/filters/tags.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/tags.php)) +- **Autocomplete** ([reportbuilder/classes/local/filters/autocomplete.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/autocomplete.php)) +- **Category** ([reportbuilder/classes/local/filters/category.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/filters/category.php)) #### Creating filters -To create a new filter, just create a new instance of **[reportbuilder/classes/local/report/filter.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/report/filter.php)** class with: +To create a new filter, just create a new instance of **[reportbuilder/classes/local/report/filter.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/local/report/filter.php)** class with: ```php * string $filterclass @@ -196,7 +196,7 @@ System reports are a consistent way of providing reporting data, with paging, fi ### Create a new system report using entities -To create a new system report just create a new class extending [reportbuilder/classes/system_report.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/system_report.php). +To create a new system report just create a new class extending [reportbuilder/classes/system_report.php]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/system_report.php). The first method that we need is ***initialise()*** : @@ -307,8 +307,8 @@ $this->set_initial_sort_column('task_log:starttime', SORT_DESC); Check out these two system reports as an example: -- **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`](https://github.com/moodle/moodle/blob/main/admin/classes/reportbuilder/local/systemreports/task_logs.php) -- **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`](https://github.com/moodle/moodle/blob/main/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) +- **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/admin/classes/reportbuilder/local/systemreports/task_logs.php) +- **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) ## Custom reports @@ -316,7 +316,7 @@ The custom reporting interface allows reports to be built with a custom view for ### Create a new data source using entities -To create a data source you need to extend [`\core_reportbuilder\datasource`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. +To create a data source you need to extend [`\core_reportbuilder\datasource`]( https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. The first method you need to build is `initialise()` @@ -612,5 +612,5 @@ The first parameter for each method is the fully qualified class name of the `da #### Unit test examples -- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/main/course/tests/reportbuilder/datasource/categories_test.php) -- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/main/badges/tests/reportbuilder/datasource/badges_test.php) +- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/course/tests/reportbuilder/datasource/categories_test.php) +- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/MOODLE_403_STABLE/badges/tests/reportbuilder/datasource/badges_test.php) diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md b/versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md index c36c2f4a14..a59ef08d0a 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/filtering.md @@ -15,7 +15,7 @@ Most filter types use an `operator` for field to define which of their operators The operator you have defined will then determine which other form fields you will need to provide values for, in our example so far that would be `value` which would be defined as `'course_categotry:name_value' => 'The name of a category'` this would mean that only a category with that exact name would be returned by default. -[Core report builder filter types](https://github.com/moodle/moodle/tree/main/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. +[Core report builder filter types](https://github.com/moodle/moodle/tree/MOODLE_404_STABLE/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. ## Text filters diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index 24388890b4..4072e8b627 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -32,7 +32,7 @@ Column instances define the data captured/displayed within a report column typic #### Creating columns -To create a new column, just create a new instance of [`reportbuilder/classes/local/report/column.php`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/report/column.php) class with: +To create a new column, just create a new instance of [`reportbuilder/classes/local/report/column.php`]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/report/column.php) class with: ```php * string $name @@ -81,20 +81,20 @@ Filters & columns are entirely separate concepts in the report, and each can be #### Filter types -- **Text** ([reportbuilder/classes/local/filters/text.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/text.php)) -- **Date** ([reportbuilder/classes/local/filters/date.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/date.php)) -- **Number** ([reportbuilder/classes/local/filters/number.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/number.php)) -- **Boolean Select** ([reportbuilder/classes/local/filters/boolean_select.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/boolean_select.php)) -- **Select** ([reportbuilder/classes/local/filters/select.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/select.php)) -- **Course selector** ([reportbuilder/classes/local/filters/course_selector.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/course_selector.php)) -- **Duration** ([reportbuilder/classes/local/filters/duration.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/duration.php)) -- **Tags** ([reportbuilder/classes/local/filters/tags.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/tags.php)) -- **Autocomplete** ([reportbuilder/classes/local/filters/autocomplete.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/autocomplete.php)) -- **Category** ([reportbuilder/classes/local/filters/category.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/category.php)) +- **Text** ([reportbuilder/classes/local/filters/text.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/text.php)) +- **Date** ([reportbuilder/classes/local/filters/date.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/date.php)) +- **Number** ([reportbuilder/classes/local/filters/number.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/number.php)) +- **Boolean Select** ([reportbuilder/classes/local/filters/boolean_select.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/boolean_select.php)) +- **Select** ([reportbuilder/classes/local/filters/select.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/select.php)) +- **Course selector** ([reportbuilder/classes/local/filters/course_selector.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/course_selector.php)) +- **Duration** ([reportbuilder/classes/local/filters/duration.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/duration.php)) +- **Tags** ([reportbuilder/classes/local/filters/tags.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/tags.php)) +- **Autocomplete** ([reportbuilder/classes/local/filters/autocomplete.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/autocomplete.php)) +- **Category** ([reportbuilder/classes/local/filters/category.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/filters/category.php)) #### Creating filters -To create a new filter, just create a new instance of **[reportbuilder/classes/local/report/filter.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/report/filter.php)** class with: +To create a new filter, just create a new instance of **[reportbuilder/classes/local/report/filter.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/report/filter.php)** class with: ```php * string $filterclass @@ -126,7 +126,7 @@ All report elements can be defined within the reports themselves - but entities #### Create an entity -To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/base.php)** class and must include these methods: +To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/entities/base.php)** class and must include these methods: ```php get_default_tables() @@ -171,8 +171,8 @@ $join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" Check out these two entities as an example to start building reports: -- **User entity**: [reportbuilder/classes/local/entities/user.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/user.php) -- **Course entity**: [reportbuilder/classes/local/entities/course.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/course.php) +- **User entity**: [reportbuilder/classes/local/entities/user.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/entities/user.php) +- **Course entity**: [reportbuilder/classes/local/entities/course.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/local/entities/course.php) ### Actions @@ -196,7 +196,7 @@ System reports are a consistent way of providing reporting data, with paging, fi ### Create a new system report using entities -To create a new system report just create a new class extending [reportbuilder/classes/system_report.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/system_report.php). +To create a new system report just create a new class extending [reportbuilder/classes/system_report.php]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/system_report.php). The first method that we need is ***initialise()*** : @@ -324,8 +324,8 @@ $join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" Check out these two system reports as an example: -- **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`](https://github.com/moodle/moodle/blob/main/admin/classes/reportbuilder/local/systemreports/task_logs.php) -- **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`](https://github.com/moodle/moodle/blob/main/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) +- **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/admin/classes/reportbuilder/local/systemreports/task_logs.php) +- **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) ## Custom reports @@ -333,7 +333,7 @@ The custom reporting interface allows reports to be built with a custom view for ### Create a new data source using entities -To create a data source you need to extend [`\core_reportbuilder\datasource`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. +To create a data source you need to extend [`\core_reportbuilder\datasource`]( https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. The first method you need to build is `initialise()` @@ -644,5 +644,5 @@ The first parameter for each method is the fully qualified class name of the `da #### Unit test examples -- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/main/course/tests/reportbuilder/datasource/categories_test.php) -- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/main/badges/tests/reportbuilder/datasource/badges_test.php) +- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/course/tests/reportbuilder/datasource/categories_test.php) +- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/MOODLE_404_STABLE/badges/tests/reportbuilder/datasource/badges_test.php) diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md b/versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md index a12024d1c2..caa5644366 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/filtering.md @@ -15,7 +15,7 @@ Most filter types use an `operator` for field to define which of their operators The operator you have defined will then determine which other form fields you will need to provide values for, in our example so far that would be `value` which would be defined as `'course_categotry:name_value' => 'The name of a category'` this would mean that only a category with that exact name would be returned by default. -[Core report builder filter types](https://github.com/moodle/moodle/tree/main/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. +[Core report builder filter types](https://github.com/moodle/moodle/tree/MOODLE_405_STABLE/reportbuilder/classes/local/filters) you can find what a filter type needs by looking at their `get_sql_filter()` method. ## Text filters diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index ed59da5653..1e2685ba49 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -32,7 +32,7 @@ Column instances define the data captured/displayed within a report column typic #### Creating columns -To create a new column, just create a new instance of [`reportbuilder/classes/local/report/column.php`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/report/column.php) class with: +To create a new column, just create a new instance of [`reportbuilder/classes/local/report/column.php`]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/report/column.php) class with: ```php * string $name @@ -81,20 +81,20 @@ Filters & columns are entirely separate concepts in the report, and each can be #### Filter types -- **Text** ([reportbuilder/classes/local/filters/text.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/text.php)) -- **Date** ([reportbuilder/classes/local/filters/date.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/date.php)) -- **Number** ([reportbuilder/classes/local/filters/number.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/number.php)) -- **Boolean Select** ([reportbuilder/classes/local/filters/boolean_select.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/boolean_select.php)) -- **Select** ([reportbuilder/classes/local/filters/select.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/select.php)) -- **Course selector** ([reportbuilder/classes/local/filters/course_selector.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/course_selector.php)) -- **Duration** ([reportbuilder/classes/local/filters/duration.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/duration.php)) -- **Tags** ([reportbuilder/classes/local/filters/tags.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/tags.php)) -- **Autocomplete** ([reportbuilder/classes/local/filters/autocomplete.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/autocomplete.php)) -- **Category** ([reportbuilder/classes/local/filters/category.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/filters/category.php)) +- **Text** ([reportbuilder/classes/local/filters/text.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/text.php)) +- **Date** ([reportbuilder/classes/local/filters/date.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/date.php)) +- **Number** ([reportbuilder/classes/local/filters/number.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/number.php)) +- **Boolean Select** ([reportbuilder/classes/local/filters/boolean_select.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/boolean_select.php)) +- **Select** ([reportbuilder/classes/local/filters/select.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/select.php)) +- **Course selector** ([reportbuilder/classes/local/filters/course_selector.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/course_selector.php)) +- **Duration** ([reportbuilder/classes/local/filters/duration.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/duration.php)) +- **Tags** ([reportbuilder/classes/local/filters/tags.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/tags.php)) +- **Autocomplete** ([reportbuilder/classes/local/filters/autocomplete.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/autocomplete.php)) +- **Category** ([reportbuilder/classes/local/filters/category.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/filters/category.php)) #### Creating filters -To create a new filter, just create a new instance of **[reportbuilder/classes/local/report/filter.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/report/filter.php)** class with: +To create a new filter, just create a new instance of **[reportbuilder/classes/local/report/filter.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/report/filter.php)** class with: ```php * string $filterclass @@ -126,7 +126,7 @@ All report elements can be defined within the reports themselves - but entities #### Create an entity -To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/base.php)** class and must include these methods: +To create an entity, the new entity class must extend **[reportbuilder/classes/local/entities/base.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/entities/base.php)** class and must include these methods: ```php get_default_tables() @@ -171,8 +171,8 @@ $join = "JOIN {user} {$useralias} ON {$useralias}.id = {$logalias}.relateduser" Check out these two entities as an example to start building reports: -- **User entity**: [reportbuilder/classes/local/entities/user.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/user.php) -- **Course entity**: [reportbuilder/classes/local/entities/course.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/local/entities/course.php) +- **User entity**: [reportbuilder/classes/local/entities/user.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/entities/user.php) +- **Course entity**: [reportbuilder/classes/local/entities/course.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/local/entities/course.php) ### Actions @@ -196,7 +196,7 @@ System reports are a consistent way of providing reporting data, with paging, fi ### Create a new system report using entities -To create a new system report just create a new class extending [reportbuilder/classes/system_report.php](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/system_report.php). +To create a new system report just create a new class extending [reportbuilder/classes/system_report.php]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/system_report.php). The first method that we need is ***initialise()*** : @@ -307,8 +307,8 @@ $this->set_initial_sort_column('task_log:starttime', SORT_DESC); Check out these two system reports as an example: -- **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`](https://github.com/moodle/moodle/blob/main/admin/classes/reportbuilder/local/systemreports/task_logs.php) -- **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`](https://github.com/moodle/moodle/blob/main/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) +- **Task logs**: [`admin/classes/reportbuilder/local/systemreports/task_logs.php`]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/admin/classes/reportbuilder/local/systemreports/task_logs.php) +- **Config changes**: [`report/configlog/classes/reportbuilder/local/systemreports/config_changes.php`]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/report/configlog/classes/reportbuilder/local/systemreports/config_changes.php) ## Custom reports @@ -316,7 +316,7 @@ The custom reporting interface allows reports to be built with a custom view for ### Create a new data source using entities -To create a data source you need to extend [`\core_reportbuilder\datasource`](https://github.com/moodle/moodle/blob/main/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. +To create a data source you need to extend [`\core_reportbuilder\datasource`]( https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/reportbuilder/classes/datasource.php). Your class must be located in the `reportbuilder\datasource` namespace of your plugin or the Moodle subsystem it is for. The first method you need to build is `initialise()` @@ -627,5 +627,5 @@ The first parameter for each method is the fully qualified class name of the `da #### Unit test examples -- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/main/course/tests/reportbuilder/datasource/categories_test.php) -- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/main/badges/tests/reportbuilder/datasource/badges_test.php) +- **Course categories** [`/course/tests/reportbuilder/datasource/categories_test.php`](https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/course/tests/reportbuilder/datasource/categories_test.php) +- **Badges** [`/badges/tests/reportbuilder/datasource/badges_test.php`](https://github.com/moodle/moodle/blob/MOODLE_405_STABLE/badges/tests/reportbuilder/datasource/badges_test.php) From e39a2c29ea5279f262388fdf60d993cd48adb4ca Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Mon, 2 Dec 2024 15:22:35 +0000 Subject: [PATCH 8/9] Make links more relative --- docs/apis/core/reportbuilder/index.md | 2 +- versioned_docs/version-4.3/apis/core/reportbuilder/index.md | 2 +- versioned_docs/version-4.4/apis/core/reportbuilder/index.md | 2 +- versioned_docs/version-4.5/apis/core/reportbuilder/index.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/apis/core/reportbuilder/index.md b/docs/apis/core/reportbuilder/index.md index 837581d640..a639060f63 100644 --- a/docs/apis/core/reportbuilder/index.md +++ b/docs/apis/core/reportbuilder/index.md @@ -474,7 +474,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](\docs\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. ```php /** diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index a718de95cb..b9330372da 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -447,7 +447,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](\versioned_docs\version-4.3\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. ```php /** diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index 4072e8b627..00b8b84798 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -479,7 +479,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](\versioned_docs\version-4.4\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. ```php /** diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index 1e2685ba49..9327013bf1 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -462,7 +462,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](\versioned_docs\version-4.5\apis\core\reportbuilder\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. ```php /** From ac1cb313f89faf4b737a10b95d7c1b140b343a14 Mon Sep 17 00:00:00 2001 From: Neill Magill Date: Mon, 2 Dec 2024 15:40:48 +0000 Subject: [PATCH 9/9] Fix the links They were being forced to use Windows style slashes and a full path when I ran `yarn lint-staged` --- docs/apis/core/reportbuilder/index.md | 2 +- versioned_docs/version-4.3/apis/core/reportbuilder/index.md | 2 +- versioned_docs/version-4.4/apis/core/reportbuilder/index.md | 2 +- versioned_docs/version-4.5/apis/core/reportbuilder/index.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/apis/core/reportbuilder/index.md b/docs/apis/core/reportbuilder/index.md index a639060f63..4422ce382a 100644 --- a/docs/apis/core/reportbuilder/index.md +++ b/docs/apis/core/reportbuilder/index.md @@ -474,7 +474,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](./filtering.md) by overriding the `get_default_condition_values()` method. ```php /** diff --git a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md index b9330372da..37950c987f 100644 --- a/versioned_docs/version-4.3/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.3/apis/core/reportbuilder/index.md @@ -447,7 +447,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](./filtering.md) by overriding the `get_default_condition_values()` method. ```php /** diff --git a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md index 00b8b84798..d7c0880ded 100644 --- a/versioned_docs/version-4.4/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.4/apis/core/reportbuilder/index.md @@ -479,7 +479,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](./filtering.md) by overriding the `get_default_condition_values()` method. ```php /** diff --git a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md index 9327013bf1..46fd4794cb 100644 --- a/versioned_docs/version-4.5/apis/core/reportbuilder/index.md +++ b/versioned_docs/version-4.5/apis/core/reportbuilder/index.md @@ -462,7 +462,7 @@ public function get_default_conditions(): array { } ``` -You may also optionally define the [initial values for any of the default conditions](.\filtering.md) by overriding the `get_default_condition_values()` method. +You may also optionally define the [initial values for any of the default conditions](./filtering.md) by overriding the `get_default_condition_values()` method. ```php /**