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
namespace tool_usertours;
18
 
19
use coding_exception;
20
use core\output\inplace_editable;
21
 
22
/**
23
 * Tour helper.
24
 *
25
 * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>
26
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27
 * @package    tool_usertours
28
 */
29
class helper {
30
    /**
31
     * @var MOVE_UP
32
     */
33
    const MOVE_UP = -1;
34
 
35
    /**
36
     * @var MOVE_DOWN
37
     */
38
    const MOVE_DOWN = 1;
39
 
40
    /**
41
     * @var boolean Has it been bootstrapped?
42
     */
43
    private static $bootstrapped = false;
44
 
45
    /**
46
     * @var string Regex to check any matching lang string.
47
     */
48
    protected const LANG_STRING_REGEX = '|^([a-zA-Z][a-zA-Z0-9\.:/_-]*),([a-zA-Z][a-zA-Z0-9\.:/_-]*)$|';
49
 
50
    /**
51
     * Get the link to edit the step.
52
     *
53
     * If no stepid is specified, then a link to create a new step is provided. The $targettype must be specified in this case.
54
     *
55
     * @param   int     $tourid     The tour that the step belongs to.
56
     * @param   int     $stepid     The step ID.
57
     * @param   int     $targettype The type of step.
58
     *
59
     * @return \moodle_url
60
     */
61
    public static function get_edit_step_link($tourid, $stepid = null, $targettype = null) {
62
        $link = new \moodle_url('/admin/tool/usertours/configure.php');
63
 
64
        if ($stepid) {
65
            $link->param('action', manager::ACTION_EDITSTEP);
66
            $link->param('id', $stepid);
67
        } else {
68
            $link->param('action', manager::ACTION_NEWSTEP);
69
            $link->param('tourid', $tourid);
70
        }
71
 
72
        return $link;
73
    }
74
 
75
    /**
76
     * Get the link to move the tour.
77
     *
78
     * @param   int     $tourid     The tour ID.
79
     * @param   int     $direction  The direction to move in
80
     *
81
     * @return \moodle_url
82
     */
83
    public static function get_move_tour_link($tourid, $direction = self::MOVE_DOWN) {
84
        $link = new \moodle_url('/admin/tool/usertours/configure.php');
85
 
86
        $link->param('action', manager::ACTION_MOVETOUR);
87
        $link->param('id', $tourid);
88
        $link->param('direction', $direction);
89
        $link->param('sesskey', sesskey());
90
 
91
        return $link;
92
    }
93
 
94
    /**
95
     * Get the link to move the step.
96
     *
97
     * @param   int     $stepid     The step ID.
98
     * @param   int     $direction  The direction to move in
99
     *
100
     * @return \moodle_url
101
     */
102
    public static function get_move_step_link($stepid, $direction = self::MOVE_DOWN) {
103
        $link = new \moodle_url('/admin/tool/usertours/configure.php');
104
 
105
        $link->param('action', manager::ACTION_MOVESTEP);
106
        $link->param('id', $stepid);
107
        $link->param('direction', $direction);
108
        $link->param('sesskey', sesskey());
109
 
110
        return $link;
111
    }
112
 
113
    /**
114
     * Get the link ot create a new step.
115
     *
116
     * @param   int         $tourid     The ID of the tour to attach this step to.
117
     * @param   int         $targettype The type of target.
118
     *
119
     * @return  \moodle_url             The required URL.
120
     */
121
    public static function get_new_step_link($tourid, $targettype = null) {
122
        $link = new \moodle_url('/admin/tool/usertours/configure.php');
123
        $link->param('action', manager::ACTION_NEWSTEP);
124
        $link->param('tourid', $tourid);
125
        $link->param('targettype', $targettype);
126
 
127
        return $link;
128
    }
129
 
130
    /**
131
     * Get the link used to view the tour.
132
     *
133
     * @param   int         $tourid     The ID of the tour to display.
134
     * @return  \moodle_url             The URL.
135
     */
136
    public static function get_view_tour_link($tourid) {
137
        return new \moodle_url('/admin/tool/usertours/configure.php', [
138
                'id'        => $tourid,
139
                'action'    => manager::ACTION_VIEWTOUR,
140
            ]);
141
    }
142
 
143
    /**
144
     * Get the link used to reset the tour state for all users.
145
     *
146
     * @param   int         $tourid     The ID of the tour to display.
147
     * @return  \moodle_url             The URL.
148
     */
149
    public static function get_reset_tour_for_all_link($tourid) {
150
        return new \moodle_url('/admin/tool/usertours/configure.php', [
151
            'id'        => $tourid,
152
            'action'    => manager::ACTION_RESETFORALL,
153
            'sesskey'   => sesskey(),
154
        ]);
155
    }
156
 
157
    /**
158
     * Get the link used to edit the tour.
159
     *
160
     * @param   int         $tourid     The ID of the tour to edit.
161
     * @return  \moodle_url             The URL.
162
     */
163
    public static function get_edit_tour_link($tourid = null) {
164
        $link = new \moodle_url('/admin/tool/usertours/configure.php');
165
 
166
        if ($tourid) {
167
            $link->param('action', manager::ACTION_EDITTOUR);
168
            $link->param('id', $tourid);
169
        } else {
170
            $link->param('action', manager::ACTION_NEWTOUR);
171
        }
172
 
173
        return $link;
174
    }
175
 
176
    /**
177
     * Get the link used to import the tour.
178
     *
179
     * @return  \moodle_url             The URL.
180
     */
181
    public static function get_import_tour_link() {
182
        $link = new \moodle_url('/admin/tool/usertours/configure.php', [
183
                'action'    => manager::ACTION_IMPORTTOUR,
184
            ]);
185
 
186
        return $link;
187
    }
188
 
189
    /**
190
     * Get the link used to export the tour.
191
     *
192
     * @param   int         $tourid     The ID of the tour to export.
193
     * @return  \moodle_url             The URL.
194
     */
195
    public static function get_export_tour_link($tourid) {
196
        $link = new \moodle_url('/admin/tool/usertours/configure.php', [
197
            'action'    => manager::ACTION_EXPORTTOUR,
198
            'id'        => $tourid,
199
        ]);
200
 
201
        return $link;
202
    }
203
 
204
    /**
205
     * Get the link used to duplicate the tour.
206
     *
207
     * @param   int         $tourid     The ID of the tour to duplicate.
208
     * @return  \moodle_url             The URL.
209
     */
210
    public static function get_duplicate_tour_link($tourid) {
1441 ariadna 211
        return new \moodle_url('/admin/tool/usertours/configure.php', [
1 efrain 212
            'action'    => manager::ACTION_DUPLICATETOUR,
213
            'id'        => $tourid,
1441 ariadna 214
            'sesskey'   => sesskey(),
1 efrain 215
        ]);
216
    }
217
 
218
    /**
219
     * Get the link used to delete the tour.
220
     *
221
     * @param   int         $tourid     The ID of the tour to delete.
222
     * @return  \moodle_url             The URL.
223
     */
224
    public static function get_delete_tour_link($tourid) {
225
        return new \moodle_url('/admin/tool/usertours/configure.php', [
226
            'id'        => $tourid,
227
            'action'    => manager::ACTION_DELETETOUR,
228
            'sesskey'   => sesskey(),
229
        ]);
230
    }
231
 
232
    /**
233
     * Get the link for listing tours.
234
     *
235
     * @return  \moodle_url             The URL.
236
     */
237
    public static function get_list_tour_link() {
238
        $link = new \moodle_url('/admin/tool/usertours/configure.php');
239
        $link->param('action', manager::ACTION_LISTTOURS);
240
 
241
        return $link;
242
    }
243
 
244
    /**
245
     * Get a filler icon for display in the actions column of a table.
246
     *
247
     * @param   string      $url            The URL for the icon.
248
     * @param   string      $icon           The icon identifier.
249
     * @param   string      $alt            The alt text for the icon.
250
     * @param   string      $iconcomponent  The icon component.
251
     * @param   array       $options        Display options.
252
     * @return  string
253
     */
254
    public static function format_icon_link($url, $icon, $alt, $iconcomponent = 'moodle', $options = []) {
255
        global $OUTPUT;
256
 
257
        return $OUTPUT->action_icon(
258
            $url,
259
            new \pix_icon($icon, $alt, $iconcomponent, [
260
                'title' => $alt,
261
            ]),
262
            null,
263
            $options
264
        );
265
    }
266
 
267
    /**
268
     * Get a filler icon for display in the actions column of a table.
269
     *
270
     * @param   array       $options        Display options.
271
     * @return  string
272
     */
273
    public static function get_filler_icon($options = []) {
274
        global $OUTPUT;
275
 
276
        return \html_writer::span(
277
            $OUTPUT->pix_icon('t/filler', '', 'tool_usertours', $options),
278
            'action-icon'
279
        );
280
    }
281
 
282
    /**
283
     * Get the link for deleting steps.
284
     *
285
     * @param   int         $stepid     The ID of the step to display.
286
     * @return  \moodle_url             The URL.
287
     */
288
    public static function get_delete_step_link($stepid) {
289
        return new \moodle_url('/admin/tool/usertours/configure.php', [
290
            'action'    => manager::ACTION_DELETESTEP,
291
            'id'        => $stepid,
292
            'sesskey'   => sesskey(),
293
        ]);
294
    }
295
 
296
    /**
297
     * Render the inplace editable used to edit the tour name.
298
     *
299
     * @param tour $tour The tour to edit.
300
     * @return inplace_editable
301
     */
302
    public static function render_tourname_inplace_editable(tour $tour): inplace_editable {
303
        $name = format_text(static::get_string_from_input($tour->get_name()), FORMAT_HTML);
304
        return new inplace_editable(
305
            'tool_usertours',
306
            'tourname',
307
            $tour->get_id(),
308
            true,
309
            \html_writer::link(
310
                $tour->get_view_link(),
311
                $name
312
            ),
313
            $tour->get_name()
314
        );
315
    }
316
 
317
    /**
318
     * Render the inplace editable used to edit the tour description.
319
     *
320
     * @param tour $tour The tour to edit.
321
     * @return inplace_editable
322
     */
323
    public static function render_tourdescription_inplace_editable(tour $tour): inplace_editable {
324
        $description = format_text(static::get_string_from_input($tour->get_description()), FORMAT_HTML);
325
        return new inplace_editable(
326
            'tool_usertours',
327
            'tourdescription',
328
            $tour->get_id(),
329
            true,
330
            $description,
331
            $tour->get_description()
332
        );
333
    }
334
 
335
    /**
336
     * Render the inplace editable used to edit the tour enable state.
337
     *
338
     * @param tour $tour The tour to edit.
339
     * @return inplace_editable
340
     */
341
    public static function render_tourenabled_inplace_editable(tour $tour): inplace_editable {
342
        global $OUTPUT;
343
 
344
        if ($tour->is_enabled()) {
345
            $icon = 't/hide';
346
            $alt = get_string('disable');
347
            $value = 1;
348
        } else {
349
            $icon = 't/show';
350
            $alt = get_string('enable');
351
            $value = 0;
352
        }
353
 
354
        $editable = new inplace_editable(
355
            'tool_usertours',
356
            'tourenabled',
357
            $tour->get_id(),
358
            true,
359
            $OUTPUT->pix_icon($icon, $alt, 'moodle', [
360
                'title' => $alt,
361
            ]),
362
            $value
363
        );
364
 
365
        $editable->set_type_toggle();
366
        return $editable;
367
    }
368
 
369
    /**
370
     * Render the inplace editable used to edit the step name.
371
     *
372
     * @param step $step The step to edit.
373
     * @return inplace_editable
374
     */
375
    public static function render_stepname_inplace_editable(step $step): inplace_editable {
376
        $title = format_text(static::get_string_from_input($step->get_title()), FORMAT_HTML);
377
 
378
        return new inplace_editable(
379
            'tool_usertours',
380
            'stepname',
381
            $step->get_id(),
382
            true,
383
            \html_writer::link(
384
                $step->get_edit_link(),
385
                $title
386
            ),
387
            $step->get_title()
388
        );
389
    }
390
 
391
    /**
392
     * Get all of the tours.
393
     *
394
     * @return  stdClass[]
395
     */
396
    public static function get_tours() {
397
        global $DB;
398
 
399
        $tours = $DB->get_records('tool_usertours_tours', [], 'sortorder ASC');
400
        $return = [];
401
        foreach ($tours as $tour) {
402
            $return[$tour->id] = tour::load_from_record($tour);
403
        }
404
        return $return;
405
    }
406
 
407
    /**
408
     * Get the specified tour.
409
     *
410
     * @param   int         $tourid     The tour that the step belongs to.
411
     * @return  tour
412
     */
413
    public static function get_tour($tourid) {
414
        return tour::instance($tourid);
415
    }
416
 
417
    /**
418
     * Fetch the tour with the specified sortorder.
419
     *
420
     * @param   int         $sortorder  The sortorder of the tour.
421
     * @return  tour
422
     */
423
    public static function get_tour_from_sortorder($sortorder) {
424
        global $DB;
425
 
426
        $tour = $DB->get_record('tool_usertours_tours', ['sortorder' => $sortorder]);
427
        return tour::load_from_record($tour);
428
    }
429
 
430
    /**
431
     * Return the count of all tours.
432
     *
433
     * @return  int
434
     */
435
    public static function count_tours() {
436
        global $DB;
437
 
438
        return $DB->count_records('tool_usertours_tours');
439
    }
440
 
441
    /**
442
     * Reset the sortorder for all tours.
443
     */
444
    public static function reset_tour_sortorder() {
445
        global $DB;
446
        $tours = $DB->get_records('tool_usertours_tours', null, 'sortorder ASC, pathmatch DESC', 'id, sortorder');
447
 
448
        $index = 0;
449
        foreach ($tours as $tour) {
450
            if ($tour->sortorder != $index) {
451
                $DB->set_field('tool_usertours_tours', 'sortorder', $index, ['id' => $tour->id]);
452
            }
453
            $index++;
454
        }
455
 
456
        // Notify the cache that a tour has changed.
457
        // Tours are only stored in the cache if there are steps.
458
        // If there step count has changed for some reason, this will change the potential cache results.
459
        cache::notify_tour_change();
460
    }
461
 
462
 
463
    /**
464
     * Get all of the steps in the tour.
465
     *
466
     * @param   int         $tourid     The tour that the step belongs to.
467
     * @return  step[]
468
     */
469
    public static function get_steps($tourid) {
470
        $steps = cache::get_stepdata($tourid);
471
 
472
        $return = [];
473
        foreach ($steps as $step) {
474
            $return[$step->id] = step::load_from_record($step);
475
        }
476
        return $return;
477
    }
478
 
479
    /**
480
     * Fetch the specified step.
481
     *
482
     * @param   int         $stepid     The id of the step to fetch.
483
     * @return  step
484
     */
485
    public static function get_step($stepid) {
486
        return step::instance($stepid);
487
    }
488
 
489
    /**
490
     * Fetch the step with the specified sortorder.
491
     *
492
     * @param   int         $tourid     The tour that the step belongs to.
493
     * @param   int         $sortorder  The sortorder of the step.
494
     * @return  step
495
     */
496
    public static function get_step_from_sortorder($tourid, $sortorder) {
497
        global $DB;
498
 
499
        $step = $DB->get_record('tool_usertours_steps', ['tourid' => $tourid, 'sortorder' => $sortorder]);
500
        return step::load_from_record($step);
501
    }
502
 
503
    /**
504
     * Handle addition of the tour into the current page.
505
     */
506
    public static function bootstrap() {
507
        global $PAGE;
508
 
509
        if (!isloggedin() || isguestuser()) {
510
            return;
511
        }
512
 
513
        if (in_array($PAGE->pagelayout, ['maintenance', 'print', 'redirect'])) {
514
            // Do not try to show user tours inside iframe, in maintenance mode,
515
            // when printing, or during redirects.
516
            return;
517
        }
518
 
519
        if (self::$bootstrapped) {
520
            return;
521
        }
522
        self::$bootstrapped = true;
523
 
524
        $tours = manager::get_current_tours();
525
 
526
        if ($tours) {
527
            $filters = static::get_all_clientside_filters();
528
 
529
            $tourdetails = array_map(function ($tour) use ($filters) {
530
                return [
531
                    'tourId' => $tour->get_id(),
532
                    'startTour' => $tour->should_show_for_user(),
533
                    'filtervalues' => $tour->get_client_filter_values($filters),
534
                ];
535
            }, $tours);
536
 
537
            $filternames = self::get_clientside_filter_module_names($filters);
538
 
539
            $PAGE->requires->js_call_amd('tool_usertours/usertours', 'init', [
540
                $tourdetails,
541
                $filternames,
542
            ]);
543
        }
544
    }
545
 
546
    /**
547
     * Get the JS module names for the filters.
548
     *
549
     * @param array $filters
550
     * @return array
551
     * @throws coding_exception
552
     */
553
    public static function get_clientside_filter_module_names(array $filters): array {
554
        $filternames = [];
555
        foreach ($filters as $filter) {
556
            if ($component = \core_component::get_component_from_classname($filter)) {
557
                $filternames[] = sprintf(
558
                    "%s/filter_%s",
559
                    $component,
560
                    $filter::get_filter_name(),
561
                );
562
            } else {
563
                throw new \coding_exception("Could not determine component for filter class {$filter}");
564
            }
565
        }
566
 
567
        return $filternames;
568
    }
569
 
570
    /**
571
     * Get a list of all possible filters.
572
     *
573
     * @return  array
574
     */
575
    public static function get_all_filters() {
576
        $hook = new hook\before_serverside_filter_fetch(array_keys(
577
            \core_component::get_component_classes_in_namespace('tool_usertours', 'local\filter')
578
        ));
579
        \core\di::get(\core\hook\manager::class)->dispatch($hook);
580
 
581
        $filters = array_filter(
582
            $hook->get_filter_list(),
583
            function ($filterclass) {
584
                $rc = new \ReflectionClass($filterclass);
585
                return $rc->isInstantiable();
586
            }
587
        );
588
 
589
        $filters = array_merge($filters, static::get_all_clientside_filters());
590
 
591
        return $filters;
592
    }
593
 
594
    /**
595
     * Get a list of all clientside filters.
596
     *
597
     * @return  array
598
     */
599
    public static function get_all_clientside_filters() {
600
        $hook = new hook\before_clientside_filter_fetch(array_keys(
601
            \core_component::get_component_classes_in_namespace('tool_usertours', 'local\clientside_filter')
602
        ));
603
        \core\di::get(\core\hook\manager::class)->dispatch($hook);
604
 
605
        $filters = array_filter(
606
            $hook->get_filter_list(),
607
            function ($filterclass) {
608
                $rc = new \ReflectionClass($filterclass);
609
                return $rc->isInstantiable();
610
            }
611
        );
612
 
613
        return $filters;
614
    }
615
 
616
    /**
617
     * Attempt to fetch any matching langstring if the content is in the
618
     * format identifier,component.
619
     *
620
     * @param string $content Step's content or Tour's name or Tour's description
621
     * @return string Processed content, any langstring will be converted to translated text
622
     */
623
    public static function get_string_from_input(string $content): string {
624
        $content = trim($content);
625
 
626
        if (preg_match(static::LANG_STRING_REGEX, $content, $matches)) {
627
            if ($matches[2] === 'moodle') {
628
                $matches[2] = 'core';
629
            }
630
 
631
            if (get_string_manager()->string_exists($matches[1], $matches[2])) {
632
                $content = get_string($matches[1], $matches[2]);
633
            }
634
        }
635
 
636
        return $content;
637
    }
638
 
639
    /**
640
     * Check if the given string contains any matching langstring.
641
     *
642
     * @param string $string
643
     * @return bool
644
     */
645
    public static function is_language_string_from_input(string $string): bool {
646
        return preg_match(static::LANG_STRING_REGEX, $string) == true;
647
    }
648
}