Skip to content

Commit

Permalink
MDL-70794 reportbuilder: implement report filters and filter types.
Browse files Browse the repository at this point in the history
Implement base filter classes as well as commonly used filter types
(e.g. text, date, select, etc).

Filters are used in reports to allow users to narrow down the data
that is being displayed.

Co-Authored-By: Paul Holden <paulh@moodle.com>
  • Loading branch information
dravek and paulholden committed Jul 28, 2021
1 parent 907ff85 commit 2a20238
Show file tree
Hide file tree
Showing 20 changed files with 2,669 additions and 0 deletions.
47 changes: 47 additions & 0 deletions lang/en/reportbuilder.php
@@ -0,0 +1,47 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Strings for component 'reportbuilder', language 'en'
*
* @package core_reportbuilder
* @copyright 2020 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

$string['filtercontains'] = 'Contains';
$string['filterdatefrom'] = 'Date from';
$string['filterdateto'] = 'Date to';
$string['filterdoesnotcontain'] = 'Does not contain';
$string['filterendswith'] = 'Ends with';
$string['filterequalorgreaterthan'] = 'Greater than or equal';
$string['filterequalorlessthan'] = 'Less than or equal';
$string['filterfieldoperator'] = '{$a} operator';
$string['filterfieldvalue'] = '{$a} value';
$string['filtergreaterthan'] = 'Greater than';
$string['filterinvalid'] = 'Invalid filter';
$string['filterisanyvalue'] = 'Is any value';
$string['filterisempty'] = 'Is empty';
$string['filterisequalto'] = 'Is equal to';
$string['filterisnotempty'] = 'Is not empty';
$string['filterisnotequalto'] = 'Is not equal to';
$string['filterlessthan'] = 'Less than';
$string['filterrange'] = 'Range';
$string['filtersapplied'] = 'Filters applied';
$string['filtersreset'] = 'Filters reset';
$string['filterstartswith'] = 'Starts with';
$string['privacy:metadata:preference:reportfilter'] = 'The stored report filters for this user';
$string['selectcourses'] = 'Select courses';
79 changes: 79 additions & 0 deletions reportbuilder/classes/external/filters/reset.php
@@ -0,0 +1,79 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

declare(strict_types=1);

namespace core_reportbuilder\external\filters;

use context_system;
use external_api;
use external_function_parameters;
use external_value;
use core_reportbuilder\local\helpers\user_filter_manager;

defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once("{$CFG->libdir}/externallib.php");

/**
* External method for resetting report filters
*
* @package core_reportbuilder
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class reset extends external_api {

/**
* External method parameters
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'reportid' => new external_value(PARAM_INT, 'Report ID'),
]);
}

/**
* External method execution
*
* @param int $reportid
* @return bool
*/
public static function execute(int $reportid): bool {
[
'reportid' => $reportid,
] = self::validate_parameters(self::execute_parameters(), [
'reportid' => $reportid,
]);

$context = context_system::instance();
self::validate_context($context);

return user_filter_manager::reset_all($reportid);
}

/**
* External method return value
*
* @return external_value
*/
public static function execute_returns(): external_value {
return new external_value(PARAM_BOOL, 'Success');
}
}
88 changes: 88 additions & 0 deletions reportbuilder/classes/local/filters/base.php
@@ -0,0 +1,88 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

declare(strict_types=1);

namespace core_reportbuilder\local\filters;

use MoodleQuickForm;
use core_reportbuilder\local\report\filter;

/**
* Base class for all report filters
*
* Filters provide a form for collecting user input, and then return appropriate SQL fragments based on these values
*
* @package core_reportbuilder
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base {

/** @var filter $filter */
protected $filter;

/** @var string $name */
protected $name;

/**
* Do not allow the constructor to be called directly or overridden
*
* @param filter $filter
*/
private function __construct(filter $filter) {
$this->filter = $filter;
$this->name = $filter->get_unique_identifier();
}

/**
* Creates an instance of a filter type, based on supplied report filter instance
*
* The report filter instance is used by reports/entities to define what should be filtered against, e.g. a SQL fragment
*
* @param filter $filter The report filter instance
* @return static
*/
final public static function create(filter $filter): self {
$filterclass = $filter->get_filter_class();

return new $filterclass($filter);
}

