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.

208 lines
9.9 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/>.
/**
* This file contains local methods for the course format Tiles (not included in lib.php as that's widely called)
* @since Moodle 2.7
* @package format_tiles
* @copyright 2018 David Watson {@link http://evolutioncode.uk}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Experimental feature allowing a teacher to click and convert any label into a page
* @param int $cmid the course module id of the label (which is recycled)
* @param stdClass $course
* @throws dml_exception
* @throws required_capability_exception
* @throws coding_exception
*/
function format_tiles_convert_label_to_page($cmid, $course) {
global $DB;
$cm = $DB->get_record('course_modules', array('id' => $cmid), '*', MUST_EXIST);
$labelmoduleid = $DB->get_record('modules', array('name' => 'label'), 'id', MUST_EXIST)->id;
if ($cm->module != $labelmoduleid) {
debugging("Cannot convert a non label - course module id " . $cmid, DEBUG_DEVELOPER);
return;
}
$label = $DB->get_record('label', array('id' => $cm->instance), '*', MUST_EXIST);
if ($label->course !== $course->id || $cm->course !== $course->id) {
debugging("Cannot convert label - incorrect course id " . $course->id, DEBUG_DEVELOPER);
return;
}
$coursecontext = context_course::instance($course->id);
require_capability('mod/page:addinstance', $coursecontext);
require_capability('moodle/course:manageactivities', $coursecontext);
// Prepare the new page database object using the label as a basis.
$newpage = $label;
// New page display name - label names may be multi line but we only want first line.
$newpage->name = format_tiles_get_first_line($label->name);
// Now the content - if the first line contains a repetition of the 'name', remove the repetition.
$newpage->content = $label->intro;
$firstline = format_tiles_get_first_line($newpage->content);
if (strpos($firstline, $newpage->name) !== false && strpos($firstline, 'PLUGINFILE') === false) {
// The first line seems to include what we are using for the name.
// Also it does not seem to contain a file link so is not adding anything - remove it.
$remainder = substr($newpage->content, strpos($newpage->content, $firstline) + strlen($firstline));
$newfirstline = str_replace($newpage->name, '', $firstline);
$newpage->content = $newfirstline . $remainder;
}
$newpage->intro = '';
$newpage->contentformat = FORMAT_HTML;
$newpage->display = 0;
$newpage->displayoptions = serialize(array(
'printheading' => get_config('page', 'printheading'),
'printintro' => get_config('page', 'printintro')
));
$newpage->timemodified = time();
$newpage->revision = 0;
// Vars $newpage->legacyfiles and $newpage->legacyfileslast are left null.
// Now add new record to the page table.
$newpageid = $DB->insert_record('page', $newpage, true);
// Make necessary changes to the course modules table.
$cm->module = $DB->get_record('modules', array('name' => 'page'), 'id', MUST_EXIST)->id;
$cm->instance = $newpageid;
$cm->timemodified = time();
$DB->update_record('course_modules', $cm);
// If label contained embedded images etc, update files table to show they now relate to page not label.
$contextid = $DB->get_record('context', array('contextlevel' => CONTEXT_MODULE, 'instanceid' => $cmid), 'id', MUST_EXIST)->id;
$files = $DB->get_records('files', array('component' => 'mod_label', 'contextid' => $contextid));
if (count($files) > 0) {
$fs = get_file_storage();
foreach ($files as $file) {
// We modify only the fields we need to in order to convert label to page i.e. component and filearea.
// We ensure that we leave the others including contextid unchanged as they are needed to generate the file URL.
// They are contextid, filepath ('/') and itemid ('0').
// We do change the pathnamehash as it is a hash of the other values so needs recalculating.
// The embedded URL is like [wwwroot]/pluginfile.php/[contextid]/[component]/[filearea]/[itemid][filepath][filename].
// e.g. [wwwroot]/pluginfile.php/7577/mod_page/content/0/an_image.png.
$pathnamehash = $fs->get_pathname_hash(
$file->contextid,
'mod_page', // New component.
'content', // New filearea.
$file->itemid,
$file->filepath,
$file->filename
);
$params = array(
'pathnamehash' => $pathnamehash,
'timemodified' => time(),
'id' => $file->id
);
$DB->execute(
"UPDATE {files}
SET pathnamehash = :pathnamehash, component = 'mod_page', filearea='content', timemodified = :timemodified
WHERE id = :id",
$params
);
}
}
// Finally remove the old label.
$DB->delete_records('label', array('id' => $label->id));
rebuild_course_cache($course->id, true);
\core\notification::info(get_string('labelconverted', 'format_tiles'));
$cm->modname = "page";
$cm->name = $newpage->name;
$event = \format_tiles\event\label_converted::create_from_cm($cm);
$event->trigger();
}
/**
* Get the first line of some text, i.e. all the text
* before char with ASCII code 10 or 13
* @param string $text the text to search
* @return string the resulting text
*/
function format_tiles_get_first_line($text) {
$text = explode(chr(13), $text)[0]; // Newline char \n.
if (strpos($text, chr(10))) { // Return char \r in case it is used instead.
$text = explode(chr(10), $text)[0];
}
return $text;
}
/**
* Which course modules is the site administrator allowing to be displayed in a modal?
* @return array the permitted modules including resource types e.g. page, pdf, HTML
* @throws dml_exception
*/
function format_tiles_allowed_modal_modules() {
$devicetype = \core_useragent::get_device_type();
if ($devicetype != \core_useragent::DEVICETYPE_TABLET && $devicetype != \core_useragent::DEVICETYPE_MOBILE
&& !(\core_useragent::is_ie())) {
// JS navigation and modals in Internet Explorer are not supported by this plugin so we disable modals here.
return array(
'resources' => explode(",", get_config('format_tiles', 'modalresources')),
'modules' => explode(",", get_config('format_tiles', 'modalmodules'))
);
} else {
return array('resources' => [], 'modules' => []);
}
}
/**
* If we are not on a mobile device we may want to ensure that tiles are nicely fitted depending on our screen width.
* E.g. avoid a row with one tile, centre the tiles on screen. JS will handle this post page load.
* However we want to handle it pre-page load if we can to avoid tiles moving around once page is loaded.
* So we have JS send the width via AJAX on first load, and we remember the value and apply it next time using inline CSS.
* This function gets the data to enable us to add the inline CSS.
* This will hide the main tiles window on page load and display a loading icon instead.
* Then post page load, JS will get the screen width, re-arrange the tiles, then hide the loading icon and show the tiles.
* If session width var has already been set (because JS already ran), we set that width initially.
* Then we can load the page immediately at that width without hiding anything.
* The skipcheck URL param is there in case anyone gets stuck at loading icon and clicks it - they escape it for session.
* @param int $courseid the course ID we are in.
* @see format_tiles_external::set_session_width() for where the session vars are set from JS.
* @return array the data to add to our mustache templates.
* @throws coding_exception
* @throws dml_exception
*/
function format_tiles_width_template_data($courseid) {
global $SESSION, $PAGE;
$data = [];
if (get_config('format_tiles', 'fittilestowidth')) {
if (optional_param('skipcheck', 0, PARAM_INT) || isset($SESSION->format_tiles_skip_width_check)) {
$SESSION->format_tiles_skip_width_check = 1;
return array('hidetilesinitially' => 0);
} else if ($PAGE->user_is_editing()
|| !get_config('format_tiles', 'usejavascriptnav')
|| get_user_preferences('format_tiles_stopjsnav', 0)) {
// Here we may don't tiles initially or restrict screen width.
return array('hidetilesinitially' => 0);
} else {
// If session screen width has been set, send it to template so we can include in inline CSS.
$sessionvar = 'format_tiles_width_' . $courseid;
$sessionvarvalue = isset($SESSION->$sessionvar) ? $SESSION->$sessionvar : 0;
$data['defaultscreenwidthsession'] = $sessionvarvalue;
// If no session screen width has yet been set, we hide the tiles initally so we can calculate correct width.
$data['hidetilesinitially'] = $sessionvarvalue == 0 ? 1 : 0;
}
return $data;
} else {
// Feature is disabled by site admin.
return array('hidetilesinitially' => 0);
}
}