Proyectos de Subversion Moodle

Rev

Rev 11 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 11 Rev 1441
Línea 16... Línea 16...
16
 
16
 
Línea 17... Línea 17...
17
declare(strict_types=1);
17
declare(strict_types=1);
Línea 18... Línea -...
18
 
-
 
19
namespace core_reportbuilder\local\helpers;
-
 
20
 
-
 
21
use core_reportbuilder\local\filters\boolean_select;
-
 
22
use core_reportbuilder\local\filters\date;
-
 
23
use core_reportbuilder\local\filters\number;
-
 
24
use core_reportbuilder\local\filters\select;
-
 
25
use core_reportbuilder\local\filters\text;
18
 
26
use core_reportbuilder\local\report\column;
-
 
27
use core_reportbuilder\local\report\filter;
19
namespace core_reportbuilder\local\helpers;
28
use lang_string;
20
 
29
use stdClass;
21
use core\lang_string;
-
 
22
use core_customfield\data_controller;
-
 
23
use core_customfield\field_controller;
-
 
24
use core_customfield\handler;
Línea 30... Línea 25...
30
use core_customfield\data_controller;
25
use core_reportbuilder\local\filters\{boolean_select, date, number, select, text};
31
use core_customfield\field_controller;
26
use core_reportbuilder\local\report\{column, filter};
32
use core_customfield\handler;
27
use stdClass;
33
 
28
 
34
/**
29
/**
35
 * Helper class for course custom fields.
30
 * Helper class for course custom fields.
36
 *
31
 *
37
 * @package   core_reportbuilder
32
 * @package   core_reportbuilder
Línea 38... Línea -...
38
 * @copyright 2021 Sara Arjona <sara@moodle.com> based on David Matamoros <davidmc@moodle.com> code.
-
 
39
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 * @copyright 2021 Sara Arjona <sara@moodle.com> based on David Matamoros <davidmc@moodle.com> code.
Línea 40... Línea 34...
40
 */
