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 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) {
211
        $link = new \moodle_url('/admin/tool/usertours/configure.php', [
212
            'action'    => manager::ACTION_DUPLICATETOUR,
213
            'id'        => $tourid,
214
        ]);
215
 
216
        return $link;
217
    }
218
 
219
    /**
220
     * Get the link used to delete the tour.
221
     *
222
     * @param   int         $tourid     The ID of the tour to delete.
223
     * @return  \moodle_url             The URL.
224
     */
225
    public static function get_delete_tour_link($tourid) {
226
        return new \moodle_url('/admin/tool/usertours/configure.php', [
227
            'id'        => $tourid,
228
            'action'    => manager::ACTION_DELETETOUR,
229
            'sesskey'   => sesskey(),
230
        ]);
231
    }
232
 
233
    /**
234
     * Get the link for listing tours.
235
     *
236
     * @return  \moodle_url             The URL.
237
     */
238
    public static function get_list_tour_link() {
239
        $link = new \moodle_url('/admin/tool/usertours/configure.php');
240
        $link->param('action', manager::ACTION_LISTTOURS);
241
 
242
        return $link;
243
    }
244
 
245
    /**
246
     * Get a filler icon for display in the actions column of a table.
247
     *
248
     * @param   string      $url            The URL for the icon.
249
     * @param   string      $icon           The icon identifier.
250
     * @param   string      $alt            The alt text for the icon.
251
     * @param   string      $iconcomponent  The icon component.
252
     * @param   array       $options        Display options.
253
     * @return  string
254
     */
255
    public static function format_icon_link($url, $icon, $alt, $iconcomponent = 'moodle', $options = []) {
256
        global $OUTPUT;
257
 
258
        return $OUTPUT->action_icon(
259
            $url,
260
            new \pix_icon($icon, $alt, $iconcomponent, [
261
                'title' => $alt,
262
            ]),
263
            null,
264
            $options
265
        );
266
    }
267
 
268
    /**
269
     * Get a filler icon for display in the actions column of a table.
270
     *
271
     * @param   array       $options        Display options.
272
     * @return  string
273
     */
274
    public static function get_filler_icon($options = []) {
275
        global $OUTPUT;
276
 
277
        return \html_writer::span(
278
            $OUTPUT->pix_icon('t/filler', '', 'tool_usertours', $options),
279
            'action-icon'
280
        );
281
    }
282
 
283
    /**
284
     * Get the link for deleting steps.
285
     *
286
     * @param   int         $stepid     The ID of the step to display.
287
     * @return  \moodle_url             The URL.
288
     */
289
    public static function get_delete_step_link($stepid) {
290
        return new \moodle_url('/admin/tool/usertours/configure.php', [
291
            'action'    => manager::ACTION_DELETESTEP,
292
            'id'        => $stepid,
293
            'sesskey'   => sesskey(),
294
        ]);
295
    }
296
 
297
    /**
298
     * Render the inplace editable used to edit the tour name.
299
     *
300
     * @param tour $tour The tour to edit.
301
     * @return inplace_editable
302
     */
303
    public static function render_tourname_inplace_editable(tour $tour): inplace_editable {
304
        $name = format_text(static::get_string_from_input($tour->get_name()), FORMAT_HTML);
305
        return new inplace_editable(
306
            'tool_usertours',
307
            'tourname',
308
            $tour->get_id(),
309
            true,
310
            \html_writer::link(
311
                $tour->get_view_link(),
312
                $name
313
            ),
314
            $tour->get_name()
315
        );
316
    }
317
 
318
    /**
319
     * Render the inplace editable used to edit the tour description.
320
     *
321
     * @param tour $tour The tour to edit.
322
     * @return inplace_editable
323
     */
324
    public static function render_tourdescription_inplace_editable(tour $tour): inplace_editable {
325
        $description = format_text(static::get_string_from_input($tour->get_description()), FORMAT_HTML);
326
        return new inplace_editable(
327
            'tool_usertours',
328
            'tourdescription',
329
            $tour->get_id(),
330
            true,
331
            $description,
332
            $tour->get_description()
333
        );
334
    }
335
 
336
    /**
337
     * Render the inplace editable used to edit the tour enable state.
338
     *
339
     * @param tour $tour The tour to edit.
340
     * @return inplace_editable
341
     */
