MDL-28135 general Updated broken and typo docs links
[moodle.git] / lib / pagelib.php
CommitLineData
50fcb1d8 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
f032aa7a 17
e0134f84 18/**
de60de04 19 * This file contains the moodle_page class. There is normally a single instance
78bfb562 20 * of this class in the $PAGE global variable. This class is a central repository
de60de04 21 * of information about the page we are building up to send back to the user.
e0134f84 22 *
78bfb562
PS
23 * @package core
24 * @subpackage lib
25 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
e0134f84 27 */
28
78bfb562 29defined('MOODLE_INTERNAL') || die();
2c144fc3 30
c13a5e71 31/**
32 * $PAGE is a central store of information about the current page we are
5c5418fe 33 * generating in response to the user's request.
34 *
35 * It does not do very much itself
c13a5e71 36 * except keep track of information, however, it serves as the access point to
37 * some more significant components like $PAGE->theme, $PAGE->requires,
38 * $PAGE->blocks, etc.
50fcb1d8 39 *
5c5418fe 40 * @copyright 2009 Tim Hunt
50fcb1d8 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
5c5418fe 42 * @since Moodle 2.0
2c144fc3 43 *
4ac8345f
SH
44 * @property-read string $activityname The type of activity we are in, for example 'forum' or 'quiz'.
45 * Will be null if this page is not within a module.
46 * @property-read object $activityrecord The row from the activities own database table (for example
47 * the forum or quiz table) that this page belongs to. Will be null
48 * if this page is not within a module.
49 * @property-read array $alternativeversions Mime type => object with ->url and ->title.
50 * @property-read blocks_manager $blocks The blocks manager object for this page.
51 * @property-read string $bodyclasses Returns a string to use within the class attribute on the body tag.
01ee99f4 52 * @property-read string $button The HTML to go where the Turn editing on button normally goes.
4ac8345f
SH
53 * @property-read bool $cacheable Defaults to true. Set to false to stop the page being cached at all.
54 * @property-read array $categories An array of all the categories the page course belongs to,
55 * starting with the immediately containing category, and working out to
56 * the top-level category. This may be the empty array if we are in the
57 * front page course.
58 * @property-read mixed $category The category that the page course belongs to. If there isn't one returns null.
59 * @property-read object $cm The course_module that this page belongs to. Will be null
60 * if this page is not within a module. This is a full cm object, as loaded
61 * by get_coursemodule_from_id or get_coursemodule_from_instance,
62 * so the extra modname and name fields are present.
63 * @property-read object $context The main context to which this page belongs.
64 * @property-read object $course The current course that we are inside - a row from the
65 * course table. (Also available as $COURSE global.) If we are not inside
66 * an actual course, this will be the site course.
e5824bb9 67 * @property-read string $devicetypeinuse The name of the device type in use
4ac8345f 68 * @property-read string $docspath The path to the Moodle docs for this page.
01ee99f4 69 * @property-read string $focuscontrol The id of the HTML element to be focused when the page has loaded.
4ac8345f
SH
70 * @property-read bool $headerprinted
71 * @property-read string $heading The main heading that should be displayed at the top of the <body>.
72 * @property-read string $headingmenu The menu (or actions) to display in the heading
73 * @property-read array $layout_options Returns arrays with options for layout file.
74 * @property-read navbar $navbar Returns the navbar object used to display the navbar
75 * @property-read global_navigation $navigation Returns the global navigation structure
76 * @property-read xml_container_stack $opencontainers Tracks XHTML tags on this page that have been opened but not closed.
77 * mainly for internal use by the rendering code.
78 * @property-read string $pagelayout The general type of page this is. For example 'normal', 'popup', 'home'.
34a2777c 79 * Allows the theme to display things differently, if it wishes to.
4ac8345f
SH
80 * @property-read string $pagetype Returns the page type string, should be used as the id for the body tag in the theme.
81 * @property-read int $periodicrefreshdelay The periodic refresh delay to use with meta refresh
82 * @property-read page_requirements_manager $requires Tracks the JavaScript, CSS files, etc. required by this page.
82721a2f 83 * @property-read settings_navigation $settingsnav
4ac8345f
SH
84 * @property-read int $state One of the STATE_... constants
85 * @property-read string $subpage The subpage identifier, if any.
86 * @property-read theme_config $theme Returns the initialised theme for this page.
87 * @property-read string $title The title that should go in the <head> section of the HTML of this page.
88 * @property-read moodle_url $url The moodle url object for this page.
c13a5e71 89 */
90class moodle_page {
91 /**#@+ Tracks the where we are in the generation of the page. */
92 const STATE_BEFORE_HEADER = 0;
93 const STATE_PRINTING_HEADER = 1;
94 const STATE_IN_BODY = 2;
34a2777c 95 const STATE_DONE = 3;
c13a5e71 96 /**#@-*/
97
753debd2 98/// Field declarations =========================================================
99
c13a5e71 100 protected $_state = self::STATE_BEFORE_HEADER;
101
102 protected $_course = null;
103
5ec434a9 104 /**
4478743c
PS
105 * If this page belongs to a module, this is the cm_info module description object.
106 * @var cm_info
5ec434a9 107 */
108 protected $_cm = null;
109
110 /**
111 * If $_cm is not null, then this will hold the corresponding row from the
112 * modname table. For example, if $_cm->modname is 'quiz', this will be a
113 * row from the quiz table.
114 */
115 protected $_module = null;
116
117 /**
118 * The context that this page belongs to.
119 */
2afe21ee 120 protected $_context = null;
121
948203a5 122 /**
123 * This holds any categories that $_course belongs to, starting with the
124 * particular category it belongs to, and working out through any parent
01ee99f4 125 * categories to the top level. These are loaded progressively, if needed.
948203a5 126 * There are three states. $_categories = null initially when nothing is
127 * loaded; $_categories = array($id => $cat, $parentid => null) when we have
128 * loaded $_course->category, but not any parents; and a complete array once
129 * everything is loaded.
130 */
131 protected $_categories = null;
132
753debd2 133 protected $_bodyclasses = array();
134
34a2777c 135 protected $_title = '';
136
137 protected $_heading = '';
138
f230ce19 139 protected $_pagetype = null;
140
191b267b 141 protected $_pagelayout = 'base';
78946b9b
PS
142
143 /**
01ee99f4 144 * List of theme layout options, these are ignored by core.
78946b9b
PS
145 * To be used in individual theme layout files only.
146 * @var array
147 */
148 protected $_layout_options = array();
34a2777c 149
08eab897 150 protected $_subpage = '';
5ed70539 151
82611d8d 152 protected $_docspath = null;
153
90723839 154 /** @var string|null A legacy class that will be added to the body tag */
d529807a 155 protected $_legacyclass = null;
156
75781f87 157 protected $_url = null;
158
34a2777c 159 protected $_alternateversions = array();
160
ad52c04f 161 protected $_blocks = null;
162
b2330db6 163 protected $_requires = null;
164
934524d7 165 protected $_blockseditingcap = 'moodle/site:manageblocks';
166
7db8dd1e
PS
167 protected $_block_actions_done = false;
168
934524d7 169 protected $_othereditingcaps = array();
170
34a2777c 171 protected $_cacheable = true;
172
173 protected $_focuscontrol = '';
174
175 protected $_button = '';
571fa828 176
b7009474 177 protected $_theme = null;
3406acde 178 /** @var global_navigation Contains the global navigation structure*/
7d2a0492 179 protected $_navigation = null;
180 /** @var null|settings_navigation Contains the settings navigation structure*/
181 protected $_settingsnav = null;
182 /** @var null|navbar Contains the navbar structure*/
183 protected $_navbar = null;
e120c61d 184 /** @var string */
185 protected $_headingmenu = null;
b7009474 186
187 /**
01ee99f4 188 * Then the theme is initialised, we save the stack trace, for use in error messages.
b7009474 189 * @var array stack trace.
190 */
191 protected $_wherethemewasinitialised = null;
192
db8d89d8 193 /** @var xhtml_container_stack tracks XHTML tags on this page that have been opened but not closed. */
194 protected $_opencontainers;
195
17a6649b 196 /**
197 * Sets the page to refresh after a given delay (in seconds) using meta refresh
198 * in {@link standard_head_html()} in outputlib.php
199 * If set to null(default) the page is not refreshed
200 * @var int|null
201 */
202 protected $_periodicrefreshdelay = null;
203
0d5890c4 204 /**
01ee99f4 205 * This is simply to improve backwards compatibility. If old code relies on
0d5890c4 206 * a page class that implements print_header, or complex logic in
207 * user_allowed_editing then we stash an instance of that other class here,
78946b9b 208 * and delegate to it in certain situations.
0d5890c4 209 */
210 protected $_legacypageobject = null;
211
ee8df661
SH
212 /**
213 * Associative array of browser shortnames (as used by check_browser_version)
214 * and their minimum required versions
215 * @var array
216 */
217 protected $_legacybrowsers = array('MSIE' => 6.0);
218
219 /**
37959dd4 220 * Is set to the name of the device type in use.
e5824bb9
SH
221 * This will we worked out when it is first used.
222 *
37959dd4 223 * @var string
ee8df661 224 */
e5824bb9 225 protected $_devicetypeinuse = null;
78bfb562 226
17c70aa0
PS
227 protected $_https_login_required = false;
228
e7f93d5c
AD
229 protected $_popup_notification_allowed = true;
230
649cf95d 231/// Magic getter methods =============================================================
5515b536 232/// Due to the __get magic below, you normally do not call these as $PAGE->magic_get_x
ad5d5997 233/// methods, but instead use the $PAGE->x syntax.
753debd2 234
c13a5e71 235 /**
34a2777c 236 * Please do not call this method directly, use the ->state syntax. {@link __get()}.
c13a5e71 237 * @return integer one of the STATE_... constants. You should not normally need
01ee99f4 238 * to use this in your code. It is intended for internal use by this class
c13a5e71 239 * and its friends like print_header, to check that everything is working as
240 * expected. Also accessible as $PAGE->state.
241 */
5515b536 242 protected function magic_get_state() {
c13a5e71 243 return $this->_state;
244 }
245
246 /**
34a2777c 247 * Please do not call this method directly, use the ->headerprinted syntax. {@link __get()}.
b7b2d0f3 248 * @return boolean has the header already been printed?
c13a5e71 249 */
5515b536 250 protected function magic_get_headerprinted() {
c13a5e71 251 return $this->_state >= self::STATE_IN_BODY;
252 }
253
254 /**
34a2777c 255 * Please do not call this method directly, use the ->course syntax. {@link __get()}.
50fcb1d8 256 *
257 * @global object
c13a5e71 258 * @return object the current course that we are inside - a row from the
259 * course table. (Also available as $COURSE global.) If we are not inside
b7b2d0f3 260 * an actual course, this will be the site course.
c13a5e71 261 */
5515b536 262 protected function magic_get_course() {
c13a5e71 263 global $SITE;
264 if (is_null($this->_course)) {
265 return $SITE;
266 }
267 return $this->_course;
268 }
269
5ec434a9 270 /**
34a2777c 271 * Please do not call this method directly, use the ->cm syntax. {@link __get()}.
5ec434a9 272 * @return object the course_module that this page belongs to. Will be null
273 * if this page is not within a module. This is a full cm object, as loaded
274 * by get_coursemodule_from_id or get_coursemodule_from_instance,
275 * so the extra modname and name fields are present.
4478743c 276 * @return cm_info
5ec434a9 277 */
5515b536 278 protected function magic_get_cm() {
5ec434a9 279 return $this->_cm;
280 }
281
282 /**
34a2777c 283 * Please do not call this method directly, use the ->activityrecord syntax. {@link __get()}.
b7b2d0f3 284 * @return object the row from the activities own database table (for example
285 * the forum or quiz table) that this page belongs to. Will be null
286 * if this page is not within a module.
5ec434a9 287 */
5515b536 288 protected function magic_get_activityrecord() {
5ec434a9 289 if (is_null($this->_module) && !is_null($this->_cm)) {
290 $this->load_activity_record();
291 }
292 return $this->_module;
293 }
294
295 /**
34a2777c 296 * Please do not call this method directly, use the ->activityname syntax. {@link __get()}.
b7b2d0f3 297 * @return string|null the The type of activity we are in, for example 'forum' or 'quiz'.
298 * Will be null if this page is not within a module.
5ec434a9 299 */
5515b536 300 protected function magic_get_activityname() {
5ec434a9 301 if (is_null($this->_cm)) {
302 return null;
303 }
304 return $this->_cm->modname;
305 }
306
948203a5 307 /**
34a2777c 308 * Please do not call this method directly, use the ->category syntax. {@link __get()}.
948203a5 309 * @return mixed the category that the page course belongs to. If there isn't one
310 * (that is, if this is the front page course) returns null.
311 */
5515b536 312 protected function magic_get_category() {
948203a5 313 $this->ensure_category_loaded();
314 if (!empty($this->_categories)) {
315 return reset($this->_categories);
316 } else {
317 return null;
318 }
319 }
320
321 /**
34a2777c 322 * Please do not call this method directly, use the ->categories syntax. {@link __get()}.
948203a5 323 * @return array an array of all the categories the page course belongs to,
324 * starting with the immediately containing category, and working out to
325 * the top-level category. This may be the empty array if we are in the
326 * front page course.
327 */
5515b536 328 protected function magic_get_categories() {
948203a5 329 $this->ensure_categories_loaded();
330 return $this->_categories;
331 }
332
2afe21ee 333 /**
34a2777c 334 * Please do not call this method directly, use the ->context syntax. {@link __get()}.
2afe21ee 335 * @return object the main context to which this page belongs.
336 */
5515b536 337 protected function magic_get_context() {
2afe21ee 338 if (is_null($this->_context)) {
eb5bdb35
PS
339 if (CLI_SCRIPT or NO_MOODLE_COOKIES) {
340 // cli scripts work in system context, do not annoy devs with debug info
341 // very few scripts do not use cookies, we can safely use system as default context there
4ee51346 342 } else {
c78f8443
MJ
343 debugging('Coding problem: $PAGE->context was not set. You may have forgotten '
344 .'to call require_login() or $PAGE->set_context(). The page may not display '
345 .'correctly as a result');
4ee51346 346 }
eb5bdb35 347 $this->_context = get_context_instance(CONTEXT_SYSTEM);
2afe21ee 348 }
349 return $this->_context;
350 }
351
f230ce19 352 /**
34a2777c 353 * Please do not call this method directly, use the ->pagetype syntax. {@link __get()}.
90723839 354 * @return string e.g. 'my-index' or 'mod-quiz-attempt'.
f230ce19 355 */
5515b536 356 protected function magic_get_pagetype() {
bd348bda 357 global $CFG;
d529807a 358 if (is_null($this->_pagetype) || isset($CFG->pagepath)) {
359 $this->initialise_default_pagetype();
f230ce19 360 }
361 return $this->_pagetype;
362 }
363
90723839
SH
364 /**
365 * Please do not call this method directly, use the ->pagetype syntax. {@link __get()}.
366 * @return string The id to use on the body tag, uses {@link magic_get_pagetype()}.
367 */
368 protected function magic_get_bodyid() {
369 return 'page-'.$this->pagetype;
370 }
371
5ed70539 372 /**
78946b9b 373 * Please do not call this method directly, use the ->pagelayout syntax. {@link __get()}.
191b267b 374 * @return string the general type of page this is. For example 'standard', 'popup', 'home'.
34a2777c 375 * Allows the theme to display things differently, if it wishes to.
376 */
5515b536 377 protected function magic_get_pagelayout() {
78946b9b
PS
378 return $this->_pagelayout;
379 }
380
381 /**
382 * Please do not call this method directly, use the ->layout_tions syntax. {@link __get()}.
4ac8345f 383 * @return array returns arrys with options for layout file
78946b9b 384 */
5515b536 385 protected function magic_get_layout_options() {
78946b9b 386 return $this->_layout_options;
34a2777c 387 }
388
389 /**
390 * Please do not call this method directly, use the ->subpage syntax. {@link __get()}.
5ed70539 391 * @return string|null The subpage identifier, if any.
392 */
5515b536 393 protected function magic_get_subpage() {
5ed70539 394 return $this->_subpage;
395 }
396
753debd2 397 /**
34a2777c 398 * Please do not call this method directly, use the ->bodyclasses syntax. {@link __get()}.
753debd2 399 * @return string the class names to put on the body element in the HTML.
400 */
5515b536 401 protected function magic_get_bodyclasses() {
753debd2 402 return implode(' ', array_keys($this->_bodyclasses));
403 }
404
82611d8d 405 /**
34a2777c 406 * Please do not call this method directly, use the ->title syntax. {@link __get()}.
407 * @return string the title that should go in the <head> section of the HTML of this page.
408 */
5515b536 409 protected function magic_get_title() {
34a2777c 410 return $this->_title;
411 }
412
413 /**
414 * Please do not call this method directly, use the ->heading syntax. {@link __get()}.
415 * @return string the main heading that should be displayed at the top of the <body>.
416 */
5515b536 417 protected function magic_get_heading() {
34a2777c 418 return $this->_heading;
419 }
420
e120c61d 421 /**
422 * Please do not call this method directly, use the ->heading syntax. {@link __get()}.
423 * @return string The menu (or actions) to display in the heading
424 */
5515b536 425 protected function magic_get_headingmenu() {
e120c61d 426 return $this->_headingmenu;
427 }
428
34a2777c 429 /**
430 * Please do not call this method directly, use the ->docspath syntax. {@link __get()}.
b7b2d0f3 431 * @return string the path to the Moodle docs for this page.
82611d8d 432 */
5515b536 433 protected function magic_get_docspath() {
82611d8d 434 if (is_string($this->_docspath)) {
435 return $this->_docspath;
436 } else {
437 return str_replace('-', '/', $this->pagetype);
438 }
439 }
440
75781f87 441 /**
34a2777c 442 * Please do not call this method directly, use the ->url syntax. {@link __get()}.
75781f87 443 * @return moodle_url the clean URL required to load the current page. (You
444 * should normally use this in preference to $ME or $FULLME.)
445 */
5515b536 446 protected function magic_get_url() {
c1df9d7c 447 global $FULLME;
75781f87 448 if (is_null($this->_url)) {
c1df9d7c 449 debugging('This page did not call $PAGE->set_url(...). Using '.s($FULLME), DEBUG_DEVELOPER);
727ae436 450 $this->_url = new moodle_url($FULLME);
451 // Make sure the guessed URL cannot lead to dangerous redirects.
452 $this->_url->remove_params('sesskey');
75781f87 453 }
ad52c04f 454 return new moodle_url($this->_url); // Return a clone for safety.
455 }
456
457 /**
34a2777c 458 * The list of alternate versions of this page.
459 * @return array mime type => object with ->url and ->title.
460 */
5515b536 461 protected function magic_get_alternateversions() {
34a2777c 462 return $this->_alternateversions;
463 }
464
465 /**
466 * Please do not call this method directly, use the ->blocks syntax. {@link __get()}.
ad52c04f 467 * @return blocks_manager the blocks manager object for this page.
468 */
5515b536 469 protected function magic_get_blocks() {
78946b9b 470 global $CFG;
ad52c04f 471 if (is_null($this->_blocks)) {
86b5ea0f 472 if (!empty($CFG->blockmanagerclass)) {
473 $classname = $CFG->blockmanagerclass;
474 } else {
475 $classname = 'block_manager';
476 }
477 $this->_blocks = new $classname($this);
ad52c04f 478 }
479 return $this->_blocks;
75781f87 480 }
481
b2330db6 482 /**
34a2777c 483 * Please do not call this method directly, use the ->requires syntax. {@link __get()}.
571fa828 484 * @return page_requirements_manager tracks the JavaScript, CSS files, etc. required by this page.
b2330db6 485 */
5515b536 486 protected function magic_get_requires() {
b2330db6 487 global $CFG;
488 if (is_null($this->_requires)) {
489 $this->_requires = new page_requirements_manager();
b2330db6 490 }
491 return $this->_requires;
492 }
493
571fa828 494 /**
34a2777c 495 * Please do not call this method directly, use the ->cacheable syntax. {@link __get()}.
496 * @return boolean can this page be cached by the user's browser.
571fa828 497 */
5515b536 498 protected function magic_get_cacheable() {
34a2777c 499 return $this->_cacheable;
500 }
501
502 /**
503 * Please do not call this method directly, use the ->focuscontrol syntax. {@link __get()}.
01ee99f4 504 * @return string the id of the HTML element to be focused when the page has loaded.
34a2777c 505 */
5515b536 506 protected function magic_get_focuscontrol() {
34a2777c 507 return $this->_focuscontrol;
508 }
509
510 /**
511 * Please do not call this method directly, use the ->button syntax. {@link __get()}.
01ee99f4 512 * @return string the HTML to go where the Turn editing on button normally goes.
34a2777c 513 */
5515b536 514 protected function magic_get_button() {
34a2777c 515 return $this->_button;
571fa828 516 }
517
b7009474 518 /**
519 * Please do not call this method directly, use the ->theme syntax. {@link __get()}.
4ac8345f 520 * @return theme_config the initialised theme for this page.
b7009474 521 */
5515b536 522 protected function magic_get_theme() {
b7009474 523 if (is_null($this->_theme)) {
524 $this->initialise_theme_and_output();
525 }
526 return $this->_theme;
527 }
528
ee8df661 529 /**
37959dd4 530 * Please do not call this method directly, use the ->devicetypeinuse syntax. {@link __get()}.
e5824bb9
SH
531 *
532 * @return string The device type being used.
ee8df661 533 */
37959dd4 534 protected function magic_get_devicetypeinuse() {
e5824bb9
SH
535 if (empty($this->_devicetypeinuse)) {
536 $this->_devicetypeinuse = get_user_device_type();
537 }
538 return $this->_devicetypeinuse;
539 }
540
541 /**
542 * Please do not call this method directly, use the ->legacythemeinuse syntax. {@link __get()}.
543 * @deprecated since 2.1
544 * @return bool
545 */
546 protected function magic_get_legacythemeinuse() {
547 debugging('$PAGE->legacythemeinuse is a deprecated property - please use $PAGE->devicetypeinuse and check if it is equal to legacy.', DEVELOPER_DEBUG);
548 return ($this->devicetypeinuse == 'legacy');
ee8df661
SH
549 }
550
17a6649b 551 /**
afa2dcad 552 * Please do not call this method directly use the ->periodicrefreshdelay syntax
553 * {@link __get()}
554 * @return int The periodic refresh delay to use with meta refresh
17a6649b 555 */
5515b536 556 protected function magic_get_periodicrefreshdelay() {
17a6649b 557 return $this->_periodicrefreshdelay;
558 }
559
db8d89d8 560 /**
561 * Please do not call this method directly use the ->opencontainers syntax. {@link __get()}
562 * @return xhtml_container_stack tracks XHTML tags on this page that have been opened but not closed.
563 * mainly for internal use by the rendering code.
564 */
5515b536 565 protected function magic_get_opencontainers() {
db8d89d8 566 if (is_null($this->_opencontainers)) {
567 $this->_opencontainers = new xhtml_container_stack();
568 }
569 return $this->_opencontainers;
570 }
571
7d2a0492 572 /**
573 * Return the navigation object
574 * @return global_navigation
575 */
5515b536 576 protected function magic_get_navigation() {
7d2a0492 577 if ($this->_navigation === null) {
3406acde 578 $this->_navigation = new global_navigation($this);
7d2a0492 579 }
580 return $this->_navigation;
581 }
582
583 /**
584 * Return a navbar object
585 * @return navbar
586 */
5515b536 587 protected function magic_get_navbar() {
7d2a0492 588 if ($this->_navbar === null) {
589 $this->_navbar = new navbar($this);
590 }
591 return $this->_navbar;
592 }
593
594 /**
595 * Returns the settings navigation object
596 * @return settings_navigation
597 */
5515b536 598 protected function magic_get_settingsnav() {
7d2a0492 599 if ($this->_settingsnav === null) {
600 $this->_settingsnav = new settings_navigation($this);
601 $this->_settingsnav->initialise();
602 }
603 return $this->_settingsnav;
604 }
605
89fbdca3 606 /**
b7b2d0f3 607 * PHP overloading magic to make the $PAGE->course syntax work by redirecting
5515b536 608 * it to the corresponding $PAGE->magic_get_course() method if there is one, and
b7b2d0f3 609 * throwing an exception if not.
7db8dd1e
PS
610 *
611 * @param $name string property name
5515b536 612 * @return mixed
89fbdca3 613 */
7db8dd1e
PS
614 public function __get($name) {
615 $getmethod = 'magic_get_' . $name;
89fbdca3 616 if (method_exists($this, $getmethod)) {
617 return $this->$getmethod();
618 } else {
7db8dd1e
PS
619 throw new coding_exception('Unknown property ' . $name . ' of $PAGE.');
620 }
621 }
622
623 /**
624 * PHP overloading magic which prevents the $PAGE->context = $context; syntax
625 *
626 * @param $name string property name
627 * @param $name mixed value
628 * @return void, throws exception if field not defined in page class
629 */
630 public function __set($name, $value) {
631 if (method_exists($this, 'set_' . $name)) {
632 throw new coding_exception('Invalid attempt to modify page object', "Use \$PAGE->set_$name() instead.");
633 } else {
634 throw new coding_exception('Invalid attempt to modify page object', "Unknown property $name");
89fbdca3 635 }
636 }
637
830dd6e9 638/// Other information getting methods ==========================================
639
649cf95d
PS
640 /**
641 * Returns instance of page renderer
642 * @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'.
643 * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
c927e35c 644 * @param string $target one of rendering target constants
649cf95d
PS
645 * @return renderer_base
646 */
c927e35c
PS
647 public function get_renderer($component, $subtype = null, $target = null) {
648 return $this->magic_get_theme()->get_renderer($this, $component, $subtype, $target);
649cf95d
PS
649 }
650
5515b536
PS
651 /**
652 * Checks to see if there are any items on the navbar object
653 * @return bool true if there are, false if not
654 */
655 public function has_navbar() {
656 if ($this->_navbar === null) {
657 $this->_navbar = new navbar($this);
658 }
659 return $this->_navbar->has_items();
660 }
661
830dd6e9 662 /**
663 * @return boolean should the current user see this page in editing mode.
664 * That is, are they allowed to edit this page, and are they currently in
665 * editing mode.
666 */
667 public function user_is_editing() {
668 global $USER;
669 return !empty($USER->editing) && $this->user_allowed_editing();
670 }
671
bb46a4fa 672 /**
673 * @return boolean does the user have permission to edit blocks on this page.
674 */
675 public function user_can_edit_blocks() {
676 return has_capability($this->_blockseditingcap, $this->_context);
677 }
678
830dd6e9 679 /**
680 * @return boolean does the user have permission to see this page in editing mode.
681 */
682 public function user_allowed_editing() {
0d5890c4 683 if ($this->_legacypageobject) {
684 return $this->_legacypageobject->user_allowed_editing();
685 }
eb5bdb35 686 return has_any_capability($this->all_editing_caps(), $this->_context);
830dd6e9 687 }
688
2c0901cb 689 /**
a8c310c2 690 * @return string a description of this page. Normally displayed in the footer in
691 * developer debug mode.
2c0901cb 692 */
693 public function debug_summary() {
a8c310c2 694 $summary = '';
78946b9b 695 $summary .= 'General type: ' . $this->pagelayout . '. ';
a8c310c2 696 if (!during_initial_install()) {
eb5bdb35 697 $summary .= 'Context ' . print_context_name($this->_context) . ' (context id ' . $this->_context->id . '). ';
a8c310c2 698 }
2c0901cb 699 $summary .= 'Page type ' . $this->pagetype . '. ';
700 if ($this->subpage) {
701 'Sub-page ' . $this->subpage . '. ';
702 }
703 return $summary;
704 }
705
753debd2 706/// Setter methods =============================================================
707
c13a5e71 708 /**
709 * Set the state. The state must be one of that STATE_... constants, and
710 * the state is only allowed to advance one step at a time.
711 * @param integer $state the new state.
712 */
713 public function set_state($state) {
714 if ($state != $this->_state + 1 || $state > self::STATE_DONE) {
715 throw new coding_exception('Invalid state passed to moodle_page::set_state. We are in state ' .
54caa598 716 $this->_state . ' and state ' . $state . ' was requested.');
c13a5e71 717 }
718
753debd2 719 if ($state == self::STATE_PRINTING_HEADER) {
08eab897 720 $this->starting_output();
c13a5e71 721 }
722
723 $this->_state = $state;
724 }
725
726 /**
727 * Set the current course. This sets both $PAGE->course and $COURSE. It also
728 * sets the right theme and locale.
729 *
730 * Normally you don't need to call this function yourself, require_login will
731 * call it for you if you pass a $course to it. You can use this function
732 * on pages that do need to call require_login().
733 *
2afe21ee 734 * Sets $PAGE->context to the course context, if it is not already set.
735 *
c13a5e71 736 * @param object the course to set as the global course.
737 */
738 public function set_course($course) {
b7009474 739 global $COURSE, $PAGE;
c13a5e71 740
741 if (empty($course->id)) {
742 throw new coding_exception('$course passed to moodle_page::set_course does not look like a proper course object.');
743 }
744
b7009474 745 $this->ensure_theme_not_set();
c13a5e71 746
d7ab8879 747 if (!empty($this->_course->id) && $this->_course->id != $course->id) {
748 $this->_categories = null;
749 }
750
c13a5e71 751 $this->_course = clone($course);
b7009474 752
753 if ($this === $PAGE) {
754 $COURSE = $this->_course;
755 moodle_setlocale();
756 }
c13a5e71 757
2afe21ee 758 if (!$this->_context) {
759 $this->set_context(get_context_instance(CONTEXT_COURSE, $this->_course->id));
760 }
c13a5e71 761 }
762
2afe21ee 763 /**
764 * Set the main context to which this page belongs.
765 * @param object $context a context object, normally obtained with get_context_instance.
766 */
767 public function set_context($context) {
eb5bdb35
PS
768 if ($context === null) {
769 // extremely ugly hack which sets context to some value in order to prevent warnings,
770 // use only for core error handling!!!!
771 if (!$this->_context) {
772 $this->_context = get_context_instance(CONTEXT_SYSTEM);
773 }
774 return;
775 }
776
777 // ideally we should set context only once
778 if (isset($this->_context)) {
779 if ($context->id == $this->_context->id) {
780 // fine - no change needed
781 } else if ($this->_context->contextlevel == CONTEXT_SYSTEM or $this->_context->contextlevel == CONTEXT_COURSE) {
782 // hmm - not ideal, but it might produce too many warnings due to the design of require_login
ce8b66c6
PS
783 } else if ($this->_context->contextlevel == CONTEXT_MODULE and $this->_context->id == get_parent_contextid($context)) {
784 // hmm - most probably somebody did require_login() and after that set the block context
eb5bdb35
PS
785 } else {
786 // we do not want devs to do weird switching of context levels on the fly,
787 // because we might have used the context already such as in text filter in page title
788 debugging('Coding problem: unsupported modification of PAGE->context from '.$this->_context->contextlevel.' to '.$context->contextlevel);
789 }
790 }
791
2afe21ee 792 $this->_context = $context;
793 }
794
5ec434a9 795 /**
796 * The course module that this page belongs to (if it does belong to one).
797 *
4478743c 798 * @param stdClass|cm_info $cm a record from course_modules table or cm_info from get_fast_modinfo().
6a630a10
PS
799 * @param stdClass $course
800 * @param stdClass $module
801 * @return void
5ec434a9 802 */
803 public function set_cm($cm, $course = null, $module = null) {
eb5bdb35
PS
804 global $DB;
805
4478743c
PS
806 if (!isset($cm->id) || !isset($cm->course)) {
807 throw new coding_exception('Invalid $cm parameter for $PAGE object, it has to be instance of cm_info or record from the course_modules table.');
5ec434a9 808 }
4478743c 809
5ec434a9 810 if (!$this->_course || $this->_course->id != $cm->course) {
811 if (!$course) {
eb5bdb35 812 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
5ec434a9 813 }
814 if ($course->id != $cm->course) {
4478743c 815 throw new coding_exception('The course you passed to $PAGE->set_cm does not correspond to the $cm.');
5ec434a9 816 }
817 $this->set_course($course);
818 }
4478743c
PS
819
820 // make sure we have a $cm from get_fast_modinfo as this contains activity access details
821 if (!($cm instanceof cm_info)) {
822 $modinfo = get_fast_modinfo($this->_course);
823 $cm = $modinfo->get_cm($cm->id);
824 }
825 $this->_cm = $cm;
ce8b66c6
PS
826
827 // unfortunately the context setting is a mess, let's try to work around some common block problems and show some debug messages
828 if (empty($this->_context) or $this->_context->contextlevel != CONTEXT_BLOCK) {
829 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
830 $this->set_context($context);
831 }
4478743c 832
5ec434a9 833 if ($module) {
834 $this->set_activity_record($module);
835 }
836 }
837
838 /**
839 * @param $module a row from the main database table for the module that this
840 * page belongs to. For example, if ->cm is a forum, then you can pass the
841 * corresponding row from the forum table here if you have it (saves a database
842 * query sometimes).
843 */
844 public function set_activity_record($module) {
845 if (is_null($this->_cm)) {
846 throw new coding_exception('You cannot call $PAGE->set_activity_record until after $PAGE->cm has been set.');
847 }
848 if ($module->id != $this->_cm->instance || $module->course != $this->_course->id) {
849 throw new coding_exception('The activity record your are trying to set does not seem to correspond to the cm that has been set.');
850 }
851 $this->_module = $module;
852 }
853
f230ce19 854 /**
855 * @param string $pagetype e.g. 'my-index' or 'mod-quiz-attempt'. Normally
856 * you do not need to set this manually, it is automatically created from the
857 * script name. However, on some pages this is overridden. For example, the
01ee99f4
PS
858 * page type for course/view.php includes the course format, for example
859 * 'course-view-weeks'. This gets used as the id attribute on <body> and
f230ce19 860 * also for determining which blocks are displayed.
861 */
862 public function set_pagetype($pagetype) {
863 $this->_pagetype = $pagetype;
864 }
865
34a2777c 866 /**
78946b9b 867 * @param string $pagelayout the page layout this is. For example 'popup', 'home'.
191b267b 868 * This properly defaults to 'base', so you only need to call this function if
78946b9b
PS
869 * you want something different. The exact range of supported layouts is specified
870 * in the standard theme.
34a2777c 871 */
78946b9b 872 public function set_pagelayout($pagelayout) {
66f63697
SH
873 /**
874 * Uncomment this to debug theme pagelayout issues like missing blocks.
875 *
876 * if (!empty($this->_wherethemewasinitialised) && $pagelayout != $this->_pagelayout) {
877 * debugging('Page layout has already been set and cannot be changed.', DEBUG_DEVELOPER);
878 * }
879 */
78946b9b 880 $this->_pagelayout = $pagelayout;
34a2777c 881 }
882
5ed70539 883 /**
884 * If context->id and pagetype are not enough to uniquely identify this page,
885 * then you can set a subpage id as well. For example, the tags page sets
886 * @param string $subpage an arbitrary identifier that, along with context->id
887 * and pagetype, uniquely identifies this page.
888 */
889 public function set_subpage($subpage) {
08eab897 890 if (empty($subpage)) {
891 $this->_subpage = '';
892 } else {
893 $this->_subpage = $subpage;
894 }
5ed70539 895 }
896
753debd2 897 /**
898 * @param string $class add this class name ot the class attribute on the body tag.
899 */
900 public function add_body_class($class) {
901 if ($this->_state > self::STATE_BEFORE_HEADER) {
902 throw new coding_exception('Cannot call moodle_page::add_body_class after output has been started.');
903 }
904 $this->_bodyclasses[$class] = 1;
905 }
906
c13a5e71 907 /**
89fbdca3 908 * @param array $classes this utility method calls add_body_class for each array element.
c13a5e71 909 */
89fbdca3 910 public function add_body_classes($classes) {
911 foreach ($classes as $class) {
912 $this->add_body_class($class);
c13a5e71 913 }
914 }
f230ce19 915
34a2777c 916 /**
e120c61d 917 * @param string $title the title that should go in the <head> section of the HTML of this page.
34a2777c 918 */
919 public function set_title($title) {
920 $title = format_string($title);
921 $title = str_replace('"', '&quot;', $title);
922 $this->_title = $title;
923 }
924
925 /**
e120c61d 926 * @param string $heading the main heading that should be displayed at the top of the <body>.
34a2777c 927 */
928 public function set_heading($heading) {
929 $this->_heading = format_string($heading);
930 }
931
e120c61d 932 /**
933 * @param string $menu The menu/content to show in the heading
934 */
935 public function set_headingmenu($menu) {
936 $this->_headingmenu = $menu;
937 }
938
948203a5 939 /**
940 * Set the course category this page belongs to manually. This automatically
01ee99f4 941 * sets $PAGE->course to be the site course. You cannot use this method if
948203a5 942 * you have already set $PAGE->course - in that case, the category must be
943 * the one that the course belongs to. This also automatically sets the
944 * page context to the category context.
945 * @param integer $categoryid The id of the category to set.
946 */
947 public function set_category_by_id($categoryid) {
948 global $SITE, $DB;
949 if (!is_null($this->_course)) {
950 throw new coding_exception('Attempt to manually set the course category when the course has been set. This is not allowed.');
951 }
952 if (is_array($this->_categories)) {
953 throw new coding_exception('Course category has already been set. You are not allowed to change it.');
954 }
b7009474 955 $this->ensure_theme_not_set();
948203a5 956 $this->set_course($SITE);
957 $this->load_category($categoryid);
958 $this->set_context(get_context_instance(CONTEXT_COURSECAT, $categoryid));
959 }
960
82611d8d 961 /**
962 * Set a different path to use for the 'Moodle docs for this page' link.
963 * By default, it uses the pagetype, which is normally the same as the
964 * script name. So, for example, for mod/quiz/attempt.php, pagetype is
965 * mod-quiz-attempt, and so docspath is mod/quiz/attempt.
966 * @param string $path the path to use at the end of the moodle docs URL.
967 */
968 public function set_docs_path($path) {
969 $this->_docspath = $path;
970 }
971
75781f87 972 /**
973 * You should call this method from every page to set the cleaned-up URL
974 * that should be used to return to this page. Used, for example, by the
975 * blocks editing UI to know where to return the user after an action.
976 * For example, course/view.php does:
977 * $id = optional_param('id', 0, PARAM_INT);
a6855934 978 * $PAGE->set_url('/course/view.php', array('id' => $id));
c909711a 979 * @param moodle_url|string $url URL relative to $CFG->wwwroot or {@link moodle_url} instance
01ee99f4 980 * @param array $params parameters to add to the URL
75781f87 981 */
a6855934 982 public function set_url($url, array $params = null) {
75781f87 983 global $CFG;
42174e18 984
a6855934 985 if (is_string($url)) {
42174e18 986 if (strpos($url, 'http') === 0) {
a6855934
PS
987 // ok
988 } else if (strpos($url, '/') === 0) {
42174e18 989 // we have to use httpswwwroot here, because of loginhttps pages
a6855934
PS
990 $url = $CFG->httpswwwroot . $url;
991 } else {
992 throw new coding_exception('Invalid parameter $url, has to be full url or in shortened form starting with /.');
42174e18 993 }
7dc928b5 994 }
42174e18 995
a6855934
PS
996 $this->_url = new moodle_url($url, $params);
997
eb788065 998 $fullurl = $this->_url->out_omit_querystring();
42174e18
PS
999 if (strpos($fullurl, "$CFG->httpswwwroot/") !== 0) {
1000 debugging('Most probably incorrect set_page() url argument, it does not match the httpswwwroot!');
1001 }
1002 $shorturl = str_replace("$CFG->httpswwwroot/", '', $fullurl);
1003
75781f87 1004 if (is_null($this->_pagetype)) {
7dc928b5 1005 $this->initialise_default_pagetype($shorturl);
75781f87 1006 }
5ec434a9 1007 if (!is_null($this->_legacypageobject)) {
de8a1d10 1008 $this->_legacypageobject->set_url($url, $params);
5ec434a9 1009 }
75781f87 1010 }
1011
727ae436 1012 /**
1013 * Make sure page URL does not contain the given URL parameter.
1014 *
1015 * This should not be necessary if the script has called set_url properly.
1016 * However, in some situations like the block editing actions; when the URL
1017 * has been guessed, it will contain dangerous block-related actions.
1018 * Therefore, the blocks code calls this function to clean up such parameters
1019 * before doing any redirect.
117bd748 1020 *
727ae436 1021 * @param string $param the name of the parameter to make sure is not in the
1022 * page URL.
1023 */
1024 public function ensure_param_not_in_url($param) {
1025 $discard = $this->url; // Make sure $this->url is lazy-loaded;
1026 $this->_url->remove_params($param);
1027 }
1028
34a2777c 1029 /**
1030 * There can be alternate versions of some pages (for example an RSS feed version).
1031 * If such other version exist, call this method, and a link to the alternate
1032 * version will be included in the <head> of the page.
1033 *
1034 * @param $title The title to give the alternate version.
1035 * @param $url The URL of the alternate version.
1036 * @param $mimetype The mime-type of the alternate version.
1037 */
1038 public function add_alternate_version($title, $url, $mimetype) {
1039 if ($this->_state > self::STATE_BEFORE_HEADER) {
1040 throw new coding_exception('Cannot call moodle_page::add_alternate_version after output has been started.');
1041 }
1042 $alt = new stdClass;
1043 $alt->title = $title;
9d88a01b 1044 $alt->url = $url;
34a2777c 1045 $this->_alternateversions[$mimetype] = $alt;
1046 }
1047
1048 /**
01ee99f4 1049 * Specify a form control should be focused when the page has loaded.
34a2777c 1050 *
01ee99f4 1051 * @param string $controlid the id of the HTML element to be focused.
34a2777c 1052 */
1053 public function set_focuscontrol($controlid) {
1054 $this->_focuscontrol = $controlid;
1055 }
1056
1057 /**
1058 * Specify a fragment of HTML that goes where the 'Turn editing on' button normally goes.
1059 *
1060 * @param string $html the HTML to display there.
1061 */
1062 public function set_button($html) {
1063 $this->_button = $html;
1064 }
1065
934524d7 1066 /**
1067 * Set the capability that allows users to edit blocks on this page. Normally
1068 * the default of 'moodle/site:manageblocks' is used, but a few pages like
1069 * the My Moodle page need to use a different capability like 'moodle/my:manageblocks'.
1070 * @param string $capability a capability.
1071 */
1072 public function set_blocks_editing_capability($capability) {
1073 $this->_blockseditingcap = $capability;
1074 }
1075
1076 /**
1077 * Some pages let you turn editing on for reasons other than editing blocks.
01ee99f4 1078 * If that is the case, you can pass other capabilities that let the user
934524d7 1079 * edit this page here.
1080 * @param string|array $capability either a capability, or an array of capabilities.
1081 */
1082 public function set_other_editing_capability($capability) {
1083 if (is_array($capability)) {
1084 $this->_othereditingcaps = array_unique($this->_othereditingcaps + $capability);
1085 } else {
1086 $this->_othereditingcaps[] = $capability;
1087 }
1088 }
1089
34a2777c 1090 /**
1091 * @return boolean $cacheable can this page be cached by the user's browser.
1092 */
1093 public function set_cacheable($cacheable) {
1094 $this->_cacheable = $cacheable;
1095 }
1096
17a6649b 1097 /**
1098 * Sets the page to periodically refresh
1099 *
1100 * This function must be called before $OUTPUT->header has been called or
1101 * a coding exception will be thrown.
1102 *
1103 * @param int $delay Sets the delay before refreshing the page, if set to null
1104 * refresh is cancelled
1105 */
1106 public function set_periodic_refresh_delay($delay=null) {
1107 if ($this->_state > self::STATE_BEFORE_HEADER) {
1108 throw new coding_exception('You cannot set a periodic refresh delay after the header has been printed');
1109 }
1110 if ($delay===null) {
1111 $this->_periodicrefreshdelay = null;
1112 } else if (is_int($delay)) {
1113 $this->_periodicrefreshdelay = $delay;
1114 }
1115 }
1116
b7009474 1117 /**
1118 * Force this page to use a particular theme.
1119 *
cbcc9852 1120 * Please use this cautiously. It is only intended to be used by the themes selector admin page.
b7009474 1121 *
1122 * @param $themename the name of the theme to use.
1123 */
1124 public function force_theme($themename) {
b7009474 1125 $this->ensure_theme_not_set();
1126 $this->_theme = theme_config::load($themename);
b7009474 1127 }
1128
1129 /**
17c70aa0
PS
1130 * This function indicates that current page requires the https
1131 * when $CFG->loginhttps enabled.
b7009474 1132 *
1133 * By using this function properly, we can ensure 100% https-ized pages
1134 * at our entire discretion (login, forgot_password, change_password)
17c70aa0 1135 * @return void
b7009474 1136 */
1137 public function https_required() {
17c70aa0
PS
1138 global $CFG;
1139
1140 if (!is_null($this->_url)) {
1141 throw new coding_exception('https_required() must be used before setting page url!');
1142 }
b7009474 1143
1144 $this->ensure_theme_not_set();
1145
17c70aa0
PS
1146 $this->_https_login_required = true;
1147
b7009474 1148 if (!empty($CFG->loginhttps)) {
b7009474 1149 $CFG->httpswwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
b7009474 1150 } else {
1151 $CFG->httpswwwroot = $CFG->wwwroot;
b7009474 1152 }
1153 }
1154
17c70aa0
PS
1155 /**
1156 * Makes sure that page previously marked with https_required()
1157 * is really using https://, if not it redirects to https://
1158 *
1159 * @return void (may redirect to https://self)
1160 */
1161 public function verify_https_required() {
1162 global $CFG, $FULLME;
1163
1164 if (is_null($this->_url)) {
1165 throw new coding_exception('verify_https_required() must be called after setting page url!');
1166 }
1167
1168 if (!$this->_https_login_required) {
1169 throw new coding_exception('verify_https_required() must be called only after https_required()!');
1170 }
1171
1172 if (empty($CFG->loginhttps)) {
1173 // https not required, so stop checking
1174 return;
1175 }
1176
1177 if (strpos($this->_url, 'https://')) {
1178 // detect if incorrect PAGE->set_url() used, it is recommended to use root-relative paths there
1179 throw new coding_exception('Invalid page url specified, it must start with https:// for pages that set https_required()!');
1180 }
1181
1182 if (!empty($CFG->sslproxy)) {
1183 // it does not make much sense to use sslproxy and loginhttps at the same time
1184 return;
1185 }
1186
1187 // now the real test and redirect!
1188 if (strpos($FULLME, 'https:') !== 0) {
1189 // this may lead to infinite redirect on misconfigured sites, in that case use $CFG->loginhttps=0; in /config.php
1190 redirect($this->_url);
1191 }
1192 }
1193
753debd2 1194/// Initialisation methods =====================================================
1195/// These set various things up in a default way.
1196
08eab897 1197 /**
1198 * This method is called when the page first moves out of the STATE_BEFORE_HEADER
1199 * state. This is our last change to initialise things.
1200 */
1201 protected function starting_output() {
144390b4 1202 global $CFG;
9d1d606e 1203
94398fb3 1204 if (!during_initial_install()) {
1205 $this->blocks->load_blocks();
a19f419d 1206 if (empty($this->_block_actions_done)) {
2a3b0763 1207 $this->_block_actions_done = true;
a19f419d 1208 if ($this->blocks->process_url_actions($this)) {
b9bc2019 1209 redirect($this->url->out(false));
a19f419d 1210 }
21d33bdf 1211 }
4578a5eb 1212 $this->blocks->create_all_block_instances();
08eab897 1213 }
1214
144390b4 1215 // If maintenance mode is on, change the page header.
1216 if (!empty($CFG->maintenance_enabled)) {
1217 $this->set_button('<a href="' . $CFG->wwwroot . '/' . $CFG->admin .
1218 '/settings.php?section=maintenancemode">' . get_string('maintenancemode', 'admin') .
1219 '</a> ' . $this->button);
21d33bdf 1220
144390b4 1221 $title = $this->title;
1222 if ($title) {
1223 $title .= ' - ';
1224 }
1225 $this->set_title($title . get_string('maintenancemode', 'admin'));
e7f93d5c
AD
1226 } else {
1227 // Show the messaging popup if there are messages
1228 message_popup_window();
144390b4 1229 }
21d33bdf 1230
21d33bdf 1231 $this->initialise_standard_body_classes();
b7009474 1232 }
1233
1234 /**
1235 * Method for use by Moodle core to set up the theme. Do not
1236 * use this in your own code.
1237 *
1238 * Make sure the right theme for this page is loaded. Tell our
1239 * blocks_manager about the theme block regions, and then, if
cbcc9852 1240 * we are $PAGE, set up the global $OUTPUT.
b7009474 1241 */
1242 public function initialise_theme_and_output() {
cbcc9852 1243 global $OUTPUT, $PAGE, $SITE;
b7009474 1244
d4a03c00 1245 if (!empty($this->_wherethemewasinitialised)) {
1246 return;
1247 }
1248
eb5bdb35
PS
1249 if (!during_initial_install()) {
1250 // detect PAGE->context mess
1251 $this->magic_get_context();
1252 }
1253
94398fb3 1254 if (!$this->_course && !during_initial_install()) {
b7009474 1255 $this->set_course($SITE);
1256 }
1257
1258 if (is_null($this->_theme)) {
1259 $themename = $this->resolve_theme();
1260 $this->_theme = theme_config::load($themename);
78946b9b 1261 $this->_layout_options = $this->_theme->pagelayout_options($this->pagelayout);
b7009474 1262 }
1263
78946b9b 1264 $this->_theme->setup_blocks($this->pagelayout, $this->blocks);
b7009474 1265
1266 if ($this === $PAGE) {
649cf95d 1267 $OUTPUT = $this->get_renderer('core');
b7009474 1268 }
1269
1270 $this->_wherethemewasinitialised = debug_backtrace();
1271 }
1272
1273 /**
1274 * Work out the theme this page should use.
1275 *
1276 * This depends on numerous $CFG settings, and the properties of this page.
1277 *
1278 * @return string the name of the theme that should be used on this page.
1279 */
1280 protected function resolve_theme() {
1281 global $CFG, $USER, $SESSION;
1282
1283 if (empty($CFG->themeorder)) {
1284 $themeorder = array('course', 'category', 'session', 'user', 'site');
1285 } else {
1286 $themeorder = $CFG->themeorder;
1287 // Just in case, make sure we always use the site theme if nothing else matched.
1288 $themeorder[] = 'site';
1289 }
1290
1291 $mnetpeertheme = '';
1292 if (isloggedin() and isset($CFG->mnet_localhost_id) and $USER->mnethostid != $CFG->mnet_localhost_id) {
1293 require_once($CFG->dirroot.'/mnet/peer.php');
1294 $mnetpeer = new mnet_peer();
1295 $mnetpeer->set_id($USER->mnethostid);
1296 if ($mnetpeer->force_theme == 1 && $mnetpeer->theme != '') {
1297 $mnetpeertheme = $mnetpeer->theme;
1298 }
1299 }
1300
b7009474 1301 foreach ($themeorder as $themetype) {
1302 switch ($themetype) {
1303 case 'course':
e5824bb9 1304 if (!empty($CFG->allowcoursethemes) && !empty($this->_course->theme) && $this->devicetypeinuse == 'default') {
37959dd4 1305 return $this->_course->theme;
b7009474 1306 }
1307
1308 case 'category':
e5824bb9 1309 if (!empty($CFG->allowcategorythemes) && $this->devicetypeinuse == 'default') {
b7009474 1310 $categories = $this->categories;
1311 foreach ($categories as $category) {
1312 if (!empty($category->theme)) {
1313 return $category->theme;
1314 }
1315 }
1316 }
1317
1318 case 'session':
1319 if (!empty($SESSION->theme)) {
1320 return $SESSION->theme;
1321 }
1322
1323 case 'user':
e5824bb9 1324 if (!empty($CFG->allowuserthemes) && !empty($USER->theme) && $this->devicetypeinuse == 'default') {
b7009474 1325 if ($mnetpeertheme) {
1326 return $mnetpeertheme;
1327 } else {
1328 return $USER->theme;
1329 }
1330 }
1331
1332 case 'site':
1333 if ($mnetpeertheme) {
1334 return $mnetpeertheme;
b7009474 1335 }
e5824bb9
SH
1336 // First try for the device the user is using.
1337 $devicetheme = get_selected_theme_for_device_type($this->devicetypeinuse);
1338 if (!empty($devicetheme)) {
1339 return $devicetheme;
1340 }
1341 // Next try for the default device (as a fallback)
1342 $devicetheme = get_selected_theme_for_device_type('default');
1343 if (!empty($devicetheme)) {
1344 return $devicetheme;
1345 }
1346 // The default device theme isn't set up - use the overall default theme.
1347 return theme_config::DEFAULT_THEME;
b7009474 1348 }
1349 }
08eab897 1350 }
1351
78bfb562 1352
d529807a 1353 /**
1354 * Sets ->pagetype from the script name. For example, if the script that was
1355 * run is mod/quiz/view.php, ->pagetype will be set to 'mod-quiz-view'.
1356 * @param string $script the path to the script that should be used to
1357 * initialise ->pagetype. If not passed the $SCRIPT global will be used.
1358 * If legacy code has set $CFG->pagepath that will be used instead, and a
1359 * developer warning issued.
1360 */
ad52c04f 1361 protected function initialise_default_pagetype($script = null) {
d529807a 1362 global $CFG, $SCRIPT;
1363
1364 if (isset($CFG->pagepath)) {
1365 debugging('Some code appears to have set $CFG->pagepath. That was a horrible deprecated thing. ' .
1366 'Don\'t do it! Try calling $PAGE->set_pagetype() instead.');
1367 $script = $CFG->pagepath;
1368 unset($CFG->pagepath);
1369 }
1370
ad52c04f 1371 if (is_null($script)) {
d529807a 1372 $script = ltrim($SCRIPT, '/');
1373 $len = strlen($CFG->admin);
1374 if (substr($script, 0, $len) == $CFG->admin) {
1375 $script = 'admin' . substr($script, $len);
1376 }
1377 }
1378
1379 $path = str_replace('.php', '', $script);
1380 if (substr($path, -1) == '/') {
1381 $path .= 'index';
1382 }
1383
1384 if (empty($path) || $path == 'index') {
1385 $this->_pagetype = 'site-index';
1386 } else {
1387 $this->_pagetype = str_replace('/', '-', $path);
1388 }
1389 }
1390
753debd2 1391 protected function initialise_standard_body_classes() {
b7009474 1392 global $CFG, $USER;
89fbdca3 1393
753debd2 1394 $pagetype = $this->pagetype;
1395 if ($pagetype == 'site-index') {
1396 $this->_legacyclass = 'course';
1397 } else if (substr($pagetype, 0, 6) == 'admin-') {
1398 $this->_legacyclass = 'admin';
753debd2 1399 }
1400 $this->add_body_class($this->_legacyclass);
1401
90723839
SH
1402 $pathbits = explode('-', trim($pagetype));
1403 for ($i=1;$i<count($pathbits);$i++) {
1404 $this->add_body_class('path-'.join('-',array_slice($pathbits, 0, $i)));
1405 }
1406
89fbdca3 1407 $this->add_body_classes(get_browser_version_classes());
e372f4c7 1408 $this->add_body_class('dir-' . get_string('thisdirection', 'langconfig'));
753debd2 1409 $this->add_body_class('lang-' . current_language());
cf615522 1410 $this->add_body_class('yui-skin-sam'); // Make YUI happy, if it is used.
59c58c36 1411 $this->add_body_class('yui3-skin-sam'); // Make YUI3 happy, if it is used.
89fbdca3 1412 $this->add_body_class($this->url_to_class_name($CFG->wwwroot));
1413
191b267b
PS
1414 $this->add_body_class('pagelayout-' . $this->_pagelayout); // extra class describing current page layout
1415
94398fb3 1416 if (!during_initial_install()) {
1417 $this->add_body_class('course-' . $this->_course->id);
eb5bdb35 1418 $this->add_body_class('context-' . $this->_context->id);
a1326170 1419 }
1420
b80856bd 1421 if (!empty($this->_cm)) {
1422 $this->add_body_class('cmid-' . $this->_cm->id);
1423 }
1424
94398fb3 1425 if (!empty($CFG->allowcategorythemes)) {
d7ab8879 1426 $this->ensure_category_loaded();
1427 foreach ($this->_categories as $catid => $notused) {
1428 $this->add_body_class('category-' . $catid);
1429 }
1430 } else {
1431 $catid = 0;
1432 if (is_array($this->_categories)) {
1433 $catids = array_keys($this->_categories);
1434 $catid = reset($catids);
1435 } else if (!empty($this->_course->category)) {
1436 $catid = $this->_course->category;
1437 }
1438 if ($catid) {
1439 $this->add_body_class('category-' . $catid);
1440 }
1441 }
1442
753debd2 1443 if (!isloggedin()) {
1444 $this->add_body_class('notloggedin');
1445 }
1446
1447 if (!empty($USER->editing)) {
1448 $this->add_body_class('editing');
39726f35
AB
1449 if (optional_param('bui_moveid', false, PARAM_INT)) {
1450 $this->add_body_class('blocks-moving');
1451 }
753debd2 1452 }
1453
1454 if (!empty($CFG->blocksdrag)) {
1455 $this->add_body_class('drag');
1456 }
ee8df661 1457
37959dd4
AF
1458 if ($this->_devicetypeinuse != 'default') {
1459 $this->add_body_class($this->_devicetypeinuse . 'theme');
ee8df661 1460 }
753debd2 1461 }
1462
5ec434a9 1463 protected function load_activity_record() {
1464 global $DB;
1465 if (is_null($this->_cm)) {
1466 return;
1467 }
1468 $this->_module = $DB->get_record($this->_cm->modname, array('id' => $this->_cm->instance));
1469 }
1470
948203a5 1471 protected function ensure_category_loaded() {
1472 if (is_array($this->_categories)) {
1473 return; // Already done.
1474 }
1475 if (is_null($this->_course)) {
1476 throw new coding_exception('Attempt to get the course category for this page before the course was set.');
1477 }
1478 if ($this->_course->category == 0) {
1479 $this->_categories = array();
1480 } else {
1481 $this->load_category($this->_course->category);
1482 }
1483 }
1484
1485 protected function load_category($categoryid) {
1486 global $DB;
1487 $category = $DB->get_record('course_categories', array('id' => $categoryid));
1488 if (!$category) {
1489 throw new moodle_exception('unknowncategory');
1490 }
1491 $this->_categories[$category->id] = $category;
1492 $parentcategoryids = explode('/', trim($category->path, '/'));
1493 array_pop($parentcategoryids);
1494 foreach (array_reverse($parentcategoryids) as $catid) {
1495 $this->_categories[$catid] = null;
1496 }
1497 }
1498
1499 protected function ensure_categories_loaded() {
1500 global $DB;
1501 $this->ensure_category_loaded();
1502 if (!is_null(end($this->_categories))) {
1503 return; // Already done.
1504 }
1505 $idstoload = array_keys($this->_categories);
1506 array_shift($idstoload);
1507 $categories = $DB->get_records_list('course_categories', 'id', $idstoload);
1508 foreach ($idstoload as $catid) {
1509 $this->_categories[$catid] = $categories[$catid];
1510 }
1511 }
1512
b7009474 1513 protected function ensure_theme_not_set() {
1514 if (!is_null($this->_theme)) {
1515 throw new coding_exception('The theme has already been set up for this page ready for output. ' .
1516 'Therefore, you can no longer change the theme, or anything that might affect what ' .
1517 'the current theme is, for example, the course.',
1518 'Stack trace when the theme was set up: ' . format_backtrace($this->_wherethemewasinitialised));
1519 }
1520 }
1521
89fbdca3 1522 protected function url_to_class_name($url) {
1523 $bits = parse_url($url);
1524 $class = str_replace('.', '-', $bits['host']);
1525 if (!empty($bits['port'])) {
1526 $class .= '--' . $bits['port'];
1527 }
1528 if (!empty($bits['path'])) {
1529 $path = trim($bits['path'], '/');
1530 if ($path) {
1531 $class .= '--' . str_replace('/', '-', $path);
1532 }
1533 }
1534 return $class;
1535 }
1536
934524d7 1537 protected function all_editing_caps() {
1538 $caps = $this->_othereditingcaps;
1539 $caps[] = $this->_blockseditingcap;
1540 return $caps;
1541 }
1542
753debd2 1543/// Deprecated fields and methods for backwards compatibility ==================
d529807a 1544
f230ce19 1545 /**
31940ba6 1546 * @deprecated since Moodle 2.0 - use $PAGE->pagetype instead.
f230ce19 1547 * @return string page type.
1548 */
1549 public function get_type() {
1550 debugging('Call to deprecated method moodle_page::get_type. Please use $PAGE->pagetype instead.');
1551 return $this->get_pagetype();
1552 }
d529807a 1553
1554 /**
1555 * @deprecated since Moodle 2.0 - use $PAGE->pagetype instead.
1556 * @return string this is what page_id_and_class used to return via the $getclass parameter.
1557 */
1558 function get_format_name() {
1559 return $this->get_pagetype();
1560 }
1561
31940ba6 1562 /**
1563 * @deprecated since Moodle 2.0 - use $PAGE->course instead.
1564 * @return object course.
1565 */
1566 public function get_courserecord() {
1567 debugging('Call to deprecated method moodle_page::get_courserecord. Please use $PAGE->course instead.');
1568 return $this->get_course();
1569 }
d529807a 1570
1571 /**
1572 * @deprecated since Moodle 2.0
1573 * @return string this is what page_id_and_class used to return via the $getclass parameter.
1574 */
1575 public function get_legacyclass() {
1576 if (is_null($this->_legacyclass)) {
753debd2 1577 $this->initialise_standard_body_classes();
d529807a 1578 }
1579 debugging('Call to deprecated method moodle_page::get_legacyclass.');
1580 return $this->_legacyclass;
1581 }
4873f5f7 1582
1583 /**
86b5ea0f 1584 * @deprecated since Moodle 2.0 - use $PAGE->blocks->get_regions() instead
4873f5f7 1585 * @return string the places on this page where blocks can go.
1586 */
1587 function blocks_get_positions() {
86b5ea0f 1588 debugging('Call to deprecated method moodle_page::blocks_get_positions. Use $PAGE->blocks->get_regions() instead.');
1589 return $this->blocks->get_regions();
4873f5f7 1590 }
1591
1592 /**
86b5ea0f 1593 * @deprecated since Moodle 2.0 - use $PAGE->blocks->get_default_region() instead
4873f5f7 1594 * @return string the default place for blocks on this page.
1595 */
1596 function blocks_default_position() {
86b5ea0f 1597 debugging('Call to deprecated method moodle_page::blocks_default_position. Use $PAGE->blocks->get_default_region() instead.');
1598 return $this->blocks->get_default_region();
4873f5f7 1599 }
1600
1601 /**
1602 * @deprecated since Moodle 2.0 - no longer used.
1603 */
1604 function blocks_get_default() {
1605 debugging('Call to deprecated method moodle_page::blocks_get_default. This method has no function any more.');
1606 }
1607
1608 /**
1609 * @deprecated since Moodle 2.0 - no longer used.
1610 */
1611 function blocks_move_position(&$instance, $move) {
1612 debugging('Call to deprecated method moodle_page::blocks_move_position. This method has no function any more.');
1613 }
ad52c04f 1614
1615 /**
1616 * @deprecated since Moodle 2.0 - use $this->url->params() instead.
1617 * @return array URL parameters for this page.
1618 */
1619 function url_get_parameters() {
1620 debugging('Call to deprecated method moodle_page::url_get_parameters. Use $this->url->params() instead.');
1621 return $this->url->params();
1622 }
1623
1624 /**
1625 * @deprecated since Moodle 2.0 - use $this->url->params() instead.
1626 * @return string URL for this page without parameters.
1627 */
1628 function url_get_path() {
47ce714b
PS
1629 debugging('Call to deprecated method moodle_page::url_get_path. Use $this->url->out() instead.');
1630 return $this->url->out();
ad52c04f 1631 }
1632
1633 /**
1634 * @deprecated since Moodle 2.0 - use $this->url->out() instead.
1635 * @return string full URL for this page.
1636 */
1637 function url_get_full($extraparams = array()) {
1638 debugging('Call to deprecated method moodle_page::url_get_full. Use $this->url->out() instead.');
b9bc2019 1639 return $this->url->out(true, $extraparams);
ad52c04f 1640 }
0d5890c4 1641
1642 /**
1643 * @deprecated since Moodle 2.0 - just a backwards compatibility hook.
1644 */
1645 function set_legacy_page_object($pageobject) {
1646 return $this->_legacypageobject = $pageobject;
1647 }
1648
1649 /**
1650 * @deprecated since Moodle 2.0 - page objects should no longer be doing print_header.
1651 * @param $_,...
1652 */
1653 function print_header($_) {
1654 if (is_null($this->_legacypageobject)) {
1655 throw new coding_exception('You have called print_header on $PAGE when there is not a legacy page class present.');
1656 }
1657 debugging('You should not longer be doing print_header via a page class.', DEBUG_DEVELOPER);
1658 $args = func_get_args();
1659 call_user_func_array(array($this->_legacypageobject, 'print_header'), $args);
1660 }
1661
1662 /**
1663 * @deprecated since Moodle 2.0
1664 * @return the 'page id'. This concept no longer exists.
1665 */
1666 function get_id() {
1667 debugging('Call to deprecated method moodle_page::get_id(). It should not be necessary any more.', DEBUG_DEVELOPER);
1668 if (!is_null($this->_legacypageobject)) {
1669 return $this->_legacypageobject->get_id();
1670 }
1671 return 0;
1672 }
5ec434a9 1673
f8b80dbd 1674 /**
1675 * @deprecated since Moodle 2.0
1676 * @return the 'page id'. This concept no longer exists.
1677 */
1678 function get_pageid() {
1679 debugging('Call to deprecated method moodle_page::get_pageid(). It should not be necessary any more.', DEBUG_DEVELOPER);
1680 if (!is_null($this->_legacypageobject)) {
1681 return $this->_legacypageobject->get_id();
1682 }
1683 return 0;
1684 }
1685
5ec434a9 1686 /**
1687 * @deprecated since Moodle 2.0 - user $PAGE->cm instead.
1688 * @return $this->cm;
1689 */
1690 function get_modulerecord() {
1691 return $this->cm;
1692 }
bf6c37c7 1693
1694 public function has_set_url() {
1695 return ($this->_url!==null);
1696 }
05c92729
SH
1697
1698 public function set_block_actions_done($setting = true) {
1699 $this->_block_actions_done = $setting;
1700 }
e7f93d5c
AD
1701
1702 /**
1703 * Are popup notifications allowed on this page?
1704 * Popup notifications may be disallowed in situations such as while upgrading or completing a quiz
1705 * @return boolean true if popup notifications may be displayed
1706 */
1707 public function get_popup_notification_allowed() {
1708 return $this->_popup_notification_allowed;
1709 }
1710
1711 /**
1712 * Allow or disallow popup notifications on this page. Popups are allowed by default.
1713 * @param boolean true if notifications are allowed. False if not allowed. They are allowed by default.
1714 * @return null
1715 */
1716 public function set_popup_notification_allowed($allowed) {
1717 $this->_popup_notification_allowed = $allowed;
1718 }
ad52c04f 1719}
1720
de60de04 1721/**
1722 * @deprecated since Moodle 2.0
0d5890c4 1723 * Not needed any more.
de60de04 1724 * @param $path the folder path
1725 * @return array an array of page types.
1726 */
3f6aba0c 1727function page_import_types($path) {
1728 global $CFG;
de60de04 1729 debugging('Call to deprecated function page_import_types.', DEBUG_DEVELOPER);
3f6aba0c 1730}
1731
7c6c0513 1732/**
d529807a 1733 * @deprecated since Moodle 2.0
0d5890c4 1734 * Do not use this any more. The global $PAGE is automatically created for you.
1735 * If you need custom behaviour, you should just set properties of that object.
d529807a 1736 * @param integer $instance legacy page instance id.
1737 * @return the global $PAGE object.
7c6c0513 1738 */
7c6c0513 1739function page_create_instance($instance) {
c85acc87 1740 global $PAGE;
d529807a 1741 return page_create_object($PAGE->pagetype, $instance);
7c6c0513 1742}
1743
9b128500 1744/**
0d5890c4 1745 * @deprecated since Moodle 2.0
1746 * Do not use this any more. The global $PAGE is automatically created for you.
1747 * If you need custom behaviour, you should just set properties of that object.
9b128500 1748 */
9b128500 1749function page_create_object($type, $id = NULL) {
5ec434a9 1750 global $CFG, $PAGE, $SITE, $ME;
0d5890c4 1751 debugging('Call to deprecated function page_create_object.', DEBUG_DEVELOPER);
93dcb13e 1752
9b128500 1753 $data = new stdClass;
1754 $data->pagetype = $type;
5ec434a9 1755 $data->pageid = $id;
9b128500 1756
1757 $classname = page_map_class($type);
f8b80dbd 1758 if (!$classname) {
1759 return $PAGE;
1760 }
ad52c04f 1761 $legacypage = new $classname;
1762 $legacypage->init_quick($data);
ad52c04f 1763
d7ab8879 1764 $course = $PAGE->course;
1765 if ($course->id != $SITE->id) {
ad52c04f 1766 $legacypage->set_course($course);
d7ab8879 1767 } else {
1768 try {
1769 $category = $PAGE->category;
1770 } catch (coding_exception $e) {
1771 // Was not set before, so no need to try to set it again.
1772 $category = false;
1773 }
1774 if ($category) {
ad52c04f 1775 $legacypage->set_category_by_id($category->id);
d7ab8879 1776 } else {
ad52c04f 1777 $legacypage->set_course($SITE);
d7ab8879 1778 }
1779 }
f474a4e5 1780
0d5890c4 1781 $legacypage->set_pagetype($type);
5ec434a9 1782
1783 $legacypage->set_url($ME);
1784 $PAGE->set_url(str_replace($CFG->wwwroot . '/', '', $legacypage->url_get_full()));
0d5890c4 1785
1786 $PAGE->set_pagetype($type);
1787 $PAGE->set_legacy_page_object($legacypage);
1788 return $PAGE;
9b128500 1789}
1790
1791/**
0d5890c4 1792 * @deprecated since Moodle 2.0
1793 * You should not be writing page subclasses any more. Just set properties on the
1794 * global $PAGE object to control its behaviour.
9b128500 1795 */
9b128500 1796function page_map_class($type, $classname = NULL) {
93dcb13e 1797 global $CFG;
1798
0d5890c4 1799 static $mappings = array(
1800 PAGE_COURSE_VIEW => 'page_course',
1801 );
9b128500 1802
93dcb13e 1803 if (!empty($type) && !empty($classname)) {
9b128500 1804 $mappings[$type] = $classname;
1805 }
93dcb13e 1806
1807 if (!isset($mappings[$type])) {
ea82d6b6 1808 debugging('Page class mapping requested for unknown type: '.$type);
f8b80dbd 1809 return null;
1810 } else if (empty($classname) && !class_exists($mappings[$type])) {
ea82d6b6 1811 debugging('Page class mapping for id "'.$type.'" exists but class "'.$mappings[$type].'" is not defined');
f8b80dbd 1812 return null;
9b128500 1813 }
1814
1815 return $mappings[$type];
1816}
1817
f032aa7a 1818/**
0d5890c4 1819 * @deprecated since Moodle 2.0
f032aa7a 1820 * Parent class from which all Moodle page classes derive
1821 *
eb5bdb35
PS
1822 * @package core
1823 * @subpackage lib
1824 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
1825 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
f032aa7a 1826 */
c13a5e71 1827class page_base extends moodle_page {
e0134f84 1828 /**
1829 * The numeric identifier of the page being described.
1830 * @var int $id
1831 */
f032aa7a 1832 var $id = NULL;
e0134f84 1833
e0134f84 1834/// Class Functions
1835
c8e0b579 1836 // HTML OUTPUT SECTION
1837
c8e0b579 1838 // SELF-REPORTING SECTION
1839
c8e0b579 1840 // Simple stuff, do not override this.
f032aa7a 1841 function get_id() {
1842 return $this->id;
1843 }
c8e0b579 1844
c8e0b579 1845 // Initialize the data members of the parent class
f032aa7a 1846 function init_quick($data) {
f032aa7a 1847 $this->id = $data->pageid;
1848 }
1849
c8e0b579 1850 function init_full() {
c8e0b579 1851 }
f032aa7a 1852}
1853
f032aa7a 1854/**
0d5890c4 1855 * @deprecated since Moodle 2.0
9d1d606e 1856 * Class that models the behavior of a moodle course.
1857 * Although this does nothing, this class declaration should be left for now
1858 * since there may be legacy class doing class page_... extends page_course
f032aa7a 1859 *
eb5bdb35
PS
1860 * @package core
1861 * @subpackage lib
1862 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
1863 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
f032aa7a 1864 */
99110470 1865class page_course extends page_base {
f032aa7a 1866}
1867
cadc69c6 1868/**
0d5890c4 1869 * @deprecated since Moodle 2.0
b83eee7d 1870 * Class that models the common parts of all activity modules
cadc69c6 1871 *
eb5bdb35
PS
1872 * @package core
1873 * @subpackage lib
1874 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
1875 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
cadc69c6 1876 */
b83eee7d 1877class page_generic_activity extends page_base {
9d1d606e 1878 // Although this function is deprecated, it should be left here because
1879 // people upgrading legacy code need to copy it. See
3b1b5018 1880 // http://docs.moodle.org/dev/Migrating_your_code_to_the_2.0_rendering_API
3b27b0fe 1881 function print_header($title, $morenavlinks = NULL, $bodytags = '', $meta = '') {
de6d81e6 1882 global $USER, $CFG, $PAGE, $OUTPUT;
de60de04 1883
6db8acb6 1884 $this->init_full();
1885 $replacements = array(
1886 '%fullname%' => format_string($this->activityrecord->name)
1887 );
1888 foreach ($replacements as $search => $replace) {
1889 $title = str_replace($search, $replace, $title);
1890 }
de60de04 1891
d8ae33a9 1892 $buttons = '<table><tr><td>'.$OUTPUT->update_module_button($this->modulerecord->id, $this->activityname).'</td>';
59e2121e 1893 if ($this->user_allowed_editing()) {
4aea3cc7 1894 $buttons .= '<td><form method="get" action="view.php"><div>'.
cfcfb9f3 1895 '<input type="hidden" name="id" value="'.$this->modulerecord->id.'" />'.
1896 '<input type="hidden" name="edit" value="'.($this->user_is_editing()?'off':'on').'" />'.
1897 '<input type="submit" value="'.get_string($this->user_is_editing()?'blockseditoff':'blocksediton').'" /></div></form></td>';
6db8acb6 1898 }
cfcfb9f3 1899 $buttons .= '</tr></table>';
de60de04 1900
de6d81e6 1901 if (!empty($morenavlinks) && is_array($morenavlinks)) {
1902 foreach ($morenavlinks as $navitem) {
1903 if (is_array($navitem) && array_key_exists('name', $navitem)) {
1904 $link = null;
1905 if (array_key_exists('link', $navitem)) {
1906 $link = $navitem['link'];
1907 }
91152a35 1908 $PAGE->navbar->add($navitem['name'], $link);
de6d81e6 1909 }
1910 }
38e179a4 1911 }
de6d81e6 1912
1913 $PAGE->set_title($title);
1914 $PAGE->set_heading($this->course->fullname);
1915 $PAGE->set_button($buttons);
91152a35 1916 echo $OUTPUT->header();
6db8acb6 1917 }
b83eee7d 1918}