Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
declare(strict_types=1);
18
 
19
namespace core_reportbuilder\local\filters;
20
 
21
use MoodleQuickForm;
22
use core_reportbuilder\local\helpers\database;
23
 
24
/**
25
 * Select report filter
26
 *
27
 * The options for the select are defined when creating the filter by calling {@see set_options} or {@see set_options_callback}
28
 *
29
 * To extend this class in your own filter (e.g. to pre-populate available options), you should override the {@see get_operators}
30
 * and/or {@see get_select_options} methods
31
 *
32
 * @package     core_reportbuilder
33
 * @copyright   2021 David Matamoros <davidmc@moodle.com>
34
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 */
36
class select extends base {
37
 
38
    /** @var int Any value */
39
    public const ANY_VALUE = 0;
40
 
41
    /** @var int Equal to */
42
    public const EQUAL_TO = 1;
43
 
44
    /** @var int Not equal to */
45
    public const NOT_EQUAL_TO = 2;
46
 
1441 ariadna 47
    /** @var int Value to indicate "Any value" for the simplified filter options  */
48
    private const OPTION_ANY_VALUE = -124567;
49
 
1 efrain 50
    /**
51
     * Returns an array of comparison operators
52
     *
53
     * @return array
54
     */
55
    protected function get_operators(): array {
56
        $operators = [
57
            self::ANY_VALUE => get_string('filterisanyvalue', 'core_reportbuilder'),
58
            self::EQUAL_TO => get_string('filterisequalto', 'core_reportbuilder'),
59
            self::NOT_EQUAL_TO => get_string('filterisnotequalto', 'core_reportbuilder')
60
        ];
61
 
62
        return $this->filter->restrict_limited_operators($operators);
63
    }
64
 
65
    /**
66
     * Return the options for the filter as an array, to be used to populate the select input field
67
     *
68
     * @return array
69
     */
70
    protected function get_select_options(): array {
1441 ariadna 71
        static $options = [];
72
 
73
        if (!array_key_exists($this->name, $options)) {
74
            $options[$this->name] = (array) $this->filter->get_options();
75
        }
76
 
77
        return $options[$this->name];
1 efrain 78
    }
79
 
80
    /**
81
     * Adds controls specific to this filter in the form.
82
     *
83
     * @param MoodleQuickForm $mform
84
     */
85
    public function setup_form(MoodleQuickForm $mform): void {
1441 ariadna 86
        $operators = $this->get_operators();
1 efrain 87
        $options = $this->get_select_options();
88
 
1441 ariadna 89
        // If a multidimensional array is passed, we need to use a different element type.
90
        $optioncountrecursive = count($options, COUNT_RECURSIVE);
91
        $element = (count($options) === $optioncountrecursive ? 'select' : 'selectgroups');
1 efrain 92
 
1441 ariadna 93
        // If operators are unrestricted, and we have upto two options, then simplify the filter to list only those.
94
        if (count($operators) === 3 && $optioncountrecursive <= 2) {
95
            $mform->addElement('hidden', "{$this->name}_operator");
96
            $mform->setType("{$this->name}_operator", PARAM_INT);
97
            $mform->setConstant("{$this->name}_operator", self::EQUAL_TO);
98
 
99
            $mform->addElement(
100
                $element,
101
                "{$this->name}_value",
102
                get_string('filterfieldvalue', 'core_reportbuilder', $this->get_header()),
103
                [self::OPTION_ANY_VALUE => $operators[self::ANY_VALUE]] + $options,
104
            )->setHiddenLabel(true);
105
        } else {
106
            $elements = [];
107
 
108
            $elements[] = $mform->createElement(
109
                'select',
110
                "{$this->name}_operator",
111
                get_string('filterfieldoperator', 'core_reportbuilder', $this->get_header()),
112
                $operators,
113
            );
114
 
115
            $elements[] = $mform->createElement(
116
                $element,
117
                "{$this->name}_value",
118
                get_string('filterfieldvalue', 'core_reportbuilder', $this->get_header()),
119
                $options,
120
            );
121
 
122
            $mform->addGroup($elements, "{$this->name}_group", $this->get_header(), '', false)
123
                ->setHiddenLabel(true);
124
 
125
            $mform->hideIf("{$this->name}_value", "{$this->name}_operator", 'eq', self::ANY_VALUE);
126
        }
1 efrain 127
    }
128
 
129
    /**
130
     * Return filter SQL
131
     *
132
     * Note that operators must be of type integer, while values can be integer or string.
133
     *
134
     * @param array $values
135
     * @return array array of two elements - SQL query and named parameters
136
     */
137
    public function get_sql_filter(array $values): array {
138
        $name = database::generate_param_name();
139
 
1441 ariadna 140
        $operator = (int) ($values["{$this->name}_operator"] ?? self::ANY_VALUE);
141
        $value = (string) ($values["{$this->name}_value"] ?? self::OPTION_ANY_VALUE);
1 efrain 142
 
143
        $fieldsql = $this->filter->get_field_sql();
144
        $params = $this->filter->get_field_params();
145
 
1441 ariadna 146
        // Get available options, if multidimensional then flatten the array.
147
        $options = $this->get_select_options();
148
        if (count($options) !== count($options, COUNT_RECURSIVE)) {
149
            $options = array_merge(...array_values($options));
150
        }
151
 
1 efrain 152
        // Validate filter form values.
1441 ariadna 153
        if ($operator === self::ANY_VALUE || !array_key_exists($value, $options)) {
1 efrain 154
            return ['', []];
155
        }
156
 
157
        switch ($operator) {
158
            case self::EQUAL_TO:
159
                $fieldsql .= "=:$name";
160
                $params[$name] = $value;
161
                break;
162
            case self::NOT_EQUAL_TO:
163
                $fieldsql .= "<>:$name";
164
                $params[$name] = $value;
165
                break;
166
            default:
167
                return ['', []];
168
        }
169
        return [$fieldsql, $params];
170
    }
171
 
172
    /**
173
     * Return sample filter values
174
     *
175
     * @return array
176
     */
177
    public function get_sample_values(): array {
178
        return [
179
            "{$this->name}_operator" => self::EQUAL_TO,
180
            "{$this->name}_value" => 1,
181
        ];
182
    }
183
}