342
    public static function render_tourenabled_inplace_editable(tour $tour): inplace_editable {
343
        global $OUTPUT;
344
 
345
        if ($tour->is_enabled()) {
346
            $icon = 't/hide';
347
            $alt = get_string('disable');
348
            $value = 1;
349
        } else {
350
            $icon = 't/show';
351
            $alt = get_string('enable');
352
            $value = 0;
353
        }
354
 
355
        $editable = new inplace_editable(
356
            'tool_usertours',
357
            'tourenabled',
358
            $tour->get_id(),
359
            true,
360
            $OUTPUT->pix_icon($icon, $alt, 'moodle', [
361
                'title' => $alt,
362
            ]),
363
            $value
364
        );
365
 
366
        $editable->set_type_toggle();
367
        return $editable;
368
    }
369
 
370
    /**
371
     * Render the inplace editable used to edit the step name.
372
     *
373
     * @param step $step The step to edit.
374
     * @return inplace_editable
375
     */
376
    public static function render_stepname_inplace_editable(step $step): inplace_editable {
377
        $title = format_text(static::get_string_from_input($step->get_title()), FORMAT_HTML);
378
 
379
        return new inplace_editable(
380
            'tool_usertours',
381
            'stepname',
382
            $step->get_id(),
383
            true,
384
            \html_writer::link(
385
                $step->get_edit_link(),
386
                $title
387
            ),
388
            $step->get_title()
389
        );
390
    }
391
 
392
    /**
393
     * Get all of the tours.
394
     *
395
     * @return  stdClass[]
396
     */
397
    public static function get_tours() {
398
        global $DB;
399
 
400
        $tours = $DB->get_records('tool_usertours_tours', [], 'sortorder ASC');
401
        $return = [];
402
        foreach ($tours as $tour) {
403
            $return[$tour->id] = tour::load_from_record($tour);
404
        }
405
        return $return;
406
    }
407
 
408
    /**
409
     * Get the specified tour.
410
     *
411
     * @param   int         $tourid     The tour that the step belongs to.
412
     * @return  tour
413
     */
414
    public static function get_tour($tourid) {
415
        return tour::instance($tourid);
416
    }
417
 
418
    /**
419
     * Fetch the tour with the specified sortorder.
420
     *
421
     * @param   int         $sortorder  The sortorder of the tour.
422
     * @return  tour
423
     */
424
    public static function get_tour_from_sortorder($sortorder) {
425
        global $DB;
426
 
427
        $tour = $DB->get_record('tool_usertours_tours', ['sortorder' => $sortorder]);
428
        return tour::load_from_record($tour);
429
    }
430
 
431
    /**
432
     * Return the count of all tours.
433
     *
434
     * @return  int
435
     */
436
    public static function count_tours() {
437
        global $DB;
438
 
439
        return $DB->count_records('tool_usertours_tours');
440
    }
441
 
442
    /**
443
     * Reset the sortorder for all tours.
444
     */
445
    public static function reset_tour_sortorder() {
446
        global $DB;
447
        $tours = $DB->get_records('tool_usertours_tours', null, 'sortorder ASC, pathmatch DESC', 'id, sortorder');
448
 
449
        $index = 0;
450
        foreach ($tours as $tour) {
451
            if ($tour->sortorder != $index) {
452
                $DB->set_field('tool_usertours_tours', 'sortorder', $index, ['id' => $tour->id]);
453
            }
454
            $index++;
455
        }
456
 
457
        // Notify the cache that a tour has changed.
458
        // Tours are only stored in the cache if there are steps.
459
        // If there step count has changed for some reason, this will change the potential cache results.
460
        cache::notify_tour_change();
461
    }
462
 
463
 
464
    /**
465
     * Get all of the steps in the tour.
466
     *
467
     * @param   int         $tourid     The tour that the step belongs to.
468
     * @return  step[]
469
     */
470
    public static function get_steps($tourid) {
471
        $steps = cache::get_stepdata($tourid);
472
 
473
        $return = [];
474
        foreach ($steps as $step) {
475
            $return[$step->id] = step::load_from_record($step);
476
        }
477
        return $return;
478
    }
479
 
480
    /**
481
     * Fetch the specified step.
482
     *
483
     * @param   int         $stepid     The id of the step to fetch.
484
     * @return  step
485
     */
486
    public static function get_step($stepid) {
487
        return step::instance($stepid);
488
    }
489
 
490
    /**
491
     * Fetch the step with the specified sortorder.
492
     *
493
     * @param   int         $tourid     The tour that the step belongs to.
494
     * @param   int         $sortorder  The sortorder of the step.
495
     * @return  step
496
     */
497
    public static function get_step_from_sortorder($tourid, $sortorder) {
498
        global $DB;
499
 
500
        $step = $DB->get_record('tool_usertours_steps', ['tourid' => $tourid, 'sortorder' => $sortorder]);
501
        return step::load_from_record($step);
502
    }
503
 