/**
* Returns the filter header
*
* @return string
*/
final public function get_header(): string {
return $this->filter->get_header();
}

/**
* Adds filter-specific form elements
*
* @param MoodleQuickForm $mform
*/
abstract public function setup_form(MoodleQuickForm $mform): void;

/**
* Returns the filter clauses to be used with SQL where
*
* @param array $values
* @return array [$sql, [...$params]]
*/
abstract public function get_sql_filter(array $values): array;
}
104 changes: 104 additions & 0 deletions reportbuilder/classes/local/filters/boolean_select.php
@@ -0,0 +1,104 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

declare(strict_types=1);

namespace core_reportbuilder\local\filters;

use lang_string;
use MoodleQuickForm;
use core_reportbuilder\local\helpers\database;

/**
* Boolean report filter
*
* This filter accepts an expression that evaluates to 1 or 0, either a simple field such as "u.suspended", or a more complex
* expression such as "CASE WHEN <EXPRESSION> THEN 1 ELSE 0 END"
*
* @package core_reportbuilder
* @copyright 2021 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class boolean_select extends base {

/** @var int Any value */
public const ANY_VALUE = 0;

/** @var int Checked */
public const CHECKED = 1;

/** @var int Not checked */
public const NOT_CHECKED = 2;

/**
* Return an array of operators available for this filter
*
* @return lang_string[]
*/
private function get_operators(): array {
$operators = [
self::ANY_VALUE => new lang_string('filterisanyvalue', 'core_reportbuilder'),
self::CHECKED => new lang_string('yes'),
self::NOT_CHECKED => new lang_string('no'),
];

return $this->filter->restrict_limited_operators($operators);
}

/**
* Setup form
*
* @param MoodleQuickForm $mform
*/
public function setup_form(MoodleQuickForm $mform): void {
$operatorlabel = get_string('filterfieldoperator', 'core_reportbuilder', $this->get_header());
$mform->addElement('select', "{$this->name}_operator", $operatorlabel, $this->get_operators())
->setHiddenLabel(true);

$mform->setType("{$this->name}_operator", PARAM_INT);
$mform->setDefault("{$this->name}_operator", self::ANY_VALUE);
}

/**
* Return filter SQL
*
* @param array $values
* @return array
*/
public function get_sql_filter(array $values): array {
$fieldsql = $this->filter->get_field_sql();
$params = $this->filter->get_field_params();

$paramname = database::generate_param_name();

$operator = $values["{$this->name}_operator"] ?? self::ANY_VALUE;
switch ($operator) {
case self::CHECKED:
$fieldsql .= " = :{$paramname}";
$params[$paramname] = 1;
break;
case self::NOT_CHECKED:
$fieldsql .= " = :{$paramname}";
$params[$paramname] = 0;
break;
default:
// Invalid or inactive filter.
return ['', []];
}

return [$fieldsql, $params];
}
}
68 changes: 68 additions & 0 deletions reportbuilder/classes/local/filters/course_selector.php
@@ -0,0 +1,68 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

declare(strict_types=1);

namespace core_reportbuilder\local\filters;

use MoodleQuickForm;
use core_reportbuilder\local\helpers\database;

/**
* Course selector filter class implementation
*
* @package core_reportbuilder
* @copyright 2021 David Matamoros <davidmc@moodle.com>.
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_selector extends base {

/**
* Setup form
*
* @param MoodleQuickForm $mform
*/
public function setup_form(MoodleQuickForm $mform): void {
$options = [
'multiple' => true,
];
$mform->addElement('course', $this->name . '_values', get_string('selectcourses', 'core_reportbuilder'), $options)
->setHiddenLabel(true);
}

/**
* Return filter SQL
*
* @param array $values
* @return array
*/
public function get_sql_filter(array $values): array {
global $DB;

$fieldsql = $this->filter->get_field_sql();
$params = $this->filter->get_field_params();

$courseids = $values["{$this->name}_values"] ?? [];
if (empty($courseids)) {
return ['', []];
}

$paramprefix = database::generate_param_name() . '_';
[$courseselect, $courseparams] = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED, $paramprefix);

return ["{$fieldsql} $courseselect", array_merge($params, $courseparams)];
}
}

0 comments on commit 2a20238

Please sign in to comment.