Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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 core_courseformat\output\local\overview;
18
 
19
use core\output\named_templatable;
20
use core\output\renderable;
21
use core\output\renderer_base;
22
use core\plugin_manager;
23
use core_courseformat\local\overview\overviewitem;
24
use core_courseformat\local\overview\overviewfactory;
25
use cm_info;
26
use stdClass;
27
 
28
/**
29
 * Class overviewtable
30
 *
31
 * @package    core_courseformat
32
 * @copyright  2025 Ferran Recio <ferran@moodle.com>
33
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class overviewtable implements renderable, named_templatable {
36
    /** @var array $header the table headers */
37
    private array $headers = [];
38
 
39
    /** @var array $columnhascontent indicate which columns has content */
40
    private array $columnhascontent = [];
41
 
42
    /**
43
     * Constructor.
44
     *
45
     * @param stdClass $course the course object.
46
     * @param string $modname the module name (or "resources" for generic resources overview).
47
     */
48
    public function __construct(
49
        /** @var stdClass the course object  */
50
        protected stdClass $course,
51
        /** @var string the module name (or "resources" for generic resources overview) */
52
        protected string $modname,
53
    ) {
54
    }
55
 
56
    #[\Override]
57
    public function export_for_template(renderer_base $output): stdClass {
58
        $activities = $this->load_all_overviews_from_each_activity($output);
59
        $headers = $this->export_headers();
60
        $result = (object) [
61
            'caption' => $this->get_table_caption(),
62
            'headers' => $headers,
63
            'activities' => $this->export_filtered_overviews($output, $activities, $headers),
64
        ];
65
        return $result;
66
    }
67
 
68
    /**
69
     * Export the filtered list of headers.
70
     *
71
     * This method will remove any header that does not have any content.
72
     *
73
     * @return array
74
     */
75
    private function export_headers(): array {
76
        return array_values(
77
            array_filter($this->headers, function ($header) {
78
                return $this->columnhascontent[$header->key];
79
            })
80
        );
81
    }
82
 
83
    /**
84
     * Exports filtered overviews for the given activities and headers.
85
     *
86
     * @param renderer_base $output
87
     * @param array $activities An array of activities, each containing an 'overviews' array and a 'cmid'.
88
     * @param array $headers An array of header objects, each containing a 'key' property.
89
     * @return array An array of filtered overviews, each containing 'cmid' and 'overviews' with rendered content.
90
     */
91
    private function export_filtered_overviews(
92
        renderer_base $output,
93
        array $activities,
94
        array $headers,
95
    ): array {
96
        $result = [];
97
        foreach ($activities as $activity) {
98
            $items = [];
99
            foreach ($headers as $header) {
100
                if (!isset($activity['overviews'][$header->key])) {
101
                    $items[] = (object) ['content' => '', 'overview' => $header->key];
102
                    continue;
103
                }
104
                /** @var overviewitem $item */
105
                $item = $activity['overviews'][$header->key];
106
                $itemsdata = (object) [
107
                    'content' => $item->get_rendered_content($output),
108
                    'overview' => $header->key,
109
                    'value' => $item->get_value(),
110
                    'textalign' => $item->get_text_align()->classes(),
111
                ];
112
 
113
                $alertcount = $item->get_alert_count();
114
                if ($alertcount > 0) {
115
                    $itemsdata->alertcount = $alertcount;
116
                    $itemsdata->alertlabel = $item->get_alert_label();
117
                }
118
 
119
                $items[] = $itemsdata;
120
            }
121
            $result[] = [
122
                'cmid' => $activity['cmid'],
123
                'overviews' => $items,
124
            ];
125
        }
126
        return $result;
127
    }
128
 
129
    /**
130
     * Loads all overviews from activities for the given course and module name.
131
     *
132
     * @param renderer_base $output
133
     * @return array An array of overviews.
134
     */
135
    private function load_all_overviews_from_each_activity(renderer_base $output): array {
136
        $result = [];
137
        foreach ($this->get_related_course_modules() as $cm) {
138
            if (!$this->is_cm_displayable($cm)) {
139
                continue;
140
            }
141
            $result[] = [
142
                'cmid' => $cm->id,
143
                'overviews' => $this->load_overview_items_from_activity($output, $cm),
144
            ];
145
        }
146
        return $result;
147
    }
148
 
149
    /**
150
     * Get all course modules related to the modname.
151
     *
152
     * @return cm_info[]
153
     */