34
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41
class custom_fields {
35
 */
42
 
-
 
43
    /** @var string $entityname Name of the entity */
-
 
44
    private $entityname;
-
 
45
 
-
 
46
    /** @var handler $handler The handler for the customfields */
-
 
47
    private $handler;
-
 
Línea 48... Línea 36...
48
 
36
class custom_fields {
49
    /** @var int $tablefieldalias The table alias and the field name (table.field) that matches the customfield instanceid. */
37
 
50
    private $tablefieldalias;
38
    use join_trait;
51
 
39
 
52
    /** @var array additional joins */
40
    /** @var handler $handler The handler for the customfields */
53
    private $joins = [];
41
    private handler $handler;
54
 
42
 
55
    /**
43
    /**
56
     * Class customfields constructor.
44
     * Constructor
-
 
45
     *
57
     *
46
     * @param string $tablefieldalias The table/field alias to match the instance ID when adding columns and filters.
58
     * @param string $tablefieldalias table alias and the field name (table.field) that matches the customfield instanceid.
47
     * @param string $entityname The entity name used when adding columns and filters.
-
 
48
     * @param string $component component name of full frankenstyle plugin name.
59
     * @param string $entityname name of the entity in the report where we add custom fields.
49
     * @param string $area name of the area (each component/plugin may define handlers for multiple areas).
-
 
50
     * @param int $itemid item id if the area uses them (usually not used).
-
 
51
     */
-
 
52
    public function __construct(
-
 
53
        /** @var string The table/field alias to match the instance ID when adding columns and filters */
60
     * @param string $component component name of full frankenstyle plugin name.
54
        private readonly string $tablefieldalias,
61
     * @param string $area name of the area (each component/plugin may define handlers for multiple areas).
55
        /** @var string The entity name used when adding columns and filters */
Línea 62... Línea 56...
62
     * @param int $itemid item id if the area uses them (usually not used).
56
        private readonly string $entityname,
63
     */
-
 
64
    public function __construct(string $tablefieldalias, string $entityname, string $component, string $area, int $itemid = 0) {
-
 
65
        $this->tablefieldalias = $tablefieldalias;
-
 
66
        $this->entityname = $entityname;
-
 
67
        $this->handler = handler::get_handler($component, $area, $itemid);
-
 
68
    }
-
 
69
 
-
 
70
    /**
-
 
71
     * Additional join that is needed.
-
 
72
     *
-
 
73
     * @param string $join
-
 
74
     * @return self
-
 
75
     */
-
 
76
    public function add_join(string $join): self {
-
 
77
        $this->joins[trim($join)] = trim($join);
-
 
78
        return $this;
-
 
79
    }
-
 
80
 
-
 
81
    /**
-
 
82
     * Additional joins that are needed.
-
 
83
     *
-
 
84
     * @param array $joins
-
 
85
     * @return self
-
 
86
     */
-
 
87
    public function add_joins(array $joins): self {
-
 
88
        foreach ($joins as $join) {
-
 
89
            $this->add_join($join);
-
 
90
        }
-
 
91
        return $this;
-
 
92
    }
-
 
93
 
-
 
94
    /**
-
 
95
     * Return joins
-
 
96
     *
57
        string $component,
97
     * @return string[]
58
        string $area,
98
     */
59
        int $itemid = 0,
99
    private function get_joins(): array {
60
    ) {
100
        return array_values($this->joins);
61
        $this->handler = handler::get_handler($component, $area, $itemid);
Línea 140... Línea 101...
140
     * Column will be named as 'customfield_' + customfield shortname.
101
     * Column will be named as 'customfield_' + customfield shortname.
141
     *
102
     *
142
     * @return column[]
103
     * @return column[]
143
     */
104
     */
144
    public function get_columns(): array {
105
    public function get_columns(): array {
145
        global $DB;
-
 
146
 
-
 
147
        $columns = [];
106
        $columns = [];
Línea 148... Línea 107...
148
 
107
 
149
        $categorieswithfields = $this->handler->get_categories_with_fields();
108
        $categorieswithfields = $this->handler->get_categories_with_fields();
150
        foreach ($categorieswithfields as $fieldcategory) {
109
        foreach ($categorieswithfields as $fieldcategory) {
151
            $categoryfields = $fieldcategory->get_fields();
110
            $categoryfields = $fieldcategory->get_fields();
152
            foreach ($categoryfields as $field) {
-
 
153
                $customdatatablealias = $this->get_table_alias($field);
-
 
154
 
111
            foreach ($categoryfields as $field) {
155
                $datacontroller = data_controller::create(0, null, $field);
-
 
156
 
112
                $datacontroller = data_controller::create(0, null, $field);
157
                $datafield = $datacontroller->datafield();
-
 
Línea -... Línea 113...
-
 
113
                $datafield = $datacontroller->datafield();
-
 
114
 
-
 
115
                $customdatatablealias = $this->get_table_alias($field);
158
                $datafieldsql = "{$customdatatablealias}.{$datafield}";
116
                $customdatasql = "{$customdatatablealias}.{$datafield}";
159
 
117
 
160
                // Long text fields should be cast for Oracle, for aggregation support.
118
                // Numeric column (non-text) should coalesce with default, for aggregation.
-
 
119
                $columntype = $this->get_column_type($field, $datafield);
-
 
120
                if (!in_array($columntype, [column::TYPE_TEXT, column::TYPE_LONGTEXT])) {
-
 
121
 
161
                $columntype = $this->get_column_type($field, $datafield);
122
                    // See MDL-78783 regarding no bound parameters, and SQL Server limitations of GROUP BY.
-
 
123
                    $customdatasql = "
-
 
124
                        CASE WHEN {$this->tablefieldalias} IS NOT NULL
-
 
125
                             THEN COALESCE({$customdatasql}, " . (float) $datacontroller->get_default_value() . ")
162
                if ($columntype === column::TYPE_LONGTEXT && $DB->get_dbfamily() === 'oracle') {
126
                             ELSE NULL
Línea 163... Línea 127...
163
                    $datafieldsql = $DB->sql_order_by_text($datafieldsql, 1024);
127
                        END";
164
                }
128
                }
165
 
129
 
166
                // Select enough fields to re-create and format each custom field instance value.
130
                // Select enough fields to re-create and format each custom field instance value.
167
                $selectfields = "{$customdatatablealias}.id, {$customdatatablealias}.contextid";
131
                $customdatasqlextra = "{$customdatatablealias}.id, {$customdatatablealias}.contextid";
168
                if ($datafield === 'value') {
132
                if ($datafield === 'value') {
Línea 169... Línea 133...
169
                    // We will take the format into account when displaying the individual values.
133
                    // We will take the format into account when displaying the individual values.
170
                    $selectfields .= ", {$customdatatablealias}.valueformat, {$customdatatablealias}.valuetrust";
134
                    $customdatasqlextra .= ", {$customdatatablealias}.valueformat, {$customdatatablealias}.valuetrust";
171
                }
135
                }
172
 
136
 
173
                $columns[] = (new column(
137
                $columns[] = (new column(
174
                    'customfield_' . $field->get('shortname'),
138
                    'customfield_' . $field->get('shortname'),
175
                    new lang_string('customfieldcolumn', 'core_reportbuilder', $field->get_formatted_name()),
139
                    new lang_string('customfieldcolumn', 'core_reportbuilder', $field->get_formatted_name(false)),
176
                    $this->entityname
-
 
177
                ))
-
 
178
                    ->add_joins($this->get_joins())
-
 
179
                    ->add_join($this->get_table_join($field))
140
                    $this->entityname
-
 
141
                ))
-
 
142
                    ->add_joins($this->get_joins())
-
 
143
                    ->add_join($this->get_table_join($field))
180
                    ->add_field($datafieldsql, $datafield)
144
                    ->set_type($columntype)
181
                    ->add_fields($selectfields)
145
                    ->add_field($customdatasql, $datafield)
182
                    ->add_field($this->tablefieldalias, 'tablefieldalias')
146
                    ->add_fields($customdatasqlextra)
183
                    ->set_type($columntype)
147
                    ->add_field($this->tablefieldalias, 'tablefieldalias')
184
                    ->set_is_sortable($columntype !== column::TYPE_LONGTEXT)
148
                    ->set_is_sortable(true)
-
 
149
                    ->add_callback(static function($value, stdClass $row, field_controller $field, ?string $aggregation): string {
-
 
150
                        if ($row->tablefieldalias === null && $value === null) {
-
 
151
                            return '';
-
 
152
                        }
185
                    ->add_callback(static function($value, stdClass $row, field_controller $field): string {
153
                        // If aggregating numeric column, populate row ID to ensure the controller is created correctly.
186
                        if ($row->tablefieldalias === null) {
154
                        if (in_array((string) $aggregation, ['avg', 'max', 'min', 'sum'])) {
187
                            return '';
155
                            $row->id ??= -1;
188
                        }
156
                        }
189
                        return (string) data_controller::create(0, $row, $field)->export_value();
157
                        return (string) data_controller::create(0, $row, $field)->export_value();
Línea 237... Línea 205...
237
     * Filter will be named as 'customfield_' + customfield shortname.
205
     * Filter will be named as 'customfield_' + customfield shortname.
238
     *
206
     *
239
     * @return filter[]
207
     * @return filter[]
240
     */
208
     */
241
    public function get_filters(): array {
209
    public function get_filters(): array {
242
        global $DB;
-
 
243
 
-
 
244
        $filters = [];
210
        $filters = [];
Línea 245... Línea 211...
245
 
211
 
246
        $categorieswithfields = $this->handler->get_categories_with_fields();
212
        $categorieswithfields = $this->handler->get_categories_with_fields();
247
        foreach ($categorieswithfields as $fieldcategory) {
213
        foreach ($categorieswithfields as $fieldcategory) {
248
            $categoryfields = $fieldcategory->get_fields();
214
            $categoryfields = $fieldcategory->get_fields();
249
            foreach ($categoryfields as $field) {
-
 
250
                $customdatatablealias = $this->get_table_alias($field);
-
 
251
 
215
            foreach ($categoryfields as $field) {
252
                $datacontroller = data_controller::create(0, null, $field);
-
 
253
 
216
                $datacontroller = data_controller::create(0, null, $field);
-
 
217
                $datafield = $datacontroller->datafield();
-
 
218
 
254
                $datafield = $datacontroller->datafield();
219
                $customdatatablealias = $this->get_table_alias($field);
255
                $datafieldsql = "{$customdatatablealias}.{$datafield}";
220
                $customdatasql = "{$customdatatablealias}.{$datafield}";
-
 
221
                $customdataparams = [];
-
 
222
 
-
 
223
                // Account for field default value, when joined to the instance table related to the custom fields.
256
                if ($datafield === 'value') {
224
                if (($fielddefault = $datacontroller->get_default_value()) !== null) {
-
 
225
                    $paramdefault = database::generate_param_name();
-
 
226
                    $customdatasql = "
-
 
227
                        CASE WHEN {$this->tablefieldalias} IS NOT NULL
-
 
228
                             THEN COALESCE({$customdatasql}, :{$paramdefault})
-
 
229
                             ELSE NULL
-
 
230
                        END";
257
                    $datafieldsql = $DB->sql_cast_to_char($datafieldsql);
231
                    $customdataparams[$paramdefault] = $fielddefault;
Línea 258... Línea -...
258
                }
-
 
259
 
232
                }
260
                $typeclass = $this->get_filter_class_type($datacontroller);
233
 
261
                $filter = (new filter(
234
                $filter = (new filter(
262
                    $typeclass,
235
                    $this->get_filter_class_type($datacontroller),
263
                    'customfield_' . $field->get('shortname'),
236
                    'customfield_' . $field->get('shortname'),
264
                    new lang_string('customfieldcolumn', 'core_reportbuilder', $field->get_formatted_name()),
237
                    new lang_string('customfieldcolumn', 'core_reportbuilder', $field->get_formatted_name(false)),
-
 
238
                    $this->entityname,
265
                    $this->entityname,
239
                    $customdatasql,
266
                    $datafieldsql
240
                    $customdataparams,
267
                ))
241
                ))
-
 
242
                    ->add_joins($this->get_joins())
Línea 268... Línea 243...
268
                    ->add_joins($this->get_joins())
243
                    ->add_join($this->get_table_join($field))
269
                    ->add_join($this->get_table_join($field));
244
                    ->set_is_available($this->handler->can_view($field, 0));
270
 
245
 
271
                // Options are stored inside configdata json string and we need to convert it to array.
-
 
272
                if ($field->get('type') === 'select') {
-
 
273
                    $filter->set_options_callback(static function() use ($field): array {
246
                // If using a select filter, then populate the options.
Línea 274... Línea 247...
274
                        return $field->get_options();
247
                if ($filter->get_filter_class() === select::class) {
275
                    });
248
                    $filter->set_options_callback(fn(): array => $field->get_options());
276
                }
249
                }