MDL-64990 tool_usertours: do not show messaging tour when disabled
[moodle.git] / admin / tool / usertours / classes / manager.php
CommitLineData
001fc061
AN
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 * Tour manager.
19 *
20 * @package tool_usertours
21 * @copyright 2016 Andrew Nicols <andrew@nicols.co.uk>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace tool_usertours;
26
27defined('MOODLE_INTERNAL') || die();
28
29use tool_usertours\local\forms;
30use tool_usertours\local\table;
3eb3d916 31use core\notification;
001fc061
AN
32
33/**
34 * Tour manager.
35 *
36 * @copyright 2016 Andrew Nicols <andrew@nicols.co.uk>
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 */
39class manager {
40
41 /**
42 * @var ACTION_LISTTOURS The action to get the list of tours.
43 */
44 const ACTION_LISTTOURS = 'listtours';
45
46 /**
47 * @var ACTION_NEWTOUR The action to create a new tour.
48 */
49 const ACTION_NEWTOUR = 'newtour';
50
51 /**
52 * @var ACTION_EDITTOUR The action to edit the tour.
53 */
54 const ACTION_EDITTOUR = 'edittour';
55
56 /**
57 * @var ACTION_MOVETOUR The action to move a tour up or down.
58 */
59 const ACTION_MOVETOUR = 'movetour';
60
61 /**
62 * @var ACTION_EXPORTTOUR The action to export the tour.
63 */
64 const ACTION_EXPORTTOUR = 'exporttour';
65
66 /**
67 * @var ACTION_IMPORTTOUR The action to import the tour.
68 */
69 const ACTION_IMPORTTOUR = 'importtour';
70
71 /**
72 * @var ACTION_DELETETOUR The action to delete the tour.
73 */
74 const ACTION_DELETETOUR = 'deletetour';
75
76 /**
77 * @var ACTION_VIEWTOUR The action to view the tour.
78 */
79 const ACTION_VIEWTOUR = 'viewtour';
80
81 /**
82 * @var ACTION_NEWSTEP The action to create a new step.
83 */
84 const ACTION_NEWSTEP = 'newstep';
85
86 /**
87 * @var ACTION_EDITSTEP The action to edit step configuration.
88 */
89 const ACTION_EDITSTEP = 'editstep';
90
91 /**
92 * @var ACTION_MOVESTEP The action to move a step up or down.
93 */
94 const ACTION_MOVESTEP = 'movestep';
95
96 /**
97 * @var ACTION_DELETESTEP The action to delete a step.
98 */
99 const ACTION_DELETESTEP = 'deletestep';
100
101 /**
102 * @var ACTION_VIEWSTEP The action to view a step.
103 */
104 const ACTION_VIEWSTEP = 'viewstep';
105
106 /**
107 * @var ACTION_HIDETOUR The action to hide a tour.
108 */
109 const ACTION_HIDETOUR = 'hidetour';
110
111 /**
112 * @var ACTION_SHOWTOUR The action to show a tour.
113 */
114 const ACTION_SHOWTOUR = 'showtour';
115
116 /**
117 * @var ACTION_RESETFORALL
118 */
119 const ACTION_RESETFORALL = 'resetforall';
120
3eb3d916
RW
121 /**
122 * @var CONFIG_SHIPPED_TOUR
123 */
124 const CONFIG_SHIPPED_TOUR = 'shipped_tour';
125
126 /**
127 * @var CONFIG_SHIPPED_FILENAME
128 */
129 const CONFIG_SHIPPED_FILENAME = 'shipped_filename';
130
131 /**
132 * @var CONFIG_SHIPPED_VERSION
133 */
134 const CONFIG_SHIPPED_VERSION = 'shipped_version';
135
001fc061
AN
136 /**
137 * This is the entry point for this controller class.
138 *
139 * @param string $action The action to perform.
140 */
141 public function execute($action) {
142 admin_externalpage_setup('tool_usertours/tours');
143 // Add the main content.
144 switch($action) {
145 case self::ACTION_NEWTOUR:
146 case self::ACTION_EDITTOUR:
147 $this->edit_tour(optional_param('id', null, PARAM_INT));
148 break;
149
150 case self::ACTION_MOVETOUR:
151 $this->move_tour(required_param('id', PARAM_INT));
152 break;
153
154 case self::ACTION_EXPORTTOUR:
155 $this->export_tour(required_param('id', PARAM_INT));
156 break;
157
158 case self::ACTION_IMPORTTOUR:
159 $this->import_tour();
160 break;
161
162 case self::ACTION_VIEWTOUR:
163 $this->view_tour(required_param('id', PARAM_INT));
164 break;
165
166 case self::ACTION_HIDETOUR:
167 $this->hide_tour(required_param('id', PARAM_INT));
168 break;
169
170 case self::ACTION_SHOWTOUR:
171 $this->show_tour(required_param('id', PARAM_INT));
172 break;
173
174 case self::ACTION_DELETETOUR:
175 $this->delete_tour(required_param('id', PARAM_INT));
176 break;
177
178 case self::ACTION_RESETFORALL:
179 $this->reset_tour_for_all(required_param('id', PARAM_INT));
180 break;
181
182 case self::ACTION_NEWSTEP:
183 case self::ACTION_EDITSTEP:
184 $this->edit_step(optional_param('id', null, PARAM_INT));
185 break;
186
187 case self::ACTION_MOVESTEP:
188 $this->move_step(required_param('id', PARAM_INT));
189 break;
190
191 case self::ACTION_DELETESTEP:
192 $this->delete_step(required_param('id', PARAM_INT));
193 break;
194
195 case self::ACTION_LISTTOURS:
196 default:
197 $this->print_tour_list();
198 break;
199 }
200 }
201
202 /**
203 * Print out the page header.
204 *
205 * @param string $title The title to display.
206 */
207 protected function header($title = null) {
208 global $OUTPUT;
209
210 // Print the page heading.
211 echo $OUTPUT->header();
212
213 if ($title === null) {
214 $title = get_string('tours', 'tool_usertours');
215 }
216
217 echo $OUTPUT->heading($title);
218 }
219
220 /**
221 * Print out the page footer.
222 *
223 * @return void
224 */
225 protected function footer() {
226 global $OUTPUT;
227
228 echo $OUTPUT->footer();
229 }
230
231 /**
232 * Print the the list of tours.
233 */
234 protected function print_tour_list() {
235 global $PAGE, $OUTPUT;
236
237 $this->header();
238 echo \html_writer::span(get_string('tourlist_explanation', 'tool_usertours'));
239 $table = new table\tour_list();
240 $tours = helper::get_tours();
241 foreach ($tours as $tour) {
242 $table->add_data_keyed($table->format_row($tour));
243 }
244
245 $table->finish_output();
246 $actions = [
247 (object) [
248 'link' => helper::get_edit_tour_link(),
249 'linkproperties' => [],
250 'img' => 'b/tour-new',
251 'title' => get_string('newtour', 'tool_usertours'),
252 ],
253 (object) [
254 'link' => helper::get_import_tour_link(),
255 'linkproperties' => [],
256 'img' => 'b/tour-import',
257 'title' => get_string('importtour', 'tool_usertours'),
258 ],
259 (object) [
592c691c 260 'link' => new \moodle_url('https://moodle.net/tours'),
001fc061
AN
261 'linkproperties' => [
262 'target' => '_blank',
263 ],
264 'img' => 'b/tour-shared',
265 'title' => get_string('sharedtourslink', 'tool_usertours'),
266 ],
267 ];
268
269 echo \html_writer::start_tag('div', [
270 'class' => 'tour-actions',
271 ]);
272
273 echo \html_writer::start_tag('ul');
274 foreach ($actions as $config) {
275 $action = \html_writer::start_tag('li');
276 $linkproperties = $config->linkproperties;
277 $linkproperties['href'] = $config->link;
278 $action .= \html_writer::start_tag('a', $linkproperties);
663640f5 279 $action .= $OUTPUT->pix_icon($config->img, $config->title, 'tool_usertours');
001fc061
AN
280 $action .= \html_writer::div($config->title);
281 $action .= \html_writer::end_tag('a');
282 $action .= \html_writer::end_tag('li');
283 echo $action;
284 }
285 echo \html_writer::end_tag('ul');
286 echo \html_writer::end_tag('div');
287
288 // JS for Tour management.
289 $PAGE->requires->js_call_amd('tool_usertours/managetours', 'setup');
290 $this->footer();
291 }
292
293 /**
294 * Return the edit tour link.
295 *
296 * @param int $id The ID of the tour
297 * @return string
298 */
299 protected function get_edit_tour_link($id = null) {
300 $addlink = helper::get_edit_tour_link($id);
301 return \html_writer::link($addlink, get_string('newtour', 'tool_usertours'));
302 }
303
304 /**
305 * Print the edit tour link.
306 *
307 * @param int $id The ID of the tour
308 */
309 protected function print_edit_tour_link($id = null) {
310 echo $this->get_edit_tour_link($id);
311 }
312
313 /**
314 * Get the import tour link.
315 *
316 * @return string
317 */
318 protected function get_import_tour_link() {
319 $importlink = helper::get_import_tour_link();
320 return \html_writer::link($importlink, get_string('importtour', 'tool_usertours'));
321 }
322
323 /**
324 * Print the edit tour page.
325 *
326 * @param int $id The ID of the tour
327 */
328 protected function edit_tour($id = null) {
329 global $PAGE;
330 if ($id) {
331 $tour = tour::instance($id);
332 $PAGE->navbar->add($tour->get_name(), $tour->get_edit_link());
333
334 } else {
335 $tour = new tour();
336 $PAGE->navbar->add(get_string('newtour', 'tool_usertours'), $tour->get_edit_link());
337 }
338
339 $form = new forms\edittour($tour);
340
341 if ($form->is_cancelled()) {
342 redirect(helper::get_list_tour_link());
343 } else if ($data = $form->get_data()) {
344 // Creating a new tour.
345 $tour->set_name($data->name);
346 $tour->set_description($data->description);
347 $tour->set_pathmatch($data->pathmatch);
348 $tour->set_enabled(!empty($data->enabled));
349
350 foreach (configuration::get_defaultable_keys() as $key) {
351 $tour->set_config($key, $data->$key);
352 }
353
354 // Save filter values.
355 foreach (helper::get_all_filters() as $filterclass) {
356 $filterclass::save_filter_values_from_form($tour, $data);
357 }
358
359 $tour->persist();
360
361 redirect(helper::get_list_tour_link());
362 } else {
363 if (empty($tour)) {
364 $this->header('newtour');
365 } else {
3eb3d916
RW
366 if (!empty($tour->get_config(self::CONFIG_SHIPPED_TOUR))) {
367 notification::add(get_string('modifyshippedtourwarning', 'tool_usertours'), notification::WARNING);
368 }
369
001fc061
AN
370 $this->header($tour->get_name());
371 $data = $tour->prepare_data_for_form();
372
373 // Prepare filter values for the form.
374 foreach (helper::get_all_filters() as $filterclass) {
375 $filterclass::prepare_filter_values_for_form($tour, $data);
376 }
377 $form->set_data($data);
378 }
379
380 $form->display();
381 $this->footer();
382 }
383 }
384
385 /**
386 * Print the export tour page.
387 *
388 * @param int $id The ID of the tour
389 */
390 protected function export_tour($id) {
391 $tour = tour::instance($id);
392
393 // Grab the full data record.
394 $export = $tour->to_record();
395
396 // Remove the id.
397 unset($export->id);
398
399 // Set the version.
400 $export->version = get_config('tool_usertours', 'version');
401
402 // Step export.
403 $export->steps = [];
404 foreach ($tour->get_steps() as $step) {
405 $record = $step->to_record();
406 unset($record->id);
407 unset($record->tourid);
408
409 $export->steps[] = $record;
410 }
411
412 $exportstring = json_encode($export);
413
414 $filename = 'tour_export_' . $tour->get_id() . '_' . time() . '.json';
415
416 // Force download.
417 header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
418 header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
419 header('Expires: ' . gmdate('D, d M Y H:i:s', 0) . 'GMT');
420 header('Pragma: no-cache');
421 header('Accept-Ranges: none');
422 header('Content-disposition: attachment; filename=' . $filename);
423 header('Content-length: ' . strlen($exportstring));
424 header('Content-type: text/calendar; charset=utf-8');
425
426 echo $exportstring;
427 die;
428 }
429
430 /**
431 * Handle tour import.
432 */
433 protected function import_tour() {
434 global $PAGE;
435 $PAGE->navbar->add(get_string('importtour', 'tool_usertours'), helper::get_import_tour_link());
436
437 $form = new forms\importtour();
438
439 if ($form->is_cancelled()) {
440 redirect(helper::get_list_tour_link());
441 } else if ($form->get_data()) {
442 // Importing a tour.
443 $tourconfigraw = $form->get_file_content('tourconfig');
444 $tour = self::import_tour_from_json($tourconfigraw);
445
446 redirect($tour->get_view_link());
447 } else {
448 $this->header();
449 $form->display();
450 $this->footer();
451 }
452 }
453
454 /**
455 * Print the view tour page.
456 *
457 * @param int $tourid The ID of the tour to display.
458 */
459 protected function view_tour($tourid) {
460 global $PAGE;
461 $tour = helper::get_tour($tourid);
462
463 $PAGE->navbar->add($tour->get_name(), $tour->get_view_link());
464
465 $this->header($tour->get_name());
466 echo \html_writer::span(get_string('viewtour_info', 'tool_usertours', [
467 'tourname' => $tour->get_name(),
468 'path' => $tour->get_pathmatch(),
469 ]));
470 echo \html_writer::div(get_string('viewtour_edit', 'tool_usertours', [
471 'editlink' => $tour->get_edit_link()->out(),
472 'resetlink' => $tour->get_reset_link()->out(),
473 ]));
474
475 $table = new table\step_list($tourid);
476 foreach ($tour->get_steps() as $step) {
477 $table->add_data_keyed($table->format_row($step));
478 }
479
480 $table->finish_output();
481 $this->print_edit_step_link($tourid);
482
483 // JS for Step management.
484 $PAGE->requires->js_call_amd('tool_usertours/managesteps', 'setup');
485
486 $this->footer();
487 }
488
489 /**
490 * Show the tour.
491 *
492 * @param int $tourid The ID of the tour to display.
493 */
494 protected function show_tour($tourid) {
495 $this->show_hide_tour($tourid, 1);
496 }
497
498 /**
499 * Hide the tour.
500 *
501 * @param int $tourid The ID of the tour to display.
502 */
503 protected function hide_tour($tourid) {
504 $this->show_hide_tour($tourid, 0);
505 }
506
507 /**
508 * Show or Hide the tour.
509 *
510 * @param int $tourid The ID of the tour to display.
511 * @param int $visibility The intended visibility.
512 */
513 protected function show_hide_tour($tourid, $visibility) {
514 global $DB;
515
516 require_sesskey();
517
518 $tour = $DB->get_record('tool_usertours_tours', array('id' => $tourid));
519 $tour->enabled = $visibility;
520 $DB->update_record('tool_usertours_tours', $tour);
521
522 redirect(helper::get_list_tour_link());
523 }
524
525 /**
526 * Delete the tour.
527 *
528 * @param int $tourid The ID of the tour to remove.
529 */
530 protected function delete_tour($tourid) {
531 require_sesskey();
532
533 $tour = tour::instance($tourid);
534 $tour->remove();
535
536 redirect(helper::get_list_tour_link());
537 }
538
539 /**
540 * Reset the tour state for all users.
541 *
542 * @param int $tourid The ID of the tour to remove.
543 */
544 protected function reset_tour_for_all($tourid) {
545 require_sesskey();
546
547 $tour = tour::instance($tourid);
548 $tour->mark_major_change();
549
550 redirect(helper::get_view_tour_link($tourid), get_string('tour_resetforall', 'tool_usertours'));
551 }
552
553 /**
554 * Get the first tour matching the current page URL.
555 *
556 * @param bool $reset Forcibly update the current tour
557 * @return tour
558 */
559 public static function get_current_tour($reset = false) {
560 global $PAGE;
561
562 static $tour = false;
563
564 if ($tour === false || $reset) {
565 $tour = self::get_matching_tours($PAGE->url);
566 }
567
568 return $tour;
569 }
570
571 /**
572 * Get the first tour matching the specified URL.
573 *
574 * @param moodle_url $pageurl The URL to match.
575 * @return tour
576 */
577 public static function get_matching_tours(\moodle_url $pageurl) {
1093e43b 578 global $PAGE;
001fc061 579
c6b44215 580 $tours = cache::get_matching_tourdata($pageurl);
001fc061
AN
581
582 foreach ($tours as $record) {
583 $tour = tour::load_from_record($record);
1093e43b 584 if ($tour->is_enabled() && $tour->matches_all_filters($PAGE->context)) {
001fc061
AN
585 return $tour;
586 }
587 }
588
589 return null;
590 }
591
592 /**
593 * Import the provided tour JSON.
594 *
595 * @param string $json The tour configuration.
596 * @return tour
597 */
598 public static function import_tour_from_json($json) {
599 $tourconfig = json_decode($json);
600
601 // We do not use this yet - we may do in the future.
602 unset($tourconfig->version);
603
604 $steps = $tourconfig->steps;
605 unset($tourconfig->steps);
606
607 $tourconfig->id = null;
608 $tourconfig->sortorder = null;
609 $tour = tour::load_from_record($tourconfig, true);
610 $tour->persist(true);
611
612 // Ensure that steps are orderered by their sortorder.
613 \core_collator::asort_objects_by_property($steps, 'sortorder', \core_collator::SORT_NUMERIC);
614
615 foreach ($steps as $stepconfig) {
616 $stepconfig->id = null;
617 $stepconfig->tourid = $tour->get_id();
618 $step = step::load_from_record($stepconfig, true);
619 $step->persist(true);
620 }
621
622 return $tour;
623 }
624
625 /**
626 * Helper to fetch the renderer.
627 *
628 * @return renderer
629 */
630 protected function get_renderer() {
631 global $PAGE;
632 return $PAGE->get_renderer('tool_usertours');
633 }
634
635 /**
636 * Print the edit step link.
637 *
638 * @param int $tourid The ID of the tour.
639 * @param int $stepid The ID of the step.
640 * @return string
641 */
642 protected function print_edit_step_link($tourid, $stepid = null) {
643 $addlink = helper::get_edit_step_link($tourid, $stepid);
644 $attributes = [];
645 if (empty($stepid)) {
646 $attributes['class'] = 'createstep';
647 }
648 echo \html_writer::link($addlink, get_string('newstep', 'tool_usertours'), $attributes);
649 }
650
651 /**
652 * Display the edit step form for the specified step.
653 *
654 * @param int $id The step to edit.
655 */
656 protected function edit_step($id) {
657 global $PAGE;
658
659 if (isset($id)) {
660 $step = step::instance($id);
661 } else {
662 $step = new step();
663 $step->set_tourid(required_param('tourid', PARAM_INT));
664 }
665
666 $tour = $step->get_tour();
3eb3d916
RW
667
668 if (!empty($tour->get_config(self::CONFIG_SHIPPED_TOUR))) {
669 notification::add(get_string('modifyshippedtourwarning', 'tool_usertours'), notification::WARNING);
670 }
671
001fc061
AN
672 $PAGE->navbar->add($tour->get_name(), $tour->get_view_link());
673 if (isset($id)) {
674 $PAGE->navbar->add($step->get_title(), $step->get_edit_link());
675 } else {
676 $PAGE->navbar->add(get_string('newstep', 'tool_usertours'), $step->get_edit_link());
677 }
678
679 $form = new forms\editstep($step->get_edit_link(), $step);
680 if ($form->is_cancelled()) {
681 redirect($step->get_tour()->get_view_link());
682 } else if ($data = $form->get_data()) {
683 $step->handle_form_submission($form, $data);
684 $step->get_tour()->reset_step_sortorder();
685 redirect($step->get_tour()->get_view_link());
686 } else {
687 if (empty($id)) {
688 $this->header(get_string('newstep', 'tool_usertours'));
689 } else {
690 $this->header(get_string('editstep', 'tool_usertours', $step->get_title()));
691 }
692 $form->set_data($step->prepare_data_for_form());
693
694 $form->display();
695 $this->footer();
696 }
697 }
698
699 /**
fbb21961 700 * Move a tour up or down and redirect once complete.
001fc061
AN
701 *
702 * @param int $id The tour to move.
703 */
704 protected function move_tour($id) {
705 require_sesskey();
706
707 $direction = required_param('direction', PARAM_INT);
708
709 $tour = tour::instance($id);
fbb21961
ED
710 self::_move_tour($tour, $direction);
711
712 redirect(helper::get_list_tour_link());
713 }
714
715 /**
716 * Move a tour up or down.
717 *
718 * @param tour $tour The tour to move.
719 *
720 * @param int $direction
721 */
722 protected static function _move_tour(tour $tour, $direction) {
001fc061
AN
723 $currentsortorder = $tour->get_sortorder();
724 $targetsortorder = $currentsortorder + $direction;
725
726 $swapwith = helper::get_tour_from_sortorder($targetsortorder);
727
728 // Set the sort order to something out of the way.
729 $tour->set_sortorder(-1);
730 $tour->persist();
731
732 // Swap the two sort orders.
733 $swapwith->set_sortorder($currentsortorder);
734 $swapwith->persist();
735
736 $tour->set_sortorder($targetsortorder);
737 $tour->persist();
001fc061
AN
738 }
739
740 /**
741 * Move a step up or down.
742 *
743 * @param int $id The step to move.
744 */
745 protected function move_step($id) {
746 require_sesskey();
747
748 $direction = required_param('direction', PARAM_INT);
749
750 $step = step::instance($id);
751 $currentsortorder = $step->get_sortorder();
752 $targetsortorder = $currentsortorder + $direction;
753
754 $tour = $step->get_tour();
755 $swapwith = helper::get_step_from_sortorder($tour->get_id(), $targetsortorder);
756
757 // Set the sort order to something out of the way.
758 $step->set_sortorder(-1);
759 $step->persist();
760
761 // Swap the two sort orders.
762 $swapwith->set_sortorder($currentsortorder);
763 $swapwith->persist();
764
765 $step->set_sortorder($targetsortorder);
766 $step->persist();
767
768 // Reset the sort order.
769 $tour->reset_step_sortorder();
770 redirect($tour->get_view_link());
771 }
772
773 /**
774 * Delete the step.
775 *
776 * @param int $stepid The ID of the step to remove.
777 */
778 protected function delete_step($stepid) {
779 require_sesskey();
780
781 $step = step::instance($stepid);
782 $tour = $step->get_tour();
783
784 $step->remove();
785 redirect($tour->get_view_link());
786 }
3eb3d916
RW
787
788 /**
789 * Make sure all of the default tours that are shipped with Moodle are created
790 * and up to date with the latest version.
791 */
792 public static function update_shipped_tours() {
793 global $DB, $CFG;
794
795 // A list of tours that are shipped with Moodle. They are in
796 // the format filename => version. The version value needs to
797 // be increased if the tour has been updated.
10df630e 798 $shippedtours = [
8ca99a92 799 '36_dashboard.json' => 3
fbb21961
ED
800 ];
801
802 // These are tours that we used to ship but don't ship any longer.
803 // We do not remove them, but we do disable them.
804 $unshippedtours = [
10df630e
RW
805 'boost_administrator.json' => 1,
806 'boost_course_view.json' => 1,
807 ];
3eb3d916 808
8ca99a92
MN
809 if ($CFG->messaging) {
810 $shippedtours['36_messaging.json'] = 3;
811 } else {
812 $unshippedtours['36_messaging.json'] = 3;
813 }
814
3eb3d916
RW
815 $existingtourrecords = $DB->get_recordset('tool_usertours_tours');
816
817 // Get all of the existing shipped tours and check if they need to be
818 // updated.
819 foreach ($existingtourrecords as $tourrecord) {
820 $tour = tour::load_from_record($tourrecord);
821
822 if (!empty($tour->get_config(self::CONFIG_SHIPPED_TOUR))) {
823 $filename = $tour->get_config(self::CONFIG_SHIPPED_FILENAME);
824 $version = $tour->get_config(self::CONFIG_SHIPPED_VERSION);
825
826 // If we know about this tour (otherwise leave it as is).
827 if (isset($shippedtours[$filename])) {
828 // And the version in the DB is an older version.
829 if ($version < $shippedtours[$filename]) {
830 // Remove the old version because it's been updated
831 // and needs to be recreated.
832 $tour->remove();
833 } else {
834 // The tour has not been updated so we don't need to
835 // do anything with it.
836 unset($shippedtours[$filename]);
837 }
838 }
fbb21961
ED
839
840 if (isset($unshippedtours[$filename])) {
841 if ($version <= $unshippedtours[$filename]) {
84dad5bf 842 $tour = tour::instance($tour->get_id());
fbb21961
ED
843 $tour->set_enabled(tour::DISABLED);
844 $tour->persist();
845 }
846 }
3eb3d916
RW
847 }
848 }
3eb3d916
RW
849 $existingtourrecords->close();
850
fbb21961 851 foreach (array_reverse($shippedtours) as $filename => $version) {
7ccb6bb3 852 $filepath = $CFG->dirroot . "/{$CFG->admin}/tool/usertours/tours/" . $filename;
3eb3d916
RW
853 $tourjson = file_get_contents($filepath);
854 $tour = self::import_tour_from_json($tourjson);
855
856 // Set some additional config data to record that this tour was
857 // added as a shipped tour.
858 $tour->set_config(self::CONFIG_SHIPPED_TOUR, true);
859 $tour->set_config(self::CONFIG_SHIPPED_FILENAME, $filename);
860 $tour->set_config(self::CONFIG_SHIPPED_VERSION, $version);
861
fbb21961
ED
862 // Bump new tours to the top of the list.
863 while ($tour->get_sortorder() > 0) {
864 self::_move_tour($tour, helper::MOVE_UP);
865 }
866
3eb3d916
RW
867 if (defined('BEHAT_SITE_RUNNING') || (defined('PHPUNIT_TEST') && PHPUNIT_TEST)) {
868 // Disable this tour if this is behat or phpunit.
869 $tour->set_enabled(false);
870 }
871
872 $tour->persist();
873 }
874 }
001fc061 875}