You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

676 lines
18 KiB

<?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 <andrew@nicols.co.uk>
* @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 <andrew@nicols.co.uk>
* @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_text($value);
$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() !== null) {
$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->get_tour()->reset_step_sortorder();
}
$this->reload();
// Notify of a change to the step configuration.
// This must be done separately to tour change notifications.
cache::notify_step_change($this->get_tourid());
// Notify the cache that a tour has changed.
// Tours are only stored in the cache if there are steps.
// If there step count has changed for some reason, this will change the potential cache results.
cache::notify_tour_change();
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();
// Notify of a change to the step configuration.
// This must be done separately to tour change notifications.
cache::notify_step_change($this->get_id());
// Notify the cache that a tour has changed.
// Tours are only stored in the cache if there are steps.
// If there step count has changed for some reason, this will change the potential cache results.
cache::notify_tour_change();
}
/**
* 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));
}
if ($this->get_targettype() !== null) {
$this->get_target()->prepare_data_for_form($data);
}
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;
}
/**
* Attempt to fetch any matching langstring if the string is in the
* format identifier,component.
*
* @param string $string
* @return string
*/
public 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;
}
}