504
    /**
505
     * Handle addition of the tour into the current page.
506
     */
507
    public static function bootstrap() {
508
        global $PAGE;
509
 
510
        if (!isloggedin() || isguestuser()) {
511
            return;
512
        }
513
 
514
        if (in_array($PAGE->pagelayout, ['maintenance', 'print', 'redirect'])) {
515
            // Do not try to show user tours inside iframe, in maintenance mode,
516
            // when printing, or during redirects.
517
            return;
518
        }
519
 
520
        if (self::$bootstrapped) {
521
            return;
522
        }
523
        self::$bootstrapped = true;
524
 
525
        $tours = manager::get_current_tours();
526
 
527
        if ($tours) {
528
            $filters = static::get_all_clientside_filters();
529
 
530
            $tourdetails = array_map(function ($tour) use ($filters) {
531
                return [
532
                    'tourId' => $tour->get_id(),
533
                    'startTour' => $tour->should_show_for_user(),
534
                    'filtervalues' => $tour->get_client_filter_values($filters),
535
                ];
536
            }, $tours);
537
 
538
            $filternames = self::get_clientside_filter_module_names($filters);
539
 
540
            $PAGE->requires->js_call_amd('tool_usertours/usertours', 'init', [
541
                $tourdetails,
542
                $filternames,
543
            ]);
544
        }
545
    }
546
 
547
    /**
548
     * Get the JS module names for the filters.
549
     *
550
     * @param array $filters
551
     * @return array
552
     * @throws coding_exception
553
     */
554
    public static function get_clientside_filter_module_names(array $filters): array {
555
        $filternames = [];
556
        foreach ($filters as $filter) {
557
            if ($component = \core_component::get_component_from_classname($filter)) {
558
                $filternames[] = sprintf(
559
                    "%s/filter_%s",
560
                    $component,
561
                    $filter::get_filter_name(),
562
                );
563
            } else {
564
                throw new \coding_exception("Could not determine component for filter class {$filter}");
565
            }
566
        }
567
 
568
        return $filternames;
569
    }
570
 
571
    /**
572
     * Get a list of all possible filters.
573
     *
574
     * @return  array
575
     */
576
    public static function get_all_filters() {
577
        $hook = new hook\before_serverside_filter_fetch(array_keys(
578
            \core_component::get_component_classes_in_namespace('tool_usertours', 'local\filter')
579
        ));
580
        \core\di::get(\core\hook\manager::class)->dispatch($hook);
581
 
582
        $filters = array_filter(
583
            $hook->get_filter_list(),
584
            function ($filterclass) {
585
                $rc = new \ReflectionClass($filterclass);
586
                return $rc->isInstantiable();
587
            }
588
        );
589
 
590
        $filters = array_merge($filters, static::get_all_clientside_filters());
591
 
592
        return $filters;
593
    }
594
 
595
    /**
596
     * Get a list of all clientside filters.
597
     *
598
     * @return  array
599
     */
600
    public static function get_all_clientside_filters() {
601
        $hook = new hook\before_clientside_filter_fetch(array_keys(
602
            \core_component::get_component_classes_in_namespace('tool_usertours', 'local\clientside_filter')
603
        ));
604
        \core\di::get(\core\hook\manager::class)->dispatch($hook);
605
 
606
        $filters = array_filter(
607
            $hook->get_filter_list(),
608
            function ($filterclass) {
609
                $rc = new \ReflectionClass($filterclass);
610
                return $rc->isInstantiable();
611
            }
612
        );
613
 
614
        return $filters;
615
    }
616
 
617
    /**
618
     * Attempt to fetch any matching langstring if the content is in the
619
     * format identifier,component.
620
     *
621
     * @param string $content Step's content or Tour's name or Tour's description
622
     * @return string Processed content, any langstring will be converted to translated text
623
     */
624
    public static function get_string_from_input(string $content): string {
625
        $content = trim($content);
626
 
627
        if (preg_match(static::LANG_STRING_REGEX, $content, $matches)) {
628
            if ($matches[2] === 'moodle') {
629
                $matches[2] = 'core';
630
            }
631
 
632
            if (get_string_manager()->string_exists($matches[1], $matches[2])) {
633
                $content = get_string($matches[1], $matches[2]);
634
            }
635
        }
636
 
637
        return $content;
638
    }
639
 
640
    /**
641
     * Check if the given string contains any matching langstring.
642
     *
643
     * @param string $string
644
     * @return bool
645
     */
646
    public static function is_language_string_from_input(string $string): bool {
647
        return preg_match(static::LANG_STRING_REGEX, $string) == true;
648
    }
649
}