Merge branch 'MDL-52777-master' of git://github.com/andrewnicols/moodle
@@ -3,6 +3,8 @@
|
||||
*/**/build/
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
auth/fc/fcFPP.php
|
||||
enrol/lti/ims-blti/
|
||||
|
||||
@@ -4,6 +4,8 @@ theme/clean/style/custom.css
|
||||
theme/more/style/custom.css
|
||||
node_modules/
|
||||
vendor/
|
||||
admin/tool/usertours/amd/src/tour.js
|
||||
admin/tool/usertours/amd/src/popper.js
|
||||
auth/cas/CAS/
|
||||
auth/fc/fcFPP.php
|
||||
enrol/lti/ims-blti/
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
define(["jquery","core/str","core/notification"],function(a,b,c){var d={removeStep:function(d){d.preventDefault(),b.get_strings([{key:"confirmstepremovaltitle",component:"tool_usertours"},{key:"confirmstepremovalquestion",component:"tool_usertours"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).done(function(b){c.confirm(b[0],b[1],b[2],b[3],a.proxy(function(){window.location=a(this).attr("href")},d.currentTarget))})},setup:function(){a("body").delegate('[data-action="delete"]',"click",d.removeStep)}};return{setup:d.setup}});
|
||||
@@ -0,0 +1 @@
|
||||
define(["jquery","core/ajax","core/str","core/notification"],function(a,b,c,d){var e={removeTour:function(b){b.preventDefault(),c.get_strings([{key:"confirmtourremovaltitle",component:"tool_usertours"},{key:"confirmtourremovalquestion",component:"tool_usertours"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],a.proxy(function(){window.location=a(this).attr("href")},b.currentTarget))})},setup:function(){a("body").delegate('[data-action="delete"]',"click",e.removeTour)}};return{setup:e.setup}});
|
||||
@@ -0,0 +1 @@
|
||||
define(["core/ajax","tool_usertours/tour","jquery","core/templates","core/str","core/log","core/notification"],function(a,b,c,d,e,f,g){var h={tourId:null,currentTour:null,context:null,init:function(a,b,d){h.tourId=a,h.context=d,"undefined"==typeof b&&(b=!0),b&&h.fetchTour(a),h.addResetLink(),c("body").on("click",'[data-action="tool_usertours/resetpagetour"]',function(a){a.preventDefault(),h.resetTourState(h.tourId)})},fetchTour:function(b){c.when(a.call([{methodname:"tool_usertours_fetch_and_start_tour",args:{tourid:b,context:h.context,pageurl:window.location.href}}])[0],d.render("tool_usertours/tourstep",{})).then(function(a,c){h.startBootstrapTour(b,c[0],a.tourconfig)}).fail(g.exception)},addResetLink:function(){e.get_string("resettouronpage","tool_usertours").done(function(a){c("footer, .logininfo").last().append('<div class="usertour"><a href="#" data-action="tool_usertours/resetpagetour">'+a+"</a></div>")})},startBootstrapTour:function(a,c,d){h.currentTour&&(d.onEnd=null,h.currentTour.endTour(),delete h.currentTour),d.eventHandlers={afterEnd:[h.markTourComplete],afterRender:[h.markStepShown]},d.tourName=d.name,delete d.name,d.template=c,d.steps=d.steps.map(function(a){return"undefined"!=typeof a.element&&(a.target=a.element,delete a.element),"undefined"!=typeof a.reflex&&(a.moveOnClick=!!a.reflex,delete a.reflex),"undefined"!=typeof a.content&&(a.body=a.content,delete a.content),a}),h.currentTour=new b(d),h.currentTour.startTour()},markStepShown:function(){var b=this.getStepConfig(this.getCurrentStepNumber());c.when(a.call([{methodname:"tool_usertours_step_shown",args:{tourid:h.tourId,context:h.context,pageurl:window.location.href,stepid:b.stepid,stepindex:this.getCurrentStepNumber()}}])[0]).fail(f.error)},markTourComplete:function(){var b=this.getStepConfig(this.getCurrentStepNumber());c.when(a.call([{methodname:"tool_usertours_complete_tour",args:{tourid:h.tourId,context:h.context,pageurl:window.location.href,stepid:b.stepid,stepindex:this.getCurrentStepNumber()}}])[0]).fail(f.error)},resetTourState:function(b){c.when(a.call([{methodname:"tool_usertours_reset_tour",args:{tourid:b,context:h.context,pageurl:window.location.href}}])[0]).then(function(a){a.startTour&&h.fetchTour(a.startTour)}).fail(g.exception)}};return{init:h.init,resetTourState:h.resetTourState}});
|
||||
@@ -0,0 +1,17 @@
|
||||
Description of External library imports into Moodle
|
||||
|
||||
Flexitour Instructions
|
||||
----------------------
|
||||
1. Clone https://github.com/andrewnicols/flexitour into an unrelated directory
|
||||
2. Copy /build/tour.js to amd/src/tour.js
|
||||
3. Open the amd/src/tour.js file and find the AMD module define.
|
||||
4. Change the "popper" inclusion to "./popper"
|
||||
5. Update thirdpartylibs.xml
|
||||
6. Run `grunt amd`
|
||||
|
||||
Popper.js Instructions
|
||||
----------------------
|
||||
1. Clone https://github.com/FezVrasta/popper.js into an unrelated directory
|
||||
2. Copy /build/popper.js to amd/src/popper.js
|
||||
3. Update thirdpartylibs.xml
|
||||
4. Run `grunt amd`
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Step management code.
|
||||
*
|
||||
* @module tool_usertours/managesteps
|
||||
* @class managesteps
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
*/
|
||||
define(
|
||||
['jquery', 'core/str', 'core/notification'],
|
||||
function($, str, notification) {
|
||||
var manager = {
|
||||
/**
|
||||
* Confirm removal of the specified step.
|
||||
*
|
||||
* @method removeStep
|
||||
* @param {EventFacade} e The EventFacade
|
||||
*/
|
||||
removeStep: function(e) {
|
||||
e.preventDefault();
|
||||
str.get_strings([
|
||||
{
|
||||
key: 'confirmstepremovaltitle',
|
||||
component: 'tool_usertours'
|
||||
},
|
||||
{
|
||||
key: 'confirmstepremovalquestion',
|
||||
component: 'tool_usertours'
|
||||
},
|
||||
{
|
||||
key: 'yes',
|
||||
component: 'moodle'
|
||||
},
|
||||
{
|
||||
key: 'no',
|
||||
component: 'moodle'
|
||||
}
|
||||
]).done(function(s) {
|
||||
notification.confirm(s[0], s[1], s[2], s[3], $.proxy(function() {
|
||||
window.location = $(this).attr('href');
|
||||
}, e.currentTarget));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup the step management UI.
|
||||
*
|
||||
* @method setup
|
||||
*/
|
||||
setup: function() {
|
||||
|
||||
$('body').delegate('[data-action="delete"]', 'click', manager.removeStep);
|
||||
}
|
||||
};
|
||||
|
||||
return /** @alias module:tool_usertours/managesteps */ {
|
||||
/**
|
||||
* Setup the step management UI.
|
||||
*
|
||||
* @method setup
|
||||
*/
|
||||
setup: manager.setup
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Tour management code.
|
||||
*
|
||||
* @module tool_usertours/managetours
|
||||
* @class managetours
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
*/
|
||||
define(
|
||||
['jquery', 'core/ajax', 'core/str', 'core/notification'],
|
||||
function($, ajax, str, notification) {
|
||||
var manager = {
|
||||
/**
|
||||
* Confirm removal of the specified tour.
|
||||
*
|
||||
* @method removeTour
|
||||
* @param {EventFacade} e The EventFacade
|
||||
*/
|
||||
removeTour: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
str.get_strings([
|
||||
{
|
||||
key: 'confirmtourremovaltitle',
|
||||
component: 'tool_usertours'
|
||||
},
|
||||
{
|
||||
key: 'confirmtourremovalquestion',
|
||||
component: 'tool_usertours'
|
||||
},
|
||||
{
|
||||
key: 'yes',
|
||||
component: 'moodle'
|
||||
},
|
||||
{
|
||||
key: 'no',
|
||||
component: 'moodle'
|
||||
}
|
||||
]).done(function(s) {
|
||||
notification.confirm(s[0], s[1], s[2], s[3], $.proxy(function() {
|
||||
window.location = $(this).attr('href');
|
||||
}, e.currentTarget));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup the tour management UI.
|
||||
*
|
||||
* @method setup
|
||||
*/
|
||||
setup: function() {
|
||||
$('body').delegate('[data-action="delete"]', 'click', manager.removeTour);
|
||||
}
|
||||
};
|
||||
|
||||
return /** @alias module:tool_usertours/managetours */ {
|
||||
/**
|
||||
* Setup the tour management UI.
|
||||
*
|
||||
* @method setup
|
||||
*/
|
||||
setup: manager.setup
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* User tour control library.
|
||||
*
|
||||
* @module tool_usertours/usertours
|
||||
* @class usertours
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
*/
|
||||
define(
|
||||
['core/ajax', 'tool_usertours/tour', 'jquery', 'core/templates', 'core/str', 'core/log', 'core/notification'],
|
||||
function(ajax, BootstrapTour, $, templates, str, log, notification) {
|
||||
var usertours = {
|
||||
tourId: null,
|
||||
|
||||
currentTour: null,
|
||||
|
||||
context: null,
|
||||
|
||||
/**
|
||||
* Initialise the user tour for the current page.
|
||||
*
|
||||
* @method init
|
||||
* @param {Number} tourId The ID of the tour to start.
|
||||
* @param {Bool} startTour Attempt to start the tour now.
|
||||
* @param {Number} context The context of the current page.
|
||||
*/
|
||||
init: function(tourId, startTour, context) {
|
||||
// Only one tour per page is allowed.
|
||||
usertours.tourId = tourId;
|
||||
|
||||
usertours.context = context;
|
||||
|
||||
if (typeof startTour === 'undefined') {
|
||||
startTour = true;
|
||||
}
|
||||
|
||||
if (startTour) {
|
||||
// Fetch the tour configuration.
|
||||
usertours.fetchTour(tourId);
|
||||
}
|
||||
|
||||
usertours.addResetLink();
|
||||
// Watch for the reset link.
|
||||
$('body').on('click', '[data-action="tool_usertours/resetpagetour"]', function(e) {
|
||||
e.preventDefault();
|
||||
usertours.resetTourState(usertours.tourId);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch the configuration specified tour, and start the tour when it has been fetched.
|
||||
*
|
||||
* @method fetchTour
|
||||
* @param {Number} tourId The ID of the tour to start.
|
||||
*/
|
||||
fetchTour: function(tourId) {
|
||||
$.when(
|
||||
ajax.call([
|
||||
{
|
||||
methodname: 'tool_usertours_fetch_and_start_tour',
|
||||
args: {
|
||||
tourid: tourId,
|
||||
context: usertours.context,
|
||||
pageurl: window.location.href,
|
||||
}
|
||||
}
|
||||
])[0],
|
||||
templates.render('tool_usertours/tourstep', {})
|
||||
).then(function(response, template) {
|
||||
usertours.startBootstrapTour(tourId, template[0], response.tourconfig);
|
||||
}).fail(notification.exception);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a reset link to the page.
|
||||
*
|
||||
* @method addResetLink
|
||||
*/
|
||||
addResetLink: function() {
|
||||
str.get_string('resettouronpage', 'tool_usertours')
|
||||
.done(function(s) {
|
||||
// Grab the last item in the page of these.
|
||||
$('footer, .logininfo')
|
||||
.last()
|
||||
.append(
|
||||
'<div class="usertour">' +
|
||||
'<a href="#" data-action="tool_usertours/resetpagetour">' +
|
||||
s +
|
||||
'</a>' +
|
||||
'</div>'
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Start the specified tour.
|
||||
*
|
||||
* @method startBootstrapTour
|
||||
* @param {Number} tourId The ID of the tour to start.
|
||||
* @param {String} template The template to use.
|
||||
* @param {Object} tourConfig The tour configuration.
|
||||
*/
|
||||
startBootstrapTour: function(tourId, template, tourConfig) {
|
||||
if (usertours.currentTour) {
|
||||
// End the current tour, but disable end tour handler.
|
||||
tourConfig.onEnd = null;
|
||||
usertours.currentTour.endTour();
|
||||
delete usertours.currentTour;
|
||||
}
|
||||
|
||||
// Normalize for the new library.
|
||||
tourConfig.eventHandlers = {
|
||||
afterEnd: [usertours.markTourComplete],
|
||||
afterRender: [usertours.markStepShown],
|
||||
};
|
||||
|
||||
// Sort out the tour name.
|
||||
tourConfig.tourName = tourConfig.name;
|
||||
delete tourConfig.name;
|
||||
|
||||
// Add the template to the configuration.
|
||||
// This enables translations of the buttons.
|
||||
tourConfig.template = template;
|
||||
|
||||
tourConfig.steps = tourConfig.steps.map(function(step) {
|
||||
if (typeof step.element !== 'undefined') {
|
||||
step.target = step.element;
|
||||
delete step.element;
|
||||
}
|
||||
|
||||
if (typeof step.reflex !== 'undefined') {
|
||||
step.moveOnClick = !!step.reflex;
|
||||
delete step.reflex;
|
||||
}
|
||||
|
||||
if (typeof step.content !== 'undefined') {
|
||||
step.body = step.content;
|
||||
delete step.content;
|
||||
}
|
||||
|
||||
return step;
|
||||
});
|
||||
|
||||
usertours.currentTour = new BootstrapTour(tourConfig);
|
||||
usertours.currentTour.startTour();
|
||||
},
|
||||
|
||||
/**
|
||||
* Mark the specified step as being shownd by the user.
|
||||
*
|
||||
* @method markStepShown
|
||||
*/
|
||||
markStepShown: function() {
|
||||
var stepConfig = this.getStepConfig(this.getCurrentStepNumber());
|
||||
$.when(
|
||||
ajax.call([
|
||||
{
|
||||
methodname: 'tool_usertours_step_shown',
|
||||
args: {
|
||||
tourid: usertours.tourId,
|
||||
context: usertours.context,
|
||||
pageurl: window.location.href,
|
||||
stepid: stepConfig.stepid,
|
||||
stepindex: this.getCurrentStepNumber(),
|
||||
}
|
||||
}
|
||||
])[0]
|
||||
).fail(log.error);
|
||||
},
|
||||
|
||||
/**
|
||||
* Mark the specified tour as being completed by the user.
|
||||
*
|
||||
* @method markTourComplete
|
||||
*/
|
||||
markTourComplete: function() {
|
||||
var stepConfig = this.getStepConfig(this.getCurrentStepNumber());
|
||||
$.when(
|
||||
ajax.call([
|
||||
{
|
||||
methodname: 'tool_usertours_complete_tour',
|
||||
args: {
|
||||
tourid: usertours.tourId,
|
||||
context: usertours.context,
|
||||
pageurl: window.location.href,
|
||||
stepid: stepConfig.stepid,
|
||||
stepindex: this.getCurrentStepNumber(),
|
||||
}
|
||||
}
|
||||
])[0]
|
||||
).fail(log.error);
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset the state, and restart the the tour on the current page.
|
||||
*
|
||||
* @method resetTourState
|
||||
* @param {Number} tourId The ID of the tour to start.
|
||||
*/
|
||||
resetTourState: function(tourId) {
|
||||
$.when(
|
||||
ajax.call([
|
||||
{
|
||||
methodname: 'tool_usertours_reset_tour',
|
||||
args: {
|
||||
tourid: tourId,
|
||||
context: usertours.context,
|
||||
pageurl: window.location.href,
|
||||
}
|
||||
}
|
||||
])[0]
|
||||
).then(function(response) {
|
||||
if (response.startTour) {
|
||||
usertours.fetchTour(response.startTour);
|
||||
}
|
||||
}).fail(notification.exception);
|
||||
}
|
||||
};
|
||||
|
||||
return /** @alias module:tool_usertours/usertours */ {
|
||||
/**
|
||||
* Initialise the user tour for the current page.
|
||||
*
|
||||
* @method init
|
||||
* @param {Number} tourId The ID of the tour to start.
|
||||
* @param {Bool} startTour Attempt to start the tour now.
|
||||
*/
|
||||
init: usertours.init,
|
||||
|
||||
/**
|
||||
* Reset the state, and restart the the tour on the current page.
|
||||
*
|
||||
* @method resetTourState
|
||||
* @param {Number} tourId The ID of the tour to restart.
|
||||
*/
|
||||
resetTourState: usertours.resetTourState
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Step configuration detail class.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Step configuration detail class.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class configuration {
|
||||
|
||||
/**
|
||||
* @var TOURDEFAULT
|
||||
*/
|
||||
const TOURDEFAULT = 'usetourdefault';
|
||||
|
||||
/**
|
||||
* Get the list of keys which can be defaulted in the tour.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_defaultable_keys() {
|
||||
return [
|
||||
'placement',
|
||||
'orphan',
|
||||
'backdrop',
|
||||
'reflex',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default value for the specified key.
|
||||
*
|
||||
* @param string $key The key for the specified value
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get_default_value($key) {
|
||||
switch($key) {
|
||||
case 'placement':
|
||||
return 'bottom';
|
||||
case 'orphan':
|
||||
case 'backdrop':
|
||||
case 'reflex':
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default value for the specified key for the step form.
|
||||
*
|
||||
* @param string $key The key for the specified value
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get_step_default_value($key) {
|
||||
switch($key) {
|
||||
case 'placement':
|
||||
case 'orphan':
|
||||
case 'backdrop':
|
||||
case 'reflex':
|
||||
return self::TOURDEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of possible placement options.
|
||||
*
|
||||
* @param string $default The default option.
|
||||
* @return array
|
||||
*/
|
||||
public static function get_placement_options($default = null) {
|
||||
$values = [
|
||||
'top' => get_string('top', 'tool_usertours'),
|
||||
'bottom' => get_string('bottom', 'tool_usertours'),
|
||||
'left' => get_string('left', 'tool_usertours'),
|
||||
'right' => get_string('right', 'tool_usertours'),
|
||||
];
|
||||
|
||||
if ($default === null) {
|
||||
return $values;
|
||||
}
|
||||
|
||||
if (!isset($values[$default])) {
|
||||
$default = self::get_default_value('placement');
|
||||
}
|
||||
|
||||
$values = array_reverse($values, true);
|
||||
$values[self::TOURDEFAULT] = get_string('defaultvalue', 'tool_usertours', $values[$default]);
|
||||
$values = array_reverse($values, true);
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* The tool_usertours step_shown event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\event;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The tool_usertours step_shown event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*
|
||||
* @property-read array $other {
|
||||
* Extra information about the event.
|
||||
*
|
||||
* - int tourid: The id of the tour
|
||||
* - string pageurl: The URL of the page viewing the tour
|
||||
* }
|
||||
*/
|
||||
class step_shown extends \core\event\base {
|
||||
|
||||
/**
|
||||
* Init method.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['crud'] = 'r';
|
||||
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
|
||||
$this->data['objecttable'] = 'tool_usertours_steps';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised general event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('event_step_shown', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom validation.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
* @return void
|
||||
*/
|
||||
protected function validate_data() {
|
||||
parent::validate_data();
|
||||
|
||||
if (!isset($this->other['tourid'])) {
|
||||
throw new \coding_exception('The \'tourid\' value must be set in other.');
|
||||
}
|
||||
|
||||
if (!isset($this->other['stepindex'])) {
|
||||
throw new \coding_exception('The \'stepindex\' value must be set in other.');
|
||||
}
|
||||
|
||||
if (!isset($this->other['pageurl'])) {
|
||||
throw new \coding_exception('The \'pageurl\' value must be set in other.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the information in 'other' to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store any other information this
|
||||
* won't be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return array an array of other values and their corresponding mapping
|
||||
*/
|
||||
public static function get_other_mapping() {
|
||||
return [
|
||||
'pageurl' => \core\event\base::NOT_MAPPED,
|
||||
'tourid' => [
|
||||
'db' => 'tool_usertours_tours',
|
||||
'restore' => \core\event\base::NOT_MAPPED,
|
||||
],
|
||||
'stepindex' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the objectid to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store an objectid this won't
|
||||
* be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return string the name of the restore mapping the objectid links to
|
||||
*/
|
||||
public static function get_objectid_mapping() {
|
||||
return [
|
||||
'db' => 'tool_usertours_steps',
|
||||
'restore' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with id '{$this->userid}' has viewed the tour with id " .
|
||||
"'{$this->other['tourid']}' at step index " .
|
||||
"'{$this->other['stepindex']}' (id '{$this->objectid}') on the page with URL " .
|
||||
"'{$this->other['pageurl']}'.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return \tool_usertours\helper::get_edit_step_link($this->other['tourid'], $this->objectid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* The tool_usertours tour_ended event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\event;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The tool_usertours tour_ended event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*
|
||||
* @property-read array $other {
|
||||
* Extra information about the event.
|
||||
*
|
||||
* - int tourid: The id of the tour
|
||||
* - string pageurl: The URL of the page viewing the tour
|
||||
* }
|
||||
*/
|
||||
class tour_ended extends \core\event\base {
|
||||
|
||||
/**
|
||||
* Init method.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['crud'] = 'c';
|
||||
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
|
||||
$this->data['objecttable'] = 'tool_usertours_tours';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised general event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('event_tour_ended', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom validation.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
* @return void
|
||||
*/
|
||||
protected function validate_data() {
|
||||
parent::validate_data();
|
||||
|
||||
if (!isset($this->other['stepindex'])) {
|
||||
throw new \coding_exception('The \'stepindex\' value must be set in other.');
|
||||
}
|
||||
|
||||
if (!isset($this->other['stepid'])) {
|
||||
throw new \coding_exception('The \'stepid\' value must be set in other.');
|
||||
}
|
||||
|
||||
if (!isset($this->other['pageurl'])) {
|
||||
throw new \coding_exception('The \'pageurl\' value must be set in other.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the information in 'other' to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store any other information this
|
||||
* won't be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return array an array of other values and their corresponding mapping
|
||||
*/
|
||||
public static function get_other_mapping() {
|
||||
return [
|
||||
'stepindex' => \core\event\base::NOT_MAPPED,
|
||||
'stepid' => [
|
||||
'db' => 'tool_usertours_steps',
|
||||
'restore' => \core\event\base::NOT_MAPPED,
|
||||
],
|
||||
'pageurl' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the objectid to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store an objectid this won't
|
||||
* be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return string the name of the restore mapping the objectid links to
|
||||
*/
|
||||
public static function get_objectid_mapping() {
|
||||
return [
|
||||
'db' => 'tool_usertours_tours',
|
||||
'restore' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with id '{$this->userid}' has ended the tour with id " .
|
||||
"'{$this->objectid}' at step index " .
|
||||
"'{$this->other['stepindex']}' (id '{$this->other['stepid']}') on the page with URL " .
|
||||
"'{$this->other['pageurl']}'.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return \tool_usertours\helper::get_view_tour_link($this->objectid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* The tool_usertours tour_reset event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\event;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The tool_usertours tour_reset event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*
|
||||
* @property-read array $other {
|
||||
* Extra information about the event.
|
||||
*
|
||||
* - int tourid: The id of the tour
|
||||
* - string pageurl: The URL of the page viewing the tour
|
||||
* }
|
||||
*/
|
||||
class tour_reset extends \core\event\base {
|
||||
|
||||
/**
|
||||
* Init method.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['crud'] = 'c';
|
||||
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
|
||||
$this->data['objecttable'] = 'tool_usertours_tours';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised general event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('event_tour_reset', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom validation.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
* @return void
|
||||
*/
|
||||
protected function validate_data() {
|
||||
parent::validate_data();
|
||||
|
||||
if (!isset($this->other['pageurl'])) {
|
||||
throw new \coding_exception('The \'pageurl\' value must be set in other.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the information in 'other' to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store any other information this
|
||||
* won't be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return array an array of other values and their corresponding mapping
|
||||
*/
|
||||
public static function get_other_mapping() {
|
||||
return [
|
||||
'pageurl' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the objectid to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store an objectid this won't
|
||||
* be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return string the name of the restore mapping the objectid links to
|
||||
*/
|
||||
public static function get_objectid_mapping() {
|
||||
return [
|
||||
'db' => 'tool_usertours_tours',
|
||||
'restore' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with id " .
|
||||
"'{$this->userid}' has reset the state of tour with id " .
|
||||
"'{$this->objectid}' on the page with URL " .
|
||||
"'{$this->other['pageurl']}'.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return \tool_usertours\helper::get_view_tour_link($this->objectid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* The tool_usertours tour_started event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\event;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The tool_usertours tour_started event.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*
|
||||
* @property-read array $other {
|
||||
* Extra information about the event.
|
||||
*
|
||||
* - int tourid: The id of the tour
|
||||
* - string pageurl: The URL of the page viewing the tour
|
||||
* }
|
||||
*/
|
||||
class tour_started extends \core\event\base {
|
||||
|
||||
/**
|
||||
* Init method.
|
||||
*/
|
||||
protected function init() {
|
||||
$this->data['crud'] = 'r';
|
||||
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
|
||||
$this->data['objecttable'] = 'tool_usertours_tours';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localised general event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name() {
|
||||
return get_string('event_tour_started', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom validation.
|
||||
*
|
||||
* @throws \coding_exception
|
||||
* @return void
|
||||
*/
|
||||
protected function validate_data() {
|
||||
parent::validate_data();
|
||||
|
||||
if (!isset($this->other['pageurl'])) {
|
||||
throw new \coding_exception('The \'pageurl\' value must be set in other.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the information in 'other' to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store any other information this
|
||||
* won't be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return array an array of other values and their corresponding mapping
|
||||
*/
|
||||
public static function get_other_mapping() {
|
||||
return [
|
||||
'pageurl' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used when restoring course logs where it is required that we
|
||||
* map the objectid to it's new value in the new course.
|
||||
*
|
||||
* Does nothing in the base class except display a debugging message warning
|
||||
* the user that the event does not contain the required functionality to
|
||||
* map this information. For events that do not store an objectid this won't
|
||||
* be called, so no debugging message will be displayed.
|
||||
*
|
||||
* @return string the name of the restore mapping the objectid links to
|
||||
*/
|
||||
public static function get_objectid_mapping() {
|
||||
return [
|
||||
'db' => 'tool_usertours_tours',
|
||||
'restore' => \core\event\base::NOT_MAPPED,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-localised event description with id's for admin use only.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return "The user with id '{$this->userid}' " .
|
||||
"has started the tour with id '{$this->objectid}' " .
|
||||
"on the page with URL '{$this->other['pageurl']}'.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns relevant URL.
|
||||
*
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return \tool_usertours\helper::get_view_tour_link($this->objectid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Web Service functions for steps.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use external_api;
|
||||
use external_function_parameters;
|
||||
use external_single_structure;
|
||||
use external_multiple_structure;
|
||||
use external_value;
|
||||
use tool_usertours\tour as tourinstance;
|
||||
use tool_usertours\step;
|
||||
|
||||
/**
|
||||
* Web Service functions for steps.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tour extends external_api {
|
||||
/**
|
||||
* Fetch the tour configuration for the specified tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to fetch.
|
||||
* @param int $context The Context ID of the current page.
|
||||
* @param string $pageurl The path of the current page.
|
||||
* @return array As described in fetch_and_start_tour_returns
|
||||
*/
|
||||
public static function fetch_and_start_tour($tourid, $context, $pageurl) {
|
||||
global $PAGE;
|
||||
|
||||
$params = self::validate_parameters(self::fetch_and_start_tour_parameters(), [
|
||||
'tourid' => $tourid,
|
||||
'context' => $context,
|
||||
'pageurl' => $pageurl,
|
||||
]);
|
||||
|
||||
$context = \context_helper::instance_by_id($params['context']);
|
||||
self::validate_context($context);
|
||||
|
||||
$tour = tourinstance::instance($params['tourid']);
|
||||
if (!$tour->should_show_for_user()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$touroutput = new \tool_usertours\output\tour($tour);
|
||||
|
||||
\tool_usertours\event\tour_started::create([
|
||||
'contextid' => $context->id,
|
||||
'objectid' => $tourid,
|
||||
'other' => [
|
||||
'pageurl' => $pageurl,
|
||||
],
|
||||
])->trigger();
|
||||
|
||||
return [
|
||||
'tourconfig' => $touroutput->export_for_template($PAGE->get_renderer('core')),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters for fetch_and_start_tour.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function fetch_and_start_tour_parameters() {
|
||||
return new external_function_parameters([
|
||||
'tourid' => new external_value(PARAM_INT, 'Tour ID'),
|
||||
'context' => new external_value(PARAM_INT, 'Context ID'),
|
||||
'pageurl' => new external_value(PARAM_URL, 'Page URL'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The return configuration for fetch_and_start_tour.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function fetch_and_start_tour_returns() {
|
||||
return new external_single_structure([
|
||||
'tourconfig' => new external_single_structure([
|
||||
'name' => new external_value(PARAM_RAW, 'Tour Name'),
|
||||
'steps' => new external_multiple_structure(self::step_structure_returns()),
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the specified tour for the current user.
|
||||
*
|
||||
* @param int $tourid The ID of the tour.
|
||||
* @param int $context The Context ID of the current page.
|
||||
* @param string $pageurl The path of the current page requesting the reset.
|
||||
* @return array As described in reset_tour_returns
|
||||
*/
|
||||
public static function reset_tour($tourid, $context, $pageurl) {
|
||||
$params = self::validate_parameters(self::reset_tour_parameters(), [
|
||||
'tourid' => $tourid,
|
||||
'context' => $context,
|
||||
'pageurl' => $pageurl,
|
||||
]);
|
||||
|
||||
$context = \context_helper::instance_by_id($params['context']);
|
||||
self::validate_context($context);
|
||||
|
||||
$tour = tourinstance::instance($params['tourid']);
|
||||
$tour->request_user_reset();
|
||||
|
||||
$result = [];
|
||||
|
||||
if ($tourinstance = \tool_usertours\manager::get_matching_tours(new \moodle_url($params['pageurl']))) {
|
||||
if ($tour->get_id() === $tourinstance->get_id()) {
|
||||
$result['startTour'] = $tour->get_id();
|
||||
|
||||
\tool_usertours\event\tour_reset::create([
|
||||
'contextid' => $context->id,
|
||||
'objectid' => $params['tourid'],
|
||||
'other' => [
|
||||
'pageurl' => $params['pageurl'],
|
||||
],
|
||||
])->trigger();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters for reset_tour.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function reset_tour_parameters() {
|
||||
return new external_function_parameters([
|
||||
'tourid' => new external_value(PARAM_INT, 'Tour ID'),
|
||||
'context' => new external_value(PARAM_INT, 'Context ID'),
|
||||
'pageurl' => new external_value(PARAM_URL, 'Current page location'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The return configuration for reset_tour.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function reset_tour_returns() {
|
||||
return new external_single_structure([
|
||||
'startTour' => new external_value(PARAM_INT, 'Tour ID', VALUE_OPTIONAL),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the specified tour as completed for the current user.
|
||||
*
|
||||
* @param int $tourid The ID of the tour.
|
||||
* @param int $context The Context ID of the current page.
|
||||
* @param string $pageurl The path of the current page.
|
||||
* @param int $stepid The step id
|
||||
* @param int $stepindex The step index
|
||||
* @return array As described in complete_tour_returns
|
||||
*/
|
||||
public static function complete_tour($tourid, $context, $pageurl, $stepid, $stepindex) {
|
||||
$params = self::validate_parameters(self::complete_tour_parameters(), [
|
||||
'tourid' => $tourid,
|
||||
'context' => $context,
|
||||
'pageurl' => $pageurl,
|
||||
'stepid' => $stepid,
|
||||
'stepindex' => $stepindex,
|
||||
]);
|
||||
|
||||
$context = \context_helper::instance_by_id($params['context']);
|
||||
self::validate_context($context);
|
||||
|
||||
$tour = tourinstance::instance($params['tourid']);
|
||||
$tour->mark_user_completed();
|
||||
|
||||
\tool_usertours\event\tour_ended::create([
|
||||
'contextid' => $context->id,
|
||||
'objectid' => $params['tourid'],
|
||||
'other' => [
|
||||
'pageurl' => $params['pageurl'],
|
||||
'stepid' => $params['stepid'],
|
||||
'stepindex' => $params['stepindex'],
|
||||
],
|
||||
])->trigger();
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters for complete_tour.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function complete_tour_parameters() {
|
||||
return new external_function_parameters([
|
||||
'tourid' => new external_value(PARAM_INT, 'Tour ID'),
|
||||
'context' => new external_value(PARAM_INT, 'Context ID'),
|
||||
'pageurl' => new external_value(PARAM_LOCALURL, 'Page URL'),
|
||||
'stepid' => new external_value(PARAM_INT, 'Step ID'),
|
||||
'stepindex' => new external_value(PARAM_INT, 'Step Number'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The return configuration for complete_tour.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function complete_tour_returns() {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the specified toru step as shown for the current user.
|
||||
*
|
||||
* @param int $tourid The ID of the tour.
|
||||
* @param int $context The Context ID of the current page.
|
||||
* @param string $pageurl The path of the current page.
|
||||
* @param int $stepid The step id
|
||||
* @param int $stepindex The step index
|
||||
* @return array As described in complete_tour_returns
|
||||
*/
|
||||
public static function step_shown($tourid, $context, $pageurl, $stepid, $stepindex) {
|
||||
$params = self::validate_parameters(self::step_shown_parameters(), [
|
||||
'tourid' => $tourid,
|
||||
'context' => $context,
|
||||
'pageurl' => $pageurl,
|
||||
'stepid' => $stepid,
|
||||
'stepindex' => $stepindex,
|
||||
]);
|
||||
|
||||
$context = \context_helper::instance_by_id($params['context']);
|
||||
self::validate_context($context);
|
||||
|
||||
$step = step::instance($params['stepid']);
|
||||
if ($step->get_tourid() !== $params['tourid']) {
|
||||
throw new \moodle_exception('Incorrect tour specified.');
|
||||
}
|
||||
|
||||
\tool_usertours\event\step_shown::create([
|
||||
'contextid' => $context->id,
|
||||
'objectid' => $params['stepid'],
|
||||
|
||||
'other' => [
|
||||
'pageurl' => $params['pageurl'],
|
||||
'tourid' => $params['tourid'],
|
||||
'stepindex' => $params['stepindex'],
|
||||
],
|
||||
])->trigger();
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters for step_shown.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function step_shown_parameters() {
|
||||
return new external_function_parameters([
|
||||
'tourid' => new external_value(PARAM_INT, 'Tour ID'),
|
||||
'context' => new external_value(PARAM_INT, 'Context ID'),
|
||||
'pageurl' => new external_value(PARAM_URL, 'Page URL'),
|
||||
'stepid' => new external_value(PARAM_INT, 'Step ID'),
|
||||
'stepindex' => new external_value(PARAM_INT, 'Step Number'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The return configuration for step_shown.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function step_shown_returns() {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard return structure for a step.
|
||||
*
|
||||
* @return external_multiple_structure
|
||||
*/
|
||||
public static function step_structure_returns() {
|
||||
return new external_single_structure([
|
||||
'title' => new external_value(PARAM_RAW,
|
||||
'Step Title'),
|
||||
'content' => new external_value(PARAM_RAW,
|
||||
'Step Content'),
|
||||
'element' => new external_value(PARAM_TEXT,
|
||||
'Step Target'),
|
||||
'placement' => new external_value(PARAM_TEXT,
|
||||
'Step Placement'),
|
||||
'delay' => new external_value(PARAM_INT,
|
||||
'Delay before showing the step (ms)', VALUE_OPTIONAL),
|
||||
'backdrop' => new external_value(PARAM_BOOL,
|
||||
'Whether a backdrop should be used', VALUE_OPTIONAL),
|
||||
'reflex' => new external_value(PARAM_BOOL,
|
||||
'Whether to move to the next step when the target element is clicked', VALUE_OPTIONAL),
|
||||
'orphan' => new external_value(PARAM_BOOL,
|
||||
'Whether to display the step even if it could not be found', VALUE_OPTIONAL),
|
||||
'stepid' => new external_value(PARAM_INT,
|
||||
'The actual ID of the step', VALUE_OPTIONAL),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,523 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tour helper.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Tour helper.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class helper {
|
||||
|
||||
/**
|
||||
* @var MOVE_UP
|
||||
*/
|
||||
const MOVE_UP = -1;
|
||||
|
||||
/**
|
||||
* @var MOVE_DOWN
|
||||
*/
|
||||
const MOVE_DOWN = 1;
|
||||
|
||||
/**
|
||||
* Get the link to edit the step.
|
||||
*
|
||||
* If no stepid is specified, then a link to create a new step is provided. The $targettype must be specified in this case.
|
||||
*
|
||||
* @param int $tourid The tour that the step belongs to.
|
||||
* @param int $stepid The step ID.
|
||||
* @param int $targettype The type of step.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public static function get_edit_step_link($tourid, $stepid = null, $targettype = null) {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php');
|
||||
|
||||
if ($stepid) {
|
||||
$link->param('action', manager::ACTION_EDITSTEP);
|
||||
$link->param('id', $stepid);
|
||||
} else {
|
||||
$link->param('action', manager::ACTION_NEWSTEP);
|
||||
$link->param('tourid', $tourid);
|
||||
}
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to move the tour.
|
||||
*
|
||||
* @param int $tourid The tour ID.
|
||||
* @param int $direction The direction to move in
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public static function get_move_tour_link($tourid, $direction = self::MOVE_DOWN) {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php');
|
||||
|
||||
$link->param('action', manager::ACTION_MOVETOUR);
|
||||
$link->param('id', $tourid);
|
||||
$link->param('direction', $direction);
|
||||
$link->param('sesskey', sesskey());
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to move the step.
|
||||
*
|
||||
* @param int $stepid The step ID.
|
||||
* @param int $direction The direction to move in
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public static function get_move_step_link($stepid, $direction = self::MOVE_DOWN) {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php');
|
||||
|
||||
$link->param('action', manager::ACTION_MOVESTEP);
|
||||
$link->param('id', $stepid);
|
||||
$link->param('direction', $direction);
|
||||
$link->param('sesskey', sesskey());
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link ot create a new step.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to attach this step to.
|
||||
* @param int $targettype The type of target.
|
||||
*
|
||||
* @return moodle_url The required URL.
|
||||
*/
|
||||
public static function get_new_step_link($tourid, $targettype = null) {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php');
|
||||
$link->param('action', manager::ACTION_NEWSTEP);
|
||||
$link->param('tourid', $tourid);
|
||||
$link->param('targettype', $targettype);
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link used to view the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to display.
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_view_tour_link($tourid) {
|
||||
return new \moodle_url('/admin/tool/usertours/configure.php', [
|
||||
'id' => $tourid,
|
||||
'action' => manager::ACTION_VIEWTOUR,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link used to reset the tour state for all users.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to display.
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_reset_tour_for_all_link($tourid) {
|
||||
return new \moodle_url('/admin/tool/usertours/configure.php', [
|
||||
'id' => $tourid,
|
||||
'action' => manager::ACTION_RESETFORALL,
|
||||
'sesskey' => sesskey(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link used to edit the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to edit.
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_edit_tour_link($tourid = null) {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php');
|
||||
|
||||
if ($tourid) {
|
||||
$link->param('action', manager::ACTION_EDITTOUR);
|
||||
$link->param('id', $tourid);
|
||||
} else {
|
||||
$link->param('action', manager::ACTION_NEWTOUR);
|
||||
}
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link used to import the tour.
|
||||
*
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_import_tour_link() {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php', [
|
||||
'action' => manager::ACTION_IMPORTTOUR,
|
||||
]);
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link used to export the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to export.
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_export_tour_link($tourid) {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php', [
|
||||
'action' => manager::ACTION_EXPORTTOUR,
|
||||
'id' => $tourid,
|
||||
]);
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link used to delete the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to delete.
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_delete_tour_link($tourid) {
|
||||
return new \moodle_url('/admin/tool/usertours/configure.php', [
|
||||
'id' => $tourid,
|
||||
'action' => manager::ACTION_DELETETOUR,
|
||||
'sesskey' => sesskey(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link for listing tours.
|
||||
*
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_list_tour_link() {
|
||||
$link = new \moodle_url('/admin/tool/usertours/configure.php');
|
||||
$link->param('action', manager::ACTION_LISTTOURS);
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a filler icon for display in the actions column of a table.
|
||||
*
|
||||
* @param string $url The URL for the icon.
|
||||
* @param string $icon The icon identifier.
|
||||
* @param string $alt The alt text for the icon.
|
||||
* @param string $iconcomponent The icon component.
|
||||
* @param array $options Display options.
|
||||
* @return string
|
||||
*/
|
||||
public static function format_icon_link($url, $icon, $alt, $iconcomponent = 'moodle', $options = array()) {
|
||||
global $OUTPUT;
|
||||
|
||||
return $OUTPUT->action_icon(
|
||||
$url,
|
||||
new \pix_icon($icon, $alt, $iconcomponent, [
|
||||
'title' => $alt,
|
||||
]),
|
||||
null,
|
||||
$options
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a filler icon for display in the actions column of a table.
|
||||
*
|
||||
* @param array $options Display options.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_filler_icon($options = array()) {
|
||||
global $OUTPUT;
|
||||
|
||||
return \html_writer::span(
|
||||
$OUTPUT->pix_icon('t/filler', '', 'tool_usertours', $options),
|
||||
'action-icon'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link for deleting steps.
|
||||
*
|
||||
* @param int $stepid The ID of the step to display.
|
||||
* @return moodle_url The URL.
|
||||
*/
|
||||
public static function get_delete_step_link($stepid) {
|
||||
return new \moodle_url('/admin/tool/usertours/configure.php', [
|
||||
'action' => manager::ACTION_DELETESTEP,
|
||||
'id' => $stepid,
|
||||
'sesskey' => sesskey(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the inplace editable used to edit the tour name.
|
||||
*
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return string
|
||||
*/
|
||||
public static function render_tourname_inplace_editable(tour $tour) {
|
||||
return new \core\output\inplace_editable(
|
||||
'tool_usertours',
|
||||
'tourname',
|
||||
$tour->get_id(),
|
||||
true,
|
||||
\html_writer::link(
|
||||
$tour->get_view_link(),
|
||||
$tour->get_name()
|
||||
),
|
||||
$tour->get_name()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the inplace editable used to edit the tour description.
|
||||
*
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return string
|
||||
*/
|
||||
public static function render_tourdescription_inplace_editable(tour $tour) {
|
||||
return new \core\output\inplace_editable(
|
||||
'tool_usertours',
|
||||
'tourdescription',
|
||||
$tour->get_id(),
|
||||
true,
|
||||
$tour->get_description(),
|
||||
$tour->get_description()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the inplace editable used to edit the tour enable state.
|
||||
*
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return string
|
||||
*/
|
||||
public static function render_tourenabled_inplace_editable(tour $tour) {
|
||||
global $OUTPUT;
|
||||
|
||||
if ($tour->is_enabled()) {
|
||||
$icon = 't/hide';
|
||||
$alt = get_string('disable');
|
||||
$value = 1;
|
||||
} else {
|
||||
$icon = 't/show';
|
||||
$alt = get_string('enable');
|
||||
$value = 0;
|
||||
}
|
||||
|
||||
$editable = new \core\output\inplace_editable(
|
||||
'tool_usertours',
|
||||
'tourenabled',
|
||||
$tour->get_id(),
|
||||
true,
|
||||
$OUTPUT->pix_icon($icon, $alt, 'moodle', [
|
||||
'title' => $alt,
|
||||
]),
|
||||
$value
|
||||
);
|
||||
|
||||
$editable->set_type_toggle();
|
||||
return $editable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the inplace editable used to edit the step name.
|
||||
*
|
||||
* @param step $step The step to edit.
|
||||
* @return string
|
||||
*/
|
||||
public static function render_stepname_inplace_editable(step $step) {
|
||||
return new \core\output\inplace_editable(
|
||||
'tool_usertours',
|
||||
'stepname',
|
||||
$step->get_id(),
|
||||
true,
|
||||
\html_writer::link(
|
||||
$step->get_edit_link(),
|
||||
$step->get_title()
|
||||
),
|
||||
$step->get_title(false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the tours.
|
||||
*
|
||||
* @return stdClass[]
|
||||
*/
|
||||
public static function get_tours() {
|
||||
global $DB;
|
||||
|
||||
$tours = $DB->get_records('tool_usertours_tours', array(), 'sortorder ASC');
|
||||
$return = [];
|
||||
foreach ($tours as $tour) {
|
||||
$return[$tour->id] = tour::load_from_record($tour);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified tour.
|
||||
*
|
||||
* @param int $tourid The tour that the step belongs to.
|
||||
* @return stdClass
|
||||
*/
|
||||
public static function get_tour($tourid) {
|
||||
return tour::instance($tourid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the tour with the specified sortorder.
|
||||
*
|
||||
* @param int $sortorder The sortorder of the tour.
|
||||
* @return tour
|
||||
*/
|
||||
public static function get_tour_from_sortorder($sortorder) {
|
||||
global $DB;
|
||||
|
||||
$tour = $DB->get_record('tool_usertours_tours', array('sortorder' => $sortorder));
|
||||
return tour::load_from_record($tour);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of all tours.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function count_tours() {
|
||||
global $DB;
|
||||
|
||||
return $DB->count_records('tool_usertours_tours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the sortorder for all tours.
|
||||
*/
|
||||
public static function reset_tour_sortorder() {
|
||||
global $DB;
|
||||
$tours = $DB->get_records('tool_usertours_tours', null, 'sortorder ASC, pathmatch DESC', 'id, sortorder');
|
||||
|
||||
$index = 0;
|
||||
foreach ($tours as $tour) {
|
||||
if ($tour->sortorder != $index) {
|
||||
$DB->set_field('tool_usertours_tours', 'sortorder', $index, array('id' => $tour->id));
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the steps in the tour.
|
||||
*
|
||||
* @param int $tourid The tour that the step belongs to.
|
||||
* @return stdClass[]
|
||||
*/
|
||||
public static function get_steps($tourid) {
|
||||
global $DB;
|
||||
|
||||
$order = 'sortorder ASC';
|
||||
|
||||
$steps = $DB->get_records('tool_usertours_steps', array('tourid' => $tourid), $order);
|
||||
$return = [];
|
||||
foreach ($steps as $step) {
|
||||
$return[$step->id] = step::load_from_record($step);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the specified step.
|
||||
*
|
||||
* @param int $stepid The id of the step to fetch.
|
||||
* @return step
|
||||
*/
|
||||
public static function get_step($stepid) {
|
||||
return step::instance($stepid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the step with the specified sortorder.
|
||||
*
|
||||
* @param int $tourid The tour that the step belongs to.
|
||||
* @param int $sortorder The sortorder of the step.
|
||||
* @return step
|
||||
*/
|
||||
public static function get_step_from_sortorder($tourid, $sortorder) {
|
||||
global $DB;
|
||||
|
||||
$step = $DB->get_record('tool_usertours_steps', array('tourid' => $tourid, 'sortorder' => $sortorder));
|
||||
return step::load_from_record($step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle addition of the tour into the current page.
|
||||
*/
|
||||
public static function bootstrap() {
|
||||
global $PAGE;
|
||||
|
||||
if ($tour = manager::get_current_tour()) {
|
||||
$PAGE->requires->js_call_amd('tool_usertours/usertours', 'init', [
|
||||
$tour->get_id(),
|
||||
$tour->should_show_for_user(),
|
||||
$PAGE->context->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the reset link to the current page.
|
||||
*/
|
||||
public static function bootstrap_reset() {
|
||||
if (manager::get_current_tour()) {
|
||||
echo \html_writer::link('', get_string('resettouronpage', 'tool_usertours'), [
|
||||
'data-action' => 'tool_usertours/resetpagetour',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all possible filters.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_all_filters() {
|
||||
$filters = \core_component::get_component_classes_in_namespace('tool_usertours', 'local\filter');
|
||||
$filters = array_keys($filters);
|
||||
|
||||
$filters = array_filter($filters, function($filterclass) {
|
||||
$rc = new \ReflectionClass($filterclass);
|
||||
return $rc->isInstantiable();
|
||||
});
|
||||
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Filter base.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\filter;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\tour;
|
||||
use context;
|
||||
|
||||
/**
|
||||
* Filter base.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class base {
|
||||
/**
|
||||
* Any Value.
|
||||
*/
|
||||
const ANYVALUE = '__ANYVALUE__';
|
||||
|
||||
/**
|
||||
* The name of the filter.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_filter_name() {
|
||||
throw new \coding_exception('get_filter_name() must be defined');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the list of available filter options.
|
||||
*
|
||||
* @return array An array whose keys are the valid options
|
||||
*/
|
||||
public static function get_filter_options() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the filter matches the specified tour and/or context.
|
||||
*
|
||||
* @param tour $tour The tour to check
|
||||
* @param context $context The context to check
|
||||
* @return boolean
|
||||
*/
|
||||
public static function filter_matches(tour $tour, context $context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the form elements for the filter to the supplied form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add filter settings to.
|
||||
*/
|
||||
public static function add_filter_to_form(\MoodleQuickForm &$mform) {
|
||||
$options = [
|
||||
static::ANYVALUE => get_string('all'),
|
||||
];
|
||||
$options += static::get_filter_options();
|
||||
|
||||
$filtername = static::get_filter_name();
|
||||
$key = "filter_{$filtername}";
|
||||
|
||||
$mform->addElement('select', $key, get_string($key, 'tool_usertours'), $options, [
|
||||
'multiple' => true,
|
||||
]);
|
||||
$mform->setDefault($key, static::ANYVALUE);
|
||||
$mform->addHelpButton($key, $key, 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the filter values for the form.
|
||||
*
|
||||
* @param tour $tour The tour to prepare values from
|
||||
* @param stdClass $data The data value
|
||||
* @return stdClass
|
||||
*/
|
||||
public static function prepare_filter_values_for_form(tour $tour, \stdClass $data) {
|
||||
$filtername = static::get_filter_name();
|
||||
|
||||
$key = "filter_{$filtername}";
|
||||
$values = $tour->get_filter_values($filtername);
|
||||
if (empty($values)) {
|
||||
$values = static::ANYVALUE;
|
||||
}
|
||||
$data->$key = $values;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the filter values from the form to the tour.
|
||||
*
|
||||
* @param tour $tour The tour to save values to
|
||||
* @param stdClass $data The data submitted in the form
|
||||
*/
|
||||
public static function save_filter_values_from_form(tour $tour, \stdClass $data) {
|
||||
$filtername = static::get_filter_name();
|
||||
|
||||
$key = "filter_{$filtername}";
|
||||
|
||||
$newvalue = $data->$key;
|
||||
foreach ($data->$key as $value) {
|
||||
if ($value === static::ANYVALUE) {
|
||||
$newvalue = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$tour->set_filter_values($filtername, $newvalue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Theme filter.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\filter;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\tour;
|
||||
use context;
|
||||
|
||||
/**
|
||||
* Theme filter.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class role extends base {
|
||||
/**
|
||||
* The name of the filter.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_filter_name() {
|
||||
return 'role';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the list of available filter options.
|
||||
*
|
||||
* @return array An array whose keys are the valid options
|
||||
* And whose values are the values to display
|
||||
*/
|
||||
public static function get_filter_options() {
|
||||
return role_get_names(null, ROLENAME_ALIAS, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the filter matches the specified tour and/or context.
|
||||
*
|
||||
* @param tour $tour The tour to check
|
||||
* @param context $context The context to check
|
||||
* @return boolean
|
||||
*/
|
||||
public static function filter_matches(tour $tour, context $context) {
|
||||
global $USER;
|
||||
|
||||
$values = $tour->get_filter_values(self::get_filter_name());
|
||||
|
||||
if (empty($values)) {
|
||||
// There are no values configured.
|
||||
// No values means all.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_siteadmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Presence within the array is sufficient. Ignore any value.
|
||||
$values = array_flip($values);
|
||||
|
||||
$cache = \cache::make_from_params(\cache_store::MODE_REQUEST, 'tool_usertours', 'filter_role');
|
||||
$cachekey = "{$USER->id}_{$context->id}";
|
||||
$userroles = $cache->get($cachekey);
|
||||
if ($userroles === false) {
|
||||
$userroles = get_user_roles_with_special($context);
|
||||
$cache->set($cachekey, $userroles);
|
||||
}
|
||||
|
||||
foreach ($userroles as $role) {
|
||||
if (isset($values[$role->roleid])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Theme filter.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\filter;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\tour;
|
||||
use context;
|
||||
|
||||
/**
|
||||
* Theme filter.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class theme extends base {
|
||||
/**
|
||||
* The name of the filter.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_filter_name() {
|
||||
return 'theme';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the list of available filter options.
|
||||
*
|
||||
* @return array An array whose keys are the valid options
|
||||
* And whose values are the values to display
|
||||
*/
|
||||
public static function get_filter_options() {
|
||||
$manager = \core_plugin_manager::instance();
|
||||
$themes = $manager->get_installed_plugins('theme');
|
||||
|
||||
$options = [];
|
||||
foreach (array_keys($themes) as $themename) {
|
||||
try {
|
||||
$theme = \theme_config::load($themename);
|
||||
} catch (Exception $e) {
|
||||
// Bad theme, just skip it for now.
|
||||
continue;
|
||||
}
|
||||
if ($themename !== $theme->name) {
|
||||
// Obsoleted or broken theme, just skip for now.
|
||||
continue;
|
||||
}
|
||||
if ($theme->hidefromselector) {
|
||||
// The theme doesn't want to be shown in the theme selector and as theme
|
||||
// designer mode is switched off we will respect that decision.
|
||||
continue;
|
||||
}
|
||||
$options[$theme->name] = get_string('pluginname', "theme_{$theme->name}");
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the filter matches the specified tour and/or context.
|
||||
*
|
||||
* @param tour $tour The tour to check
|
||||
* @param context $context The context to check
|
||||
* @return boolean
|
||||
*/
|
||||
public static function filter_matches(tour $tour, context $context) {
|
||||
global $PAGE;
|
||||
|
||||
$values = $tour->get_filter_values('theme');
|
||||
|
||||
if (empty($values)) {
|
||||
// There are no values configured.
|
||||
// No values means all.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Presence within the array is sufficient. Ignore any value.
|
||||
$values = array_flip($values);
|
||||
return isset($values[$PAGE->theme->name]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Form for editing steps.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\forms;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
|
||||
/**
|
||||
* Form for editing steps.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class editstep extends \moodleform {
|
||||
/**
|
||||
* @var tool_usertours\step $step
|
||||
*/
|
||||
protected $step;
|
||||
|
||||
/**
|
||||
* Create the edit step form.
|
||||
*
|
||||
* @param string $target The target of the form.
|
||||
* @param step $step The step being editted.
|
||||
*/
|
||||
public function __construct($target, \tool_usertours\step $step) {
|
||||
$this->step = $step;
|
||||
|
||||
parent::__construct($target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form definition.
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
$types = [];
|
||||
foreach (\tool_usertours\target::get_target_types() as $value => $type) {
|
||||
$types[$value] = get_string('target_' . $type, 'tool_usertours');
|
||||
}
|
||||
$mform->addElement('select', 'targettype', get_string('targettype', 'tool_usertours'), $types);
|
||||
|
||||
// The target configuration.
|
||||
foreach (\tool_usertours\target::get_target_types() as $value => $type) {
|
||||
$targetclass = \tool_usertours\target::get_classname($type);
|
||||
$targetclass::add_config_to_form($mform);
|
||||
}
|
||||
|
||||
// Title of the step.
|
||||
$mform->addElement('textarea', 'title', get_string('title', 'tool_usertours'));
|
||||
$mform->addRule('title', get_string('required'), 'required', null, 'client');
|
||||
$mform->setType('title', PARAM_TEXT);
|
||||
$mform->addHelpButton('title', 'title', 'tool_usertours');
|
||||
|
||||
$mform->addElement('textarea', 'content', get_string('content', 'tool_usertours'));
|
||||
$mform->addRule('content', get_string('required'), 'required', null, 'client');
|
||||
$mform->setType('content', PARAM_RAW);
|
||||
$mform->addHelpButton('content', 'content', 'tool_usertours');
|
||||
|
||||
// Add the step configuration.
|
||||
// All step configuration is defined in the step.
|
||||
$this->step->add_config_to_form($mform);
|
||||
|
||||
// And apply any form constraints.
|
||||
foreach (\tool_usertours\target::get_target_types() as $value => $type) {
|
||||
$targetclass = \tool_usertours\target::get_classname($type);
|
||||
$targetclass::add_disabled_constraints_to_form($mform);
|
||||
}
|
||||
|
||||
$this->add_action_buttons();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Form for editing tours.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\forms;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
|
||||
use \tool_usertours\helper;
|
||||
|
||||
/**
|
||||
* Form for editing tours.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class edittour extends \moodleform {
|
||||
/**
|
||||
* @var tool_usertours\tour $tour
|
||||
*/
|
||||
protected $tour;
|
||||
|
||||
/**
|
||||
* Create the edit tour form.
|
||||
*
|
||||
* @param tour $tour The tour being editted.
|
||||
*/
|
||||
public function __construct(\tool_usertours\tour $tour) {
|
||||
$this->tour = $tour;
|
||||
|
||||
parent::__construct($tour->get_edit_link());
|
||||
}
|
||||
|
||||
/**
|
||||
* Form definition.
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
// ID of existing tour.
|
||||
$mform->addElement('hidden', 'id');
|
||||
$mform->setType('id', PARAM_INT);
|
||||
|
||||
// Name of the tour.
|
||||
$mform->addElement('text', 'name', get_string('name', 'tool_usertours'));
|
||||
$mform->addRule('name', get_string('required'), 'required', null, 'client');
|
||||
$mform->setType('name', PARAM_TEXT);
|
||||
|
||||
// Admin-only descriptions.
|
||||
$mform->addElement('textarea', 'description', get_string('description', 'tool_usertours'));
|
||||
$mform->setType('description', PARAM_RAW);
|
||||
|
||||
// Application.
|
||||
$mform->addElement('text', 'pathmatch', get_string('pathmatch', 'tool_usertours'));
|
||||
$mform->setType('pathmatch', PARAM_RAW);
|
||||
$mform->addHelpButton('pathmatch', 'pathmatch', 'tool_usertours');
|
||||
|
||||
$mform->addElement('checkbox', 'enabled', get_string('enabled', 'tool_usertours'));
|
||||
|
||||
// Configuration.
|
||||
$this->tour->add_config_to_form($mform);
|
||||
|
||||
// Filters.
|
||||
$mform->addElement('header', 'filters', get_string('filter_header', 'tool_usertours'));
|
||||
$mform->addElement('static', 'filterhelp', '', get_string('filter_help', 'tool_usertours'));
|
||||
|
||||
foreach (helper::get_all_filters() as $filterclass) {
|
||||
$filterclass::add_filter_to_form($mform);
|
||||
}
|
||||
|
||||
$this->add_action_buttons();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Form for editing tours.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\forms;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
|
||||
/**
|
||||
* Form for importing tours.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class importtour extends \moodleform {
|
||||
/**
|
||||
* Create the import tour form.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct(\tool_usertours\helper::get_import_tour_link());
|
||||
}
|
||||
|
||||
/**
|
||||
* Form definition.
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
$mform->addElement('filepicker', 'tourconfig', get_string('tourconfig', 'tool_usertours'));
|
||||
$mform->addRule('tourconfig', null, 'required');
|
||||
|
||||
$this->add_action_buttons();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Table to show the list of steps in a tour.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\table;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\helper;
|
||||
use tool_usertours\tour;
|
||||
use tool_usertours\step;
|
||||
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
/**
|
||||
* Table to show the list of steps in a tour.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class step_list extends \flexible_table {
|
||||
|
||||
/**
|
||||
* @var int $tourid The id of the tour.
|
||||
*/
|
||||
protected $tourid;
|
||||
|
||||
/**
|
||||
* Construct the table for the specified tour ID.
|
||||
*
|
||||
* @param int $tourid The id of the tour.
|
||||
*/
|
||||
public function __construct($tourid) {
|
||||
parent::__construct('steps');
|
||||
$this->tourid = $tourid;
|
||||
|
||||
$baseurl = new \moodle_url('/tool/usertours/configure.php', array(
|
||||
'id' => $tourid,
|
||||
));
|
||||
$this->define_baseurl($baseurl);
|
||||
|
||||
// Column definition.
|
||||
$this->define_columns(array(
|
||||
'title',
|
||||
'content',
|
||||
'target',
|
||||
'actions',
|
||||
));
|
||||
|
||||
$this->define_headers(array(
|
||||
get_string('title', 'tool_usertours'),
|
||||
get_string('content', 'tool_usertours'),
|
||||
get_string('target', 'tool_usertours'),
|
||||
get_string('actions', 'tool_usertours'),
|
||||
));
|
||||
|
||||
$this->set_attribute('class', 'admintable generaltable steptable');
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's title column.
|
||||
*
|
||||
* @param step $step The step for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_title(step $step) {
|
||||
global $OUTPUT;
|
||||
return $OUTPUT->render(helper::render_stepname_inplace_editable($step));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's content column.
|
||||
*
|
||||
* @param step $step The step for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_content(step $step) {
|
||||
return $step->get_content(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's target column.
|
||||
*
|
||||
* @param step $step The step for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_target(step $step) {
|
||||
return $step->get_target()->get_displayname();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's actions column.
|
||||
*
|
||||
* @param step $step The step for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_actions(step $step) {
|
||||
$actions = [];
|
||||
|
||||
if ($step->is_first_step()) {
|
||||
$actions[] = helper::get_filler_icon();
|
||||
} else {
|
||||
$actions[] = helper::format_icon_link($step->get_moveup_link(), 't/up', get_string('movestepup', 'tool_usertours'));
|
||||
}
|
||||
|
||||
if ($step->is_last_step()) {
|
||||
$actions[] = helper::get_filler_icon();
|
||||
} else {
|
||||
$actions[] = helper::format_icon_link($step->get_movedown_link(), 't/down',
|
||||
get_string('movestepdown', 'tool_usertours'));
|
||||
}
|
||||
|
||||
$actions[] = helper::format_icon_link($step->get_edit_link(), 't/edit', get_string('edit'));
|
||||
|
||||
$actions[] = helper::format_icon_link($step->get_delete_link(), 't/delete', get_string('delete'), 'moodle', [
|
||||
'data-action' => 'delete',
|
||||
'data-id' => $step->get_id(),
|
||||
]);
|
||||
|
||||
return implode(' ', $actions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Table to show the list of tours.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\table;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\helper;
|
||||
use tool_usertours\tour;
|
||||
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
/**
|
||||
* Table to show the list of tours.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tour_list extends \flexible_table {
|
||||
/**
|
||||
* Construct the tour table.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct('tours');
|
||||
|
||||
$baseurl = new \moodle_url('/tool/usertours/configure.php');
|
||||
$this->define_baseurl($baseurl);
|
||||
|
||||
// Column definition.
|
||||
$this->define_columns(array(
|
||||
'name',
|
||||
'description',
|
||||
'appliesto',
|
||||
'enabled',
|
||||
'actions',
|
||||
));
|
||||
|
||||
$this->define_headers(array(
|
||||
get_string('name', 'tool_usertours'),
|
||||
get_string('description', 'tool_usertours'),
|
||||
get_string('appliesto', 'tool_usertours'),
|
||||
get_string('enabled', 'tool_usertours'),
|
||||
get_string('actions', 'tool_usertours'),
|
||||
));
|
||||
|
||||
$this->set_attribute('class', 'admintable generaltable');
|
||||
$this->setup();
|
||||
|
||||
$this->tourcount = helper::count_tours();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's name column.
|
||||
*
|
||||
* @param tour $tour The tour for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_name(tour $tour) {
|
||||
global $OUTPUT;
|
||||
return $OUTPUT->render(helper::render_tourname_inplace_editable($tour));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's description column.
|
||||
*
|
||||
* @param tour $tour The tour for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_description(tour $tour) {
|
||||
global $OUTPUT;
|
||||
return $OUTPUT->render(helper::render_tourdescription_inplace_editable($tour));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's appliesto column.
|
||||
*
|
||||
* @param tour $tour The tour for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_appliesto(tour $tour) {
|
||||
return $tour->get_pathmatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's enabled column.
|
||||
*
|
||||
* @param tour $tour The tour for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_enabled(tour $tour) {
|
||||
global $OUTPUT;
|
||||
return $OUTPUT->render(helper::render_tourenabled_inplace_editable($tour));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current row's actions column.
|
||||
*
|
||||
* @param tour $tour The tour for this row.
|
||||
* @return string
|
||||
*/
|
||||
protected function col_actions(tour $tour) {
|
||||
$actions = [];
|
||||
|
||||
if ($tour->is_first_tour()) {
|
||||
$actions[] = helper::get_filler_icon();
|
||||
} else {
|
||||
$actions[] = helper::format_icon_link($tour->get_moveup_link(), 't/up',
|
||||
get_string('movetourup', 'tool_usertours'));
|
||||
}
|
||||
|
||||
if ($tour->is_last_tour($this->tourcount)) {
|
||||
$actions[] = helper::get_filler_icon();
|
||||
} else {
|
||||
$actions[] = helper::format_icon_link($tour->get_movedown_link(), 't/down',
|
||||
get_string('movetourdown', 'tool_usertours'));
|
||||
}
|
||||
|
||||
$actions[] = helper::format_icon_link($tour->get_view_link(), 't/viewdetails', get_string('view'));
|
||||
$actions[] = helper::format_icon_link($tour->get_edit_link(), 't/edit', get_string('edit'));
|
||||
$actions[] = helper::format_icon_link($tour->get_export_link(), 't/export',
|
||||
get_string('exporttour', 'tool_usertours'), 'tool_usertours');
|
||||
$actions[] = helper::format_icon_link($tour->get_delete_link(), 't/delete', get_string('delete'), null, [
|
||||
'data-action' => 'delete',
|
||||
'data-id' => $tour->get_id(),
|
||||
]);
|
||||
|
||||
return implode(' ', $actions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Target base.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\target;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\step;
|
||||
|
||||
/**
|
||||
* Target base.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class base {
|
||||
/**
|
||||
* @var step $step The step being targetted.
|
||||
*/
|
||||
protected $step;
|
||||
|
||||
/**
|
||||
* @var array $forcedsettings The settings forced by this type.
|
||||
*/
|
||||
protected static $forcedsettings = [];
|
||||
|
||||
/**
|
||||
* Create the target type.
|
||||
*
|
||||
* @param step $step The step being targetted.
|
||||
*/
|
||||
public function __construct(step $step) {
|
||||
$this->step = $step;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the target value to a valid CSS selector for use in the
|
||||
* output configuration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function convert_to_css();
|
||||
|
||||
/**
|
||||
* Convert the step target to a friendly name for use in the UI.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_displayname();
|
||||
|
||||
/**
|
||||
* Add the target type configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
*/
|
||||
public static function add_config_to_form(\MoodleQuickForm $mform) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the disabledIf values.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
*/
|
||||
public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the specified step setting is forced by this target type.
|
||||
*
|
||||
* @param string $key The name of the key to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_setting_forced($key) {
|
||||
return isset(static::$forcedsettings[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of the forced setting.
|
||||
*
|
||||
* @param string $key The name of the key to check.
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_forced_setting_value($key) {
|
||||
if ($this->is_setting_forced($key)) {
|
||||
return static::$forcedsettings[$key];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the targetvalue from the form for this target type.
|
||||
*
|
||||
* @param stdClass $data The data submitted in the form
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_value_from_form($data);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Block target.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\target;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\step;
|
||||
|
||||
/**
|
||||
* Block target.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class block extends base {
|
||||
|
||||
/**
|
||||
* Convert the target value to a valid CSS selector for use in the
|
||||
* output configuration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert_to_css() {
|
||||
// The block has the following CSS class selector style:
|
||||
// .block-region .block_[name] .
|
||||
return sprintf('.block-region .block_%s', $this->step->get_targetvalue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the step target to a friendly name for use in the UI.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_displayname() {
|
||||
return get_string('block_named', 'tool_usertours', $this->get_block_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the translated name of the block.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_block_name() {
|
||||
return get_string('pluginname', self::get_frankenstyle($this->step->get_targetvalue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the frankenstyle name of the block.
|
||||
*
|
||||
* @param string $block The block name.
|
||||
* @return The frankenstyle block name.
|
||||
*/
|
||||
protected static function get_frankenstyle($block) {
|
||||
return sprintf('block_%s', $block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the target type configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
* @return $this
|
||||
*/
|
||||
public static function add_config_to_form(\MoodleQuickForm $mform) {
|
||||
global $PAGE;
|
||||
|
||||
$blocks = [];
|
||||
foreach ($PAGE->blocks->get_installed_blocks() as $block) {
|
||||
$blocks[$block->name] = get_string('pluginname', 'block_' . $block->name);
|
||||
}
|
||||
|
||||
$mform->addElement('select', 'targetvalue_block', get_string('block', 'tool_usertours'), $blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the disabledIf values.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
*/
|
||||
public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
|
||||
$mform->disabledIf('targetvalue_block', 'targettype', 'noteq',
|
||||
\tool_usertours\target::get_target_constant_for_class(get_class()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the targetvalue from the form for this target type.
|
||||
*
|
||||
* @param stdClass $data The data submitted in the form
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_from_form($data) {
|
||||
return $data->targetvalue_block;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Selector target.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\target;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\step;
|
||||
|
||||
/**
|
||||
* Selector target.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class selector extends base {
|
||||
|
||||
/**
|
||||
* Convert the target value to a valid CSS selector for use in the
|
||||
* output configuration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert_to_css() {
|
||||
return $this->step->get_targetvalue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the step target to a friendly name for use in the UI.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_displayname() {
|
||||
return get_string('selectordisplayname', 'tool_usertours', $this->step->get_targetvalue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_title() {
|
||||
return get_string('selector_defaulttitle', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_default_content() {
|
||||
return get_string('selector_defaultcontent', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the target type configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
* @return $this
|
||||
*/
|
||||
public static function add_config_to_form(\MoodleQuickForm $mform) {
|
||||
$mform->addElement('text', 'targetvalue_selector', get_string('cssselector', 'tool_usertours'));
|
||||
$mform->setType('targetvalue_selector', PARAM_RAW);
|
||||
$mform->addHelpButton('targetvalue_selector', 'target_selector_targetvalue', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the disabledIf values.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
*/
|
||||
public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
|
||||
$mform->disabledIf('targetvalue_selector', 'targettype', 'noteq',
|
||||
\tool_usertours\target::get_target_constant_for_class(get_class()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the targetvalue from the form for this target type.
|
||||
*
|
||||
* @param stdClass $data The data submitted in the form
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_from_form($data) {
|
||||
return $data->targetvalue_selector;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A step designed to be orphaned.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\local\target;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\step;
|
||||
|
||||
/**
|
||||
* A step designed to be orphaned.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class unattached extends base {
|
||||
/**
|
||||
* @var array $forcedsettings The settings forced by this type.
|
||||
*/
|
||||
protected static $forcedsettings = [
|
||||
'placement' => 'top',
|
||||
'orphan' => true,
|
||||
'reflex' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Convert the target value to a valid CSS selector for use in the
|
||||
* output configuration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function convert_to_css() {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the step target to a friendly name for use in the UI.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_displayname() {
|
||||
return get_string('target_unattached', 'tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the target type configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
* @return $this
|
||||
*/
|
||||
public static function add_config_to_form(\MoodleQuickForm $mform) {
|
||||
// There is no relevant value here.
|
||||
$mform->addElement('hidden', 'targetvalue_unattached', '');
|
||||
$mform->setType('targetvalue_unattached', PARAM_TEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the disabledIf values.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
*/
|
||||
public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
|
||||
$myvalue = \tool_usertours\target::get_target_constant_for_class(get_class());
|
||||
|
||||
foreach (array_keys(self::$forcedsettings) as $settingname) {
|
||||
$mform->disabledIf($settingname, 'targettype', 'eq', $myvalue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the targetvalue from the form for this target type.
|
||||
*
|
||||
* @param stdClass $data The data submitted in the form
|
||||
* @return string
|
||||
*/
|
||||
public function get_value_from_form($data) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,769 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tour manager.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\local\forms;
|
||||
use tool_usertours\local\table;
|
||||
|
||||
/**
|
||||
* Tour manager.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class manager {
|
||||
|
||||
/**
|
||||
* @var ACTION_LISTTOURS The action to get the list of tours.
|
||||
*/
|
||||
const ACTION_LISTTOURS = 'listtours';
|
||||
|
||||
/**
|
||||
* @var ACTION_NEWTOUR The action to create a new tour.
|
||||
*/
|
||||
const ACTION_NEWTOUR = 'newtour';
|
||||
|
||||
/**
|
||||
* @var ACTION_EDITTOUR The action to edit the tour.
|
||||
*/
|
||||
const ACTION_EDITTOUR = 'edittour';
|
||||
|
||||
/**
|
||||
* @var ACTION_MOVETOUR The action to move a tour up or down.
|
||||
*/
|
||||
const ACTION_MOVETOUR = 'movetour';
|
||||
|
||||
/**
|
||||
* @var ACTION_EXPORTTOUR The action to export the tour.
|
||||
*/
|
||||
const ACTION_EXPORTTOUR = 'exporttour';
|
||||
|
||||
/**
|
||||
* @var ACTION_IMPORTTOUR The action to import the tour.
|
||||
*/
|
||||
const ACTION_IMPORTTOUR = 'importtour';
|
||||
|
||||
/**
|
||||
* @var ACTION_DELETETOUR The action to delete the tour.
|
||||
*/
|
||||
const ACTION_DELETETOUR = 'deletetour';
|
||||
|
||||
/**
|
||||
* @var ACTION_VIEWTOUR The action to view the tour.
|
||||
*/
|
||||
const ACTION_VIEWTOUR = 'viewtour';
|
||||
|
||||
/**
|
||||
* @var ACTION_NEWSTEP The action to create a new step.
|
||||
*/
|
||||
const ACTION_NEWSTEP = 'newstep';
|
||||
|
||||
/**
|
||||
* @var ACTION_EDITSTEP The action to edit step configuration.
|
||||
*/
|
||||
const ACTION_EDITSTEP = 'editstep';
|
||||
|
||||
/**
|
||||
* @var ACTION_MOVESTEP The action to move a step up or down.
|
||||
*/
|
||||
const ACTION_MOVESTEP = 'movestep';
|
||||
|
||||
/**
|
||||
* @var ACTION_DELETESTEP The action to delete a step.
|
||||
*/
|
||||
const ACTION_DELETESTEP = 'deletestep';
|
||||
|
||||
/**
|
||||
* @var ACTION_VIEWSTEP The action to view a step.
|
||||
*/
|
||||
const ACTION_VIEWSTEP = 'viewstep';
|
||||
|
||||
/**
|
||||
* @var ACTION_HIDETOUR The action to hide a tour.
|
||||
*/
|
||||
const ACTION_HIDETOUR = 'hidetour';
|
||||
|
||||
/**
|
||||
* @var ACTION_SHOWTOUR The action to show a tour.
|
||||
*/
|
||||
const ACTION_SHOWTOUR = 'showtour';
|
||||
|
||||
/**
|
||||
* @var ACTION_RESETFORALL
|
||||
*/
|
||||
const ACTION_RESETFORALL = 'resetforall';
|
||||
|
||||
/**
|
||||
* This is the entry point for this controller class.
|
||||
*
|
||||
* @param string $action The action to perform.
|
||||
*/
|
||||
public function execute($action) {
|
||||
admin_externalpage_setup('tool_usertours/tours');
|
||||
// Add the main content.
|
||||
switch($action) {
|
||||
case self::ACTION_NEWTOUR:
|
||||
case self::ACTION_EDITTOUR:
|
||||
$this->edit_tour(optional_param('id', null, PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_MOVETOUR:
|
||||
$this->move_tour(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_EXPORTTOUR:
|
||||
$this->export_tour(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_IMPORTTOUR:
|
||||
$this->import_tour();
|
||||
break;
|
||||
|
||||
case self::ACTION_VIEWTOUR:
|
||||
$this->view_tour(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_HIDETOUR:
|
||||
$this->hide_tour(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_SHOWTOUR:
|
||||
$this->show_tour(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_DELETETOUR:
|
||||
$this->delete_tour(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_RESETFORALL:
|
||||
$this->reset_tour_for_all(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_NEWSTEP:
|
||||
case self::ACTION_EDITSTEP:
|
||||
$this->edit_step(optional_param('id', null, PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_MOVESTEP:
|
||||
$this->move_step(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_DELETESTEP:
|
||||
$this->delete_step(required_param('id', PARAM_INT));
|
||||
break;
|
||||
|
||||
case self::ACTION_LISTTOURS:
|
||||
default:
|
||||
$this->print_tour_list();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out the page header.
|
||||
*
|
||||
* @param string $title The title to display.
|
||||
*/
|
||||
protected function header($title = null) {
|
||||
global $OUTPUT;
|
||||
|
||||
// Print the page heading.
|
||||
echo $OUTPUT->header();
|
||||
|
||||
if ($title === null) {
|
||||
$title = get_string('tours', 'tool_usertours');
|
||||
}
|
||||
|
||||
echo $OUTPUT->heading($title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print out the page footer.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function footer() {
|
||||
global $OUTPUT;
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the the list of tours.
|
||||
*/
|
||||
protected function print_tour_list() {
|
||||
global $PAGE, $OUTPUT;
|
||||
|
||||
$this->header();
|
||||
echo \html_writer::span(get_string('tourlist_explanation', 'tool_usertours'));
|
||||
$table = new table\tour_list();
|
||||
$tours = helper::get_tours();
|
||||
foreach ($tours as $tour) {
|
||||
$table->add_data_keyed($table->format_row($tour));
|
||||
}
|
||||
|
||||
$table->finish_output();
|
||||
$actions = [
|
||||
(object) [
|
||||
'link' => helper::get_edit_tour_link(),
|
||||
'linkproperties' => [],
|
||||
'img' => 'b/tour-new',
|
||||
'title' => get_string('newtour', 'tool_usertours'),
|
||||
],
|
||||
(object) [
|
||||
'link' => helper::get_import_tour_link(),
|
||||
'linkproperties' => [],
|
||||
'img' => 'b/tour-import',
|
||||
'title' => get_string('importtour', 'tool_usertours'),
|
||||
],
|
||||
(object) [
|
||||
'link' => new \moodle_url('https://moodle.net/mod/data/view.php', [
|
||||
'id' => 17,
|
||||
]),
|
||||
'linkproperties' => [
|
||||
'target' => '_blank',
|
||||
],
|
||||
'img' => 'b/tour-shared',
|
||||
'title' => get_string('sharedtourslink', 'tool_usertours'),
|
||||
],
|
||||
];
|
||||
|
||||
echo \html_writer::start_tag('div', [
|
||||
'class' => 'tour-actions',
|
||||
]);
|
||||
|
||||
echo \html_writer::start_tag('ul');
|
||||
foreach ($actions as $config) {
|
||||
$action = \html_writer::start_tag('li');
|
||||
$linkproperties = $config->linkproperties;
|
||||
$linkproperties['href'] = $config->link;
|
||||
$action .= \html_writer::start_tag('a', $linkproperties);
|
||||
$action .= \html_writer::img(
|
||||
$OUTPUT->pix_url($config->img, 'tool_usertours'),
|
||||
$config->title);
|
||||
$action .= \html_writer::div($config->title);
|
||||
$action .= \html_writer::end_tag('a');
|
||||
$action .= \html_writer::end_tag('li');
|
||||
echo $action;
|
||||
}
|
||||
echo \html_writer::end_tag('ul');
|
||||
echo \html_writer::end_tag('div');
|
||||
|
||||
// JS for Tour management.
|
||||
$PAGE->requires->js_call_amd('tool_usertours/managetours', 'setup');
|
||||
$this->footer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the edit tour link.
|
||||
*
|
||||
* @param int $id The ID of the tour
|
||||
* @return string
|
||||
*/
|
||||
protected function get_edit_tour_link($id = null) {
|
||||
$addlink = helper::get_edit_tour_link($id);
|
||||
return \html_writer::link($addlink, get_string('newtour', 'tool_usertours'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the edit tour link.
|
||||
*
|
||||
* @param int $id The ID of the tour
|
||||
*/
|
||||
protected function print_edit_tour_link($id = null) {
|
||||
echo $this->get_edit_tour_link($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the import tour link.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_import_tour_link() {
|
||||
$importlink = helper::get_import_tour_link();
|
||||
return \html_writer::link($importlink, get_string('importtour', 'tool_usertours'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the edit tour page.
|
||||
*
|
||||
* @param int $id The ID of the tour
|
||||
*/
|
||||
protected function edit_tour($id = null) {
|
||||
global $PAGE;
|
||||
if ($id) {
|
||||
$tour = tour::instance($id);
|
||||
$PAGE->navbar->add($tour->get_name(), $tour->get_edit_link());
|
||||
|
||||
} else {
|
||||
$tour = new tour();
|
||||
$PAGE->navbar->add(get_string('newtour', 'tool_usertours'), $tour->get_edit_link());
|
||||
}
|
||||
|
||||
$form = new forms\edittour($tour);
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
redirect(helper::get_list_tour_link());
|
||||
} else if ($data = $form->get_data()) {
|
||||
// Creating a new tour.
|
||||
$tour->set_name($data->name);
|
||||
$tour->set_description($data->description);
|
||||
$tour->set_pathmatch($data->pathmatch);
|
||||
$tour->set_enabled(!empty($data->enabled));
|
||||
|
||||
foreach (configuration::get_defaultable_keys() as $key) {
|
||||
$tour->set_config($key, $data->$key);
|
||||
}
|
||||
|
||||
// Save filter values.
|
||||
foreach (helper::get_all_filters() as $filterclass) {
|
||||
$filterclass::save_filter_values_from_form($tour, $data);
|
||||
}
|
||||
|
||||
$tour->persist();
|
||||
|
||||
redirect(helper::get_list_tour_link());
|
||||
} else {
|
||||
if (empty($tour)) {
|
||||
$this->header('newtour');
|
||||
} else {
|
||||
$this->header($tour->get_name());
|
||||
$data = $tour->prepare_data_for_form();
|
||||
|
||||
// Prepare filter values for the form.
|
||||
foreach (helper::get_all_filters() as $filterclass) {
|
||||
$filterclass::prepare_filter_values_for_form($tour, $data);
|
||||
}
|
||||
$form->set_data($data);
|
||||
}
|
||||
|
||||
$form->display();
|
||||
$this->footer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the export tour page.
|
||||
*
|
||||
* @param int $id The ID of the tour
|
||||
*/
|
||||
protected function export_tour($id) {
|
||||
$tour = tour::instance($id);
|
||||
|
||||
// Grab the full data record.
|
||||
$export = $tour->to_record();
|
||||
|
||||
// Remove the id.
|
||||
unset($export->id);
|
||||
|
||||
// Set the version.
|
||||
$export->version = get_config('tool_usertours', 'version');
|
||||
|
||||
// Step export.
|
||||
$export->steps = [];
|
||||
foreach ($tour->get_steps() as $step) {
|
||||
$record = $step->to_record();
|
||||
unset($record->id);
|
||||
unset($record->tourid);
|
||||
|
||||
$export->steps[] = $record;
|
||||
}
|
||||
|
||||
$exportstring = json_encode($export);
|
||||
|
||||
$filename = 'tour_export_' . $tour->get_id() . '_' . time() . '.json';
|
||||
|
||||
// Force download.
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
||||
header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', 0) . 'GMT');
|
||||
header('Pragma: no-cache');
|
||||
header('Accept-Ranges: none');
|
||||
header('Content-disposition: attachment; filename=' . $filename);
|
||||
header('Content-length: ' . strlen($exportstring));
|
||||
header('Content-type: text/calendar; charset=utf-8');
|
||||
|
||||
echo $exportstring;
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle tour import.
|
||||
*/
|
||||
protected function import_tour() {
|
||||
global $PAGE;
|
||||
$PAGE->navbar->add(get_string('importtour', 'tool_usertours'), helper::get_import_tour_link());
|
||||
|
||||
$form = new forms\importtour();
|
||||
|
||||
if ($form->is_cancelled()) {
|
||||
redirect(helper::get_list_tour_link());
|
||||
} else if ($form->get_data()) {
|
||||
// Importing a tour.
|
||||
$tourconfigraw = $form->get_file_content('tourconfig');
|
||||
$tour = self::import_tour_from_json($tourconfigraw);
|
||||
|
||||
redirect($tour->get_view_link());
|
||||
} else {
|
||||
$this->header();
|
||||
$form->display();
|
||||
$this->footer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the view tour page.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to display.
|
||||
*/
|
||||
protected function view_tour($tourid) {
|
||||
global $PAGE;
|
||||
$tour = helper::get_tour($tourid);
|
||||
|
||||
$PAGE->navbar->add($tour->get_name(), $tour->get_view_link());
|
||||
|
||||
$this->header($tour->get_name());
|
||||
echo \html_writer::span(get_string('viewtour_info', 'tool_usertours', [
|
||||
'tourname' => $tour->get_name(),
|
||||
'path' => $tour->get_pathmatch(),
|
||||
]));
|
||||
echo \html_writer::div(get_string('viewtour_edit', 'tool_usertours', [
|
||||
'editlink' => $tour->get_edit_link()->out(),
|
||||
'resetlink' => $tour->get_reset_link()->out(),
|
||||
]));
|
||||
|
||||
$table = new table\step_list($tourid);
|
||||
foreach ($tour->get_steps() as $step) {
|
||||
$table->add_data_keyed($table->format_row($step));
|
||||
}
|
||||
|
||||
$table->finish_output();
|
||||
$this->print_edit_step_link($tourid);
|
||||
|
||||
// JS for Step management.
|
||||
$PAGE->requires->js_call_amd('tool_usertours/managesteps', 'setup');
|
||||
|
||||
$this->footer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to display.
|
||||
*/
|
||||
protected function show_tour($tourid) {
|
||||
$this->show_hide_tour($tourid, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to display.
|
||||
*/
|
||||
protected function hide_tour($tourid) {
|
||||
$this->show_hide_tour($tourid, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or Hide the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to display.
|
||||
* @param int $visibility The intended visibility.
|
||||
*/
|
||||
protected function show_hide_tour($tourid, $visibility) {
|
||||
global $DB;
|
||||
|
||||
require_sesskey();
|
||||
|
||||
$tour = $DB->get_record('tool_usertours_tours', array('id' => $tourid));
|
||||
$tour->enabled = $visibility;
|
||||
$DB->update_record('tool_usertours_tours', $tour);
|
||||
|
||||
redirect(helper::get_list_tour_link());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the tour.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to remove.
|
||||
*/
|
||||
protected function delete_tour($tourid) {
|
||||
require_sesskey();
|
||||
|
||||
$tour = tour::instance($tourid);
|
||||
$tour->remove();
|
||||
|
||||
redirect(helper::get_list_tour_link());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the tour state for all users.
|
||||
*
|
||||
* @param int $tourid The ID of the tour to remove.
|
||||
*/
|
||||
protected function reset_tour_for_all($tourid) {
|
||||
require_sesskey();
|
||||
|
||||
$tour = tour::instance($tourid);
|
||||
$tour->mark_major_change();
|
||||
|
||||
redirect(helper::get_view_tour_link($tourid), get_string('tour_resetforall', 'tool_usertours'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first tour matching the current page URL.
|
||||
*
|
||||
* @param bool $reset Forcibly update the current tour
|
||||
* @return tour
|
||||
*/
|
||||
public static function get_current_tour($reset = false) {
|
||||
global $PAGE;
|
||||
|
||||
static $tour = false;
|
||||
|
||||
if ($tour === false || $reset) {
|
||||
$tour = self::get_matching_tours($PAGE->url);
|
||||
}
|
||||
|
||||
return $tour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first tour matching the specified URL.
|
||||
*
|
||||
* @param moodle_url $pageurl The URL to match.
|
||||
* @return tour
|
||||
*/
|
||||
public static function get_matching_tours(\moodle_url $pageurl) {
|
||||
global $DB, $PAGE;
|
||||
|
||||
// Do not show tours whilst upgrades are pending.
|
||||
if (moodle_needs_upgrading()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$sql = <<<EOF
|
||||
SELECT * FROM {tool_usertours_tours}
|
||||
WHERE enabled = 1
|
||||
AND ? LIKE pathmatch
|
||||
ORDER BY sortorder ASC
|
||||
EOF;
|
||||
|
||||
$tours = $DB->get_records_sql($sql, array(
|
||||
$pageurl->out_as_local_url(),
|
||||
));
|
||||
|
||||
foreach ($tours as $record) {
|
||||
$tour = tour::load_from_record($record);
|
||||
if ($tour->is_enabled() && $tour->matches_all_filters($PAGE->context) & $tour->get_steps() > 0) {
|
||||
return $tour;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import the provided tour JSON.
|
||||
*
|
||||
* @param string $json The tour configuration.
|
||||
* @return tour
|
||||
*/
|
||||
public static function import_tour_from_json($json) {
|
||||
$tourconfig = json_decode($json);
|
||||
|
||||
// We do not use this yet - we may do in the future.
|
||||
unset($tourconfig->version);
|
||||
|
||||
$steps = $tourconfig->steps;
|
||||
unset($tourconfig->steps);
|
||||
|
||||
$tourconfig->id = null;
|
||||
$tourconfig->sortorder = null;
|
||||
$tour = tour::load_from_record($tourconfig, true);
|
||||
$tour->persist(true);
|
||||
|
||||
// Ensure that steps are orderered by their sortorder.
|
||||
\core_collator::asort_objects_by_property($steps, 'sortorder', \core_collator::SORT_NUMERIC);
|
||||
|
||||
foreach ($steps as $stepconfig) {
|
||||
$stepconfig->id = null;
|
||||
$stepconfig->tourid = $tour->get_id();
|
||||
$step = step::load_from_record($stepconfig, true);
|
||||
$step->persist(true);
|
||||
}
|
||||
|
||||
return $tour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to fetch the renderer.
|
||||
*
|
||||
* @return renderer
|
||||
*/
|
||||
protected function get_renderer() {
|
||||
global $PAGE;
|
||||
return $PAGE->get_renderer('tool_usertours');
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the edit step link.
|
||||
*
|
||||
* @param int $tourid The ID of the tour.
|
||||
* @param int $stepid The ID of the step.
|
||||
* @return string
|
||||
*/
|
||||
protected function print_edit_step_link($tourid, $stepid = null) {
|
||||
$addlink = helper::get_edit_step_link($tourid, $stepid);
|
||||
$attributes = [];
|
||||
if (empty($stepid)) {
|
||||
$attributes['class'] = 'createstep';
|
||||
}
|
||||
echo \html_writer::link($addlink, get_string('newstep', 'tool_usertours'), $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the edit step form for the specified step.
|
||||
*
|
||||
* @param int $id The step to edit.
|
||||
*/
|
||||
protected function edit_step($id) {
|
||||
global $PAGE;
|
||||
|
||||
if (isset($id)) {
|
||||
$step = step::instance($id);
|
||||
} else {
|
||||
$step = new step();
|
||||
$step->set_tourid(required_param('tourid', PARAM_INT));
|
||||
}
|
||||
|
||||
$tour = $step->get_tour();
|
||||
$PAGE->navbar->add($tour->get_name(), $tour->get_view_link());
|
||||
if (isset($id)) {
|
||||
$PAGE->navbar->add($step->get_title(), $step->get_edit_link());
|
||||
} else {
|
||||
$PAGE->navbar->add(get_string('newstep', 'tool_usertours'), $step->get_edit_link());
|
||||
}
|
||||
|
||||
$form = new forms\editstep($step->get_edit_link(), $step);
|
||||
if ($form->is_cancelled()) {
|
||||
redirect($step->get_tour()->get_view_link());
|
||||
} else if ($data = $form->get_data()) {
|
||||
$step->handle_form_submission($form, $data);
|
||||
$step->get_tour()->reset_step_sortorder();
|
||||
redirect($step->get_tour()->get_view_link());
|
||||
} else {
|
||||
if (empty($id)) {
|
||||
$this->header(get_string('newstep', 'tool_usertours'));
|
||||
} else {
|
||||
$this->header(get_string('editstep', 'tool_usertours', $step->get_title()));
|
||||
}
|
||||
$form->set_data($step->prepare_data_for_form());
|
||||
|
||||
$form->display();
|
||||
$this->footer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a tour up or down.
|
||||
*
|
||||
* @param int $id The tour to move.
|
||||
*/
|
||||
protected function move_tour($id) {
|
||||
require_sesskey();
|
||||
|
||||
$direction = required_param('direction', PARAM_INT);
|
||||
|
||||
$tour = tour::instance($id);
|
||||
$currentsortorder = $tour->get_sortorder();
|
||||
$targetsortorder = $currentsortorder + $direction;
|
||||
|
||||
$swapwith = helper::get_tour_from_sortorder($targetsortorder);
|
||||
|
||||
// Set the sort order to something out of the way.
|
||||
$tour->set_sortorder(-1);
|
||||
$tour->persist();
|
||||
|
||||
// Swap the two sort orders.
|
||||
$swapwith->set_sortorder($currentsortorder);
|
||||
$swapwith->persist();
|
||||
|
||||
$tour->set_sortorder($targetsortorder);
|
||||
$tour->persist();
|
||||
|
||||
redirect(helper::get_list_tour_link());
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a step up or down.
|
||||
*
|
||||
* @param int $id The step to move.
|
||||
*/
|
||||
protected function move_step($id) {
|
||||
require_sesskey();
|
||||
|
||||
$direction = required_param('direction', PARAM_INT);
|
||||
|
||||
$step = step::instance($id);
|
||||
$currentsortorder = $step->get_sortorder();
|
||||
$targetsortorder = $currentsortorder + $direction;
|
||||
|
||||
$tour = $step->get_tour();
|
||||
$swapwith = helper::get_step_from_sortorder($tour->get_id(), $targetsortorder);
|
||||
|
||||
// Set the sort order to something out of the way.
|
||||
$step->set_sortorder(-1);
|
||||
$step->persist();
|
||||
|
||||
// Swap the two sort orders.
|
||||
$swapwith->set_sortorder($currentsortorder);
|
||||
$swapwith->persist();
|
||||
|
||||
$step->set_sortorder($targetsortorder);
|
||||
$step->persist();
|
||||
|
||||
// Reset the sort order.
|
||||
$tour->reset_step_sortorder();
|
||||
redirect($tour->get_view_link());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the step.
|
||||
*
|
||||
* @param int $stepid The ID of the step to remove.
|
||||
*/
|
||||
protected function delete_step($stepid) {
|
||||
require_sesskey();
|
||||
|
||||
$step = step::instance($stepid);
|
||||
$tour = $step->get_tour();
|
||||
|
||||
$step->remove();
|
||||
redirect($tour->get_view_link());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Renderer.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Renderer.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class renderer extends \plugin_renderer_base {
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tour Step Renderable.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\step as stepsource;
|
||||
|
||||
/**
|
||||
* Tour Step Renderable.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class step implements \renderable {
|
||||
|
||||
/**
|
||||
* @var The step instance.
|
||||
*/
|
||||
protected $step;
|
||||
|
||||
/**
|
||||
* The step output.
|
||||
*
|
||||
* @param stepsource $step The step being output.
|
||||
*/
|
||||
public function __construct(stepsource $step) {
|
||||
$this->step = $step;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the step configuration.
|
||||
*
|
||||
* @param renderer_base $output The renderer.
|
||||
* @return object
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
global $PAGE;
|
||||
$step = $this->step;
|
||||
|
||||
$result = (object) [
|
||||
'stepid' => $step->get_id(),
|
||||
'title' => external_format_text(
|
||||
static::get_string_from_input($step->get_title()),
|
||||
FORMAT_HTML,
|
||||
$PAGE->context->id,
|
||||
'tool_usertours',
|
||||
null,
|
||||
null,
|
||||
[
|
||||
'filter' => true,
|
||||
]
|
||||
)[0],
|
||||
'content' => external_format_text(
|
||||
static::get_string_from_input($step->get_content()),
|
||||
FORMAT_HTML,
|
||||
$PAGE->context->id,
|
||||
'tool_usertours',
|
||||
null,
|
||||
null,
|
||||
[
|
||||
'filter' => true,
|
||||
]
|
||||
)[0],
|
||||
'element' => $step->get_target()->convert_to_css(),
|
||||
];
|
||||
|
||||
$result->content = str_replace("\n", "<br>\n", $result->content);
|
||||
|
||||
foreach ($step->get_config_keys() as $key) {
|
||||
$result->$key = $step->get_config($key);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to fetch any matching langstring if the string is in the
|
||||
* format identifier,component.
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
protected static function get_string_from_input($string) {
|
||||
$string = trim($string);
|
||||
|
||||
if (preg_match('|^([a-zA-Z][a-zA-Z0-9\.:/_-]*),([a-zA-Z][a-zA-Z0-9\.:/_-]*)$|', $string, $matches)) {
|
||||
if ($matches[2] === 'moodle') {
|
||||
$matches[2] = 'core';
|
||||
}
|
||||
|
||||
if (get_string_manager()->string_exists($matches[1], $matches[2])) {
|
||||
$string = get_string($matches[1], $matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tour renderable.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\tour as toursource;
|
||||
|
||||
/**
|
||||
* Tour renderable.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tour implements \renderable {
|
||||
|
||||
/**
|
||||
* @var The tour instance.
|
||||
*/
|
||||
protected $tour;
|
||||
|
||||
/**
|
||||
* The tour output.
|
||||
*
|
||||
* @param toursource $tour The tour being output.
|
||||
*/
|
||||
public function __construct (toursource $tour) {
|
||||
$this->tour = $tour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for export.
|
||||
*
|
||||
* @param \renderer_base $output The output renderable.
|
||||
* @return object
|
||||
*/
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
$result = (object) [
|
||||
'name' => $this->tour->get_tour_key(),
|
||||
'steps' => [],
|
||||
];
|
||||
|
||||
foreach ($this->tour->get_steps() as $step) {
|
||||
$result->steps[] = (new step($step))->export_for_template($output);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,629 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Step class.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Step class.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class step {
|
||||
|
||||
/**
|
||||
* @var int $id The id of the step.
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var int $tourid The id of the tour that this step belongs to.
|
||||
*/
|
||||
protected $tourid;
|
||||
|
||||
/**
|
||||
* @var tour $tour The tour class that this step belongs to.
|
||||
*/
|
||||
protected $tour;
|
||||
|
||||
/**
|
||||
* @var string $title The title of the step.
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* @var string $content The content of this step.
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* @var int $targettype The type of target.
|
||||
*/
|
||||
protected $targettype;
|
||||
|
||||
/**
|
||||
* @var string $targetvalue The value for this type of target.
|
||||
*/
|
||||
protected $targetvalue;
|
||||
|
||||
/**
|
||||
* @var int $sortorder The sort order.
|
||||
*/
|
||||
protected $sortorder;
|
||||
|
||||
/**
|
||||
* @var object $config The configuration as an object.
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var bool $dirty Whether the step has been changed since it was loaded
|
||||
*/
|
||||
protected $dirty = false;
|
||||
|
||||
/**
|
||||
* Fetch the step instance.
|
||||
*
|
||||
* @param int $id The id of the step to be retrieved.
|
||||
* @return step
|
||||
*/
|
||||
public static function instance($id) {
|
||||
$step = new step();
|
||||
return $step->fetch($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the step instance.
|
||||
*
|
||||
* @param stdClass $record The step record to be loaded.
|
||||
* @param boolean $clean Clean the values.
|
||||
* @return step
|
||||
*/
|
||||
public static function load_from_record($record, $clean = false) {
|
||||
$step = new self();
|
||||
return $step->reload_from_record($record, $clean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the step instance.
|
||||
*
|
||||
* @param int $id The id of the step to be retrieved.
|
||||
* @return step
|
||||
*/
|
||||
protected function fetch($id) {
|
||||
global $DB;
|
||||
|
||||
return $this->reload_from_record(
|
||||
$DB->get_record('tool_usertours_steps', array('id' => $id))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the current step from the datbase.
|
||||
*
|
||||
* @return step
|
||||
*/
|
||||
protected function reload() {
|
||||
return $this->fetch($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the current step from the supplied record.
|
||||
*
|
||||
* @param stdClass $record The step record to be loaded.
|
||||
* @param boolean $clean Clean the values.
|
||||
* @return step
|
||||
*/
|
||||
protected function reload_from_record($record, $clean = false) {
|
||||
$this->id = $record->id;
|
||||
$this->tourid = $record->tourid;
|
||||
if ($clean) {
|
||||
$this->title = clean_param($record->title, PARAM_TEXT);
|
||||
$this->content = clean_text($record->content);
|
||||
} else {
|
||||
$this->title = $record->title;
|
||||
$this->content = $record->content;
|
||||
}
|
||||
$this->targettype = $record->targettype;
|
||||
$this->targetvalue = $record->targetvalue;
|
||||
$this->sortorder = $record->sortorder;
|
||||
$this->config = json_decode($record->configdata);
|
||||
$this->dirty = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the step.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Tour ID of the step.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_tourid() {
|
||||
return $this->tourid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Tour instance that this step belongs to.
|
||||
*
|
||||
* @return tour
|
||||
*/
|
||||
public function get_tour() {
|
||||
if ($this->tour === null) {
|
||||
$this->tour = tour::instance($this->tourid);
|
||||
}
|
||||
return $this->tour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the id of the tour.
|
||||
*
|
||||
* @param int $value The id of the tour.
|
||||
* @return self
|
||||
*/
|
||||
public function set_tourid($value) {
|
||||
$this->tourid = $value;
|
||||
$this->tour = null;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Title of the step.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title for this step.
|
||||
*
|
||||
* @param string $value The new title to use.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_title($value) {
|
||||
$this->title = clean_param($value, PARAM_TEXT);
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the body content of the step.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_content() {
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content value for this step.
|
||||
*
|
||||
* @param string $value The new content to use.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_content($value) {
|
||||
$this->content = clean_text($value);
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content value for this step.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_targettype() {
|
||||
return $this->targettype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of target for this step.
|
||||
*
|
||||
* @param string $value The new target to use.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_targettype($value) {
|
||||
$this->targettype = $value;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target value for this step.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_targetvalue() {
|
||||
return $this->targetvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target value for this step.
|
||||
*
|
||||
* @param string $value The new target value to use.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_targetvalue($value) {
|
||||
$this->targetvalue = $value;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target instance for this step.
|
||||
*
|
||||
* @return target
|
||||
*/
|
||||
public function get_target() {
|
||||
return target::get_target_instance($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sortorder for this step.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_sortorder() {
|
||||
return (int) $this->sortorder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this step is the first step in the tour.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_first_step() {
|
||||
return ($this->get_sortorder() === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this step is the last step in the tour.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_last_step() {
|
||||
$stepcount = $this->get_tour()->count_steps();
|
||||
return ($this->get_sortorder() === $stepcount - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sortorder for this step.
|
||||
*
|
||||
* @param int $value The new sortorder to use.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_sortorder($value) {
|
||||
$this->sortorder = $value;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to move this step up in the sortorder.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_moveup_link() {
|
||||
return helper::get_move_step_link($this->get_id(), helper::MOVE_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to move this step down in the sortorder.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_movedown_link() {
|
||||
return helper::get_move_step_link($this->get_id(), helper::MOVE_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the specified configuration item.
|
||||
*
|
||||
* If notvalue was found, and no default was specified, the default for the tour will be used.
|
||||
*
|
||||
* @param string $key The configuration key to set.
|
||||
* @param mixed $default The default value to use if a value was not found.
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_config($key = null, $default = null) {
|
||||
if ($this->config === null) {
|
||||
$this->config = (object) array();
|
||||
}
|
||||
|
||||
if ($key === null) {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
if ($this->get_targettype()) {
|
||||
$target = $this->get_target();
|
||||
if ($target->is_setting_forced($key)) {
|
||||
return $target->get_forced_setting_value($key);
|
||||
}
|
||||
}
|
||||
|
||||
if (property_exists($this->config, $key)) {
|
||||
return $this->config->$key;
|
||||
}
|
||||
|
||||
if ($default !== null) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->get_tour()->get_config($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration item as specified.
|
||||
*
|
||||
* @param string $key The configuration key to set.
|
||||
* @param mixed $value The new value for the configuration item.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_config($key, $value) {
|
||||
if ($this->config === null) {
|
||||
$this->config = (object) array();
|
||||
}
|
||||
|
||||
if ($value === null) {
|
||||
unset($this->config->$key);
|
||||
} else {
|
||||
$this->config->$key = $value;
|
||||
}
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the edit link for this step.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_edit_link() {
|
||||
return helper::get_edit_step_link($this->tourid, $this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the delete link for this step.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_delete_link() {
|
||||
return helper::get_delete_step_link($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare this step for saving to the database.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function to_record() {
|
||||
return (object) array(
|
||||
'id' => $this->id,
|
||||
'tourid' => $this->tourid,
|
||||
'title' => $this->title,
|
||||
'content' => $this->content,
|
||||
'targettype' => $this->targettype,
|
||||
'targetvalue' => $this->targetvalue,
|
||||
'sortorder' => $this->sortorder,
|
||||
'configdata' => json_encode($this->config),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the next sort-order value.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function calculate_sortorder() {
|
||||
$count = $this->get_tour()->count_steps();
|
||||
$this->sortorder = $count;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the tour and it's configuration to the database.
|
||||
*
|
||||
* @param boolean $force Whether to force writing to the database.
|
||||
* @return $this
|
||||
*/
|
||||
public function persist($force = false) {
|
||||
global $DB;
|
||||
|
||||
if (!$this->dirty && !$force) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->id) {
|
||||
$record = $this->to_record();
|
||||
$DB->update_record('tool_usertours_steps', $record);
|
||||
} else {
|
||||
$this->calculate_sortorder();
|
||||
$record = $this->to_record();
|
||||
unset($record->id);
|
||||
$this->id = $DB->insert_record('tool_usertours_steps', $record);
|
||||
}
|
||||
|
||||
$this->reload();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this step.
|
||||
*/
|
||||
public function remove() {
|
||||
global $DB;
|
||||
|
||||
if ($this->id === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$DB->delete_records('tool_usertours_steps', array('id' => $this->id));
|
||||
$this->get_tour()->reset_step_sortorder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of possible placement options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_placement_options() {
|
||||
return configuration::get_placement_options(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of possible configuration keys.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_config_keys() {
|
||||
return [
|
||||
'placement',
|
||||
'orphan',
|
||||
'backdrop',
|
||||
'reflex',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the step configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_config_to_form(\MoodleQuickForm $mform) {
|
||||
$tour = $this->get_tour();
|
||||
|
||||
$options = configuration::get_placement_options($tour->get_config('placement'));
|
||||
$mform->addElement('select', 'placement', get_string('placement', 'tool_usertours'), $options);
|
||||
$mform->addHelpButton('placement', 'placement', 'tool_usertours');
|
||||
|
||||
$this->add_config_field_to_form($mform, 'orphan');
|
||||
$this->add_config_field_to_form($mform, 'backdrop');
|
||||
$this->add_config_field_to_form($mform, 'reflex');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified step field configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
* @param string $key The key to add.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_config_field_to_form(\MoodleQuickForm $mform, $key) {
|
||||
$tour = $this->get_tour();
|
||||
|
||||
$default = (bool) $tour->get_config($key);
|
||||
|
||||
$options = [
|
||||
true => get_string('yes'),
|
||||
false => get_string('no'),
|
||||
];
|
||||
|
||||
if (!isset($options[$default])) {
|
||||
$default = configuration::get_default_value($key);
|
||||
}
|
||||
|
||||
$options = array_reverse($options, true);
|
||||
$options[configuration::TOURDEFAULT] = get_string('defaultvalue', 'tool_usertours', $options[$default]);
|
||||
$options = array_reverse($options, true);
|
||||
|
||||
$mform->addElement('select', $key, get_string($key, 'tool_usertours'), $options);
|
||||
$mform->setDefault($key, configuration::TOURDEFAULT);
|
||||
$mform->addHelpButton($key, $key, 'tool_usertours');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the configuration data for the moodle form.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function prepare_data_for_form() {
|
||||
$data = $this->to_record();
|
||||
foreach (self::get_config_keys() as $key) {
|
||||
$data->$key = $this->get_config($key, configuration::get_step_default_value($key));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle submission of the step editing form.
|
||||
*
|
||||
* @param local\forms\editstep $mform The sumitted form.
|
||||
* @param stdClass $data The submitted data.
|
||||
* @return $this
|
||||
*/
|
||||
public function handle_form_submission(local\forms\editstep &$mform, \stdClass $data) {
|
||||
$this->set_title($data->title);
|
||||
$this->set_content($data->content);
|
||||
$this->set_targettype($data->targettype);
|
||||
|
||||
$this->set_targetvalue($this->get_target()->get_value_from_form($data));
|
||||
|
||||
foreach (self::get_config_keys() as $key) {
|
||||
if (!$this->get_target()->is_setting_forced($key)) {
|
||||
if (isset($data->$key)) {
|
||||
$value = $data->$key;
|
||||
} else {
|
||||
$value = configuration::TOURDEFAULT;
|
||||
}
|
||||
if ($value === configuration::TOURDEFAULT) {
|
||||
$this->set_config($key, null);
|
||||
} else {
|
||||
$this->set_config($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->persist();
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Target class.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Target class.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class target {
|
||||
|
||||
/**
|
||||
* @var TARGET_SELECTOR The target is a CSS selector.
|
||||
*/
|
||||
const TARGET_SELECTOR = 0;
|
||||
|
||||
/**
|
||||
* @var TARGET_BLOCK The target is a block.
|
||||
*/
|
||||
const TARGET_BLOCK = 1;
|
||||
|
||||
/**
|
||||
* @var TARGET_UNATTACHED The target is unattached to any specific node.
|
||||
*/
|
||||
const TARGET_UNATTACHED = 2;
|
||||
|
||||
/**
|
||||
* @var array $mapping The list of target type to target name.
|
||||
*/
|
||||
protected static $mapping = [
|
||||
self::TARGET_BLOCK => 'block',
|
||||
self::TARGET_SELECTOR => 'selector',
|
||||
self::TARGET_UNATTACHED => 'unattached',
|
||||
];
|
||||
|
||||
/**
|
||||
* Return the name of the class for this target type.
|
||||
*
|
||||
* @param int $type The type of target.
|
||||
* @return string The class name.
|
||||
*/
|
||||
public static function get_classname($type) {
|
||||
$targettype = self::$mapping[self::get_target_constant($type)];
|
||||
return "\\tool_usertours\\local\\target\\{$targettype}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance of the class for this target.
|
||||
*
|
||||
* @param step $step The step.
|
||||
* @return target The target instance.
|
||||
*/
|
||||
public static function get_target_type(step $step) {
|
||||
if (!isset(self::$mapping[$step->get_targettype()])) {
|
||||
throw new \moodle_exception('Unknown Target type');
|
||||
}
|
||||
|
||||
$targettype = self::$mapping[$step->get_targettype()];
|
||||
return "\\tool_usertours\\local\\target\\{$targettype}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the constant used to describe this target.
|
||||
*
|
||||
* @param string $type The type of the target.
|
||||
* @return int The constant for this target.
|
||||
*/
|
||||
public static function get_target_constant($type) {
|
||||
return array_search($type, self::$mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the constant used to describe this class.
|
||||
*
|
||||
* @param string $classname The fully-qualified class name of the target
|
||||
* @return int The constant for this target.
|
||||
*/
|
||||
public static function get_target_constant_for_class($classname) {
|
||||
$rc = new \ReflectionClass($classname);
|
||||
|
||||
return self::get_target_constant($rc->getShortName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance of the class for this target.
|
||||
*
|
||||
* @param step $step The step.
|
||||
* @return target The target instance.
|
||||
*/
|
||||
public static function get_target_instance(step $step) {
|
||||
$targetclass = self::get_target_type($step);
|
||||
return new $targetclass($step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the complete lits of target types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_target_types() {
|
||||
return self::$mapping;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,761 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tour class.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Tour class.
|
||||
*
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tour {
|
||||
|
||||
/**
|
||||
* The tour is currently disabled
|
||||
*
|
||||
* @var DISABLED
|
||||
*/
|
||||
const DISABLED = 0;
|
||||
|
||||
/**
|
||||
* The tour is currently disabled
|
||||
*
|
||||
* @var DISABLED
|
||||
*/
|
||||
const ENABLED = 1;
|
||||
|
||||
/**
|
||||
* The user preference value to indicate the time of completion of the tour for a user.
|
||||
*
|
||||
* @var TOUR_LAST_COMPLETED_BY_USER
|
||||
*/
|
||||
const TOUR_LAST_COMPLETED_BY_USER = 'tool_usertours_tour_completion_time_';
|
||||
|
||||
/**
|
||||
* The user preference value to indicate the time that a user last requested to see the tour.
|
||||
*
|
||||
* @var TOUR_REQUESTED_BY_USER
|
||||
*/
|
||||
const TOUR_REQUESTED_BY_USER = 'tool_usertours_tour_reset_time_';
|
||||
|
||||
/**
|
||||
* @var $id The tour ID.
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var $name The tour name.
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @var $description The tour description.
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* @var $pathmatch The tour pathmatch.
|
||||
*/
|
||||
protected $pathmatch;
|
||||
|
||||
/**
|
||||
* @var $enabled The tour enabled state.
|
||||
*/
|
||||
protected $enabled;
|
||||
|
||||
/**
|
||||
* @var $sortorder The sort order.
|
||||
*/
|
||||
protected $sortorder;
|
||||
|
||||
/**
|
||||
* @var $dirty Whether the current view of the tour has been modified.
|
||||
*/
|
||||
protected $dirty = false;
|
||||
|
||||
/**
|
||||
* @var $config The configuration object for the tour.
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var $filtervalues The filter configuration object for the tour.
|
||||
*/
|
||||
protected $filtervalues;
|
||||
|
||||
/**
|
||||
* @var $steps The steps in this tour.
|
||||
*/
|
||||
protected $steps = [];
|
||||
|
||||
/**
|
||||
* Create an instance of the specified tour.
|
||||
*
|
||||
* @param int $id The ID of the tour to load.
|
||||
* @return tour
|
||||
*/
|
||||
public static function instance($id) {
|
||||
$tour = new self();
|
||||
return $tour->fetch($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of tour from its provided DB record.
|
||||
*
|
||||
* @param stdClass $record The record of the tour to load.
|
||||
* @param boolean $clean Clean the values.
|
||||
* @return tour
|
||||
*/
|
||||
public static function load_from_record($record, $clean = false) {
|
||||
$tour = new self();
|
||||
return $tour->reload_from_record($record, $clean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the specified tour into the current object.
|
||||
*
|
||||
* @param int $id The ID of the tour to fetch.
|
||||
* @return tour
|
||||
*/
|
||||
protected function fetch($id) {
|
||||
global $DB;
|
||||
|
||||
return $this->reload_from_record(
|
||||
$DB->get_record('tool_usertours_tours', array('id' => $id), '*', MUST_EXIST)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the current tour from database.
|
||||
*
|
||||
* @return tour
|
||||
*/
|
||||
protected function reload() {
|
||||
return $this->fetch($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the tour into the current object.
|
||||
*
|
||||
* @param stdClass $record The record to reload.
|
||||
* @param boolean $clean Clean the values.
|
||||
* @return tour
|
||||
*/
|
||||
protected function reload_from_record($record, $clean = false) {
|
||||
$this->id = $record->id;
|
||||
if (!property_exists($record, 'description')) {
|
||||
if (property_exists($record, 'comment')) {
|
||||
$record->description = $record->comment;
|
||||
unset($record->comment);
|
||||
}
|
||||
}
|
||||
if ($clean) {
|
||||
$this->name = clean_param($record->name, PARAM_TEXT);
|
||||
$this->description = clean_text($record->description);
|
||||
} else {
|
||||
$this->name = $record->name;
|
||||
$this->description = $record->description;
|
||||
}
|
||||
$this->pathmatch = $record->pathmatch;
|
||||
$this->enabled = $record->enabled;
|
||||
if (isset($record->sortorder)) {
|
||||
$this->sortorder = $record->sortorder;
|
||||
}
|
||||
$this->config = json_decode($record->configdata);
|
||||
$this->dirty = false;
|
||||
$this->steps = [];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all steps in the tour.
|
||||
*
|
||||
* @return stdClass[]
|
||||
*/
|
||||
public function get_steps() {
|
||||
if (empty($this->steps)) {
|
||||
$this->steps = helper::get_steps($this->id);
|
||||
}
|
||||
|
||||
return $this->steps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of steps in the tour.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_steps() {
|
||||
return count($this->get_steps());
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the tour.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the tour.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the tour to the specified value.
|
||||
*
|
||||
* @param string $value The new name.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_name($value) {
|
||||
$this->name = clean_param($value, PARAM_TEXT);
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The description associated with the tour.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the description of the tour to the specified value.
|
||||
*
|
||||
* @param string $value The new description.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_description($value) {
|
||||
$this->description = clean_text($value);
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The path match for the tour.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_pathmatch() {
|
||||
return $this->pathmatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the patchmatch of the tour to the specified value.
|
||||
*
|
||||
* @param string $value The new patchmatch.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_pathmatch($value) {
|
||||
$this->pathmatch = $value;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The enabled state of the tour.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_enabled() {
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the tour is currently enabled.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_enabled() {
|
||||
return ($this->enabled == self::ENABLED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the enabled state of the tour to the specified value.
|
||||
*
|
||||
* @param boolean $value The new state.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_enabled($value) {
|
||||
$this->enabled = $value;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The link to view this tour.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_view_link() {
|
||||
return helper::get_view_tour_link($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The link to edit this tour.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_edit_link() {
|
||||
return helper::get_edit_tour_link($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The link to reset the state of this tour for all users.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_reset_link() {
|
||||
return helper::get_reset_tour_for_all_link($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The link to export this tour.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_export_link() {
|
||||
return helper::get_export_tour_link($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The link to remove this tour.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_delete_link() {
|
||||
return helper::get_delete_tour_link($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare this tour for saving to the database.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function to_record() {
|
||||
return (object) array(
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'pathmatch' => $this->pathmatch,
|
||||
'enabled' => $this->enabled,
|
||||
'sortorder' => $this->sortorder,
|
||||
'configdata' => json_encode($this->config),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sortorder for this tour.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_sortorder() {
|
||||
return (int) $this->sortorder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this tour is the first tour.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_first_tour() {
|
||||
return ($this->get_sortorder() === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this tour is the last tour.
|
||||
*
|
||||
* @param int $tourcount The pre-fetched count of tours
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_last_tour($tourcount = null) {
|
||||
if ($tourcount === null) {
|
||||
$tourcount = helper::count_tours();
|
||||
}
|
||||
return ($this->get_sortorder() === ($tourcount - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sortorder for this tour.
|
||||
*
|
||||
* @param int $value The new sortorder to use.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_sortorder($value) {
|
||||
$this->sortorder = $value;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the next sort-order value.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function calculate_sortorder() {
|
||||
$this->sortorder = helper::count_tours();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to move this tour up in the sortorder.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_moveup_link() {
|
||||
return helper::get_move_tour_link($this->get_id(), helper::MOVE_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link to move this tour down in the sortorder.
|
||||
*
|
||||
* @return moodle_url
|
||||
*/
|
||||
public function get_movedown_link() {
|
||||
return helper::get_move_tour_link($this->get_id(), helper::MOVE_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the specified configuration item.
|
||||
*
|
||||
* @param string $key The configuration key to set.
|
||||
* @param mixed $default The default value to use if a value was not found.
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_config($key = null, $default = null) {
|
||||
if ($this->config === null) {
|
||||
$this->config = (object) array();
|
||||
}
|
||||
if ($key === null) {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
if (property_exists($this->config, $key)) {
|
||||
return $this->config->$key;
|
||||
}
|
||||
|
||||
if ($default !== null) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return configuration::get_default_value($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration item as specified.
|
||||
*
|
||||
* @param string $key The configuration key to set.
|
||||
* @param mixed $value The new value for the configuration item.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_config($key, $value) {
|
||||
if ($this->config === null) {
|
||||
$this->config = (object) array();
|
||||
}
|
||||
$this->config->$key = $value;
|
||||
$this->dirty = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the tour and it's configuration to the database.
|
||||
*
|
||||
* @param boolean $force Whether to force writing to the database.
|
||||
* @return $this
|
||||
*/
|
||||
public function persist($force = false) {
|
||||
global $DB;
|
||||
|
||||
if (!$this->dirty && !$force) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->id) {
|
||||
$record = $this->to_record();
|
||||
$DB->update_record('tool_usertours_tours', $record);
|
||||
} else {
|
||||
$this->calculate_sortorder();
|
||||
$record = $this->to_record();
|
||||
unset($record->id);
|
||||
$this->id = $DB->insert_record('tool_usertours_tours', $record);
|
||||
}
|
||||
|
||||
$this->reload();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this step.
|
||||
*/
|
||||
public function remove() {
|
||||
global $DB;
|
||||
|
||||
if ($this->id === null) {
|
||||
// Nothing to delete - this tour has not been persisted.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Delete all steps associated with this tour.
|
||||
// Note, although they are currently just DB records, there may be other components in the future.
|
||||
foreach ($this->get_steps() as $step) {
|
||||
$step->remove();
|
||||
}
|
||||
|
||||
// Remove the configuration for the tour.
|
||||
$DB->delete_records('tool_usertours_tours', array('id' => $this->id));
|
||||
|
||||
helper::reset_tour_sortorder();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the sortorder for all steps in the tour.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function reset_step_sortorder() {
|
||||
global $DB;
|
||||
$steps = $DB->get_records('tool_usertours_steps', array('tourid' => $this->id), 'sortorder ASC', 'id');
|
||||
|
||||
$index = 0;
|
||||
foreach ($steps as $step) {
|
||||
$DB->set_field('tool_usertours_steps', 'sortorder', $index, array('id' => $step->id));
|
||||
$index++;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this tour should be displayed to the user.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function should_show_for_user() {
|
||||
if (!$this->is_enabled()) {
|
||||
// The tour is disabled - it should not be shown.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($tourcompletiondate = get_user_preferences(self::TOUR_LAST_COMPLETED_BY_USER . $this->get_id(), null)) {
|
||||
if ($tourresetdate = get_user_preferences(self::TOUR_REQUESTED_BY_USER . $this->get_id(), null)) {
|
||||
if ($tourresetdate >= $tourcompletiondate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$lastmajorupdate = $this->get_config('majorupdatetime', time());
|
||||
if ($tourcompletiondate > $lastmajorupdate) {
|
||||
// The user has completed the tour since the last major update.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key for this tour.
|
||||
* This is used in the session cookie to determine whether the user has seen this tour before.
|
||||
*/
|
||||
public function get_tour_key() {
|
||||
$tourtime = $this->get_config('majorupdatetime', null);
|
||||
|
||||
if ($tourtime === null) {
|
||||
// This tour has no majorupdate time.
|
||||
// Set one now to prevent repeated displays to the user.
|
||||
$this->set_config('majorupdatetime', time());
|
||||
$this->persist();
|
||||
$tourtime = $this->get_config('majorupdatetime', null);
|
||||
}
|
||||
|
||||
if ($userresetdate = get_user_preferences(self::TOUR_REQUESTED_BY_USER . $this->get_id(), null)) {
|
||||
$tourtime = max($tourtime, $userresetdate);
|
||||
}
|
||||
|
||||
return sprintf('tool_usertours_%d_%s', $this->get_id(), $tourtime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the requested by user date.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function request_user_reset() {
|
||||
set_user_preference(self::TOUR_REQUESTED_BY_USER . $this->get_id(), time());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this tour as completed for this user.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function mark_user_completed() {
|
||||
set_user_preference(self::TOUR_LAST_COMPLETED_BY_USER . $this->get_id(), time());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a tour giving it a new major update time.
|
||||
* This will ensure that it is displayed to all users, even those who have already seen it.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function mark_major_change() {
|
||||
global $DB;
|
||||
|
||||
// Clear old reset and completion notes.
|
||||
$DB->delete_records('user_preferences', ['name' => self::TOUR_LAST_COMPLETED_BY_USER . $this->get_id()]);
|
||||
$DB->delete_records('user_preferences', ['name' => self::TOUR_REQUESTED_BY_USER . $this->get_id()]);
|
||||
$this->set_config('majorupdatetime', time());
|
||||
$this->persist();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the step configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
* @return $this
|
||||
*/
|
||||
public function add_config_to_form(\MoodleQuickForm &$mform) {
|
||||
$options = configuration::get_placement_options();
|
||||
$mform->addElement('select', 'placement', get_string('placement', 'tool_usertours'), $options);
|
||||
$mform->addHelpButton('placement', 'placement', 'tool_usertours');
|
||||
|
||||
$this->add_config_field_to_form($mform, 'orphan');
|
||||
$this->add_config_field_to_form($mform, 'backdrop');
|
||||
$this->add_config_field_to_form($mform, 'reflex');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified step field configuration to the form.
|
||||
*
|
||||
* @param MoodleQuickForm $mform The form to add configuration to.
|
||||
* @param string $key The key to add.
|
||||
* @return $this
|
||||
*/
|
||||
protected function add_config_field_to_form(\MoodleQuickForm &$mform, $key) {
|
||||
$options = [
|
||||
true => get_string('yes'),
|
||||
false => get_string('no'),
|
||||
];
|
||||
$mform->addElement('select', $key, get_string($key, 'tool_usertours'), $options);
|
||||
$mform->setDefault($key, configuration::get_default_value($key));
|
||||
$mform->addHelpButton($key, $key, 'tool_usertours');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the configuration data for the moodle form.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function prepare_data_for_form() {
|
||||
$data = $this->to_record();
|
||||
foreach (configuration::get_defaultable_keys() as $key) {
|
||||
$data->$key = $this->get_config($key, configuration::get_default_value($key));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configured filter values.
|
||||
*
|
||||
* @param string $filter The filter to retrieve values for.
|
||||
* @return array
|
||||
*/
|
||||
public function get_filter_values($filter) {
|
||||
if ($allvalues = (array) $this->get_config('filtervalues')) {
|
||||
if (isset($allvalues[$filter])) {
|
||||
return $allvalues[$filter];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the values for the specified filter.
|
||||
*
|
||||
* @param string $filter The filter to set.
|
||||
* @param array $values The values to set.
|
||||
* @return $this
|
||||
*/
|
||||
public function set_filter_values($filter, array $values = []) {
|
||||
$allvalues = (array) $this->get_config('filtervalues', []);
|
||||
$allvalues[$filter] = $values;
|
||||
|
||||
return $this->set_config('filtervalues', $allvalues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this tour matches all filters.
|
||||
*
|
||||
* @param context $context The context to check
|
||||
* @return bool
|
||||
*/
|
||||
public function matches_all_filters(\context $context) {
|
||||
$filters = helper::get_all_filters();
|
||||
|
||||
// All filters must match.
|
||||
// If any one filter fails to match, we return false.
|
||||
foreach ($filters as $filterclass) {
|
||||
if (!$filterclass::filter_matches($this, $context)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Configuration page.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
$action = optional_param('action', \tool_usertours\manager::ACTION_LISTTOURS, PARAM_ALPHANUMEXT);
|
||||
|
||||
$pluginmanager = new \tool_usertours\manager();
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
$pluginmanager->execute(
|
||||
$action
|
||||
);
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Plugin capabilities.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$capabilities = array(
|
||||
'tool/usertours:managetours' => [
|
||||
'captype' => 'write',
|
||||
'riskbitmask' => RISK_XSS,
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'archetypes' => [
|
||||
'manager' => CAP_ALLOW,
|
||||
]
|
||||
],
|
||||
);
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Install code for tours.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
/**
|
||||
* Perform the post-install procedures.
|
||||
*/
|
||||
function xmldb_tool_usertours_install() {
|
||||
global $DB;
|
||||
|
||||
$localplugin = core_plugin_manager::instance()->get_plugin_info('local_usertours');
|
||||
if ($localplugin) {
|
||||
// If the old local plugin was previously installed, copy over the data from the old tables.
|
||||
|
||||
// The 'comment' field was renamed to 'description' in:
|
||||
// * 3.0 version 2015111604
|
||||
// * 3.1 version 2016052303
|
||||
// We need to attempt to fetch comment for these older versions.
|
||||
$hasdescription = ($localplugin->versiondb < 2016052301 && $localplugin->versiondb >= 2015111604);
|
||||
$hasdescription = $hasdescription || ($localplugin->versiondb > 2016052303);
|
||||
|
||||
$tours = $DB->get_recordset('usertours_tours');
|
||||
$mapping = [];
|
||||
foreach ($tours as $tour) {
|
||||
if (!$hasdescription) {
|
||||
if (property_exists($tour, 'comment')) {
|
||||
$tour->description = $tour->comment;
|
||||
unset($tour->comment);
|
||||
} else {
|
||||
$tour->description = '';
|
||||
}
|
||||
}
|
||||
$mapping[$tour->id] = $DB->insert_record('tool_usertours_tours', $tour);
|
||||
}
|
||||
$tours->close();
|
||||
|
||||
$steps = $DB->get_recordset('usertours_steps');
|
||||
foreach ($steps as $step) {
|
||||
if (!isset($mapping[$step->tourid])) {
|
||||
// Skip this one. It has somehow become orphaned.
|
||||
continue;
|
||||
}
|
||||
$step->tourid = $mapping[$step->tourid];
|
||||
$DB->insert_record('tool_usertours_steps', $step);
|
||||
}
|
||||
$steps->close();
|
||||
|
||||
// Delete the old records.
|
||||
$DB->delete_records('usertours_steps', null);
|
||||
$DB->delete_records('usertours_tours', null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="tool/usertours/db" VERSION="20160830" COMMENT="XMLDB file for Moodle tool/usertours"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
<TABLES>
|
||||
<TABLE NAME="tool_usertours_tours" COMMENT="List of tours">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="Name of the user tour"/>
|
||||
<FIELD NAME="description" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
|
||||
<FIELD NAME="pathmatch" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
|
||||
<FIELD NAME="enabled" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="configdata" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="tool_usertours_steps" COMMENT="Steps in an tour">
|
||||
<FIELDS>
|
||||
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
|
||||
<FIELD NAME="tourid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="title" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Title of the step"/>
|
||||
<FIELD NAME="content" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Content of the user tour - allow for multilang tags"/>
|
||||
<FIELD NAME="targettype" TYPE="int" LENGTH="2" NOTNULL="true" SEQUENCE="false" COMMENT="Type of the target (e.g. block, CSS selector, etc.)"/>
|
||||
<FIELD NAME="targetvalue" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The value for the specified target type."/>
|
||||
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="configdata" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
<KEY NAME="tourid-tour" TYPE="foreign" FIELDS="tourid" REFTABLE="tool_usertours_tours" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="orderedsteps" UNIQUE="false" FIELDS="tourid, sortorder"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
</TABLES>
|
||||
</XMLDB>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* List of Web Services for the tool_usertours plugin.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$functions = array(
|
||||
'tool_usertours_fetch_and_start_tour' => array(
|
||||
'classname' => 'tool_usertours\external\tour',
|
||||
'methodname' => 'fetch_and_start_tour',
|
||||
'description' => 'Fetch the specified tour',
|
||||
'type' => 'read',
|
||||
'capabilities' => '',
|
||||
'ajax' => true,
|
||||
),
|
||||
|
||||
'tool_usertours_step_shown' => array(
|
||||
'classname' => 'tool_usertours\external\tour',
|
||||
'methodname' => 'step_shown',
|
||||
'description' => 'Mark the specified step as completed for the current user',
|
||||
'type' => 'write',
|
||||
'capabilities' => '',
|
||||
'ajax' => true,
|
||||
),
|
||||
|
||||
'tool_usertours_complete_tour' => array(
|
||||
'classname' => 'tool_usertours\external\tour',
|
||||
'methodname' => 'complete_tour',
|
||||
'description' => 'Mark the specified tour as completed for the current user',
|
||||
'type' => 'write',
|
||||
'capabilities' => '',
|
||||
'ajax' => true,
|
||||
),
|
||||
|
||||
'tool_usertours_reset_tour' => array(
|
||||
'classname' => 'tool_usertours\external\tour',
|
||||
'methodname' => 'reset_tour',
|
||||
'description' => 'Remove the specified tour',
|
||||
'type' => 'write',
|
||||
'capabilities' => '',
|
||||
'ajax' => true,
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Strings for tool_usertours.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['actions'] = 'Actions';
|
||||
$string['appliesto'] = 'Applies to';
|
||||
$string['block'] = 'Block';
|
||||
$string['block_named'] = 'Block named \'{$a}\'';
|
||||
$string['bottom'] = 'Bottom';
|
||||
$string['description'] = 'Description';
|
||||
$string['confirmstepremovalquestion'] = 'Are you sure that you wish to remove this step?';
|
||||
$string['confirmstepremovaltitle'] = 'Confirm step removal';
|
||||
$string['confirmtourremovalquestion'] = 'Are you sure that you wish to remove this tour?';
|
||||
$string['confirmtourremovaltitle'] = 'Confirm tour removal';
|
||||
$string['content'] = 'Content';
|
||||
$string['content_help'] = 'This is the content of the step.
|
||||
You can enter a content in the following formats:
|
||||
<dl>
|
||||
<dt>Plain text</dt>
|
||||
<dd>A plain text description</dd>
|
||||
<dt>Moodle MultiLang</dt>
|
||||
<dd>A string which makes use of the Moodle MultiLang format</dd>
|
||||
<dt>Moodle Translated string</dt>
|
||||
<dd>A value found in a standard Moodle language file in the format identifier,component</dd>
|
||||
</dl>';
|
||||
$string['cssselector'] = 'CSS Selector';
|
||||
$string['defaultvalue'] = 'Default ({$a})';
|
||||
$string['delay'] = 'Delay before showing the step';
|
||||
$string['done'] = 'Done';
|
||||
$string['editstep'] = 'Editing "{$a}"';
|
||||
$string['enabled'] = 'Enabled';
|
||||
$string['event_tour_started'] = 'Tour started';
|
||||
$string['event_tour_reset'] = 'Tour reset';
|
||||
$string['event_tour_ended'] = 'Tour ended';
|
||||
$string['event_step_shown'] = 'Step shown';
|
||||
$string['exporttour'] = 'Export tour';
|
||||
$string['filter_header'] = 'Tour filters';
|
||||
$string['filter_help'] = 'Your can choose which conditions your tour will be shown under.
|
||||
All of the filters must match for a tour to be shown to that user.';
|
||||
$string['filter_theme'] = 'Theme';
|
||||
$string['filter_theme_help'] = 'Show the tour when the user is using one of the selected themes.';
|
||||
$string['filter_role'] = 'Role';
|
||||
$string['filter_role_help'] = 'Only show the tour to users with one of the specified roles.';
|
||||
$string['importtour'] = 'Import tour';
|
||||
$string['left'] = 'Left';
|
||||
$string['movestepdown'] = 'Move step down';
|
||||
$string['movestepup'] = 'Move step up';
|
||||
$string['movetourdown'] = 'Move tour down';
|
||||
$string['movetourup'] = 'Move tour up';
|
||||
$string['name'] = 'Name';
|
||||
$string['newstep'] = 'Create step';
|
||||
$string['newstep'] = 'New step';
|
||||
$string['newtour'] = 'Create a new tour';
|
||||
$string['next'] = 'Next';
|
||||
$string['pathmatch'] = 'Apply to URL match';
|
||||
$string['pathmatch_help'] = 'Tours will be displayed on any page whose URL matches this value.
|
||||
|
||||
You can use the % character as a wildcard to mean anything.
|
||||
Some example values include:
|
||||
|
||||
* /my/% - to match the Dashboard
|
||||
* /course/view.php?id=2 - to match a specific course
|
||||
* /mod/forum/view.php% - to match the forum discussion list
|
||||
* /user/profile.php% - to match the user profile page';
|
||||
$string['placement'] = 'Placement';
|
||||
$string['pluginname'] = 'User Tours';
|
||||
$string['resettouronpage'] = 'Reset user tour on this page';
|
||||
$string['right'] = 'Right';
|
||||
$string['select_block'] = 'Select a block';
|
||||
$string['select_targettype'] = 'Every step is associated with a part of the page which you must choose. To make this easier there are several types of target for different types of page content.
|
||||
<dl>
|
||||
<dt>Block</dt>
|
||||
<dd>Display the step next to the first matching block of the type on the page</dd>
|
||||
<dt>Selector</dt>
|
||||
<dd>CSS Selectors are a powerful way which allow you to select different parts of the page based on metadata built into the page.</dd>
|
||||
<dt>Display in middle of the page</dt>
|
||||
<dd>Instead of associating the step with a specific part of the page you can have it displayed in the middle of the page.</dd>
|
||||
</dl>';
|
||||
$string['selector_defaulttitle'] = 'Enter a descriptive title';
|
||||
$string['selectordisplayname'] = 'A CSS selector matching \'{$a}\'';
|
||||
$string['skip'] = 'Skip';
|
||||
$string['target'] = 'Target';
|
||||
$string['target_block'] = 'Block';
|
||||
$string['target_selector'] = 'Selector';
|
||||
$string['target_unattached'] = 'Display in middle of page';
|
||||
$string['targettype'] = 'Target type';
|
||||
$string['title'] = 'Title';
|
||||
$string['title_help'] = 'This is the title shown at the top of the step.
|
||||
You can enter a title in the following formats:
|
||||
<dl>
|
||||
<dt>Plain text</dt>
|
||||
<dd>A plain text description</dd>
|
||||
<dt>Moodle MultiLang</dt>
|
||||
<dd>A string which makes use of the Moodle MultiLang format</dd>
|
||||
<dt>Moodle Translated string</dt>
|
||||
<dd>A value found in a standard Moodle language file in the format identifier,component</dd>
|
||||
</dl>';
|
||||
$string['top'] = 'Top';
|
||||
$string['tourconfig'] = 'Tour configuration file to import';
|
||||
$string['tourlist_explanation'] = 'You can create as many tours as you like and enable them for different parts of Moodle. Only one tour can be created per page.';
|
||||
$string['tours'] = 'Tours';
|
||||
$string['pausetour'] = 'Pause';
|
||||
$string['resumetour'] = 'Resume';
|
||||
$string['endtour'] = 'End tour';
|
||||
$string['orphan'] = 'Show if target not found';
|
||||
$string['orphan_help'] = 'Show the step if the target could not be found on the page.';
|
||||
$string['backdrop'] = 'Show with backdrop';
|
||||
$string['backdrop_help'] = 'You can use a backdrop to highlight the part of the page that you are pointing to.
|
||||
|
||||
Note: Backdrops are not compatible with some parts of the page such as the navigation bar.
|
||||
';
|
||||
$string['reflex'] = 'Move on click';
|
||||
$string['reflex_help'] = 'Move on to the next step when the target is clicked on.';
|
||||
$string['placement_help'] = 'You can place a step either above, below, to the left of, or to the right of the target.
|
||||
|
||||
The best options are top, or bottom as these adjust better for mobile display.';
|
||||
$string['delay_help'] = 'You can optionally choose to add a delay before the step is displayed.
|
||||
|
||||
This delay is in milliseconds.';
|
||||
$string['selecttype'] = 'Select step type';
|
||||
$string['sharedtourslink'] = 'Tour repository';
|
||||
$string['usertours'] = 'User tours';
|
||||
$string['usertours:managetours'] = 'Create, edit, and remove user tours';
|
||||
$string['target_selector_targetvalue'] = 'CSS Selectors';
|
||||
$string['target_selector_targetvalue_help'] = 'You can use a "CSS Selector" to target almost any element on the page.
|
||||
|
||||
CSS Selectors are very powerful and you can easily find parts of the page by building up the selector gradually.
|
||||
|
||||
Mozilla provide some [very good
|
||||
documentation](https://developer.mozilla.org/en/docs/Web/Guide/CSS/Getting_started/Selectors)
|
||||
for selectors which may help you to build your selectors.
|
||||
|
||||
You will also find your browser\'s developer tools to be extremely useful in creating these selectors:
|
||||
|
||||
* [Google Chrome](https://developer.chrome.com/devtools#dom-and-styles)
|
||||
* [Mozilla Firefox](https://developer.mozilla.org/en-US/docs/Tools/DOM_Property_Viewer)
|
||||
* [Microsoft Edge](https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/f12-devtools-guide/)
|
||||
* [Apple Safari](https://developer.apple.com/library/iad/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/ResourcesandtheDOM/ResourcesandtheDOM.html#//apple_ref/doc/uid/TP40007874-CH3-SW1)
|
||||
';
|
||||
$string['viewtour_info'] = 'This is the \'{$a->tourname}\' tour. It applies to the path \'{$a->path}\'.';
|
||||
$string['viewtour_edit'] = 'You can <a href="{$a->editlink}">edit the tour defaults</a> and <a href="{$a->resetlink}">force the tour to be displayed</a> to all users again.';
|
||||
$string['tour_resetforall'] = 'The state of the tour has been reset. It will be displayed to all users again.';
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tour.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use tool_usertours\helper;
|
||||
|
||||
/**
|
||||
* Manage inplace editable saves.
|
||||
*
|
||||
* @param string $itemtype The type of item.
|
||||
* @param int $itemid The ID of the item.
|
||||
* @param mixed $newvalue The new value
|
||||
* @return string
|
||||
*/
|
||||
function tool_usertours_inplace_editable($itemtype, $itemid, $newvalue) {
|
||||
$context = \context_system::instance();
|
||||
external_api::validate_context($context);
|
||||
require_capability('tool/usertours:managetours', $context);
|
||||
|
||||
if ($itemtype === 'tourname') {
|
||||
$tour = helper::get_tour($itemid);
|
||||
$tour->set_name($newvalue)->persist();
|
||||
|
||||
return helper::render_tourname_inplace_editable($tour);
|
||||
} else if ($itemtype === 'tourdescription') {
|
||||
$tour = helper::get_tour($itemid);
|
||||
$tour->set_description($newvalue)->persist();
|
||||
|
||||
return helper::render_tourdescription_inplace_editable($tour);
|
||||
} else if ($itemtype === 'tourenabled') {
|
||||
$tour = helper::get_tour($itemid);
|
||||
$tour->set_enabled(!!$newvalue)->persist();
|
||||
return helper::render_tourenabled_inplace_editable($tour);
|
||||
} else if ($itemtype === 'stepname') {
|
||||
$step = helper::get_step($itemid);
|
||||
$step->set_title($newvalue)->persist();
|
||||
|
||||
return helper::render_stepname_inplace_editable($step);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the user navigation to bootstrap tours.
|
||||
*/
|
||||
function tool_usertours_extend_navigation_user() {
|
||||
\tool_usertours\helper::bootstrap();
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 257 B |
@@ -0,0 +1,3 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M7.9 16c4 0 7.4-3 7.8-7h-3c-.5 2-2.5 4-4.9 4-2.8 0-5-2.2-5-5s2.2-5 5-5c1.1 0 2.1 0 3 1h-1c-.5 0-.8.5-.8 1.1v1c0 .5.3.9.8.9h5c.6 0 1.2-.4 1.2-.9v-5c0-.6-.6-1.1-1.2-1.1h-1c-.5 0-.8.5-.8 1.1V2C12 .9 9.9.2 8 .2 3.6.2 0 3.7 0 8.1 0 12.4 3.5 16 7.9 16z" fill="#999"/></svg>
|
||||
|
After Width: | Height: | Size: 571 B |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 266 B |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]>
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="12px" height="12px" viewBox="0 0 12 12" style="overflow:visible;enable-background:new 0 0 12 12;"
|
||||
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
|
||||
<defs>
|
||||
</defs>
|
||||
<path style="fill:#999999;" d="M12,7v4c0,0.5-0.5,1-1,1h-0.5l0,0H1c-0.5,0-1-0.5-1-1V7c0-0.5,0.5-1,1-1h0.5c0.5,0,1,0.5,1,1l0,2.5h7
|
||||
V7c0-0.5,0.5-1,1-1H11C11.5,6,12,6.5,12,7z M9.9,3.6L6.6,0.3C6.4,0.1,6.2,0,5.9,0C5.7,0,5.4,0.1,5.2,0.3L1.9,3.6
|
||||
C1.5,4,1.5,4.6,1.9,5l0.3,0.3c0.4,0.4,1,0.4,1.4,0l1-1.1l0,2.7c0,0.5,0.5,1,1,1l0.5,0c0.5,0,1-0.5,1-1l0-2.7l1,1
|
||||
c0.4,0.4,1,0.4,1.4,0L10,5C10.3,4.6,10.3,4,9.9,3.6z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
]>
|
||||
<svg version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
x="0px" y="0px" width="12px" height="12px" viewBox="0 0 12 12" style="overflow:visible;enable-background:new 0 0 12 12;"
|
||||
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
|
||||
<defs>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 637 B |
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Settings page.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die;
|
||||
|
||||
$capabilities = [
|
||||
'tool/usertours:managetours',
|
||||
];
|
||||
if ($hassiteconfig || has_any_capability($capabilities, context_system::instance())) {
|
||||
$ADMIN->add(
|
||||
'appearance',
|
||||
new admin_externalpage(
|
||||
'tool_usertours/tours',
|
||||
get_string('usertours', 'tool_usertours'),
|
||||
new moodle_url('/admin/tool/usertours/configure.php'),
|
||||
'tool/usertours:managetours'
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
div[data-flexitour="backdrop"] {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
span[data-flexitour="container"].orphan {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
span[data-flexitour="container"].orphan div[data-role="arrow"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body div[data-flexitour="step-background-fader"],
|
||||
body div[data-flexitour="step-background"] {
|
||||
position: absolute;
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
div[data-flexitour="step-background-fader"],
|
||||
[data-flexitour="step-backdrop"] > td,
|
||||
[data-flexitour="step-backdrop"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
span[data-flexitour="container"].orphan div[data-role="arrow"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.path-admin-local-usertours .stepcreator .input-append {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.tour-actions > ul {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-actions > ul > li {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.tour-actions > ul {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tour-actions > ul > li {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #ccc;
|
||||
display: inline-block;
|
||||
height: 9em;
|
||||
margin: .5em;
|
||||
text-align: center;
|
||||
width: 13em;
|
||||
}
|
||||
|
||||
.tour-actions > ul > li > a {
|
||||
height: 100%;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_usertours/selecttarget
|
||||
|
||||
Template for selecting the type of step target in a dialogue.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* targetTypes [object]
|
||||
** type
|
||||
** title
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"targetType": [
|
||||
{
|
||||
type: 1,
|
||||
title: "CSS Selector"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}}
|
||||
<span class="stepcreator" data-step="selecttarget">
|
||||
<form>
|
||||
<label for="select_targettype">{{# str }} select_targettype, tool_usertours {{/ str }}</label>
|
||||
<div class="input-append">
|
||||
<select name="targettype" id="select_targettype" class="input-xlarge">
|
||||
{{# targetTypes }}
|
||||
<option value="{{ type }}">
|
||||
{{ title }}
|
||||
</option>
|
||||
{{/ targetTypes }}
|
||||
</select>
|
||||
<button class="btn next" type="submit">
|
||||
{{# str }} next, tool_usertours {{/ str }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</span>
|
||||
@@ -0,0 +1,62 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_usertours/tourstep
|
||||
|
||||
Template used as a template to render step bubbles with their content
|
||||
in a user tour.
|
||||
|
||||
Classes required for JS:
|
||||
* arrow
|
||||
* popover-title
|
||||
* popover-content
|
||||
* popover-navigation
|
||||
* popover-title
|
||||
|
||||
Data attributes required for JS:
|
||||
* data-role=prev
|
||||
* data-role=next
|
||||
* data-role=pause-resume
|
||||
* data-pause-text
|
||||
* data-resume-text
|
||||
* data-role=end
|
||||
* data-placeholder=body
|
||||
* data-placeholder=title
|
||||
|
||||
Context variables required for this template:
|
||||
* None
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
|
||||
}}
|
||||
<div class="modal" data-role="flexitour-step">
|
||||
<div data-role="arrow"></div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true" data-role="end">×</button>
|
||||
<h3 data-placeholder="title"></h3>
|
||||
</div>
|
||||
<div class="modal-body" data-placeholder="body"></div>
|
||||
<div class="modal-footer">
|
||||
<div class="btn-group">
|
||||
<button href="#" class="btn" data-role="previous">{{# str }} previous, moodle {{/ str }}</button>
|
||||
<button href="#" class="btn btn-primary" data-role="next">{{# str }} next, moodle {{/ str }}</button>
|
||||
</div>
|
||||
<button class="btn" data-role="end"> {{# str }} endtour, tool_usertours {{/ str }} </button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* User tour related steps definitions.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @category test
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
|
||||
|
||||
use Behat\Gherkin\Node\TableNode as TableNode;
|
||||
/**
|
||||
* User tour related steps definitions.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @category test
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_tool_usertours extends behat_base {
|
||||
|
||||
/**
|
||||
* Add a new user tour.
|
||||
*
|
||||
* @Given /^I add a new user tour with:$/
|
||||
* @param TableNode $table
|
||||
*/
|
||||
public function i_add_a_new_user_tour_with(TableNode $table) {
|
||||
$this->execute('behat_tool_usertours::i_open_the_user_tour_settings_page');
|
||||
$this->execute('behat_general::click_link', get_string('newtour', 'tool_usertours'));
|
||||
|
||||
// Fill form and post.
|
||||
$this->execute('behat_forms::i_set_the_following_fields_to_these_values', $table);
|
||||
$this->execute('behat_forms::press_button', get_string('savechanges', 'moodle'));
|
||||
$this->execute('behat_general::i_wait_to_be_redirected');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new steps to a user tour.
|
||||
*
|
||||
* @Given /^I add steps to the "(?P<tour_name_string>(?:[^"]|\\")*)" tour:$/
|
||||
* @param string $tourname The name of the tour to add steps to.
|
||||
* @param TableNode $table
|
||||
*/
|
||||
public function i_add_steps_to_the_named_tour($tourname, TableNode $table) {
|
||||
$this->execute('behat_tool_usertours::i_open_the_user_tour_settings_page');
|
||||
$this->execute('behat_general::click_link', $this->escape($tourname));
|
||||
|
||||
foreach ($table->getHash() as $step) {
|
||||
$this->execute('behat_general::click_link', get_string('newstep', 'tool_usertours'));
|
||||
|
||||
foreach ($step as $locator => $value) {
|
||||
$this->execute('behat_forms::i_set_the_field_to', [$this->escape($locator), $this->escape($value)]);
|
||||
}
|
||||
|
||||
$this->execute('behat_forms::press_button', get_string('savechanges', 'moodle'));
|
||||
$this->execute('behat_general::i_wait_to_be_redirected');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to the user tour settings page.
|
||||
*
|
||||
* @Given /^I open the User tour settings page$/
|
||||
*/
|
||||
public function i_open_the_user_tour_settings_page() {
|
||||
$this->execute('behat_navigation::i_navigate_to_node_in', [
|
||||
get_string('usertours', 'tool_usertours'),
|
||||
implode(' > ', [
|
||||
get_string('administrationsite', 'moodle'),
|
||||
get_string('appearance', 'admin'),
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
@tool @tool_usertours
|
||||
Feature: Add a new user tour
|
||||
In order to help users learn of new features
|
||||
As an administrator
|
||||
I need to create a user tour
|
||||
|
||||
@javascript
|
||||
Scenario: Add a new tour
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And I log in as "admin"
|
||||
And I add a new user tour with:
|
||||
| Name | First tour |
|
||||
| Description | My first tour |
|
||||
| Apply to URL match | /my/% |
|
||||
| Enabled | 1 |
|
||||
And I add steps to the "First tour" tour:
|
||||
| targettype | Title | Content |
|
||||
| Display in middle of page | Welcome | Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful |
|
||||
And I add steps to the "First tour" tour:
|
||||
| targettype | targetvalue_block | Title | Content |
|
||||
| Block | Course overview | Course overview | This area shows you what's happening in some of your courses |
|
||||
| Block | Calendar | Calendar | This is the Calendar. All of your assignments and due dates can be found here |
|
||||
And I add steps to the "First tour" tour:
|
||||
| targettype | targetvalue_selector | Title | Content |
|
||||
| Selector | .usermenu | User menu | This is your personal user menu. You'll find your personal preferences and your user profile here. |
|
||||
When I click on "Dashboard" "link" in the "Navigation" "block"
|
||||
Then I should see "Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful"
|
||||
And I press "Next"
|
||||
And I should see "This area shows you what's happening in some of your courses"
|
||||
And I should not see "This is the Calendar. All of your assignments and due dates can be found here"
|
||||
And I press "Next"
|
||||
And I should see "This is the Calendar. All of your assignments and due dates can be found here"
|
||||
And I should not see "This area shows you what's happening in some of your courses"
|
||||
And I press "Prev"
|
||||
And I should not see "This is the Calendar. All of your assignments and due dates can be found here"
|
||||
And I should see "This area shows you what's happening in some of your courses"
|
||||
And I press "End tour"
|
||||
And I should not see "This area shows you what's happening in some of your courses"
|
||||
And I click on "Dashboard" "link" in the "Navigation" "block"
|
||||
And I should not see "Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful"
|
||||
And I should not see "This area shows you what's happening in some of your courses"
|
||||
And I follow "Reset user tour on this page"
|
||||
And I should see "Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful"
|
||||
|
||||
@javascript
|
||||
Scenario: A hidden tour should not be visible
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And I log in as "admin"
|
||||
And I add a new user tour with:
|
||||
| Name | First tour |
|
||||
| Description | My first tour |
|
||||
| Apply to URL match | /my/% |
|
||||
| Enabled | 0 |
|
||||
And I add steps to the "First tour" tour:
|
||||
| targettype | Title | Content |
|
||||
| Display in middle of page | Welcome | Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful |
|
||||
When I click on "Dashboard" "link" in the "Navigation" "block"
|
||||
Then I should not see "Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful"
|
||||
|
||||
@javascript
|
||||
Scenario: Tour visibility can be toggled
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
And I log in as "admin"
|
||||
And I add a new user tour with:
|
||||
| Name | First tour |
|
||||
| Description | My first tour |
|
||||
| Apply to URL match | /my/% |
|
||||
| Enabled | 0 |
|
||||
And I add steps to the "First tour" tour:
|
||||
| targettype | Title | Content |
|
||||
| Display in middle of page | Welcome | Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful |
|
||||
And I open the User tour settings page
|
||||
When I click on "Enable" "link" in the "My first tour" "table_row"
|
||||
And I click on "Dashboard" "link" in the "Navigation" "block"
|
||||
Then I should see "Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful"
|
||||
@@ -0,0 +1,62 @@
|
||||
@tool @tool_usertours
|
||||
Feature: Apply tour filters to a tour
|
||||
In order to give more directed tours
|
||||
As an administrator
|
||||
I need to create a user tour with filters applied
|
||||
|
||||
@javascript
|
||||
Scenario: Add a tour for a different theme
|
||||
Given I log in as "admin"
|
||||
And I add a new user tour with:
|
||||
| Name | First tour |
|
||||
| Description | My first tour |
|
||||
| Apply to URL match | /my/% |
|
||||
| Enabled | 1 |
|
||||
| Theme | More |
|
||||
And I add steps to the "First tour" tour:
|
||||
| targettype | Title | Content |
|
||||
| Display in middle of page | Welcome | Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful |
|
||||
When I click on "Dashboard" "link" in the "Navigation" "block"
|
||||
Then I should not see "Welcome to your personal learning space. We'd like to give you a quick tour to show you some of the areas you may find helpful"
|
||||
|
||||
@javascript
|
||||
Scenario: Add a tour for a specific role
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | format | enablecompletion |
|
||||
| Course 1 | C1 | topics | 1 |
|
||||
And the following "users" exist:
|
||||
| username |
|
||||
| editor1 |
|
||||
| teacher1 |
|
||||
| student1 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| editor1 | C1 | editingteacher |
|
||||
| teacher1 | C1 | teacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I add a new user tour with:
|
||||
| Name | First tour |
|
||||
| Description | My first tour |
|
||||
| Apply to URL match | /course/view.php% |
|
||||
| Enabled | 1 |
|
||||
| Role | Student,Non-editing teacher |
|
||||
And I add steps to the "First tour" tour:
|
||||
| targettype | Title | Content |
|
||||
| Display in middle of page | Welcome | Welcome to your course tour.|
|
||||
And I log out
|
||||
And I log in as "editor1"
|
||||
And I am on site homepage
|
||||
When I follow "Course 1"
|
||||
Then I should not see "Welcome to your course tour."
|
||||
And I log out
|
||||
And I log in as "student1"
|
||||
And I am on site homepage
|
||||
And I follow "Course 1"
|
||||
And I should see "Welcome to your course tour."
|
||||
And I click on "End tour" "button"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I am on site homepage
|
||||
And I follow "Course 1"
|
||||
And I should see "Welcome to your course tour."
|
||||
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests for manager.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
|
||||
/**
|
||||
* Tests for step.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class manager_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* @var moodle_database
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Setup to store the DB reference.
|
||||
*/
|
||||
public function setUp() {
|
||||
global $DB;
|
||||
|
||||
$this->db = $DB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down to restore the original DB reference.
|
||||
*/
|
||||
public function tearDown() {
|
||||
global $DB;
|
||||
|
||||
$DB = $this->db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to mock the database.
|
||||
*
|
||||
* @return moodle_database
|
||||
*/
|
||||
public function mock_database() {
|
||||
global $DB;
|
||||
|
||||
$DB = $this->getMockBuilder('moodle_database')->getMock();
|
||||
|
||||
return $DB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider to ensure that all modification actions require the session key.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sesskey_required_provider() {
|
||||
$tourid = rand(1, 100);
|
||||
$stepid = rand(1, 100);
|
||||
|
||||
return [
|
||||
'Tour removal' => [
|
||||
'delete_tour',
|
||||
[$tourid],
|
||||
],
|
||||
'Step removal' => [
|
||||
'delete_step',
|
||||
[$stepid],
|
||||
],
|
||||
'Tour visibility' => [
|
||||
'show_hide_tour',
|
||||
[$tourid, true],
|
||||
],
|
||||
'Move step' => [
|
||||
'move_step',
|
||||
[$stepid],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that all modification actions require the session key.
|
||||
*
|
||||
* @dataProvider sesskey_required_provider
|
||||
* @param string $function The function to test
|
||||
* @param array $arguments The arguments to pass with it
|
||||
*/
|
||||
public function test_sesskey_required($function, $arguments) {
|
||||
$manager = new \tool_usertours\manager();
|
||||
|
||||
$rc = new \ReflectionClass('\tool_usertours\manager');
|
||||
$rcm = $rc->getMethod($function);
|
||||
$rcm->setAccessible(true);
|
||||
|
||||
$this->setExpectedException('moodle_exception', 'A required parameter (sesskey) was missing');
|
||||
$rcm->invokeArgs($manager, $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data Provider for get_matching_tours tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_matching_tours_provider() {
|
||||
global $CFG;
|
||||
|
||||
$alltours = [
|
||||
[
|
||||
'pathmatch' => '/my/%',
|
||||
'enabled' => false,
|
||||
'name' => 'Failure',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/my/%',
|
||||
'enabled' => true,
|
||||
'name' => 'My tour enabled',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/my/%',
|
||||
'enabled' => false,
|
||||
'name' => 'Failure',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/course/?id=%foo=bar',
|
||||
'enabled' => false,
|
||||
'name' => 'Failure',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/course/?id=%foo=bar',
|
||||
'enabled' => true,
|
||||
'name' => 'course tour with additional params enabled',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/course/?id=%foo=bar',
|
||||
'enabled' => false,
|
||||
'name' => 'Failure',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/course/?id=%',
|
||||
'enabled' => false,
|
||||
'name' => 'Failure',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/course/?id=%',
|
||||
'enabled' => true,
|
||||
'name' => 'course tour enabled',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
[
|
||||
'pathmatch' => '/course/?id=%',
|
||||
'enabled' => false,
|
||||
'name' => 'Failure',
|
||||
'description' => '',
|
||||
'configdata' => '',
|
||||
],
|
||||
];
|
||||
|
||||
return [
|
||||
'No matches found' => [
|
||||
$alltours,
|
||||
$CFG->wwwroot . '/some/invalid/value',
|
||||
null,
|
||||
],
|
||||
'Never return a disabled tour' => [
|
||||
$alltours,
|
||||
$CFG->wwwroot . '/my/index.php',
|
||||
'My tour enabled',
|
||||
],
|
||||
'My not course' => [
|
||||
$alltours,
|
||||
$CFG->wwwroot . '/my/index.php',
|
||||
'My tour enabled',
|
||||
],
|
||||
'My with params' => [
|
||||
$alltours,
|
||||
$CFG->wwwroot . '/my/index.php?id=42',
|
||||
'My tour enabled',
|
||||
],
|
||||
'Course with params' => [
|
||||
$alltours,
|
||||
$CFG->wwwroot . '/course/?id=42',
|
||||
'course tour enabled',
|
||||
],
|
||||
'Course with params and trailing content' => [
|
||||
$alltours,
|
||||
$CFG->wwwroot . '/course/?id=42&foo=bar',
|
||||
'course tour with additional params enabled',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for the get_matching_tours function.
|
||||
*
|
||||
* @dataProvider get_matching_tours_provider
|
||||
* @param array $alltours The list of tours to insert
|
||||
* @param string $url The URL to test
|
||||
* @param string $expected The name of the expected matching tour
|
||||
*/
|
||||
public function test_get_matching_tours($alltours, $url, $expected) {
|
||||
$this->resetAfterTest();
|
||||
|
||||
foreach ($alltours as $tourconfig) {
|
||||
$tourconfig = (object) $tourconfig;
|
||||
$tourconfig->id = null;
|
||||
$tour = \tool_usertours\tour::load_from_record($tourconfig, true);
|
||||
$tour->persist(true);
|
||||
}
|
||||
|
||||
$match = \tool_usertours\manager::get_matching_tours(new moodle_url($url));
|
||||
if ($expected === null) {
|
||||
$this->assertNull($match);
|
||||
} else {
|
||||
$this->assertEquals($expected, $match->get_name());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for the get_matching_tours function when requiring an upgrade
|
||||
*
|
||||
* @dataProvider get_matching_tours_provider
|
||||
* @param array $alltours The list of tours to insert
|
||||
* @param string $url The URL to test
|
||||
* @param string $expected The name of the expected matching tour
|
||||
*/
|
||||
public function test_get_matching_tours_requires_upgrade($alltours, $url, $expected) {
|
||||
$this->resetAfterTest();
|
||||
|
||||
global $CFG;
|
||||
unset($CFG->version);
|
||||
|
||||
foreach ($alltours as $tourconfig) {
|
||||
$tourconfig = (object) $tourconfig;
|
||||
$tourconfig->id = null;
|
||||
$tour = \tool_usertours\tour::load_from_record($tourconfig, true);
|
||||
$tour->persist(true);
|
||||
}
|
||||
|
||||
$this->assertNull(\tool_usertours\manager::get_matching_tours(new moodle_url($url)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests for role filter.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Tests for role filter.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_usertours_role_filter_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* @var $course Test course
|
||||
*/
|
||||
protected $course;
|
||||
|
||||
/**
|
||||
* @var $student Test student
|
||||
*/
|
||||
protected $student;
|
||||
|
||||
/**
|
||||
* @var $teacher Test teacher
|
||||
*/
|
||||
protected $teacher;
|
||||
|
||||
/**
|
||||
* @var $editingteacher Test editor
|
||||
*/
|
||||
protected $editingteacher;
|
||||
|
||||
/**
|
||||
* @var $roles List of all roles
|
||||
*/
|
||||
protected $roles;
|
||||
|
||||
public function setUp() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
$generator = $this->getDataGenerator();
|
||||
|
||||
$this->course = $generator->create_course();
|
||||
$this->roles = $DB->get_records_menu('role', [], null, 'shortname, id');
|
||||
$this->testroles = ['student', 'teacher', 'editingteacher'];
|
||||
|
||||
foreach ($this->testroles as $role) {
|
||||
$user = $this->$role = $generator->create_user();
|
||||
$generator->enrol_user($user->id, $this->course->id, $this->roles[$role]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the filter_matches function when any is set.
|
||||
*/
|
||||
public function test_filter_matches_any() {
|
||||
$context = \context_course::instance($this->course->id);
|
||||
|
||||
// Note: No need to persist this tour.
|
||||
$tour = new \tool_usertours\tour();
|
||||
$tour->set_filter_values('role', []);
|
||||
|
||||
// Note: The role filter does not use the context.
|
||||
foreach ($this->testroles as $role) {
|
||||
$this->setUser($this->$role);
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
|
||||
// The admin should always be able to view too.
|
||||
$this->setAdminUser();
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the filter_matches function when one role is set.
|
||||
*/
|
||||
public function test_filter_matches_single_role() {
|
||||
$context = \context_course::instance($this->course->id);
|
||||
|
||||
$roles = [
|
||||
$this->roles['student'],
|
||||
];
|
||||
|
||||
// Note: No need to persist this tour.
|
||||
$tour = new \tool_usertours\tour();
|
||||
$tour->set_filter_values('role', $roles);
|
||||
|
||||
// Note: The role filter does not use the context.
|
||||
foreach ($this->testroles as $role) {
|
||||
$this->setUser($this->$role);
|
||||
if ($role === 'student') {
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
} else {
|
||||
$this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
}
|
||||
|
||||
// The admin should always be able to view too.
|
||||
$this->setAdminUser();
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the filter_matches function when multiple roles are set.
|
||||
*/
|
||||
public function test_filter_matches_multiple_role() {
|
||||
$context = \context_course::instance($this->course->id);
|
||||
|
||||
$roles = [
|
||||
$this->roles['teacher'],
|
||||
$this->roles['editingteacher'],
|
||||
];
|
||||
|
||||
// Note: No need to persist this tour.
|
||||
$tour = new \tool_usertours\tour();
|
||||
$tour->set_filter_values('role', $roles);
|
||||
|
||||
// Note: The role filter does not use the context.
|
||||
foreach ($this->testroles as $role) {
|
||||
$this->setUser($this->$role);
|
||||
if ($role === 'student') {
|
||||
$this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
} else {
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
}
|
||||
|
||||
// The admin should always be able to view too.
|
||||
$this->setAdminUser();
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the filter_matches function when one user has multiple roles.
|
||||
*/
|
||||
public function test_filter_matches_multiple_role_one_user() {
|
||||
$context = \context_course::instance($this->course->id);
|
||||
|
||||
$roles = [
|
||||
$this->roles['student'],
|
||||
];
|
||||
|
||||
$this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->roles['teacher']);
|
||||
|
||||
// Note: No need to persist this tour.
|
||||
$tour = new \tool_usertours\tour();
|
||||
$tour->set_filter_values('role', $roles);
|
||||
|
||||
|
||||
// Note: The role filter does not use the context.
|
||||
foreach ($this->testroles as $role) {
|
||||
$this->setUser($this->$role);
|
||||
if ($role === 'student') {
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
} else {
|
||||
$this->assertFalse(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
}
|
||||
|
||||
// The admin should always be able to view too.
|
||||
$this->setAdminUser();
|
||||
$this->assertTrue(\tool_usertours\local\filter\role::filter_matches($tour, $context));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests for step.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Tests for step.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class step_output_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Data Provider for get_string_from_inpu.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_string_from_input_provider() {
|
||||
return [
|
||||
'Text' => [
|
||||
'example',
|
||||
'example',
|
||||
],
|
||||
'Text which looks like a langstring' => [
|
||||
'example,fakecomponent',
|
||||
'example,fakecomponent',
|
||||
],
|
||||
'Text which is a langstring' => [
|
||||
'administration,core',
|
||||
'Administration',
|
||||
],
|
||||
'Text which is a langstring but uses "moodle" instead of "core"' => [
|
||||
'administration,moodle',
|
||||
'Administration',
|
||||
],
|
||||
'Text which is a langstring, but with extra whitespace' => [
|
||||
' administration,moodle ',
|
||||
'Administration',
|
||||
],
|
||||
'Looks like a langstring, but has incorrect space around comma' => [
|
||||
'administration , moodle',
|
||||
'administration , moodle',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the get_string_from_input function returns translated
|
||||
* strings correctly.
|
||||
*
|
||||
* @dataProvider get_string_from_input_provider
|
||||
* @param string $string The string to test
|
||||
* @param string $expected The expected result
|
||||
*/
|
||||
public function test_get_string_from_input($string, $expected) {
|
||||
$rc = new ReflectionClass('\\tool_usertours\\output\\step');
|
||||
$rcm = $rc->getMethod('get_string_from_input');
|
||||
$rcm->setAccessible(true);
|
||||
$this->assertEquals($expected, $rcm->invoke(null, $string));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,806 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests for step.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/formslib.php');
|
||||
|
||||
/**
|
||||
* Tests for step.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class step_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* @var moodle_database
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Setup to store the DB reference.
|
||||
*/
|
||||
public function setUp() {
|
||||
global $DB;
|
||||
|
||||
$this->db = $DB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down to restore the original DB reference.
|
||||
*/
|
||||
public function tearDown() {
|
||||
global $DB;
|
||||
|
||||
$DB = $this->db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to mock the database.
|
||||
*
|
||||
* @return moodle_database
|
||||
*/
|
||||
public function mock_database() {
|
||||
global $DB;
|
||||
|
||||
$DB = $this->getMockBuilder('moodle_database')
|
||||
->getMock()
|
||||
;
|
||||
|
||||
return $DB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the dirty value tester.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dirty_value_provider() {
|
||||
return [
|
||||
'tourid' => [
|
||||
'tourid',
|
||||
[1],
|
||||
],
|
||||
'title' => [
|
||||
'title',
|
||||
['Lorem'],
|
||||
],
|
||||
'content' => [
|
||||
'content',
|
||||
['Lorem'],
|
||||
],
|
||||
'targettype' => [
|
||||
'targettype',
|
||||
['Lorem'],
|
||||
],
|
||||
'targetvalue' => [
|
||||
'targetvalue',
|
||||
['Lorem'],
|
||||
],
|
||||
'sortorder' => [
|
||||
'sortorder',
|
||||
[1],
|
||||
],
|
||||
'config' => [
|
||||
'config',
|
||||
['key', 'value'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the fetch function.
|
||||
*/
|
||||
public function test_fetch() {
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods(['reload_from_record'])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$idretval = rand(1, 100);
|
||||
$DB = $this->mock_database();
|
||||
$DB->method('get_record')
|
||||
->willReturn($idretval)
|
||||
;
|
||||
|
||||
$retval = rand(1, 100);
|
||||
$step->expects($this->once())
|
||||
->method('reload_from_record')
|
||||
->with($this->equalTo($idretval))
|
||||
->wilLReturn($retval)
|
||||
;
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcm = $rc->getMethod('fetch');
|
||||
$rcm->setAccessible(true);
|
||||
|
||||
$id = rand(1, 100);
|
||||
$this->assertEquals($retval, $rcm->invoke($step, 'fetch', $id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that setters mark things as dirty.
|
||||
*
|
||||
* @dataProvider dirty_value_provider
|
||||
* @param string $name The key to update
|
||||
* @param string $value The value to set
|
||||
*/
|
||||
public function test_dirty_values($name, $value) {
|
||||
$step = new \tool_usertours\step();
|
||||
$method = 'set_' . $name;
|
||||
call_user_func_array([$step, $method], $value);
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('dirty');
|
||||
$rcp->setAccessible(true);
|
||||
|
||||
$this->assertTrue($rcp->getValue($step));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for is_first_step.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function step_sortorder_provider() {
|
||||
return [
|
||||
[0, 5, true, false],
|
||||
[1, 5, false, false],
|
||||
[4, 5, false, true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test is_first_step.
|
||||
*
|
||||
* @dataProvider step_sortorder_provider
|
||||
* @param int $sortorder The sortorder to check
|
||||
* @param int $count Unused in this function
|
||||
* @param bool $isfirst Whether this is the first step
|
||||
* @param bool $islast Whether this is the last step
|
||||
*/
|
||||
public function test_is_first_step($sortorder, $count, $isfirst, $islast) {
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods(['get_sortorder'])
|
||||
->getMock();
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('get_sortorder')
|
||||
->willReturn($sortorder)
|
||||
;
|
||||
|
||||
$this->assertEquals($isfirst, $step->is_first_step());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test is_last_step.
|
||||
*
|
||||
* @dataProvider step_sortorder_provider
|
||||
* @param int $sortorder The sortorder to check
|
||||
* @param int $count Total number of steps for this test
|
||||
* @param bool $isfirst Whether this is the first step
|
||||
* @param bool $islast Whether this is the last step
|
||||
*/
|
||||
public function test_is_last_step($sortorder, $count, $isfirst, $islast) {
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods(['get_sortorder', 'get_tour'])
|
||||
->getMock();
|
||||
|
||||
$tour = $this->getMockBuilder(\tool_usertours\tour::class)
|
||||
->setMethods(['count_steps'])
|
||||
->getMock();
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('get_tour')
|
||||
->willReturn($tour)
|
||||
;
|
||||
|
||||
$tour->expects($this->once())
|
||||
->method('count_steps')
|
||||
->willReturn($count)
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('get_sortorder')
|
||||
->willReturn($sortorder)
|
||||
;
|
||||
|
||||
$this->assertEquals($islast, $step->is_last_step());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_config with no keys provided.
|
||||
*/
|
||||
public function test_get_config_no_keys() {
|
||||
$step = new \tool_usertours\step();
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('config');
|
||||
$rcp->setAccessible(true);
|
||||
|
||||
$allvalues = (object) [
|
||||
'some' => 'value',
|
||||
'another' => 42,
|
||||
'key' => [
|
||||
'somethingelse',
|
||||
],
|
||||
];
|
||||
|
||||
$rcp->setValue($step, $allvalues);
|
||||
|
||||
$this->assertEquals($allvalues, $step->get_config());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for get_config.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_config_provider() {
|
||||
$allvalues = (object) [
|
||||
'some' => 'value',
|
||||
'another' => 42,
|
||||
'key' => [
|
||||
'somethingelse',
|
||||
],
|
||||
];
|
||||
|
||||
$tourconfig = rand(1, 100);
|
||||
$forcedconfig = rand(1, 100);
|
||||
|
||||
return [
|
||||
'No initial config' => [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$tourconfig,
|
||||
false,
|
||||
$forcedconfig,
|
||||
(object) [],
|
||||
],
|
||||
'All values' => [
|
||||
$allvalues,
|
||||
null,
|
||||
null,
|
||||
$tourconfig,
|
||||
false,
|
||||
$forcedconfig,
|
||||
$allvalues,
|
||||
],
|
||||
'Valid string value' => [
|
||||
$allvalues,
|
||||
'some',
|
||||
null,
|
||||
$tourconfig,
|
||||
false,
|
||||
$forcedconfig,
|
||||
'value',
|
||||
],
|
||||
'Valid array value' => [
|
||||
$allvalues,
|
||||
'key',
|
||||
null,
|
||||
$tourconfig,
|
||||
false,
|
||||
$forcedconfig,
|
||||
['somethingelse'],
|
||||
],
|
||||
'Invalid value' => [
|
||||
$allvalues,
|
||||
'notavalue',
|
||||
null,
|
||||
$tourconfig,
|
||||
false,
|
||||
$forcedconfig,
|
||||
$tourconfig,
|
||||
],
|
||||
'Configuration value' => [
|
||||
$allvalues,
|
||||
'placement',
|
||||
null,
|
||||
$tourconfig,
|
||||
false,
|
||||
$forcedconfig,
|
||||
$tourconfig,
|
||||
],
|
||||
'Invalid value with default' => [
|
||||
$allvalues,
|
||||
'notavalue',
|
||||
'somedefault',
|
||||
$tourconfig,
|
||||
false,
|
||||
$forcedconfig,
|
||||
'somedefault',
|
||||
],
|
||||
'Value forced at target' => [
|
||||
$allvalues,
|
||||
'somevalue',
|
||||
'somedefault',
|
||||
$tourconfig,
|
||||
true,
|
||||
$forcedconfig,
|
||||
$forcedconfig,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_config with valid keys provided.
|
||||
*
|
||||
* @dataProvider get_config_provider
|
||||
* @param object $values The config values
|
||||
* @param string $key The key
|
||||
* @param mixed $default The default value
|
||||
* @param mixed $tourconfig The tour config
|
||||
* @param bool $isforced Whether the setting is forced
|
||||
* @param mixed $forcedvalue The example value
|
||||
* @param mixed $expected The expected value
|
||||
*/
|
||||
public function test_get_config_valid_keys($values, $key, $default, $tourconfig, $isforced, $forcedvalue, $expected) {
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods(['get_target', 'get_targettype', 'get_tour'])
|
||||
->getMock();
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('config');
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, $values);
|
||||
|
||||
$target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$target->expects($this->any())
|
||||
->method('is_setting_forced')
|
||||
->willReturn($isforced)
|
||||
;
|
||||
|
||||
$target->expects($this->any())
|
||||
->method('get_forced_setting_value')
|
||||
->with($this->equalTo($key))
|
||||
->willReturn($forcedvalue)
|
||||
;
|
||||
|
||||
$step->expects($this->any())
|
||||
->method('get_targettype')
|
||||
->willReturn('type')
|
||||
;
|
||||
|
||||
$step->expects($this->any())
|
||||
->method('get_target')
|
||||
->willReturn($target)
|
||||
;
|
||||
|
||||
$tour = $this->getMockBuilder(\tool_usertours\tour::class)
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$tour->expects($this->any())
|
||||
->method('get_config')
|
||||
->willReturn($tourconfig)
|
||||
;
|
||||
|
||||
$step->expects($this->any())
|
||||
->method('get_tour')
|
||||
->willReturn($tour)
|
||||
;
|
||||
|
||||
$this->assertEquals($expected, $step->get_config($key, $default));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for set_config.
|
||||
*/
|
||||
public function set_config_provider() {
|
||||
$allvalues = (object) [
|
||||
'some' => 'value',
|
||||
'another' => 42,
|
||||
'key' => [
|
||||
'somethingelse',
|
||||
],
|
||||
];
|
||||
|
||||
$randvalue = rand(1, 100);
|
||||
|
||||
$provider = [];
|
||||
|
||||
$newvalues = $allvalues;
|
||||
$newvalues->some = 'unset';
|
||||
$provider['Unset an existing value'] = [
|
||||
$allvalues,
|
||||
'some',
|
||||
null,
|
||||
$newvalues,
|
||||
];
|
||||
|
||||
$newvalues = $allvalues;
|
||||
$newvalues->some = $randvalue;
|
||||
$provider['Set an existing value'] = [
|
||||
$allvalues,
|
||||
'some',
|
||||
$randvalue,
|
||||
$newvalues,
|
||||
];
|
||||
|
||||
$provider['Set a new value'] = [
|
||||
$allvalues,
|
||||
'newkey',
|
||||
$randvalue,
|
||||
(object) array_merge((array) $allvalues, ['newkey' => $randvalue]),
|
||||
];
|
||||
|
||||
return $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that set_config works in the anticipated fashion.
|
||||
*
|
||||
* @dataProvider set_config_provider
|
||||
* @param mixed $initialvalues The inital value to set
|
||||
* @param string $key The key to test
|
||||
* @param mixed $newvalue The new value to set
|
||||
* @param mixed $expected The expected value
|
||||
*/
|
||||
public function test_set_config($initialvalues, $key, $newvalue, $expected) {
|
||||
$step = new \tool_usertours\step();
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('config');
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, $initialvalues);
|
||||
|
||||
$target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$target->expects($this->any())
|
||||
->method('is_setting_forced')
|
||||
->willReturn(false)
|
||||
;
|
||||
|
||||
$step->set_config($key, $newvalue);
|
||||
|
||||
$this->assertEquals($expected, $rcp->getValue($step));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that non-dirty tours are not persisted.
|
||||
*/
|
||||
public function test_persist_non_dirty() {
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods([
|
||||
'to_record',
|
||||
'reload',
|
||||
])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$step->expects($this->never())
|
||||
->method('to_record')
|
||||
;
|
||||
|
||||
$step->expects($this->never())
|
||||
->method('reload')
|
||||
;
|
||||
|
||||
$this->assertSame($step, $step->persist());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that new dirty steps are persisted.
|
||||
*/
|
||||
public function test_persist_dirty_new() {
|
||||
// Mock the database.
|
||||
$DB = $this->mock_database();
|
||||
$DB->expects($this->once())
|
||||
->method('insert_record')
|
||||
->willReturn(42)
|
||||
;
|
||||
|
||||
// Mock the tour.
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods([
|
||||
'to_record',
|
||||
'calculate_sortorder',
|
||||
'reload',
|
||||
])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('to_record')
|
||||
->willReturn((object)['id' => 42]);
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('calculate_sortorder')
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('reload')
|
||||
;
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('dirty');
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, true);
|
||||
|
||||
$this->assertSame($step, $step->persist());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that new non-dirty, forced steps are persisted.
|
||||
*/
|
||||
public function test_persist_force_new() {
|
||||
global $DB;
|
||||
|
||||
// Mock the database.
|
||||
$DB = $this->mock_database();
|
||||
$DB->expects($this->once())
|
||||
->method('insert_record')
|
||||
->willReturn(42)
|
||||
;
|
||||
|
||||
// Mock the tour.
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods([
|
||||
'to_record',
|
||||
'calculate_sortorder',
|
||||
'reload',
|
||||
])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('to_record')
|
||||
->willReturn((object)['id' => 42]);
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('calculate_sortorder')
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('reload')
|
||||
;
|
||||
|
||||
$this->assertSame($step, $step->persist(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that existing dirty steps are persisted.
|
||||
*/
|
||||
public function test_persist_dirty_existing() {
|
||||
// Mock the database.
|
||||
$DB = $this->mock_database();
|
||||
$DB->expects($this->once())
|
||||
->method('update_record')
|
||||
;
|
||||
|
||||
// Mock the tour.
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods([
|
||||
'to_record',
|
||||
'calculate_sortorder',
|
||||
'reload',
|
||||
])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('to_record')
|
||||
->willReturn((object)['id' => 42]);
|
||||
;
|
||||
|
||||
$step->expects($this->never())
|
||||
->method('calculate_sortorder')
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('reload')
|
||||
;
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('id');
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, 42);
|
||||
|
||||
$rcp = $rc->getProperty('dirty');
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, true);
|
||||
|
||||
$this->assertSame($step, $step->persist());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that existing non-dirty, forced steps are persisted.
|
||||
*/
|
||||
public function test_persist_force_existing() {
|
||||
global $DB;
|
||||
|
||||
// Mock the database.
|
||||
$DB = $this->mock_database();
|
||||
$DB->expects($this->once())
|
||||
->method('update_record')
|
||||
;
|
||||
|
||||
// Mock the tour.
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods([
|
||||
'to_record',
|
||||
'calculate_sortorder',
|
||||
'reload',
|
||||
])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('to_record')
|
||||
->willReturn((object)['id' => 42]);
|
||||
;
|
||||
|
||||
$step->expects($this->never())
|
||||
->method('calculate_sortorder')
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('reload')
|
||||
;
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('id');
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, 42);
|
||||
|
||||
$this->assertSame($step, $step->persist(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a tour which has never been persisted is removed correctly.
|
||||
*/
|
||||
public function test_remove_non_persisted() {
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods(null)
|
||||
->getMock()
|
||||
;
|
||||
|
||||
// Mock the database.
|
||||
$DB = $this->mock_database();
|
||||
$DB->expects($this->never())
|
||||
->method('delete_records')
|
||||
;
|
||||
|
||||
$this->assertNull($step->remove());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a tour which has been persisted is removed correctly.
|
||||
*/
|
||||
public function test_remove_persisted() {
|
||||
$id = rand(1, 100);
|
||||
|
||||
$tour = $this->getMockBuilder(\tool_usertours\tour::class)
|
||||
->setMethods([
|
||||
'reset_step_sortorder',
|
||||
])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$tour->expects($this->once())
|
||||
->method('reset_step_sortorder')
|
||||
;
|
||||
|
||||
$step = $this->getMockBuilder(\tool_usertours\step::class)
|
||||
->setMethods([
|
||||
'get_tour',
|
||||
])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$step->expects($this->once())
|
||||
->method('get_tour')
|
||||
->willReturn($tour)
|
||||
;
|
||||
|
||||
// Mock the database.
|
||||
$DB = $this->mock_database();
|
||||
$DB->expects($this->once())
|
||||
->method('delete_records')
|
||||
->with($this->equalTo('tool_usertours_steps'), $this->equalTo(['id' => $id]))
|
||||
;
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
$rcp = $rc->getProperty('id');
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, $id);
|
||||
|
||||
$this->assertEquals($id, $step->get_id());
|
||||
$this->assertNull($step->remove());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the get_ tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getter_provider() {
|
||||
return [
|
||||
'id' => [
|
||||
'id',
|
||||
rand(1, 100),
|
||||
],
|
||||
'tourid' => [
|
||||
'tourid',
|
||||
rand(1, 100),
|
||||
],
|
||||
'title' => [
|
||||
'title',
|
||||
'Lorem',
|
||||
],
|
||||
'content' => [
|
||||
'content',
|
||||
'Lorem',
|
||||
],
|
||||
'targettype' => [
|
||||
'targettype',
|
||||
'Lorem',
|
||||
],
|
||||
'targetvalue' => [
|
||||
'targetvalue',
|
||||
'Lorem',
|
||||
],
|
||||
'sortorder' => [
|
||||
'sortorder',
|
||||
rand(1, 100),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getters return the configured value.
|
||||
*
|
||||
* @dataProvider getter_provider
|
||||
* @param string $key The key to test
|
||||
* @param mixed $value The expected value
|
||||
*/
|
||||
public function test_getters($key, $value) {
|
||||
$step = new \tool_usertours\step();
|
||||
|
||||
$rc = new \ReflectionClass(\tool_usertours\step::class);
|
||||
|
||||
$rcp = $rc->getProperty($key);
|
||||
$rcp->setAccessible(true);
|
||||
$rcp->setValue($step, $value);
|
||||
|
||||
$getter = 'get_' . $key;
|
||||
|
||||
$this->assertEquals($value, $step->$getter());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests for theme filter.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Tests for theme filter.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_usertours_theme_filter_testcase extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Data Provider for filter_matches function.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filter_matches_provider() {
|
||||
return [
|
||||
'No config set; Matches' => [
|
||||
null,
|
||||
'boost',
|
||||
true,
|
||||
],
|
||||
'Empty config set; Matches' => [
|
||||
[],
|
||||
'boost',
|
||||
true,
|
||||
],
|
||||
'Single matching value set; Matches' => [
|
||||
['boost'],
|
||||
'boost',
|
||||
true,
|
||||
],
|
||||
'Multiple values set including matching; Matches' => [
|
||||
['boost', 'clean'],
|
||||
'boost',
|
||||
true,
|
||||
],
|
||||
'Single value set; No match' => [
|
||||
['clean'],
|
||||
'boost',
|
||||
false,
|
||||
],
|
||||
'Multiple values set; No match' => [
|
||||
['clean', 'artificial'],
|
||||
'boost',
|
||||
false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the filter_matches function.
|
||||
*
|
||||
* @dataProvider filter_matches_provider
|
||||
* @param array $filtervalues The filter values
|
||||
* @param string $currenttheme The name of the current theme
|
||||
* @param boolean $expected Whether the tour is expected to match
|
||||
*/
|
||||
public function test_filter_matches($filtervalues, $currenttheme, $expected) {
|
||||
global $PAGE;
|
||||
|
||||
$filtername = \tool_usertours\local\filter\theme::class;
|
||||
|
||||
// Note: No need to persist this tour.
|
||||
$tour = new \tool_usertours\tour();
|
||||
if ($filtervalues !== null) {
|
||||
$tour->set_filter_values('theme', $filtervalues);
|
||||
}
|
||||
|
||||
$PAGE->theme->name = $currenttheme;
|
||||
|
||||
// Note: The theme filter does not use the context.
|
||||
$this->assertEquals($expected, $filtername::filter_matches($tour, \context_system::instance()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<libraries>
|
||||
<library>
|
||||
<location>amd/src/tour.js</location>
|
||||
<name>Flexitour</name>
|
||||
<license>GPLv3</license>
|
||||
<version>0.9.6</version>
|
||||
<licenseversion>3</licenseversion>
|
||||
</library>
|
||||
<library>
|
||||
<location>amd/src/popper.js</location>
|
||||
<name>Popper.js</name>
|
||||
<license>MIT</license>
|
||||
<version>v0.6.4</version>
|
||||
<licenseversion></licenseversion>
|
||||
</library>
|
||||
</libraries>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Version information.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2016 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2016101800; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2016052300; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_usertours'; // Full name of the plugin (used for diagnostics).
|
||||
@@ -1908,7 +1908,7 @@ class core_plugin_manager {
|
||||
'dbtransfer', 'filetypes', 'generator', 'health', 'innodb', 'installaddon',
|
||||
'langimport', 'log', 'lp', 'lpimportcsv', 'lpmigrate', 'messageinbound', 'mobile', 'multilangupgrade', 'monitor',
|
||||
'phpunit', 'profiling', 'recyclebin', 'replace', 'spamcleaner', 'task', 'templatelibrary',
|
||||
'unittest', 'uploadcourse', 'uploaduser', 'unsuproles', 'xmldb'
|
||||
'unittest', 'uploadcourse', 'uploaduser', 'unsuproles', 'usertours', 'xmldb'
|
||||
),
|
||||
|
||||
'webservice' => array(
|
||||
|
||||
@@ -38,3 +38,4 @@ $breadcrumb-divider-rtl: "◀" !default;
|
||||
@import "moodle/expendable";
|
||||
@import "moodle/sticky-footer";
|
||||
@import "moodle/popover-region";
|
||||
@import "moodle/tool_usertours";
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Tour step must sit above all other UI components.
|
||||
* The backdrop is the lowest point in the tour.
|
||||
* Everything else is in the container, and the target background should be at the same z-index.
|
||||
* ----- moodle
|
||||
* ---- step backdrop
|
||||
* --- step container
|
||||
* --- step target background
|
||||
*/
|
||||
$flexitour-base-zindex: 1040;
|
||||
|
||||
// The backdrop is the backdrop used in 'modal' step display.
|
||||
div[data-flexitour="backdrop"] {
|
||||
background-color: #{$modal-backdrop-bg};
|
||||
opacity: #{$modal-backdrop-opacity};
|
||||
|
||||
// The backdrop needs to have a lower z-index than everything else in the tour, but higher than everything else in Moodle.
|
||||
z-index: #{$flexitour-base-zindex};
|
||||
}
|
||||
|
||||
// The step-background is used to highlight the region targetted in the step.
|
||||
div[data-flexitour="step-background-fader"],
|
||||
div[data-flexitour="step-background"] {
|
||||
@include border-radius($border-radius-lg);
|
||||
|
||||
// The step container, and the target background should be at the same z-index.
|
||||
z-index: #{$flexitour-base-zindex} + 1;
|
||||
}
|
||||
|
||||
span[data-flexitour="container"],
|
||||
div[data-flexitour="step-background-fader"],
|
||||
[data-flexitour="step-backdrop"] > td,
|
||||
[data-flexitour="step-backdrop"] {
|
||||
// The step container, and the target background should be at the same z-index.
|
||||
z-index: #{$flexitour-base-zindex} + 2;
|
||||
}
|
||||
|
||||
span[data-flexitour="container"] {
|
||||
.modal-dialog {
|
||||
/**
|
||||
* Remove all margins to:
|
||||
* 1) ensure that the arrow touches the target; and
|
||||
* 2) ensure that the focus border touches the modal.
|
||||
*/
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div[data-role="arrow"] {
|
||||
border-width: #{$popover-arrow-outer-width};
|
||||
}
|
||||
|
||||
div[data-role="arrow"],
|
||||
div[data-role="arrow"]:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: #{$popover-arrow-width};
|
||||
}
|
||||
|
||||
// We need to know the opposite sides for arrow placement.
|
||||
$opposites:
|
||||
(
|
||||
top: bottom,
|
||||
bottom: top,
|
||||
left: right,
|
||||
right: left,
|
||||
);
|
||||
|
||||
// These are the next leading side and allow for placement half-way along the step dialogue.
|
||||
$sides:
|
||||
(
|
||||
top: left,
|
||||
bottom: left,
|
||||
left: top,
|
||||
right: top,
|
||||
);
|
||||
|
||||
@each $direction in map-keys($opposites) {
|
||||
$opposite: map_get($opposites, $direction);
|
||||
$side: map_get($sides, $direction);
|
||||
$oppositeside: map_get($opposites, $side);
|
||||
|
||||
&[x-placement="#{$direction}"],
|
||||
&[x-placement="#{$direction}-start"] {
|
||||
margin-#{$opposite}: #{$popover-arrow-width};
|
||||
div[data-role="arrow"] {
|
||||
#{$opposite}: -#{$popover-arrow-outer-width};
|
||||
#{$side}: 50%;
|
||||
margin-#{$side}: -#{$popover-arrow-outer-width};
|
||||
border-#{$opposite}-width: 0;
|
||||
border-#{$direction}-color: #{$popover-arrow-outer-color};
|
||||
}
|
||||
div[data-role="arrow"]:after {
|
||||
#{$opposite}: 1px;
|
||||
margin-#{$side}: -#{$popover-arrow-width};
|
||||
content: " ";
|
||||
border-#{$opposite}-width: 0;
|
||||
border-#{$direction}-color: #{$popover-arrow-color};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template tool_usertours/tourstep
|
||||
|
||||
Template used as a template to render step bubbles with their content
|
||||
in a user tour.
|
||||
|
||||
Classes required for JS:
|
||||
* arrow
|
||||
* popover-title
|
||||
* popover-content
|
||||
* popover-navigation
|
||||
* popover-title
|
||||
|
||||
Data attributes required for JS:
|
||||
* data-role=prev
|
||||
* data-role=next
|
||||
* data-role=pause-resume
|
||||
* data-pause-text
|
||||
* data-resume-text
|
||||
* data-role=end
|
||||
* data-placeholder=body
|
||||
* data-placeholder=title
|
||||
|
||||
Context variables required for this template:
|
||||
* None
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
|
||||
}}
|
||||
<div class="modal-dialog" role="document" data-role="flexitour-step">
|
||||
<div class="modal-content">
|
||||
<div class="tooltip-arrow" data-role="arrow"></div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close" data-role="end">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title" data-placeholder="title"></h4>
|
||||
</div>
|
||||
<div class="modal-body" data-placeholder="body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-role="previous">{{# str }} previous, moodle {{/ str }}</button>
|
||||
<button type="button" class="btn btn-primary" data-role="next">{{# str }} next, moodle {{/ str }}</button>
|
||||
<button class="btn btn-secondary" data-role="end"> {{# str }} endtour, tool_usertours {{/ str }} </button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,6 +60,7 @@ body {
|
||||
@import "moodle/buttons";
|
||||
@import "moodle/grade";
|
||||
@import "moodle/dock";
|
||||
@import "moodle/tool_usertours";
|
||||
|
||||
// Styles for mustache templates.
|
||||
@import "moodle/templates";
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* Tour step must sit above all other UI components.
|
||||
* The backdrop is the lowest point in the tour.
|
||||
* Everything else is in the container, and the target background should be at the same z-index.
|
||||
* ----- moodle
|
||||
* ---- step backdrop
|
||||
* --- step container
|
||||
* --- step target background
|
||||
*/
|
||||
@flexitour-base-zindex: 4030;
|
||||
|
||||
// The backdrop is the backdrop used in 'modal' step display.
|
||||
div[data-flexitour="backdrop"] {
|
||||
.modal-backdrop();
|
||||
|
||||
// The backdrop needs to have a lower z-index than everything else in the tour, but higher than everything else in Moodle.
|
||||
z-index: @flexitour-base-zindex;
|
||||
}
|
||||
|
||||
// The step-background is used to highlight the region targetted in the step.
|
||||
div[data-flexitour="step-background-fader"],
|
||||
div[data-flexitour="step-background"] {
|
||||
.border-radius(6px);
|
||||
|
||||
// The step target background should be above the base.
|
||||
z-index: (@flexitour-base-zindex + 1);
|
||||
}
|
||||
|
||||
span[data-flexitour="container"],
|
||||
div[data-flexitour="step-background-fader"],
|
||||
[data-flexitour="step-backdrop"] > td,
|
||||
[data-flexitour="step-backdrop"] {
|
||||
// The step target background should be above the base.
|
||||
z-index: (@flexitour-base-zindex + 2);
|
||||
}
|
||||
|
||||
span[data-flexitour="container"] {
|
||||
div[data-role="flexitour-step"] {
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(0, 0, 0, .2);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
|
||||
|
||||
> div {
|
||||
// When targetting some regions, the selectors override the modal ones.
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
position: static;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
div[data-role="arrow"] {
|
||||
border-width: @popoverArrowOuterWidth;
|
||||
}
|
||||
|
||||
div[data-role="arrow"]:after {
|
||||
content: " ";
|
||||
}
|
||||
|
||||
div[data-role="arrow"],
|
||||
div[data-role="arrow"]:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: @popoverArrowWidth;
|
||||
}
|
||||
|
||||
&[x-placement="top"],
|
||||
&[x-placement="top-start"] {
|
||||
margin-bottom: @popoverArrowWidth;
|
||||
div[data-role="arrow"] {
|
||||
bottom: -@popoverArrowOuterWidth;
|
||||
left: 50%;
|
||||
margin-left: -@popoverArrowOuterWidth;
|
||||
border-bottom-width: 0;
|
||||
border-top-color: @popoverArrowOuterColor;
|
||||
}
|
||||
div[data-role="arrow"]:after {
|
||||
bottom: 1px;
|
||||
margin-left: -@popoverArrowWidth;
|
||||
border-bottom-width: 0;
|
||||
border-top-color: @popoverArrowColor;
|
||||
}
|
||||
}
|
||||
|
||||
&[x-placement="bottom"],
|
||||
&[x-placement="bottom-start"] {
|
||||
margin-top: @popoverArrowWidth;
|
||||
div[data-role="arrow"] {
|
||||
top: -@popoverArrowOuterWidth;
|
||||
left: 50%;
|
||||
margin-left: -@popoverArrowOuterWidth;
|
||||
border-top-width: 0;
|
||||
border-bottom-color: @popoverArrowOuterColor;
|
||||
}
|
||||
div[data-role="arrow"]:after {
|
||||
top: 1px;
|
||||
margin-left: -@popoverArrowWidth;
|
||||
border-top-width: 0;
|
||||
border-bottom-color: @popoverArrowColor;
|
||||
}
|
||||
}
|
||||
|
||||
&[x-placement="left"],
|
||||
&[x-placement="left-start"] {
|
||||
margin-right: @popoverArrowWidth;
|
||||
div[data-role="arrow"] {
|
||||
right: -@popoverArrowOuterWidth;
|
||||
top: 50%;
|
||||
margin-top: -@popoverArrowOuterWidth;
|
||||
border-right-width: 0;
|
||||
border-left-color: @popoverArrowOuterColor;
|
||||
}
|
||||
div[data-role="arrow"]:after {
|
||||
right: 1px;
|
||||
margin-top: -@popoverArrowWidth;
|
||||
border-right-width: 0;
|
||||
border-left-color: @popoverArrowColor;
|
||||
}
|
||||
}
|
||||
|
||||
&[x-placement="right"],
|
||||
&[x-placement="right-start"] {
|
||||
margin-left: @popoverArrowWidth;
|
||||
div[data-role="arrow"] {
|
||||
left: -@popoverArrowOuterWidth;
|
||||
top: 50%;
|
||||
margin-top: -@popoverArrowOuterWidth;
|
||||
border-left-width: 0;
|
||||
border-right-color: @popoverArrowOuterColor;
|
||||
}
|
||||
div[data-role="arrow"]:after {
|
||||
left: 1px;
|
||||
margin-top: -@popoverArrowWidth;
|
||||
border-left-width: 0;
|
||||
border-right-color: @popoverArrowColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16665,6 +16665,152 @@ body.has_dock div#dock {
|
||||
padding-left: 65px;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Tour step must sit above all other UI components.
|
||||
* The backdrop is the lowest point in the tour.
|
||||
* Everything else is in the container, and the target background should be at the same z-index.
|
||||
* ----- moodle
|
||||
* ---- step backdrop
|
||||
* --- step container
|
||||
* --- step target background
|
||||
*/
|
||||
div[data-flexitour="backdrop"] {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1040;
|
||||
background-color: #000;
|
||||
opacity: 0.8;
|
||||
filter: alpha(opacity=80);
|
||||
z-index: 4049;
|
||||
background-color: #aaa;
|
||||
opacity: 0.4;
|
||||
z-index: 4030;
|
||||
}
|
||||
div[data-flexitour="backdrop"].fade {
|
||||
opacity: 0;
|
||||
}
|
||||
div[data-flexitour="step-background-fader"],
|
||||
div[data-flexitour="step-background"] {
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
z-index: 4031;
|
||||
}
|
||||
span[data-flexitour="container"],
|
||||
div[data-flexitour="step-background-fader"],
|
||||
[data-flexitour="step-backdrop"] > td,
|
||||
[data-flexitour="step-backdrop"] {
|
||||
z-index: 4032;
|
||||
}
|
||||
span[data-flexitour="container"] div[data-role="flexitour-step"] {
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
span[data-flexitour="container"] div[data-role="flexitour-step"] > div {
|
||||
display: block;
|
||||
margin: 0;
|
||||
}
|
||||
span[data-flexitour="container"] .modal {
|
||||
position: static;
|
||||
margin-left: 0;
|
||||
}
|
||||
span[data-flexitour="container"] div[data-role="arrow"] {
|
||||
border-width: 11px;
|
||||
}
|
||||
span[data-flexitour="container"] div[data-role="arrow"]:after {
|
||||
content: " ";
|
||||
}
|
||||
span[data-flexitour="container"] div[data-role="arrow"],
|
||||
span[data-flexitour="container"] div[data-role="arrow"]:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: 10px;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="top"],
|
||||
span[data-flexitour="container"][x-placement="top-start"] {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="top"] div[data-role="arrow"],
|
||||
span[data-flexitour="container"][x-placement="top-start"] div[data-role="arrow"] {
|
||||
bottom: -11px;
|
||||
left: 50%;
|
||||
margin-left: -11px;
|
||||
border-bottom-width: 0;
|
||||
border-top-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="top"] div[data-role="arrow"]:after,
|
||||
span[data-flexitour="container"][x-placement="top-start"] div[data-role="arrow"]:after {
|
||||
bottom: 1px;
|
||||
margin-left: -10px;
|
||||
border-bottom-width: 0;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="bottom"],
|
||||
span[data-flexitour="container"][x-placement="bottom-start"] {
|
||||
margin-top: 10px;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="bottom"] div[data-role="arrow"],
|
||||
span[data-flexitour="container"][x-placement="bottom-start"] div[data-role="arrow"] {
|
||||
top: -11px;
|
||||
left: 50%;
|
||||
margin-left: -11px;
|
||||
border-top-width: 0;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="bottom"] div[data-role="arrow"]:after,
|
||||
span[data-flexitour="container"][x-placement="bottom-start"] div[data-role="arrow"]:after {
|
||||
top: 1px;
|
||||
margin-left: -10px;
|
||||
border-top-width: 0;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="left"],
|
||||
span[data-flexitour="container"][x-placement="left-start"] {
|
||||
margin-right: 10px;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="left"] div[data-role="arrow"],
|
||||
span[data-flexitour="container"][x-placement="left-start"] div[data-role="arrow"] {
|
||||
right: -11px;
|
||||
top: 50%;
|
||||
margin-top: -11px;
|
||||
border-right-width: 0;
|
||||
border-left-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="left"] div[data-role="arrow"]:after,
|
||||
span[data-flexitour="container"][x-placement="left-start"] div[data-role="arrow"]:after {
|
||||
right: 1px;
|
||||
margin-top: -10px;
|
||||
border-right-width: 0;
|
||||
border-left-color: #fff;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="right"],
|
||||
span[data-flexitour="container"][x-placement="right-start"] {
|
||||
margin-left: 10px;
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="right"] div[data-role="arrow"],
|
||||
span[data-flexitour="container"][x-placement="right-start"] div[data-role="arrow"] {
|
||||
left: -11px;
|
||||
top: 50%;
|
||||
margin-top: -11px;
|
||||
border-left-width: 0;
|
||||
border-right-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
span[data-flexitour="container"][x-placement="right"] div[data-role="arrow"]:after,
|
||||
span[data-flexitour="container"][x-placement="right-start"] div[data-role="arrow"]:after {
|
||||
left: 1px;
|
||||
margin-top: -10px;
|
||||
border-left-width: 0;
|
||||
border-right-color: #fff;
|
||||
}
|
||||
/* Styling for mustache templates */
|
||||
/* stylelint-disable declaration-block-no-duplicate-properties, no-browser-hacks */
|
||||
/* stylelint-enable */
|
||||
|
||||