-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathlocallib.php
208 lines (194 loc) · 9.88 KB
/
locallib.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<?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);
}
}