Merge branch 'MDL-82529' of https://github.com/dravek/moodle into main

This commit is contained in:
Paul Holden
2024-07-22 12:36:40 +01:00
5 changed files with 128 additions and 102 deletions
@@ -0,0 +1,9 @@
issueNumber: MDL-82529
notes:
core_reportbuilder:
- message: >-
Methods add_columns_from_entity(), add_filters_from_entity() and
report_element_search() have been moved from
\core_reportbuilder\datasource class to \core_reportbuilder\base class
in order to be available also for system reports
type: improved
@@ -188,12 +188,7 @@ class cohorts extends system_report {
* unique identifier
*/
protected function add_filters(): void {
$filters = [
'cohort:name',
'cohort:idnumber',
'cohort:description',
];
$this->add_filters_from_entities($filters);
$this->add_filters_from_entity('cohort', ['name', 'idnumber', 'description', 'customfield*']);
}
/**
+24 -2
View File
@@ -65,6 +65,15 @@ Feature: View cohort list
@javascript
Scenario: Cohorts list can be filtered
Given the following "custom field categories" exist:
| name | component | area | itemid |
| Newcat | core_cohort | cohort | 0 |
And the following "custom fields" exist:
| name | category | type | shortname | description | configdata |
| Field checkbox | Newcat | checkbox | checkbox | | |
And the following "cohorts" exist:
| name | idnumber | contextlevel | reference | customfield_checkbox |
| Cohort with CF | CH4 | Category | CAT1 | 1 |
When I log in as "admin"
And I navigate to "Users > Accounts > Cohorts" in site administration
And I follow "All cohorts"
@@ -73,11 +82,24 @@ Feature: View cohort list
| Name operator | Contains |
| Name value | category 1 |
And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element"
Then the following should exist in the "reportbuilder-table" table:
Then the following should exist in the "Cohorts" table:
| Category | Name |
| Cat 1 | Cohort in category 1 |
And the following should not exist in the "reportbuilder-table" table:
And the following should not exist in the "Cohorts" table:
| Category | Name |
| Cat 2 | Cohort in category 2 |
| Cat 3 | Cohort in category 3 |
| System | System cohort |
And I click on "Reset all" "button" in the "[data-region='report-filters']" "css_element"
And I set the following fields in the "Field checkbox" "core_reportbuilder > Filter" to these values:
| Field checkbox operator | Yes |
And I click on "Apply" "button" in the "[data-region='report-filters']" "css_element"
And the following should exist in the "Cohorts" table:
| Category | Name |
| Cat 1 | Cohort with CF |
And the following should not exist in the "Cohorts" table:
| Category | Name |
| Cat 1 | Cohort in category 1 |
| Cat 2 | Cohort in category 2 |
| Cat 3 | Cohort in category 3 |
| System | System cohort |
-94
View File
@@ -47,41 +47,6 @@ abstract class datasource extends base {
/** @var array $activeconditions */
private $activeconditions;
/**
* Add columns from the given entity name to be available to use in a custom report
*
* Wildcard matching is supported with '*' in both $include and $exclude, e.g. ['customfield*']
*
* @param string $entityname
* @param string[] $include Include only these columns, if omitted then include all
* @param string[] $exclude Exclude these columns, if omitted then exclude none
* @throws coding_exception If both $include and $exclude are non-empty
*/
final protected function add_columns_from_entity(string $entityname, array $include = [], array $exclude = []): void {
if (!empty($include) && !empty($exclude)) {
throw new coding_exception('Cannot specify columns to include and exclude simultaneously');
}
$entity = $this->get_entity($entityname);
// Retrieve filtered columns from entity, respecting given $include/$exclude parameters.
$columns = array_filter($entity->get_columns(), function(column $column) use ($include, $exclude): bool {
if (!empty($include)) {
return $this->report_element_search($column->get_name(), $include);
}
if (!empty($exclude)) {
return !$this->report_element_search($column->get_name(), $exclude);
}
return true;
});
foreach ($columns as $column) {
$this->add_column($column);
}
}
/**
* Add default datasource columns to the report
*
@@ -180,41 +145,6 @@ abstract class datasource extends base {
return $this->activecolumns['values'];
}
/**
* Add filters from the given entity name to be available to use in a custom report
*
* Wildcard matching is supported with '*' in both $include and $exclude, e.g. ['customfield*']
*
* @param string $entityname
* @param string[] $include Include only these filters, if omitted then include all
* @param string[] $exclude Exclude these filters, if omitted then exclude none
* @throws coding_exception If both $include and $exclude are non-empty
*/
final protected function add_filters_from_entity(string $entityname, array $include = [], array $exclude = []): void {
if (!empty($include) && !empty($exclude)) {
throw new coding_exception('Cannot specify filters to include and exclude simultaneously');
}
$entity = $this->get_entity($entityname);
// Retrieve filtered filters from entity, respecting given $include/$exclude parameters.
$filters = array_filter($entity->get_filters(), function(filter $filter) use ($include, $exclude): bool {
if (!empty($include)) {
return $this->report_element_search($filter->get_name(), $include);
}
if (!empty($exclude)) {
return !$this->report_element_search($filter->get_name(), $exclude);
}
return true;
});
foreach ($filters as $filter) {
$this->add_filter($filter);
}
}
/**
* Add default datasource filters to the report
*
@@ -421,28 +351,4 @@ abstract class datasource extends base {
final public static function report_elements_modified(int $reportid): void {
self::$elementsmodified[$reportid] = microtime(true);
}
/**
* Search for given element within list of search items, supporting '*' wildcards
*
* @param string $element
* @param string[] $search
* @return bool
*/
private function report_element_search(string $element, array $search): bool {
foreach ($search as $item) {
// Simple matching.
if ($element === $item) {
return true;
}
// Wildcard matching.
if (strpos($item, '*') !== false) {
$pattern = '/^' . str_replace('\*', '.*', preg_quote($item)) . '$/';
return (bool) preg_match($pattern, $element);
}
}
return false;
}
}
@@ -374,6 +374,41 @@ abstract class base {
return $this->add_column($this->get_entity($entityname)->get_column($columnname));
}
/**
* Add columns from the given entity name to be available to use in a custom report
*
* Wildcard matching is supported with '*' in both $include and $exclude, e.g. ['customfield*']
*
* @param string $entityname
* @param string[] $include Include only these columns, if omitted then include all
* @param string[] $exclude Exclude these columns, if omitted then exclude none
* @throws coding_exception If both $include and $exclude are non-empty
*/
final protected function add_columns_from_entity(string $entityname, array $include = [], array $exclude = []): void {
if (!empty($include) && !empty($exclude)) {
throw new coding_exception('Cannot specify columns to include and exclude simultaneously');
}
$entity = $this->get_entity($entityname);
// Retrieve filtered columns from entity, respecting given $include/$exclude parameters.
$columns = array_filter($entity->get_columns(), function(column $column) use ($include, $exclude): bool {
if (!empty($include)) {
return $this->report_element_search($column->get_name(), $include);
}
if (!empty($exclude)) {
return !$this->report_element_search($column->get_name(), $exclude);
}
return true;
});
foreach ($columns as $column) {
$this->add_column($column);
}
}
/**
* Add given columns to the report from one or more entities
*
@@ -636,6 +671,41 @@ abstract class base {
return $this->add_filter($this->get_entity($entityname)->get_filter($filtername));
}
/**
* Add filters from the given entity name to be available to use in a custom report
*
* Wildcard matching is supported with '*' in both $include and $exclude, e.g. ['customfield*']
*
* @param string $entityname
* @param string[] $include Include only these filters, if omitted then include all
* @param string[] $exclude Exclude these filters, if omitted then exclude none
* @throws coding_exception If both $include and $exclude are non-empty
*/
final protected function add_filters_from_entity(string $entityname, array $include = [], array $exclude = []): void {
if (!empty($include) && !empty($exclude)) {
throw new coding_exception('Cannot specify filters to include and exclude simultaneously');
}
$entity = $this->get_entity($entityname);
// Retrieve filtered filters from entity, respecting given $include/$exclude parameters.
$filters = array_filter($entity->get_filters(), function(filter $filter) use ($include, $exclude): bool {
if (!empty($include)) {
return $this->report_element_search($filter->get_name(), $include);
}
if (!empty($exclude)) {
return !$this->report_element_search($filter->get_name(), $exclude);
}
return true;
});
foreach ($filters as $filter) {
$this->add_filter($filter);
}
}
/**
* Add given filters to the report from one or more entities
*
@@ -829,4 +899,28 @@ abstract class base {
public function get_attributes(): array {
return $this->attributes;
}
/**
* Search for given element within list of search items, supporting '*' wildcards
*
* @param string $element
* @param string[] $search
* @return bool
*/
final protected function report_element_search(string $element, array $search): bool {
foreach ($search as $item) {
// Simple matching.
if ($element === $item) {
return true;
}
// Wildcard matching.
if (strpos($item, '*') !== false) {
$pattern = '/^' . str_replace('\*', '.*', preg_quote($item)) . '$/';
return (bool) preg_match($pattern, $element);
}
}
return false;
}
}