mirror of
https://github.com/moodle/moodle.git
synced 2025-04-20 16:04:25 +02:00
Merge branch 'MDL-72783-master-test' of https://github.com/rezaies/moodle
This commit is contained in:
commit
5b730e1149
2
admin/tool/usertours/amd/build/tour.min.js
vendored
2
admin/tool/usertours/amd/build/tour.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1435,10 +1435,14 @@ const Tour = class {
|
||||
|
||||
let drawertop = 0;
|
||||
if (targetNode.parents('[data-usertour="scroller"]').length) {
|
||||
drawertop = targetNode.parents('[data-usertour="scroller"]').scrollTop();
|
||||
background.css({
|
||||
position: 'fixed'
|
||||
});
|
||||
const scrollerElement = targetNode.parents('[data-usertour="scroller"]');
|
||||
const navigationBuffer = scrollerElement.offset().top;
|
||||
if (scrollerElement.scrollTop() >= navigationBuffer) {
|
||||
drawertop = scrollerElement.scrollTop() - navigationBuffer;
|
||||
background.css({
|
||||
position: 'fixed'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
background.css({
|
||||
|
@ -84,13 +84,22 @@ EOF;
|
||||
// Attempt to determine whether this is the front page.
|
||||
// This is a special case because the frontpage uses a shortened page path making it difficult to detect exactly.
|
||||
$isfrontpage = $targetmatch->compare(new \moodle_url('/'), URL_MATCH_BASE);
|
||||
$isdashboard = $targetmatch->compare(new \moodle_url('/my/'), URL_MATCH_BASE);
|
||||
$target = $targetmatch->out_as_local_url();
|
||||
return array_filter($tours, function($tour) use ($isfrontpage, $target) {
|
||||
if ($isfrontpage && $tour->pathmatch === 'FRONTPAGE') {
|
||||
return array_filter($tours, function($tour) use ($isfrontpage, $isdashboard, $target) {
|
||||
if (($isfrontpage || $isdashboard) && $tour->pathmatch === 'FRONTPAGE') {
|
||||
return true;
|
||||
}
|
||||
$pattern = preg_quote($tour->pathmatch, '@');
|
||||
$pattern = str_replace('%', '.*', $pattern);
|
||||
if (strpos($pattern, '%') !== false) {
|
||||
// The URL match format is something like: /my/%.
|
||||
// We need to find all the URLs which match the first part of the pattern.
|
||||
$pattern = str_replace('%', '.*', $pattern);
|
||||
} else {
|
||||
// The URL match format is something like: /my/courses.php.
|
||||
// We need to find all the URLs which match with whole pattern.
|
||||
$pattern .= '$';
|
||||
}
|
||||
return !!preg_match("@{$pattern}@", $target);
|
||||
});
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
use core\output\inplace_editable;
|
||||
use tool_usertours\local\clientside_filter\clientside_filter;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
@ -51,6 +52,11 @@ class helper {
|
||||
*/
|
||||
private static $bootstrapped = false;
|
||||
|
||||
/**
|
||||
* @var string Regex to check any matching lang string.
|
||||
*/
|
||||
protected const LANG_STRING_REGEX = '|^([a-zA-Z][a-zA-Z0-9\.:/_-]*),([a-zA-Z][a-zA-Z0-9\.:/_-]*)$|';
|
||||
|
||||
/**
|
||||
* Get the link to edit the step.
|
||||
*
|
||||
@ -302,18 +308,19 @@ class helper {
|
||||
/**
|
||||
* Render the inplace editable used to edit the tour name.
|
||||
*
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return string
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return inplace_editable
|
||||
*/
|
||||
public static function render_tourname_inplace_editable(tour $tour) {
|
||||
return new \core\output\inplace_editable(
|
||||
public static function render_tourname_inplace_editable(tour $tour): inplace_editable {
|
||||
$name = format_text(static::get_string_from_input($tour->get_name()), FORMAT_HTML);
|
||||
return new inplace_editable(
|
||||
'tool_usertours',
|
||||
'tourname',
|
||||
$tour->get_id(),
|
||||
true,
|
||||
\html_writer::link(
|
||||
$tour->get_view_link(),
|
||||
$tour->get_name()
|
||||
$name
|
||||
),
|
||||
$tour->get_name()
|
||||
);
|
||||
@ -322,16 +329,17 @@ class helper {
|
||||
/**
|
||||
* Render the inplace editable used to edit the tour description.
|
||||
*
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return string
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return inplace_editable
|
||||
*/
|
||||
public static function render_tourdescription_inplace_editable(tour $tour) {
|
||||
return new \core\output\inplace_editable(
|
||||
public static function render_tourdescription_inplace_editable(tour $tour): inplace_editable {
|
||||
$description = format_text(static::get_string_from_input($tour->get_description()), FORMAT_HTML);
|
||||
return new inplace_editable(
|
||||
'tool_usertours',
|
||||
'tourdescription',
|
||||
$tour->get_id(),
|
||||
true,
|
||||
$tour->get_description(),
|
||||
$description,
|
||||
$tour->get_description()
|
||||
);
|
||||
}
|
||||
@ -339,10 +347,10 @@ class helper {
|
||||
/**
|
||||
* Render the inplace editable used to edit the tour enable state.
|
||||
*
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return string
|
||||
* @param tour $tour The tour to edit.
|
||||
* @return inplace_editable
|
||||
*/
|
||||
public static function render_tourenabled_inplace_editable(tour $tour) {
|
||||
public static function render_tourenabled_inplace_editable(tour $tour): inplace_editable {
|
||||
global $OUTPUT;
|
||||
|
||||
if ($tour->is_enabled()) {
|
||||
@ -355,7 +363,7 @@ class helper {
|
||||
$value = 0;
|
||||
}
|
||||
|
||||
$editable = new \core\output\inplace_editable(
|
||||
$editable = new inplace_editable(
|
||||
'tool_usertours',
|
||||
'tourenabled',
|
||||
$tour->get_id(),
|
||||
@ -373,13 +381,13 @@ class helper {
|
||||
/**
|
||||
* Render the inplace editable used to edit the step name.
|
||||
*
|
||||
* @param step $step The step to edit.
|
||||
* @return string
|
||||
* @param step $step The step to edit.
|
||||
* @return inplace_editable
|
||||
*/
|
||||
public static function render_stepname_inplace_editable(step $step) {
|
||||
$title = format_text(step::get_string_from_input($step->get_title()), FORMAT_HTML);
|
||||
public static function render_stepname_inplace_editable(step $step): inplace_editable {
|
||||
$title = format_text(static::get_string_from_input($step->get_title()), FORMAT_HTML);
|
||||
|
||||
return new \core\output\inplace_editable(
|
||||
return new inplace_editable(
|
||||
'tool_usertours',
|
||||
'stepname',
|
||||
$step->get_id(),
|
||||
@ -585,4 +593,37 @@ class helper {
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to fetch any matching langstring if the content is in the
|
||||
* format identifier,component.
|
||||
*
|
||||
* @param string $content Step's content or Tour's name or Tour's description
|
||||
* @return string Processed content, any langstring will be converted to translated text
|
||||
*/
|
||||
public static function get_string_from_input(string $content): string {
|
||||
$content = trim($content);
|
||||
|
||||
if (preg_match(static::LANG_STRING_REGEX, $content, $matches)) {
|
||||
if ($matches[2] === 'moodle') {
|
||||
$matches[2] = 'core';
|
||||
}
|
||||
|
||||
if (get_string_manager()->string_exists($matches[1], $matches[2])) {
|
||||
$content = get_string($matches[1], $matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string contains any matching langstring.
|
||||
*
|
||||
* @param string $string
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_language_string_from_input(string $string): bool {
|
||||
return preg_match(static::LANG_STRING_REGEX, $string) == true;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
namespace tool_usertours\local\forms;
|
||||
|
||||
use stdClass;
|
||||
use tool_usertours\helper;
|
||||
use tool_usertours\step;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
@ -188,7 +189,7 @@ class editstep extends \moodleform {
|
||||
public function set_data($data): void {
|
||||
$data = (object) $data;
|
||||
if (!isset($data->contenttype)) {
|
||||
if (!empty($data->content['text']) && step::is_language_string_from_input($data->content['text'])) {
|
||||
if (!empty($data->content['text']) && helper::is_language_string_from_input($data->content['text'])) {
|
||||
$data->contenttype = static::CONTENTTYPE_LANGSTRING;
|
||||
$data->contentlangstring = $data->content['text'];
|
||||
|
||||
|
@ -67,10 +67,12 @@ class edittour extends \moodleform {
|
||||
$mform->addElement('text', 'name', get_string('name', 'tool_usertours'));
|
||||
$mform->addRule('name', get_string('required'), 'required', null, 'client');
|
||||
$mform->setType('name', PARAM_TEXT);
|
||||
$mform->addHelpButton('name', 'name', 'tool_usertours');
|
||||
|
||||
// Admin-only descriptions.
|
||||
$mform->addElement('textarea', 'description', get_string('description', 'tool_usertours'));
|
||||
$mform->setType('description', PARAM_RAW);
|
||||
$mform->addHelpButton('description', 'description', 'tool_usertours');
|
||||
|
||||
// Application.
|
||||
$mform->addElement('text', 'pathmatch', get_string('pathmatch', 'tool_usertours'));
|
||||
|
@ -101,7 +101,10 @@ class step_list extends \flexible_table {
|
||||
$content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $systemcontext->id,
|
||||
'tool_usertours', 'stepcontent', $step->get_id());
|
||||
|
||||
return format_text(step::get_string_from_input($content), $step->get_contentformat());
|
||||
$content = helper::get_string_from_input($content);
|
||||
$content = step::get_step_image_from_input($content);
|
||||
|
||||
return format_text($content, $step->get_contentformat());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -353,7 +353,7 @@ class manager {
|
||||
global $PAGE;
|
||||
if ($id) {
|
||||
$tour = tour::instance($id);
|
||||
$PAGE->navbar->add($tour->get_name(), $tour->get_edit_link());
|
||||
$PAGE->navbar->add(helper::get_string_from_input($tour->get_name()), $tour->get_edit_link());
|
||||
|
||||
} else {
|
||||
$tour = new tour();
|
||||
@ -393,7 +393,8 @@ class manager {
|
||||
notification::add(get_string('modifyshippedtourwarning', 'tool_usertours'), notification::WARNING);
|
||||
}
|
||||
|
||||
$this->header($tour->get_name());
|
||||
$tourname = !empty($tour->get_name()) ? helper::get_string_from_input($tour->get_name()) : '';
|
||||
$this->header($tourname);
|
||||
$data = $tour->prepare_data_for_form();
|
||||
|
||||
// Prepare filter values for the form.
|
||||
@ -475,12 +476,13 @@ class manager {
|
||||
protected function view_tour($tourid) {
|
||||
global $PAGE;
|
||||
$tour = helper::get_tour($tourid);
|
||||
$tourname = helper::get_string_from_input($tour->get_name());
|
||||
|
||||
$PAGE->navbar->add($tour->get_name(), $tour->get_view_link());
|
||||
$PAGE->navbar->add($tourname, $tour->get_view_link());
|
||||
|
||||
$this->header($tour->get_name());
|
||||
$this->header($tourname);
|
||||
echo \html_writer::span(get_string('viewtour_info', 'tool_usertours', [
|
||||
'tourname' => $tour->get_name(),
|
||||
'tourname' => $tourname,
|
||||
'path' => $tour->get_pathmatch(),
|
||||
]));
|
||||
echo \html_writer::div(get_string('viewtour_edit', 'tool_usertours', [
|
||||
@ -728,9 +730,9 @@ class manager {
|
||||
notification::add(get_string('modifyshippedtourwarning', 'tool_usertours'), notification::WARNING);
|
||||
}
|
||||
|
||||
$PAGE->navbar->add($tour->get_name(), $tour->get_view_link());
|
||||
$PAGE->navbar->add(helper::get_string_from_input($tour->get_name()), $tour->get_view_link());
|
||||
if (isset($id)) {
|
||||
$PAGE->navbar->add($step->get_title(), $step->get_edit_link());
|
||||
$PAGE->navbar->add(helper::get_string_from_input($step->get_title()), $step->get_edit_link());
|
||||
} else {
|
||||
$PAGE->navbar->add(get_string('newstep', 'tool_usertours'), $step->get_edit_link());
|
||||
}
|
||||
@ -746,7 +748,7 @@ class manager {
|
||||
if (empty($id)) {
|
||||
$this->header(get_string('newstep', 'tool_usertours'));
|
||||
} else {
|
||||
$this->header(get_string('editstep', 'tool_usertours', $step->get_title()));
|
||||
$this->header(get_string('editstep', 'tool_usertours', helper::get_string_from_input($step->get_title())));
|
||||
}
|
||||
$form->set_data($step->prepare_data_for_form());
|
||||
|
||||
@ -862,6 +864,10 @@ class manager {
|
||||
// the format filename => version. The version value needs to
|
||||
// be increased if the tour has been updated.
|
||||
$shippedtours = [
|
||||
'40_tour_navigation_dashboard.json' => 1,
|
||||
'40_tour_navigation_mycourse.json' => 1,
|
||||
'40_tour_navigation_course_teacher.json' => 1,
|
||||
'40_tour_navigation_course_student.json' => 1,
|
||||
];
|
||||
|
||||
// These are tours that we used to ship but don't ship any longer.
|
||||
|
@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . "/filelib.php");
|
||||
|
||||
use tool_usertours\helper;
|
||||
use tool_usertours\step as stepsource;
|
||||
|
||||
/**
|
||||
@ -67,16 +68,19 @@ class step implements \renderable {
|
||||
$content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $systemcontext->id,
|
||||
'tool_usertours', 'stepcontent', $step->get_id());
|
||||
|
||||
$content = helper::get_string_from_input($content);
|
||||
$content = $step::get_step_image_from_input($content);
|
||||
|
||||
$result = (object) [
|
||||
'stepid' => $step->get_id(),
|
||||
'title' => external_format_text(
|
||||
stepsource::get_string_from_input($step->get_title()),
|
||||
helper::get_string_from_input($step->get_title()),
|
||||
FORMAT_HTML,
|
||||
$PAGE->context->id,
|
||||
'tool_usertours'
|
||||
)[0],
|
||||
'content' => external_format_text(
|
||||
stepsource::get_string_from_input($content),
|
||||
$content,
|
||||
$step->get_contentformat(),
|
||||
$PAGE->context->id,
|
||||
'tool_usertours'
|
||||
|
@ -92,11 +92,6 @@ class step {
|
||||
*/
|
||||
protected $dirty = false;
|
||||
|
||||
/**
|
||||
* @var string Regex to check any matching lang string.
|
||||
*/
|
||||
protected const LANG_STRING_REGEX = '|^([a-zA-Z][a-zA-Z0-9\.:/_-]*),([a-zA-Z][a-zA-Z0-9\.:/_-]*)$|';
|
||||
|
||||
/**
|
||||
* @var bool $isimporting Whether the step is being imported or not.
|
||||
*/
|
||||
@ -801,13 +796,16 @@ class step {
|
||||
* Attempt to fetch any matching langstring if the string is in the
|
||||
* format identifier,component.
|
||||
*
|
||||
* @deprecated since Moodle 4.0 MDL-72783. Please use helper::get_string_from_input() instead.
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function get_string_from_input($string) {
|
||||
debugging('Use of ' . __FUNCTION__ .
|
||||
'() have been deprecated, please update your code to use helper::get_string_from_input()', DEBUG_DEVELOPER);
|
||||
$string = trim($string);
|
||||
|
||||
if (preg_match(static::LANG_STRING_REGEX, $string, $matches)) {
|
||||
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';
|
||||
}
|
||||
@ -821,12 +819,27 @@ class step {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string contains any matching langstring.
|
||||
* Attempt to replace PIXICON placeholder with the correct images for tour step content.
|
||||
*
|
||||
* @param string $string Tour step content
|
||||
* @return bool
|
||||
* @param string $content Tour content
|
||||
* @return string Processed tour content
|
||||
*/
|
||||
public static function is_language_string_from_input(string $string): bool {
|
||||
return preg_match(static::LANG_STRING_REGEX, $string) == true;
|
||||
public static function get_step_image_from_input(string $content): string {
|
||||
global $OUTPUT;
|
||||
|
||||
if (preg_match('/(?<=@@PIXICON::).*?(?=@@)/', $content, $matches)) {
|
||||
$bits = explode('::', $matches[0]);
|
||||
$identifier = $bits[0];
|
||||
$component = $bits[1];
|
||||
if ($component == 'moodle') {
|
||||
$component = 'core';
|
||||
}
|
||||
$image = \html_writer::img($OUTPUT->image_url($identifier, $component)->out(false),
|
||||
'', ['class' => 'img-fluid']);
|
||||
$contenttoreplace = '@@PIXICON::' . $matches[0] . '@@';
|
||||
$content = str_replace($contenttoreplace, $image, $content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
@ -114,11 +114,12 @@ function xmldb_tool_usertours_upgrade($oldversion) {
|
||||
upgrade_plugin_savepoint(true, 2021101300, 'tool', 'usertours');
|
||||
}
|
||||
|
||||
if ($oldversion < 2021101301) {
|
||||
if ($oldversion < 2021101302) {
|
||||
// Update shipped tours.
|
||||
// Normally, we just bump the version numbers because we need to call update_shipped_tours only once.
|
||||
manager::update_shipped_tours();
|
||||
|
||||
upgrade_plugin_savepoint(true, 2021101301, 'tool', 'usertours');
|
||||
upgrade_plugin_savepoint(true, 2021101302, 'tool', 'usertours');
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -31,6 +31,9 @@ $string['block_named'] = 'Block named \'{$a}\'';
|
||||
$string['cachedef_stepdata'] = 'List of user tour steps';
|
||||
$string['cachedef_tourdata'] = 'List of enabled user tours information which is fetched on every page';
|
||||
$string['description'] = 'Description';
|
||||
$string['description_help'] = 'The description of a tour may be added as plain text, enclosed in multilang tags (for use with the multi-language content filter) if required.
|
||||
|
||||
Alternatively, a language string ID may be entered in the format identifier,component (with no brackets or space after the comma).';
|
||||
$string['displaystepnumbers'] = 'Display step numbers';
|
||||
$string['displaystepnumbers_help'] = 'Whether to display a step number count e.g. 1/4, 2/4 etc. to indicate the length of the user tour.';
|
||||
$string['confirmstepremovalquestion'] = 'Are you sure that you wish to remove this step?';
|
||||
@ -93,6 +96,9 @@ $string['movestepup'] = 'Move step up';
|
||||
$string['movetourdown'] = 'Move tour down';
|
||||
$string['movetourup'] = 'Move tour up';
|
||||
$string['name'] = 'Name';
|
||||
$string['name_help'] = 'The name of a tour may be added as plain text, enclosed in multilang tags (for use with the multi-language content filter) if required.
|
||||
|
||||
Alternatively, a language string ID may be entered in the format identifier,component (with no brackets or space after the comma).';
|
||||
$string['newstep'] = 'Create step';
|
||||
$string['newstep'] = 'New step';
|
||||
$string['newtour'] = 'Create a new tour';
|
||||
@ -260,6 +266,28 @@ $string['tour_activityinfo_course_student_content'] = 'Activity dates and/or wha
|
||||
$string['tour_activityinfo_course_teacher_title'] = 'New: Activity information';
|
||||
$string['tour_activityinfo_course_teacher_content'] = 'New course settings \'Show completion conditions\' and \'Show activity dates\' enable you to choose whether activity completion conditions (if set) and/or dates are displayed for students on the course page.';
|
||||
|
||||
// 4.0 New navigation tour.
|
||||
$string['tour_navigation_course_announcements_teacher_content'] = '@@PIXICON::tour/tour_course_admin_3::tool_usertours@@<br>Post important news here.';
|
||||
$string['tour_navigation_course_announcements_teacher_title'] = 'Something to tell everyone?';
|
||||
$string['tour_navigation_course_edit_teacher_content'] = '@@PIXICON::tour/tour_course_admin_1::tool_usertours@@<br>Add new content or edit existing content.';
|
||||
$string['tour_navigation_course_edit_teacher_title'] = 'Activate edit mode';
|
||||
$string['tour_navigation_course_index_student_content'] = '@@PIXICON::tour/tour_course_student::tool_usertours@@<br>Browse through activities and track your progress.';
|
||||
$string['tour_navigation_course_index_student_title'] = 'Find your way around';
|
||||
$string['tour_navigation_course_index_teacher_content'] = '@@PIXICON::tour/tour_course_admin_2::tool_usertours@@<br>Drag and drop activities to re-order course content.';
|
||||
$string['tour_navigation_course_index_teacher_title'] = 'Course index';
|
||||
$string['tour_navigation_course_student_tour_des'] = 'Where to browse through activities in a course';
|
||||
$string['tour_navigation_course_student_tour_name'] = 'Course index';
|
||||
$string['tour_navigation_course_teacher_tour_des'] = 'Edit mode, drag and drop of activities and posting announcements in a course';
|
||||
$string['tour_navigation_course_teacher_tour_name'] = 'Course editing';
|
||||
$string['tour_navigation_dashboard_content'] = '@@PIXICON::tour/tour_dashboard::tool_usertours@@<br>This side panel can contain more features.';
|
||||
$string['tour_navigation_dashboard_title'] = 'Expand to explore!';
|
||||
$string['tour_navigation_dashboard_tour_des'] = 'Where blocks can be found on the Dashboard';
|
||||
$string['tour_navigation_dashboard_tour_name'] = 'Block drawer';
|
||||
$string['tour_navigation_mycourses_content'] = '@@PIXICON::tour/tour_mycourses::tool_usertours@@<br>Add, copy, delete and hide courses from this menu.';
|
||||
$string['tour_navigation_mycourses_title'] = 'Courses and categories';
|
||||
$string['tour_navigation_mycourses_tour_des'] = 'Course management options on the My courses page';
|
||||
$string['tour_navigation_mycourses_tour_name'] = 'Course management';
|
||||
|
||||
$string['tour_final_step_title'] = 'End of tour';
|
||||
$string['tour_final_step_content'] = 'This is the end of your user tour. It won\'t show again unless you reset it using the link in the footer.';
|
||||
|
||||
|
@ -24,15 +24,16 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core\output\inplace_editable;
|
||||
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
|
||||
* @param string $itemtype The type of item.
|
||||
* @param int $itemid The ID of the item.
|
||||
* @param mixed $newvalue The new value
|
||||
* @return inplace_editable
|
||||
*/
|
||||
function tool_usertours_inplace_editable($itemtype, $itemid, $newvalue) {
|
||||
$context = \context_system::instance();
|
||||
|
BIN
admin/tool/usertours/pix/tour/tour_course_admin_1.png
Normal file
BIN
admin/tool/usertours/pix/tour/tour_course_admin_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
admin/tool/usertours/pix/tour/tour_course_admin_2.png
Normal file
BIN
admin/tool/usertours/pix/tour/tour_course_admin_2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
admin/tool/usertours/pix/tour/tour_course_admin_3.png
Normal file
BIN
admin/tool/usertours/pix/tour/tour_course_admin_3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
admin/tool/usertours/pix/tour/tour_course_student.png
Normal file
BIN
admin/tool/usertours/pix/tour/tour_course_student.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
admin/tool/usertours/pix/tour/tour_dashboard.png
Normal file
BIN
admin/tool/usertours/pix/tour/tour_dashboard.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
admin/tool/usertours/pix/tour/tour_mycourses.png
Normal file
BIN
admin/tool/usertours/pix/tour/tour_mycourses.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
@ -11,6 +11,11 @@ Feature: Apply content type to a tour
|
||||
| Description | My first tour |
|
||||
| Apply to URL match | /my/% |
|
||||
| Tour is enabled | 1 |
|
||||
And I add a new user tour with:
|
||||
| Name | tour_activityinfo_activity_student_title,tool_usertours |
|
||||
| Description | tour_activityinfo_activity_student_content,tool_usertours |
|
||||
| Apply to URL match | /my/% |
|
||||
| Tour is enabled | 0 |
|
||||
|
||||
@javascript
|
||||
Scenario: User can choose the the content type of the tour step
|
||||
@ -42,6 +47,7 @@ Feature: Apply content type to a tour
|
||||
And I should see "New: Activity information"
|
||||
And I should see "New course settings 'Show completion conditions' and 'Show activity dates' enable you to choose whether activity completion conditions (if set) and/or dates are displayed for students on the course page."
|
||||
And I click on "Edit" "link" in the "New: Activity information" "table_row"
|
||||
And I should see "Editing \"New: Activity information\""
|
||||
And the field "Title" matches value "tour_activityinfo_course_teacher_title,tool_usertours"
|
||||
And the field "Moodle language identifier" matches value "tour_activityinfo_course_teacher_content,tool_usertours"
|
||||
|
||||
@ -57,6 +63,20 @@ Feature: Apply content type to a tour
|
||||
And I should see "New: Activity information"
|
||||
And I should see "Test content"
|
||||
And I click on "Edit" "link" in the "New: Activity information" "table_row"
|
||||
And I should see "Editing \"New: Activity information\""
|
||||
And I should not see "Moodle language identifier"
|
||||
And the field "Title" matches value "tour_activityinfo_course_teacher_title,tool_usertours"
|
||||
And the field "id_content" matches value "<b>Test content</b>"
|
||||
|
||||
@javascript
|
||||
Scenario: Tour name and description can be translatable
|
||||
Given I open the User tour settings page
|
||||
And I should see "New: Activity information"
|
||||
And I should see "Activity dates plus what to do to complete the activity are shown on the activity page."
|
||||
When I click on "View" "link" in the "New: Activity information" "table_row"
|
||||
Then I should see "New: Activity information"
|
||||
And I should see "This is the 'New: Activity information' tour. It applies to the path '/my/%'."
|
||||
And I click on "edit the tour defaults" "link"
|
||||
And I should see "New: Activity information"
|
||||
And the field "Name" matches value "tour_activityinfo_activity_student_title,tool_usertours"
|
||||
And the field "Description" matches value "tour_activityinfo_activity_student_content,tool_usertours"
|
||||
|
@ -164,7 +164,7 @@ class cache_testcase extends advanced_testcase {
|
||||
'Matches expected glob' => [
|
||||
$tourconfigs,
|
||||
'/my/index.php',
|
||||
['my_glob_1', 'my_glob_2'],
|
||||
['my_glob_1', 'my_glob_2', 'frontpage_match'],
|
||||
],
|
||||
'Matches expected glob and exact' => [
|
||||
$tourconfigs,
|
||||
|
84
admin/tool/usertours/tests/helper_test.php
Normal file
84
admin/tool/usertours/tests/helper_test.php
Normal file
@ -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 helper.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2022 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace tool_usertours;
|
||||
|
||||
use advanced_testcase;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Tests for helper.
|
||||
*
|
||||
* @package tool_usertours
|
||||
* @copyright 2022 Huong Nguyen <huongnv13@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class helper_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Data Provider for get_string_from_input.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_string_from_input_provider(): array {
|
||||
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 langstring 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) {
|
||||
$this->assertEquals($expected, helper::get_string_from_input($string));
|
||||
}
|
||||
}
|
@ -825,47 +825,24 @@ class step_testcase extends advanced_testcase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Data Provider for get_string_from_input.
|
||||
*
|
||||
* @return array
|
||||
* Ensure that the get_step_image_from_input function replace PIXICON placeholder with the correct images correctly.
|
||||
*/
|
||||
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',
|
||||
],
|
||||
];
|
||||
}
|
||||
public function test_get_step_image_from_input() {
|
||||
$stepcontent = '@@PIXICON::tour/tour_mycourses::tool_usertours@@<br>Test';
|
||||
$stepcontent = \tool_usertours\step::get_step_image_from_input($stepcontent);
|
||||
|
||||
/**
|
||||
* Ensure that the get_string_from_input function returns langstring 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) {
|
||||
$this->assertEquals($expected, \tool_usertours\step::get_string_from_input($string));
|
||||
// If the format is correct, PIXICON placeholder will be replaced with the img tag.
|
||||
$this->assertStringStartsWith('<img', $stepcontent);
|
||||
$this->assertStringEndsWith('Test', $stepcontent);
|
||||
$this->assertStringNotContainsString('PIXICON', $stepcontent);
|
||||
|
||||
$stepcontent = '@@PIXICON::tour/tour_mycourses<br>Test';
|
||||
$stepcontent = \tool_usertours\step::get_step_image_from_input($stepcontent);
|
||||
|
||||
// If the format is not correct, PIXICON placeholder will not be replaced with the img tag.
|
||||
$this->assertStringStartsNotWith('<img', $stepcontent);
|
||||
$this->assertStringStartsWith('@@PIXICON', $stepcontent);
|
||||
$this->assertStringEndsWith('Test', $stepcontent);
|
||||
$this->assertStringContainsString('PIXICON', $stepcontent);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "tour_navigation_course_student_tour_name,tool_usertours",
|
||||
"description": "tour_navigation_course_student_tour_des,tool_usertours",
|
||||
"pathmatch": "\/course\/view.php%",
|
||||
"enabled": "1",
|
||||
"sortorder": "3",
|
||||
"endtourlabel": "",
|
||||
"configdata": "{\"placement\":\"right\",\"orphan\":\"0\",\"backdrop\":\"1\",\"reflex\":\"0\",\"filtervalues\":{\"accessdate\":{\"filter_accessdate\":\"tool_usertours_accountcreation\",\"filter_accessdate_range\":0,\"filter_accessdate_enabled\":\"0\"},\"category\":[],\"course\":[],\"courseformat\":[],\"role\":[\"student\"],\"theme\":[\"boost\"],\"cssselector\":[]},\"majorupdatetime\":1641972472,\"shipped_tour\":true,\"shipped_filename\":\"40_tour_navigation_course_student.json\",\"shipped_version\":1}",
|
||||
"displaystepnumbers": true,
|
||||
"version": "2021101301",
|
||||
"steps": [
|
||||
{
|
||||
"title": "tour_navigation_course_index_student_title,tool_usertours",
|
||||
"content": "tour_navigation_course_index_student_content,tool_usertours",
|
||||
"contentformat": "1",
|
||||
"targettype": "0",
|
||||
"targetvalue": "#theme_boost-drawers-courseindex .drawercontent",
|
||||
"sortorder": "0",
|
||||
"configdata": "{}"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "tour_navigation_course_teacher_tour_name,tool_usertours",
|
||||
"description": "tour_navigation_course_teacher_tour_des,tool_usertours",
|
||||
"pathmatch": "\/course\/view.php%",
|
||||
"enabled": "1",
|
||||
"sortorder": "2",
|
||||
"endtourlabel": "",
|
||||
"configdata": "{\"placement\":\"bottom\",\"orphan\":\"0\",\"backdrop\":\"1\",\"reflex\":\"0\",\"filtervalues\":{\"accessdate\":{\"filter_accessdate\":\"tool_usertours_accountcreation\",\"filter_accessdate_range\":0,\"filter_accessdate_enabled\":\"0\"},\"category\":[],\"course\":[],\"courseformat\":[],\"role\":[\"-1\",\"coursecreator\",\"manager\",\"teacher\",\"editingteacher\"],\"theme\":[\"boost\"],\"cssselector\":[]},\"majorupdatetime\":1641972470,\"shipped_tour\":true,\"shipped_filename\":\"40_tour_navigation_course_teacher.json\",\"shipped_version\":1}",
|
||||
"displaystepnumbers": true,
|
||||
"version": "2021101301",
|
||||
"steps": [
|
||||
{
|
||||
"title": "tour_navigation_course_edit_teacher_title,tool_usertours",
|
||||
"content": "tour_navigation_course_edit_teacher_content,tool_usertours",
|
||||
"contentformat": "1",
|
||||
"targettype": "0",
|
||||
"targetvalue": "form.editmode-switch-form",
|
||||
"sortorder": "0",
|
||||
"configdata": "{}"
|
||||
},
|
||||
{
|
||||
"title": "tour_navigation_course_index_teacher_title,tool_usertours",
|
||||
"content": "tour_navigation_course_index_teacher_content,tool_usertours",
|
||||
"contentformat": "1",
|
||||
"targettype": "0",
|
||||
"targetvalue": "#theme_boost-drawers-courseindex .drawercontent",
|
||||
"sortorder": "1",
|
||||
"configdata": "{\"placement\":\"right\"}"
|
||||
},
|
||||
{
|
||||
"title": "tour_navigation_course_announcements_teacher_title,tool_usertours",
|
||||
"content": "tour_navigation_course_announcements_teacher_content,tool_usertours",
|
||||
"contentformat": "1",
|
||||
"targettype": "0",
|
||||
"targetvalue": ".course-content .course-content-item-content .activity-item[data-activityname=\"Announcements\"]",
|
||||
"sortorder": "2",
|
||||
"configdata": "{\"placement\":\"left\"}"
|
||||
}
|
||||
]
|
||||
}
|
22
admin/tool/usertours/tours/40_tour_navigation_dashboard.json
Normal file
22
admin/tool/usertours/tours/40_tour_navigation_dashboard.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "tour_navigation_dashboard_tour_name,tool_usertours",
|
||||
"description": "tour_navigation_dashboard_tour_des,tool_usertours",
|
||||
"pathmatch": "FRONTPAGE",
|
||||
"enabled": "1",
|
||||
"sortorder": "0",
|
||||
"endtourlabel": "",
|
||||
"configdata": "{\"placement\":\"left\",\"orphan\":\"0\",\"backdrop\":\"1\",\"reflex\":\"0\",\"filtervalues\":{\"accessdate\":{\"filter_accessdate\":\"tool_usertours_accountcreation\",\"filter_accessdate_range\":0,\"filter_accessdate_enabled\":\"0\"},\"category\":[],\"course\":[],\"courseformat\":[],\"role\":[],\"theme\":[\"boost\"],\"cssselector\":[]},\"majorupdatetime\":1641972465,\"shipped_tour\":true,\"shipped_filename\":\"40_tour_navigation_dashboard.json\",\"shipped_version\":1}",
|
||||
"displaystepnumbers": true,
|
||||
"version": "2021101301",
|
||||
"steps": [
|
||||
{
|
||||
"title": "tour_navigation_dashboard_title,tool_usertours",
|
||||
"content": "tour_navigation_dashboard_content,tool_usertours",
|
||||
"contentformat": "1",
|
||||
"targettype": "0",
|
||||
"targetvalue": ".drawer-toggles .drawer-toggler.drawer-right-toggle",
|
||||
"sortorder": "0",
|
||||
"configdata": "{\"placement\":\"left\"}"
|
||||
}
|
||||
]
|
||||
}
|
22
admin/tool/usertours/tours/40_tour_navigation_mycourse.json
Normal file
22
admin/tool/usertours/tours/40_tour_navigation_mycourse.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "tour_navigation_mycourses_tour_name,tool_usertours",
|
||||
"description": "tour_navigation_mycourses_tour_des,tool_usertours",
|
||||
"pathmatch": "\/my\/courses.php",
|
||||
"enabled": "1",
|
||||
"sortorder": "1",
|
||||
"endtourlabel": "I understand",
|
||||
"configdata": "{\"placement\":\"bottom\",\"orphan\":\"0\",\"backdrop\":\"1\",\"reflex\":\"0\",\"filtervalues\":{\"accessdate\":{\"filter_accessdate\":\"tool_usertours_accountcreation\",\"filter_accessdate_range\":0,\"filter_accessdate_enabled\":\"0\"},\"category\":[],\"course\":[],\"courseformat\":[],\"role\":[],\"theme\":[\"boost\"],\"cssselector\":[]},\"majorupdatetime\":1641972468,\"shipped_tour\":true,\"shipped_filename\":\"40_tour_navigation_mycourse.json\",\"shipped_version\":1}",
|
||||
"displaystepnumbers": true,
|
||||
"version": "2021101301",
|
||||
"steps": [
|
||||
{
|
||||
"title": "tour_navigation_mycourses_title,tool_usertours",
|
||||
"content": "tour_navigation_mycourses_content,tool_usertours",
|
||||
"contentformat": "1",
|
||||
"targettype": "0",
|
||||
"targetvalue": ".header-actions-container .btn-group",
|
||||
"sortorder": "0",
|
||||
"configdata": "{}"
|
||||
}
|
||||
]
|
||||
}
|
@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2021101301; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2021101302; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2021052500; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_usertours'; // Full name of the plugin (used for diagnostics).
|
||||
|
Loading…
x
Reference in New Issue
Block a user