Proyectos de Subversion Moodle

Rev

| 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
namespace mod_lti\reportbuilder\local\systemreports;
18
 
19
use core_reportbuilder\local\helpers\database;
20
use core_reportbuilder\local\report\column;
21
use mod_lti\reportbuilder\local\entities\tool_types;
22
use core_reportbuilder\system_report;
23
 
24
/**
25
 * Course external tools list system report class implementation.
26
 *
27
 * @package    mod_lti
28
 * @copyright  2023 Jake Dallimore <jrhdallimore@gmail.com>
29
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 */
31
class course_external_tools_list extends system_report {
32
 
33
    /** @var \stdClass the course to constrain the report to. */
34
    protected \stdClass $course;
35
 
36
    /** @var int the usage count for the tool represented in a row, and set by row_callback(). */
37
    protected int $perrowtoolusage = 0;
38
 
39
    /**
40
     * Initialise report, we need to set the main table, load our entities and set columns/filters
41
     */
42
    protected function initialise(): void {
43
        global $DB, $CFG;
44
        require_once($CFG->dirroot . '/mod/lti/locallib.php');
45
 
46
        $this->course = get_course($this->get_context()->instanceid);
47
 
48
        // Our main entity, it contains all the column definitions that we need.
49
        $entitymain = new tool_types();
50
        $entitymainalias = $entitymain->get_table_alias('lti_types');
51
 
52
        $this->set_main_table('lti_types', $entitymainalias);
53
        $this->add_entity($entitymain);
54
 
55
        // Now we can call our helper methods to add the content we want to include in the report.
56
        $this->add_columns($entitymain);
57
        $this->add_filters();
58
        $this->add_actions();
59
 
60
        // We need id and course in the actions column, without entity prefixes, so add these here.
61
        // We also need access to the tool usage count in a few places (the usage column as well as the actions column).
62
        $ti = database::generate_param_name(); // Tool instance param.
63
        $this->add_base_fields("{$entitymainalias}.id, {$entitymainalias}.course, ".
64
            "(SELECT COUNT($ti.id)
65
                FROM {lti} $ti
66
                WHERE $ti.typeid = {$entitymainalias}.id) AS toolusage");
67
 
68
        // Join the types_categories table, to include only tools available to the current course's category.
69
        $cattablealias = database::generate_alias();
70
        $joinsql = "LEFT JOIN {lti_types_categories} {$cattablealias}
71
                           ON ({$cattablealias}.typeid = {$entitymainalias}.id)";
72
        $this->add_join($joinsql);
73
 
74
        // Scope the report to the course context and include only those tools available to the category.
75
        $paramprefix = database::generate_param_name();
76
        $coursevisibleparam = database::generate_param_name();
77
        $categoryparam = database::generate_param_name();
78
        $toolstateparam = database::generate_param_name();
79
        [$insql, $params] = $DB->get_in_or_equal([get_site()->id, $this->course->id], SQL_PARAMS_NAMED, "{$paramprefix}_");
80
        $wheresql = "{$entitymainalias}.course {$insql} ".
81
            "AND {$entitymainalias}.coursevisible NOT IN (:{$coursevisibleparam}) ".
82
            "AND ({$cattablealias}.id IS NULL OR {$cattablealias}.categoryid = :{$categoryparam}) ".
83
            "AND {$entitymainalias}.state = :{$toolstateparam}";
84
        $params = array_merge(
85
            $params,
86
            [
87
                $coursevisibleparam => LTI_COURSEVISIBLE_NO,
88
                $categoryparam => $this->course->category,
89
                $toolstateparam => LTI_TOOL_STATE_CONFIGURED
90
            ]
91
        );
92
        $this->add_base_condition_sql($wheresql, $params);
93
 
94
        $this->set_downloadable(false, get_string('pluginname', 'mod_lti'));
95
        $this->set_default_per_page(10);
96
        $this->set_default_no_results_notice(null);
97
    }
98
 
99
    /**
100
     * Validates access to view this report
101
     *
102
     * @return bool
103
     */
104
    protected function can_view(): bool {
105
        return has_capability('mod/lti:addpreconfiguredinstance', $this->get_context());
106
    }
107
 
108
    public function row_callback(\stdClass $row): void {
109
        $this->perrowtoolusage = $row->toolusage;
110
    }
111
 
112
    /**
113
     * Adds the columns we want to display in the report.
114
     *
115
     * They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
116
     * unique identifier
117
     * @param tool_types $tooltypesentity
118
     * @return void
119
     */
120
    protected function add_columns(tool_types $tooltypesentity): void {
121
        $entitymainalias = $tooltypesentity->get_table_alias('lti_types');
122
 
123
        $columns = [
124
            'tool_types:name',
125
            'tool_types:description',
126
        ];
127
 
128
        $this->add_columns_from_entities($columns);
129
 
130
        // Tool usage column using a custom SQL subquery (defined in initialise method) to count tool instances within the course.
131
        // TODO: This should be replaced with proper column aggregation once that's added to system_report instances in MDL-76392.
132
        $this->add_column(new column(
133
            'usage',
134
            new \lang_string('usage', 'mod_lti'),
135
            $tooltypesentity->get_entity_name()
136
        ))
137
            ->set_type(column::TYPE_INTEGER)
138
            ->set_is_sortable(true)
139
            ->add_field("{$entitymainalias}.id")
140
            ->add_callback(fn() => $this->perrowtoolusage);
141
 
142
        // Enable toggle column.
143
        $this->add_column((new column(
144
            'showinactivitychooser',
145
            new \lang_string('showinactivitychooser', 'mod_lti'),
146
            $tooltypesentity->get_entity_name()
147
        ))
148
            // Site tools can be overridden on course level.
149
            ->add_join("LEFT JOIN {lti_coursevisible} lc ON lc.typeid = {$entitymainalias}.id AND lc.courseid = " . $this->course->id)
150
            ->set_type(column::TYPE_INTEGER)
151
            ->add_fields("{$entitymainalias}.id, {$entitymainalias}.coursevisible, lc.coursevisible as coursevisibleoverridden")
152
            ->set_is_sortable(false)
153
            ->set_callback(function(int $id, \stdClass $row): string {
154
                global $PAGE;
155
                $coursevisible = $row->coursevisible;
156
                $courseid = $this->course->id;
157
                if (!empty($row->coursevisibleoverridden)) {
158
                    $coursevisible = $row->coursevisibleoverridden;
159
                }
160
 
161
                if ($coursevisible == LTI_COURSEVISIBLE_ACTIVITYCHOOSER) {
162
                    $coursevisible = true;
163
                } else {
164
                    $coursevisible = false;
165
                }
166
 
167
                $renderer = $PAGE->get_renderer('core_reportbuilder');
168
                $attributes = [
169
                    ['name' => 'id', 'value' => $row->id],
170
                    ['name' => 'courseid', 'value' => $courseid],
171
                    ['name' => 'action', 'value' => 'showinactivitychooser-toggle'],
172
                    ['name' => 'state', 'value' => $coursevisible],
173
                ];
174
                $label = $coursevisible ? get_string('dontshowinactivitychooser', 'mod_lti')
175
                    : get_string('showinactivitychooser', 'mod_lti');
176
 
177
                $disabled = !has_capability('mod/lti:addcoursetool', \context_course::instance($courseid));
178
 
179
                return $renderer->render_from_template('core/toggle', [
180
                    'id' => 'showinactivitychooser-toggle-' . $row->id,
181
                    'checked' => $coursevisible,
182
                    'disabled' => $disabled,
183
                    'dataattributes' => $attributes,
184
                    'label' => $label,
185
                    'labelclasses' => 'sr-only'
186
                ]);
187
            })
188
        );
189
 
190
        // Attempt to create a dummy actions column, working around the limitations of the official actions feature.
191
        $this->add_column(new column(
192
            'actions', new \lang_string('actions'),
193
            $tooltypesentity->get_entity_name()
194
        ))
195
            ->set_type(column::TYPE_TEXT)
196
            ->set_is_sortable(false)
197
            ->add_fields("{$entitymainalias}.id, {$entitymainalias}.course, {$entitymainalias}.name")
198
            ->add_callback(function($field, $row) {
199
                global $OUTPUT;
200
 
201
                // Lock actions for site-level preconfigured tools.
202
                if (get_site()->id == $row->course) {
203
                    return \html_writer::div(
204
                        \html_writer::div(
205
                            $OUTPUT->pix_icon('t/locked', get_string('courseexternaltoolsnoeditpermissions', 'mod_lti')
206
                        ), 'tool-action-icon-container'), 'd-flex justify-content-end'
207
                    );
208
                }
209
 
210
                // Lock actions when the user can't add course tools.
211
                if (!has_capability('mod/lti:addcoursetool', \context_course::instance($row->course))) {
212
                    return \html_writer::div(
213
                        \html_writer::div(
214
                            $OUTPUT->pix_icon('t/locked', get_string('courseexternaltoolsnoeditpermissions', 'mod_lti')
215
                        ), 'tool-action-icon-container'), 'd-flex justify-content-end'
216
                    );
217
                }
218
 
219
                // Build and display an action menu.
220
                $menu = new \action_menu();
221
                $menu->set_menu_trigger($OUTPUT->pix_icon('i/moremenu', get_string('actions', 'core')),
222
                    'btn btn-icon d-flex align-items-center justify-content-center'); // TODO check 'actions' lang string with UX.
223
 
224
                $menu->add(new \action_menu_link(
225
                    new \moodle_url('/mod/lti/coursetooledit.php', ['course' => $row->course, 'typeid' => $row->id]),
226
                    null,
227
                    get_string('edit', 'core'),
228
                    null
229
                ));
230
 
231
                $menu->add(new \action_menu_link(
232
                    new \moodle_url('#'),
233
                    null,
234
                    get_string('delete', 'core'),
235
                    null,
236
                    [
237
                        'data-action' => 'course-tool-delete',
238
                        'data-course-tool-id' => $row->id,
239
                        'data-course-tool-name' => $row->name,
240
                        'data-course-tool-usage' => $this->perrowtoolusage,
241
                        'class' => 'text-danger',
242
                    ],
243
                ));
244
 
245
                return $OUTPUT->render($menu);
246
            });
247
 
248
        // Default sorting.
249
        $this->set_initial_sort_column('tool_types:name', SORT_ASC);
250
    }
251
 
252
    /**
253
     * Add any actions for this report.
254
     *
255
     * @return void
256
     */
257
    protected function add_actions(): void {
258
    }
259
 
260
    /**
261
     * Adds the filters we want to display in the report
262
     *
263
     * They are all provided by the entities we previously added in the {@see initialise} method, referencing each by their
264
     * unique identifier
265
     */
266
    protected function add_filters(): void {
267
 
268
        $this->add_filters_from_entities([]);
269
    }
270
}