154
    private function get_related_course_modules(): array {
155
        $modinfo = get_fast_modinfo($this->course->id);
156
        if ($this->modname == 'resource') {
157
            $result = $this->get_all_resource_intances($modinfo);
158
        } else {
159
            $result = $modinfo->get_instances_of($this->modname);
160
        }
161
        $modinfo->sort_cm_array($result);
162
        return $result;
163
    }
164
 
165
    /**
166
     * Get the table caption.
167
     *
168
     * @return string
169
     */
170
    private function get_table_caption(): string {
171
        if ($this->modname === 'resource') {
172
            $name = get_string('resource');
173
        } else {
174
            $pluginman = plugin_manager::instance();
175
            $name = $pluginman->plugin_name($this->modname);
176
        }
177
        return get_string('overview_table_caption', 'core_course', $name);
178
    }
179
 
180
    /**
181
     * Get all resource instances.
182
     *
183
     * This is a very specific case where the same overview table shows
184
     * several plugins at once. This is not a common use case and only
185
     * happens for MOD_ARCHETYPE_RESOURCE plugins.
186
     *
187
     * @param mixed $modinfo
188
     * @return array
189
     */
190
    private function get_all_resource_intances($modinfo): array {
191
        $resources = [];
192
        $archetypes = [];
193
        foreach ($modinfo->cms as $cm) {
194
            if (!array_key_exists($cm->modname, $archetypes)) {
195
                $archetypes[$cm->modname] = plugin_supports(
196
                    type: 'mod',
197
                    name: $cm->modname,
198
                    feature: FEATURE_MOD_ARCHETYPE,
199
                    default: MOD_ARCHETYPE_OTHER
200
                );
201
            }
202
            if ($archetypes[$cm->modname] == MOD_ARCHETYPE_RESOURCE) {
203
                $resources[] = $cm;
204
            }
205
        }
206
        return $resources;
207
    }
208
 
209
    /**
210
     * Check if the course module is displayable in the overview table.
211
     *
212
     * @param cm_info $cm
213
     * @return bool
214
     */
215
    private function is_cm_displayable(cm_info $cm): bool {
216
        // Folder is an exception because it has settings to be displayed in the course
217
        // page without having a view link.
218
        return $cm->uservisible && ($cm->has_view() || strcmp($cm->modname, 'folder') === 0);
219
    }
220
 
221
    /**
222
     * Loads overview items from a given activity.
223
     *
224
     * @param renderer_base $output
225
     * @param cm_info $cm
226
     * @return array An associative array containing the overview items for the activity.
227
     */
228
    private function load_overview_items_from_activity(renderer_base $output, cm_info $cm): array {
229
        global $PAGE;
230
        $overview = overviewfactory::create($cm);
231
 
232
        $row = [
233
            'name' => $overview->get_name_overview($output),
234
            'duedate' => $overview->get_due_date_overview($output),
235
            'completion' => $overview->get_completion_overview($output),
236
        ];
237
 
238
        $row = array_merge($row, $overview->get_extra_overview_items($output));
239
 
240
        $gradeitems = $overview->get_grades_overviews();
241
        if (!empty($gradeitems)) {
242
            foreach ($gradeitems as $gradeitem) {
243
                $row[$gradeitem->get_name()] = $gradeitem;
244
            }
245
        }
246
 
247
        // Actions are always the last column, if any.
248
        $row['actions'] = $overview->get_actions_overview($output);
249
 
250
        $row = array_filter($row, function ($item) {
251
            return $item !== null;
252
        });
253
 
254
        $this->register_columns($row);
255
 
256
        $result = [];
257
        foreach ($row as $key => $item) {
258
            $result[$key] = $item;
259
        }
260
        return $result;
261
    }
262
 
263
    /**
264
     * Register a new row into the table.
265
     *
266
     * @param overviewitem[] $row
267
     * @return void
268
     */
269
    private function register_columns(array $row): void {
270
        foreach ($row as $key => $item) {
271
            if (!isset($this->columnhascontent[$key])) {
272
                $this->columnhascontent[$key] = false;
273
                $this->headers[] = (object) [
274
                    'name' => $item->get_name(),
275
                    'key' => $key,
276
                    'textalign' => $item->get_text_align()->classes(),
277
                ];
278
            }
279
            $this->columnhascontent[$key] = $this->columnhascontent[$key] || $item->get_value() !== null;
280
        }
281
    }
282
 
283
    /**
284
     * Get the template name.
285
     *
286
     * @param renderer_base $renderer Renderer base.
287
     * @return string
288
     */
289
    public function get_template_name(renderer_base $renderer): string {
290
        return 'core_courseformat/local/overview/overviewtable';
291
    }
292
}