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
/**
18
 * Discussion list renderer.
19
 *
20
 * @package    mod_forum
21
 * @copyright  2019 Andrew Nicols <andrew@nicols.co.uk>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace mod_forum\local\renderers;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
use mod_forum\grades\forum_gradeitem;
30
use mod_forum\local\entities\forum as forum_entity;
31
use mod_forum\local\factories\legacy_data_mapper as legacy_data_mapper_factory;
32
use mod_forum\local\factories\exporter as exporter_factory;
33
use mod_forum\local\factories\vault as vault_factory;
34
use mod_forum\local\factories\url as url_factory;
35
use mod_forum\local\managers\capability as capability_manager;
36
use mod_forum\local\vaults\discussion_list as discussion_list_vault;
37
use renderer_base;
38
use stdClass;
39
use core\output\notification;
40
use mod_forum\local\data_mappers\legacy\forum;
41
use mod_forum\local\factories\builder as builder_factory;
42
 
43
require_once($CFG->dirroot . '/mod/forum/lib.php');
44
 
45
/**
46
 * The discussion list renderer.
47
 *
48
 * @package    mod_forum
49
 * @copyright  2019 Andrew Nicols <andrew@nicols.co.uk>
50
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
51
 */
52
class discussion_list {
53
    /** @var forum_entity The forum being rendered */
54
    private $forum;
55
 
56
    /** @var stdClass The DB record for the forum being rendered */
57
    private $forumrecord;
58
 
59
    /** @var renderer_base The renderer used to render the view */
60
    private $renderer;
61
 
62
    /** @var legacy_data_mapper_factory $legacydatamapperfactory Legacy data mapper factory */
63
    private $legacydatamapperfactory;
64
 
65
    /** @var exporter_factory $exporterfactory Exporter factory */
66
    private $exporterfactory;
67
 
68
    /** @var vault_factory $vaultfactory Vault factory */
69
    private $vaultfactory;
70
 
71
    /** @var capability_manager $capabilitymanager Capability manager */
72
    private $capabilitymanager;
73
 
74
    /** @var url_factory $urlfactory URL factory */
75
    private $urlfactory;
76
 
77
    /** @var array $notifications List of notification HTML */
78
    private $notifications;
79
 
80
    /** @var builder_factory $builderfactory Builder factory */
81
    private $builderfactory;
82
 
83
    /** @var callable $postprocessfortemplate Function to process exported posts before template rendering */
84
    private $postprocessfortemplate;
85
 
86
    /** @var string $template The template to use when displaying */
87
    private $template;
88
 
89
    /** @var gradeitem The gradeitem instance associated with this forum */
90
    private $forumgradeitem;
91
 
92
    /**
93
     * Constructor for a new discussion list renderer.
94
     *
95
     * @param   forum_entity        $forum The forum entity to be rendered
96
     * @param   renderer_base       $renderer The renderer used to render the view
97
     * @param   legacy_data_mapper_factory $legacydatamapperfactory The factory used to fetch a legacy record
98
     * @param   exporter_factory    $exporterfactory The factory used to fetch exporter instances
99
     * @param   vault_factory       $vaultfactory The factory used to fetch the vault instances
100
     * @param   builder_factory     $builderfactory The factory used to fetch the builder instances
101
     * @param   capability_manager  $capabilitymanager The managed used to check capabilities on the forum
102
     * @param   url_factory         $urlfactory The factory used to create URLs in the forum
103
     * @param   string              $template
104
     * @param   notification[]      $notifications A list of any notifications to be displayed within the page
105
     * @param   callable|null       $postprocessfortemplate Callback function to process discussion lists for templates
106
     */
107
    public function __construct(
108
        forum_entity $forum,
109
        renderer_base $renderer,
110
        legacy_data_mapper_factory $legacydatamapperfactory,
111
        exporter_factory $exporterfactory,
112
        vault_factory $vaultfactory,
113
        builder_factory $builderfactory,
114
        capability_manager $capabilitymanager,
115
        url_factory $urlfactory,
116
        forum_gradeitem $forumgradeitem,
117
        string $template,
118
        array $notifications = [],
119
        callable $postprocessfortemplate = null
120
    ) {
121
        $this->forum = $forum;
122
        $this->renderer = $renderer;
123
        $this->legacydatamapperfactory = $legacydatamapperfactory;
124
        $this->exporterfactory = $exporterfactory;
125
        $this->vaultfactory = $vaultfactory;
126
        $this->builderfactory = $builderfactory;
127
        $this->capabilitymanager = $capabilitymanager;
128
 
129
        $this->urlfactory = $urlfactory;
130
        $this->notifications = $notifications;
131
        $this->postprocessfortemplate = $postprocessfortemplate;
132
        $this->template = $template;
133
        $this->forumgradeitem = $forumgradeitem;
134
 
135
        $forumdatamapper = $this->legacydatamapperfactory->get_forum_data_mapper();
136
        $this->forumrecord = $forumdatamapper->to_legacy_object($forum);
137
    }
138
 
139
    /**
140
     * Render for the specified user.
141
     *
142
     * @param   stdClass    $user The user to render for
143
     * @param   cm_info     $cm The course module info for this discussion list
144
     * @param   int         $groupid The group to render
145
     * @param   int         $sortorder The sort order to use when selecting the discussions in the list
146
     * @param   int         $pageno The zero-indexed page number to use
147
     * @param   int         $pagesize The number of discussions to show on the page
148
     * @param   int         $displaymode The discussion display mode
149
     * @param   bool        $enablediscussioncreation To show the discussion button.
150
     * @return  string      The rendered content for display
151
     */
152
    public function render(
153
        stdClass $user,
154
        \cm_info $cm,
155
        ?int $groupid,
156
        ?int $sortorder,
157
        ?int $pageno,
158
        ?int $pagesize,
159
        int $displaymode = null,
160
        bool $enablediscussioncreation = true
161
    ): string {
162
        global $PAGE;
163
 
164
        $forum = $this->forum;
165
        $course = $forum->get_course_record();
166
 
167
        $forumexporter = $this->exporterfactory->get_forum_exporter(
168
            $user,
169
            $this->forum,
170
            $groupid
171
        );
172
 
173
        $pagesize = $this->get_page_size($pagesize);
174
        $pageno = $this->get_page_number($pageno);
175
 
176
        // Count all forum discussion posts.
177
        $alldiscussionscount = mod_forum_count_all_discussions($forum, $user, $groupid);
178
 
179
        // Get all forum discussion summaries.
180
        $discussions = mod_forum_get_discussion_summaries($forum, $user, $groupid, $sortorder, $pageno, $pagesize);
181
 
182
        $capabilitymanager = $this->capabilitymanager;
183
        $hasanyactions = false;
184
        $hasanyactions = $hasanyactions || $capabilitymanager->can_favourite_discussion($user);
185
        $hasanyactions = $hasanyactions || $capabilitymanager->can_pin_discussions($user);
186
        $hasanyactions = $hasanyactions || $capabilitymanager->can_manage_forum($user);
187
 
188
        $forumview = [
189
            'forum' => (array) $forumexporter->export($this->renderer),
190
            'contextid' => $forum->get_context()->id,
191
            'cmid' => $cm->id,
192
            'groupid' => $groupid,
193
            'name' => format_string($forum->get_name()),
194
            'courseid' => $course->id,
195
            'coursename' => format_string($course->shortname),
196
            'experimentaldisplaymode' => $displaymode == FORUM_MODE_NESTED_V2,
197
            'gradingcomponent' => $this->forumgradeitem->get_grading_component_name(),
198
            'gradingcomponentsubtype' => $this->forumgradeitem->get_grading_component_subtype(),
199
            'sendstudentnotifications' => $forum->should_notify_students_default_when_grade_for_forum(),
200
            'gradeonlyactiveusers' => $this->forumgradeitem->should_grade_only_active_users(),
201
            'hasanyactions' => $hasanyactions,
202
            'groupchangemenu' => groups_print_activity_menu(
203
                $cm,
204
                $this->urlfactory->get_forum_view_url_from_forum($forum),
205
                true
206
            ),
207
            'hasmore' => ($alldiscussionscount > $pagesize),
208
            'notifications' => $this->get_notifications($user, $groupid),
209
            'settings' => [
210
                'excludetext' => true,
211
                'togglemoreicon' => true,
212
                'excludesubscription' => true
213
            ],
214
            'totaldiscussioncount' => $alldiscussionscount,
215
            'userid' => $user->id,
216
            'visiblediscussioncount' => count($discussions),
217
            'enablediscussioncreation' => $enablediscussioncreation,
218
        ];
219
 
220
        if ($forumview['forum']['capabilities']['create']) {
221
            $forumview['newdiscussionhtml'] = $this->get_discussion_form($user, $cm, $groupid);
222
        }
223
 
224
        if (!$discussions) {
225
            return $this->renderer->render_from_template($this->template, $forumview);
226
        }
227
 
228
        if ($this->postprocessfortemplate !== null) {
229
            // We've got some post processing to do!
230
            $exportedposts = ($this->postprocessfortemplate) ($discussions, $user, $forum);
231
        }
232
 
11 efrain 233
        $baseurl = new \moodle_url($PAGE->url, ['o' => $sortorder, 's' => $pagesize]);
1 efrain 234
 
235
        $forumview = array_merge(
236
            $forumview,
237
            [
238
                'pagination' => $this->renderer->render(new \paging_bar($alldiscussionscount, $pageno, $pagesize, $baseurl, 'p')),
239
            ],
240
            $exportedposts
241
        );
242
 
243
        $firstdiscussion = reset($discussions);
244
        $forumview['firstgradeduserid'] = $firstdiscussion->get_latest_post_author()->get_id();
245
 
246
        return $this->renderer->render_from_template($this->template, $forumview);
247
    }
248
 
249
    /**
250
     * Add new discussion button to the action bar for tertiary nav.
251
     *
252
     * @param stdClass $user The user object.
253
     * @param int|null $groupid The group id.
254
     * @return string rendered HTML string
255
     */
256
    public function render_new_discussion(stdClass $user, ?int $groupid): string {
257
        $forumexporter = $this->exporterfactory->get_forum_exporter(
258
            $user,
259
            $this->forum,
260
            $groupid
261
        );
262
 
263
        $forumview = [
264
            'forum' => (array) $forumexporter->export($this->renderer),
265
        ];
266
 
267
        return $this->renderer->render_from_template('mod_forum/forum_new_discussion_actionbar', $forumview);
268
    }
269
 
270
    /**
271
     * Get the mod_forum_post_form. This is the default boiler plate from mod_forum/post_form.php with the inpage flag caveat
272
     *
273
     * @param stdClass $user The user the form is being generated for
274
     * @param \cm_info $cm
275
     * @param int $groupid The groupid if any
276
     *
277
     * @return string The rendered html
278
     */
279
    private function get_discussion_form(stdClass $user, \cm_info $cm, ?int $groupid) {
280
        $forum = $this->forum;
281
        $forumrecord = $this->legacydatamapperfactory->get_forum_data_mapper()->to_legacy_object($forum);
282
        $modcontext = \context_module::instance($cm->id);
283
        $coursecontext = \context_course::instance($forum->get_course_id());
284
        $post = (object) [
285
            'course' => $forum->get_course_id(),
286
            'forum' => $forum->get_id(),
287
            'discussion' => 0,           // Ie discussion # not defined yet.
288
            'parent' => 0,
289
            'subject' => '',
290
            'userid' => $user->id,
291
            'message' => '',
292
            'messageformat' => editors_get_preferred_format(),
293
            'messagetrust' => 0,
294
            'groupid' => $groupid,
295
        ];
296
        $thresholdwarning = forum_check_throttling($forumrecord, $cm);
297
 
298
        $formparams = array(
299
            'course' => $forum->get_course_record(),
300
            'cm' => $cm,
301
            'coursecontext' => $coursecontext,
302
            'modcontext' => $modcontext,
303
            'forum' => $forumrecord,
304
            'post' => $post,
305
            'subscribe' => \mod_forum\subscriptions::is_subscribed($user->id, $forumrecord,
306
                null, $cm),
307
            'thresholdwarning' => $thresholdwarning,
308
            'inpagereply' => true,
309
            'edit' => 0
310
        );
311
        $posturl = new \moodle_url('/mod/forum/post.php');
312
        $mformpost = new \mod_forum_post_form($posturl, $formparams, 'post', '', array('id' => 'mformforum'));
313
        $discussionsubscribe = \mod_forum\subscriptions::get_user_default_subscription($forumrecord, $coursecontext, $cm, null);
314
 
315
        $params = array('reply' => 0, 'forum' => $forumrecord->id, 'edit' => 0) +
316
            (isset($post->groupid) ? array('groupid' => $post->groupid) : array()) +
317
            array(
318
                'userid' => $post->userid,
319
                'parent' => $post->parent,
320
                'discussion' => $post->discussion,
321
                'course' => $forum->get_course_id(),
322
                'discussionsubscribe' => $discussionsubscribe
323
            );
324
        $mformpost->set_data($params);
325
 
326
        return $mformpost->render();
327
    }
328
 
329
    /**
330
     * Fetch the page size to use when displaying the page.
331
     *
332
     * @param   int         $pagesize The number of discussions to show on the page
333
     * @return  int         The normalised page size
334
     */
335
    private function get_page_size(?int $pagesize): int {
336
        if (null === $pagesize || $pagesize <= 0) {
337
            $pagesize = discussion_list_vault::PAGESIZE_DEFAULT;
338
        }
339
 
340
        return $pagesize;
341
    }
342
 
343
    /**
344
     * Fetch the current page number (zero-indexed).
345
     *
346
     * @param   int         $pageno The zero-indexed page number to use
347
     * @return  int         The normalised page number
348
     */
349
    private function get_page_number(?int $pageno): int {
350
        if (null === $pageno || $pageno < 0) {
351
            $pageno = 0;
352
        }
353
 
354
        return $pageno;
355
    }
356
 
357
    /**
358
     * Get the list of notification for display.
359
     *
360
     * @param stdClass $user The viewing user
361
     * @param int|null $groupid The forum's group id
362
     * @return      array
363
     */
364
    private function get_notifications(stdClass $user, ?int $groupid): array {
365
        $notifications = $this->notifications;
366
        $forum = $this->forum;
367
        $capabilitymanager = $this->capabilitymanager;
368
 
369
        if ($forum->is_cutoff_date_reached()) {
370
            $notifications[] = (new notification(
371
                    get_string('cutoffdatereached', 'forum'),
372
                    notification::NOTIFY_INFO
373
            ))->set_show_closebutton();
374
        }
375
 
376
        if ($forum->has_blocking_enabled()) {
377
            $notifications[] = (new notification(
378
                get_string('thisforumisthrottled', 'forum', [
379
                    'blockafter' => $forum->get_block_after(),
380
                    'blockperiod' => get_string('secondstotime' . $forum->get_block_period())
381
                ]),
382
                notification::NOTIFY_INFO
383
            ))->set_show_closebutton();
384
        }
385
 
386
        if ($forum->is_in_group_mode() && !$capabilitymanager->can_access_all_groups($user)) {
387
            if ($groupid === null) {
388
                if (!$capabilitymanager->can_post_to_my_groups($user)) {
389
                    $notifications[] = (new notification(
390
                        get_string('cannotadddiscussiongroup', 'mod_forum'),
391
                        \core\output\notification::NOTIFY_WARNING
392
                    ))->set_show_closebutton();
393
                } else {
394
                    $notifications[] = (new notification(
395
                        get_string('cannotadddiscussionall', 'mod_forum'),
396
                        \core\output\notification::NOTIFY_WARNING
397
                    ))->set_show_closebutton();
398
                }
399
            } else if (!$capabilitymanager->can_access_group($user, $groupid)) {
400
                $notifications[] = (new notification(
401
                    get_string('cannotadddiscussion', 'mod_forum'),
402
                    \core\output\notification::NOTIFY_WARNING
403
                ))->set_show_closebutton();
404
            }
405
        }
406
 
407
        if ('qanda' === $forum->get_type() && !$capabilitymanager->can_manage_forum($user)) {
408
            $notifications[] = (new notification(
409
                get_string('qandanotify', 'forum'),
410
                notification::NOTIFY_INFO
411
            ))->set_show_closebutton()->set_extra_classes(['mt-3']);
412
        }
413
 
414
        if ('eachuser' === $forum->get_type()) {
415
            $notifications[] = (new notification(
416
                get_string('allowsdiscussions', 'forum'),
417
                notification::NOTIFY_INFO)
418
            )->set_show_closebutton();
419
        }
420
 
421
        return array_map(function($notification) {
422
            return $notification->export_for_template($this->renderer);
423
        }, $notifications);
424
    }
425
}