forked from moodle/moodle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.php
465 lines (437 loc) · 15.9 KB
/
lib.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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
<?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/>.
/**
* Base class for course format plugins
*
* @package core_course
* @copyright 2012 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
/**
* Returns an instance of format class (extending format_base) for given course
*
* @param int|stdClass $courseorid either course id or
* an object that has the property 'format' and may contain property 'id'
* @return format_base
*/
function course_get_format($courseorid) {
return format_base::instance($courseorid);
}
/**
* Base class for course formats
*
* Each course format must declare class
* class format_FORMATNAME extends format_base {}
* in file lib.php
*
* For each course just one instance of this class is created and it will always be returned by
* course_get_format($courseorid). Format may store it's specific course-dependent options in
* variables of this class.
*
* In rare cases instance of child class may be created just for format without course id
* i.e. to check if format supports AJAX.
*
* Also course formats may extend class section_info and overwrite
* format_base::build_section_cache() to return more information about sections.
*
* If you are upgrading from Moodle 2.3 start with copying the class format_legacy and renaming
* it to format_FORMATNAME, then move the code from your callback functions into
* appropriate functions of the class.
*
* @package core_course
* @copyright 2012 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class format_base {
/** @var int Id of the course in this instance (maybe 0) */
protected $courseid;
/** @var string format used for this course. Please note that it can be different from
* course.format field if course referes to non-existing of disabled format */
protected $format;
/** @var stdClass data for course object, please use {@link format_base::get_course()} */
protected $course = false;
/** @var array cached instances */
private static $instances = array();
/**
* Creates a new instance of class
*
* Please use {@link course_get_format($courseorid)} to get an instance of the format class
*
* @param string $format
* @param int $courseid
* @return format_base
*/
protected function __construct($format, $courseid) {
$this->format = $format;
$this->courseid = $courseid;
}
/**
* Validates that course format exists and enabled and returns either itself or default format
*
* @param string $format
* @return string
*/
protected static final function get_format_or_default($format) {
if ($format === 'site') {
return $format;
}
$plugins = get_plugin_list('format'); // TODO MDL-35260 filter only enabled
if (isset($plugins[$format])) {
return $format;
}
// Else return default format
$defaultformat = reset($plugins); // TODO MDL-35260 get default format from config
debugging('Format plugin format_'.$format.' is not found or is not enabled. Using default format_'.$defaultformat, DEBUG_DEVELOPER);
return $defaultformat;
}
/**
* Get class name for the format
*
* If course format xxx does not declare class format_xxx, format_legacy will be returned.
* This function also includes lib.php file from corresponding format plugin
*
* @param string $format
* @return string
*/
protected static final function get_class_name($format) {
global $CFG;
static $classnames = array('site' => 'format_site');
if (!isset($classnames[$format])) {
$plugins = get_plugin_list('format');
$usedformat = self::get_format_or_default($format);
if (file_exists($plugins[$usedformat].'/lib.php')) {
require_once($plugins[$usedformat].'/lib.php');
}
$classnames[$format] = 'format_'. $usedformat;
if (!class_exists($classnames[$format])) {
require_once($CFG->dirroot.'/course/format/formatlegacy.php');
$classnames[$format] = 'format_legacy';
}
}
return $classnames[$format];
}
/**
* Returns an instance of the class
*
* @todo MDL-35727 use MUC for caching of instances, limit the number of cached instances
*
* @param int|stdClass $courseorid either course id or
* an object that has the property 'format' and may contain property 'id'
* @return format_base
*/
public static final function instance($courseorid) {
global $DB;
if (!is_object($courseorid)) {
$courseid = (int)$courseorid;
if ($courseid && isset(self::$instances[$courseid]) && count(self::$instances[$courseid]) == 1) {
$formats = array_keys(self::$instances[$courseid]);
$format = reset($formats);
} else {
$format = $DB->get_field('course', 'format', array('id' => $courseid), MUST_EXIST);
}
} else {
$format = $courseorid->format;
if (isset($courseorid->id)) {
$courseid = clean_param($courseorid->id, PARAM_INT);
} else {
$courseid = 0;
}
}
// validate that format exists and enabled, use default otherwise
$format = self::get_format_or_default($format);
if (!isset(self::$instances[$courseid][$format])) {
$classname = self::get_class_name($format);
self::$instances[$courseid][$format] = new $classname($format, $courseid);
}
return self::$instances[$courseid][$format];
}
/**
* Resets cache for the course (or all caches)
* To be called from {@link rebuild_course_cache()}
*
* @param int $courseid
*/
public static final function reset_course_cache($courseid = 0) {
if ($courseid) {
if (isset(self::$instances[$courseid])) {
foreach (self::$instances[$courseid] as $format => $object) {
// in case somebody keeps the reference to course format object
self::$instances[$courseid][$format]->course = false;
}
unset(self::$instances[$courseid]);
}
} else {
self::$instances = array();
}
}
/**
* Returns the format name used by this course
*
* @return string
*/
public final function get_format() {
return $this->format;
}
/**
* Returns id of the course (0 if course is not specified)
*
* @return int
*/
public final function get_courseid() {
return $this->courseid;
}
/**
* Returns a record from course database table plus additional fields
* that course format defines
*
* @return stdClass
*/
public function get_course() {
global $DB;
if (!$this->courseid) {
return null;
}
if ($this->course === false) {
$this->course = $DB->get_record('course', array('id' => $this->courseid));
}
return $this->course;
}
/**
* Returns true if this course format uses sections
*
* This function may be called without specifying the course id
* i.e. in {@link course_format_uses_sections()}
*
* Developers, note that if course format does use sections there should be defined a language
* string with the name 'sectionname' defining what the section relates to in the format, i.e.
* $string['sectionname'] = 'Topic';
* or
* $string['sectionname'] = 'Week';
*
* @return bool
*/
public function uses_sections() {
return false;
}
/**
* Returns a list of sections used in the course
*
* This is a shortcut to get_fast_modinfo()->get_section_info_all()
* @see get_fast_modinfo()
* @see course_modinfo::get_section_info_all()
*
* @return array of section_info objects
*/
public final function get_sections() {
if ($course = $this->get_course()) {
$modinfo = get_fast_modinfo($course);
return $modinfo->get_section_info_all();
}
return array();
}
/**
* Returns information about section used in course
*
* @param int|stdClass $section either section number (field course_section.section) or row from course_section table
* @param int $strictness
* @return section_info
*/
public final function get_section($section, $strictness = IGNORE_MISSING) {
if (is_object($section)) {
$sectionnum = $section->section;
} else {
$sectionnum = $section;
}
$sections = $this->get_sections();
if (array_key_exists($sectionnum, $sections)) {
return $sections[$sectionnum];
}
if ($strictness == MUST_EXIST) {
throw new moodle_exception('sectionnotexist');
}
return null;
}
/**
* Returns the display name of the given section that the course prefers.
*
* @param int|stdClass $section Section object from database or just field course_sections.section
* @return Display name that the course format prefers, e.g. "Topic 2"
*/
public function get_section_name($section) {
if (is_object($section)) {
$sectionnum = $section->section;
} else {
$sectionnum = $section;
}
return get_string('sectionname', 'format_'.$this->format) . ' ' . $sectionnum;
}
/**
* Returns the information about the ajax support in the given source format
*
* The returned object's property (boolean)capable indicates that
* the course format supports Moodle course ajax features.
* The property (array)testedbrowsers can be used as a parameter for {@link ajaxenabled()}.
*
* @return stdClass
*/
public function supports_ajax() {
// no support by default
$ajaxsupport = new stdClass();
$ajaxsupport->capable = false;
$ajaxsupport->testedbrowsers = array();
return $ajaxsupport;
}
/**
* Custom action after section has been moved in AJAX mode
*
* Used in course/rest.php
*
* @return array This will be passed in ajax respose
*/
public function ajax_section_move() {
return null;
}
/**
* The URL to use for the specified course (with section)
*
* Please note that course view page /course/view.php?id=COURSEID is hardcoded in many
* places in core and contributed modules. If course format wants to change the location
* of the view script, it is not enough to change just this function. Do not forget
* to add proper redirection.
*
* @param int|stdClass $section Section object from database or just field course_sections.section
* if null the course view page is returned
* @param array $options options for view URL. At the moment core uses:
* 'navigation' (bool) if true and section has no separate page, the function returns null
* 'sr' (int) used by multipage formats to specify to which section to return
* @return null|moodle_url
*/
public function get_view_url($section, $options = array()) {
$course = $this->get_course();
$url = new moodle_url('/course/view.php', array('id' => $course->id));
$sr = null;
if (array_key_exists('sr', $options)) {
$sr = $options['sr'];
}
if (is_object($section)) {
$sectionno = $section->section;
} else {
$sectionno = $section;
}
if ($sectionno !== null) {
if ($sr !== null) {
if ($sr) {
$usercoursedisplay = COURSE_DISPLAY_MULTIPAGE;
$sectionno = $sr;
} else {
$usercoursedisplay = COURSE_DISPLAY_SINGLEPAGE;
}
} else {
$usercoursedisplay = $course->coursedisplay;
}
if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) {
$url->param('section', $sectionno);
} else {
if (!empty($options['navigation'])) {
return null;
}
$url->set_anchor('section-'.$sectionno);
}
}
return $url;
}
/**
* Loads all of the course sections into the navigation
*
* By default the method {@link global_navigation::load_generic_course_sections()} is called
*
* @param global_navigation $navigation
* @param navigation_node $node The course node within the navigation
* @return array Array of sections where each element also contains the element 'sectionnode'
* referring to the corresponding section node
*/
public function extend_course_navigation(&$navigation, navigation_node $node) {
if ($course = $this->get_course()) {
return $navigation->load_generic_course_sections($course, $node);
}
return array();
}
/**
* Returns the list of blocks to be automatically added for the newly created course
*
* @see blocks_add_default_course_blocks()
*
* @return array of default blocks, must contain two keys BLOCK_POS_LEFT and BLOCK_POS_RIGHT
* each of values is an array of block names (for left and right side columns)
*/
public function get_default_blocks() {
global $CFG;
if (!empty($CFG->defaultblocks)){
return blocks_parse_default_blocks_list($CFG->defaultblocks);
}
$blocknames = array(
BLOCK_POS_LEFT => array(),
BLOCK_POS_RIGHT => array('search_forums', 'news_items', 'calendar_upcoming', 'recent_activity')
);
return $blocknames;
}
/**
* Allows course format to execute code on moodle_page::set_course()
*
* @param moodle_page $page instance of page calling set_course
*/
public function page_set_course(moodle_page $page) {
}
/**
* Allows course format to execute code on moodle_page::set_cm()
*
* Current module can be accessed as $page->cm (returns instance of cm_info)
*
* @param moodle_page $page instance of page calling set_cm
*/
public function page_set_cm(moodle_page $page) {
}
}
/**
* Pseudo course format used for the site main page
*
* @package core_course
* @copyright 2012 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class format_site extends format_base {
/**
* Returns the display name of the given section that the course prefers.
*
* @param int|stdClass $section Section object from database or just field section.section
* @return Display name that the course format prefers, e.g. "Topic 2"
*/
function get_section_name($section) {
return get_string('site');
}
/**
* For this fake course referring to the whole site, the site homepage is always returned
* regardless of arguments
*
* @param int|stdClass $section
* @param array $options
* @return null|moodle_url
*/
public function get_view_url($section, $options = array()) {
return new moodle_url('/');
}
}