PageRenderTime 84ms CodeModel.GetById 25ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/pagelib.php

https://bitbucket.org/ngmares/moodle
PHP | 2220 lines | 963 code | 239 blank | 1018 comment | 209 complexity | 6cf33fe2ccd873f6b92dd54cbe5d1294 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2// This file is part of Moodle - http://moodle.org/
   3//
   4// Moodle is free software: you can redistribute it and/or modify
   5// it under the terms of the GNU General Public License as published by
   6// the Free Software Foundation, either version 3 of the License, or
   7// (at your option) any later version.
   8//
   9// Moodle is distributed in the hope that it will be useful,
  10// but WITHOUT ANY WARRANTY; without even the implied warranty of
  11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12// GNU General Public License for more details.
  13//
  14// You should have received a copy of the GNU General Public License
  15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16
  17/**
  18 * This file contains the moodle_page class. There is normally a single instance
  19 * of this class in the $PAGE global variable. This class is a central repository
  20 * of information about the page we are building up to send back to the user.
  21 *
  22 * @package core
  23 * @category page
  24 * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  25 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  26 */
  27
  28defined('MOODLE_INTERNAL') || die();
  29
  30/**
  31 * $PAGE is a central store of information about the current page we are
  32 * generating in response to the user's request.
  33 *
  34 * It does not do very much itself
  35 * except keep track of information, however, it serves as the access point to
  36 * some more significant components like $PAGE->theme, $PAGE->requires,
  37 * $PAGE->blocks, etc.
  38 *
  39 * @copyright 2009 Tim Hunt
  40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41 * @since Moodle 2.0
  42 * @package core
  43 * @category page
  44 *
  45 * The following properties are alphabetical. Please keep it that way so that its
  46 * easy to maintain.
  47 *
  48 * @property-read string $activityname The type of activity we are in, for example 'forum' or 'quiz'.
  49 *      Will be null if this page is not within a module.
  50 * @property-read stdClass $activityrecord The row from the activities own database table (for example
  51 *      the forum or quiz table) that this page belongs to. Will be null
  52 *      if this page is not within a module.
  53 * @property-read array $alternativeversions Mime type => object with ->url and ->title.
  54 * @property-read blocks_manager $blocks The blocks manager object for this page.
  55 * @property-read string $bodyclasses A string to use within the class attribute on the body tag.
  56 * @property-read string $bodyid A string to use as the id of the body tag.
  57 * @property-read string $button The HTML to go where the Turn editing on button normally goes.
  58 * @property-read bool $cacheable Defaults to true. Set to false to stop the page being cached at all.
  59 * @property-read array $categories An array of all the categories the page course belongs to,
  60 *      starting with the immediately containing category, and working out to
  61 *      the top-level category. This may be the empty array if we are in the
  62 *      front page course.
  63 * @property-read mixed $category The category that the page course belongs to.
  64 * @property-read cm_info $cm The course_module that this page belongs to. Will be null
  65 *      if this page is not within a module. This is a full cm object, as loaded
  66 *      by get_coursemodule_from_id or get_coursemodule_from_instance,
  67 *      so the extra modname and name fields are present.
  68 * @property-read context $context The main context to which this page belongs.
  69 * @property-read stdClass $course The current course that we are inside - a row from the
  70 *      course table. (Also available as $COURSE global.) If we are not inside
  71 *      an actual course, this will be the site course.
  72 * @property-read string $devicetypeinuse The name of the device type in use
  73 * @property-read string $docspath The path to the Moodle docs for this page.
  74 * @property-read string $focuscontrol The id of the HTML element to be focused when the page has loaded.
  75 * @property-read bool $headerprinted True if the page header has already been printed.
  76 * @property-read string $heading The main heading that should be displayed at the top of the <body>.
  77 * @property-read string $headingmenu The menu (or actions) to display in the heading
  78 * @property-read array $layout_options An arrays with options for the layout file.
  79 * @property-read array $legacythemeinuse True if the legacy browser theme is in use.
  80 * @property-read navbar $navbar The navbar object used to display the navbar
  81 * @property-read global_navigation $navigation The navigation structure for this page.
  82 * @property-read xml_container_stack $opencontainers Tracks XHTML tags on this page that have been opened but not closed.
  83 *      mainly for internal use by the rendering code.
  84 * @property-read string $pagelayout The general type of page this is. For example 'normal', 'popup', 'home'.
  85 *      Allows the theme to display things differently, if it wishes to.
  86 * @property-read string $pagetype The page type string, should be used as the id for the body tag in the theme.
  87 * @property-read int $periodicrefreshdelay The periodic refresh delay to use with meta refresh
  88 * @property-read page_requirements_manager $requires Tracks the JavaScript, CSS files, etc. required by this page.
  89 * @property-read settings_navigation $settingsnav The settings navigation
  90 * @property-read int $state One of the STATE_... constants
  91 * @property-read string $subpage The subpage identifier, if any.
  92 * @property-read theme_config $theme The theme for this page.
  93 * @property-read string $title The title that should go in the <head> section of the HTML of this page.
  94 * @property-read moodle_url $url The moodle url object for this page.
  95 */
  96class moodle_page {
  97
  98    /** The state of the page before it has printed the header **/
  99    const STATE_BEFORE_HEADER = 0;
 100
 101    /** The state the page is in temporarily while the header is being printed **/
 102    const STATE_PRINTING_HEADER = 1;
 103
 104    /** The state the page is in while content is presumably being printed **/
 105    const STATE_IN_BODY = 2;
 106
 107    /**
 108     * The state the page is when the footer has been printed and its function is
 109     * complete.
 110     */
 111    const STATE_DONE = 3;
 112
 113    /**
 114     * @var int The current state of the page. The state a page is within
 115     * determines what actions are possible for it.
 116     */
 117    protected $_state = self::STATE_BEFORE_HEADER;
 118
 119    /**
 120     * @var stdClass The course currently associated with this page.
 121     * If not has been provided the front page course is used.
 122     */
 123    protected $_course = null;
 124
 125    /**
 126     * @var cm_info If this page belongs to a module, this is the cm_info module
 127     * description object.
 128     */
 129    protected $_cm = null;
 130
 131    /**
 132     * @var stdClass If $_cm is not null, then this will hold the corresponding
 133     * row from the modname table. For example, if $_cm->modname is 'quiz', this
 134     * will be a row from the quiz table.
 135     */
 136    protected $_module = null;
 137
 138    /**
 139     * @var context The context that this page belongs to.
 140     */
 141    protected $_context = null;
 142
 143    /**
 144     * @var array This holds any categories that $_course belongs to, starting with the
 145     * particular category it belongs to, and working out through any parent
 146     * categories to the top level. These are loaded progressively, if needed.
 147     * There are three states. $_categories = null initially when nothing is
 148     * loaded; $_categories = array($id => $cat, $parentid => null) when we have
 149     * loaded $_course->category, but not any parents; and a complete array once
 150     * everything is loaded.
 151     */
 152    protected $_categories = null;
 153
 154    /**
 155     * @var array An array of CSS classes that should be added to the body tag in HTML.
 156     */
 157    protected $_bodyclasses = array();
 158
 159    /**
 160     * @var string The title for the page. Used within the title tag in the HTML head.
 161     */
 162    protected $_title = '';
 163
 164    /**
 165     * @var string The string to use as the heading of the page. Shown near the top of the
 166     * page within most themes.
 167     */
 168    protected $_heading = '';
 169
 170    /**
 171     * @var string The pagetype is used to describe the page and defaults to a representation
 172     * of the physical path to the page e.g. my-index, mod-quiz-attempt
 173     */
 174    protected $_pagetype = null;
 175
 176    /**
 177     * @var string The pagelayout to use when displaying this page. The
 178     * pagelayout needs to have been defined by the theme in use, or one of its
 179     * parents. By default base is used however standard is the more common layout.
 180     * Note that this gets automatically set by core during operations like
 181     * require_login.
 182     */
 183    protected $_pagelayout = 'base';
 184
 185    /**
 186     * @var array List of theme layout options, these are ignored by core.
 187     * To be used in individual theme layout files only.
 188     */
 189    protected $_layout_options = array();
 190
 191    /**
 192     * @var string An optional arbitrary parameter that can be set on pages where the context
 193     * and pagetype is not enough to identify the page.
 194     */
 195    protected $_subpage = '';
 196
 197    /**
 198     * @var string Set a different path to use for the 'Moodle docs for this page' link.
 199     * By default, it uses the path of the file for instance mod/quiz/attempt.
 200     */
 201    protected $_docspath = null;
 202
 203    /**
 204     * @var string A legacy class that will be added to the body tag
 205     */
 206    protected $_legacyclass = null;
 207
 208    /**
 209     * @var moodle_url The URL for this page. This is mandatory and must be set
 210     * before output is started.
 211     */
 212    protected $_url = null;
 213
 214    /**
 215     * @var array An array of links to alternative versions of this page.
 216     * Primarily used for RSS versions of the current page.
 217     */
 218    protected $_alternateversions = array();
 219
 220    /**
 221     * @var block_manager The blocks manager for this page. It is reponsible for
 222     * the blocks and there content on this page.
 223     */
 224    protected $_blocks = null;
 225
 226    /**
 227     * @var page_requirements_manager Page requirements manager. It is reponsible
 228     * for all JavaScript and CSS resources required by this page.
 229     */
 230    protected $_requires = null;
 231
 232    /**
 233     * @var string The capability required by the user in order to edit blocks
 234     * and block settings on this page.
 235     */
 236    protected $_blockseditingcap = 'moodle/site:manageblocks';
 237
 238    /**
 239     * @var bool An internal flag to record when block actions have been processed.
 240     * Remember block actions occur on the current URL and it is important that
 241     * even they are never executed more than once.
 242     */
 243    protected $_block_actions_done = false;
 244
 245    /**
 246     * @var array An array of any other capabilities the current user must have
 247     * in order to editing the page and/or its content (not just blocks).
 248     */
 249    protected $_othereditingcaps = array();
 250
 251    /**
 252     * @var bool Sets whether this page should be cached by the browser or not.
 253     * If it is set to true (default) the page is served with caching headers.
 254     */
 255    protected $_cacheable = true;
 256
 257    /**
 258     * @var string Can be set to the ID of an element on the page, if done that
 259     * element receives focus when the page loads.
 260     */
 261    protected $_focuscontrol = '';
 262
 263    /**
 264     * @var string HTML to go where the turn on editing button is located. This
 265     * is nearly a legacy item and not used very often any more.
 266     */
 267    protected $_button = '';
 268
 269    /**
 270     * @var theme_config The theme to use with this page. This has to be properly
 271     * initialised via {@link moodle_page::initialise_theme_and_output()} which
 272     * happens magically before any operation that requires it.
 273     */
 274    protected $_theme = null;
 275
 276    /**
 277     * @var global_navigation Contains the global navigation structure.
 278     */
 279    protected $_navigation = null;
 280
 281    /**
 282     * @var settings_navigation Contains the settings navigation structure.
 283     */
 284    protected $_settingsnav = null;
 285
 286    /**
 287     * @var navbar Contains the navbar structure.
 288     */
 289    protected $_navbar = null;
 290
 291    /**
 292     * @var string The menu (or actions) to display in the heading.
 293     */
 294    protected $_headingmenu = null;
 295
 296    /**
 297     * @var array stack trace. Then the theme is initialised, we save the stack
 298     * trace, for use in error messages.
 299     */
 300    protected $_wherethemewasinitialised = null;
 301
 302    /**
 303     * @var xhtml_container_stack Tracks XHTML tags on this page that have been
 304     * opened but not closed.
 305     */
 306    protected $_opencontainers;
 307
 308    /**
 309     * @var int Sets the page to refresh after a given delay (in seconds) using
 310     * meta refresh in {@link standard_head_html()} in outputlib.php
 311     * If set to null(default) the page is not refreshed
 312     */
 313    protected $_periodicrefreshdelay = null;
 314
 315    /**
 316     * @var stdClass This is simply to improve backwards compatibility. If old
 317     * code relies on a page class that implements print_header, or complex logic
 318     * in user_allowed_editing then we stash an instance of that other class here,
 319     * and delegate to it in certain situations.
 320     */
 321    protected $_legacypageobject = null;
 322
 323    /**
 324     * @var array Associative array of browser shortnames (as used by check_browser_version)
 325     * and their minimum required versions
 326     */
 327    protected $_legacybrowsers = array('MSIE' => 6.0);
 328
 329    /**
 330     * @var string Is set to the name of the device type in use.
 331     * This will we worked out when it is first used.
 332     */
 333    protected $_devicetypeinuse = null;
 334
 335    /**
 336     * @var bool Used to determine if HTTPS should be required for login.
 337     */
 338    protected $_https_login_required = false;
 339
 340    /**
 341     * @var bool Determines if popup notifications allowed on this page.
 342     * Code such as the quiz module disables popup notifications in situations
 343     * such as upgrading or completing a quiz.
 344     */
 345    protected $_popup_notification_allowed = true;
 346
 347    // Magic getter methods =============================================================
 348    // Due to the __get magic below, you normally do not call these as $PAGE->magic_get_x
 349    // methods, but instead use the $PAGE->x syntax.
 350
 351    /**
 352     * Please do not call this method directly, use the ->state syntax. {@link moodle_page::__get()}.
 353     * @return integer one of the STATE_XXX constants. You should not normally need
 354     * to use this in your code. It is intended for internal use by this class
 355     * and its friends like print_header, to check that everything is working as
 356     * expected. Also accessible as $PAGE->state.
 357     */
 358    protected function magic_get_state() {
 359        return $this->_state;
 360    }
 361
 362    /**
 363     * Please do not call this method directly, use the ->headerprinted syntax. {@link moodle_page::__get()}.
 364     * @return bool has the header already been printed?
 365     */
 366    protected function magic_get_headerprinted() {
 367        return $this->_state >= self::STATE_IN_BODY;
 368    }
 369
 370    /**
 371     * Please do not call this method directly, use the ->course syntax. {@link moodle_page::__get()}.
 372     * @return stdClass the current course that we are inside - a row from the
 373     * course table. (Also available as $COURSE global.) If we are not inside
 374     * an actual course, this will be the site course.
 375     */
 376    protected function magic_get_course() {
 377        global $SITE;
 378        if (is_null($this->_course)) {
 379            return $SITE;
 380        }
 381        return $this->_course;
 382    }
 383
 384    /**
 385     * Please do not call this method directly, use the ->cm syntax. {@link moodle_page::__get()}.
 386     * @return cm_info the course_module that this page belongs to. Will be null
 387     * if this page is not within a module. This is a full cm object, as loaded
 388     * by get_coursemodule_from_id or get_coursemodule_from_instance,
 389     * so the extra modname and name fields are present.
 390     */
 391    protected function magic_get_cm() {
 392        return $this->_cm;
 393    }
 394
 395    /**
 396     * Please do not call this method directly, use the ->activityrecord syntax. {@link moodle_page::__get()}.
 397     * @return stdClass the row from the activities own database table (for example
 398     * the forum or quiz table) that this page belongs to. Will be null
 399     * if this page is not within a module.
 400     */
 401    protected function magic_get_activityrecord() {
 402        if (is_null($this->_module) && !is_null($this->_cm)) {
 403            $this->load_activity_record();
 404        }
 405        return $this->_module;
 406    }
 407
 408    /**
 409     * Please do not call this method directly, use the ->activityname syntax. {@link moodle_page::__get()}.
 410     * @return string the The type of activity we are in, for example 'forum' or 'quiz'.
 411     * Will be null if this page is not within a module.
 412     */
 413    protected function magic_get_activityname() {
 414        if (is_null($this->_cm)) {
 415            return null;
 416        }
 417        return $this->_cm->modname;
 418    }
 419
 420    /**
 421     * Please do not call this method directly, use the ->category syntax. {@link moodle_page::__get()}.
 422     * @return stdClass the category that the page course belongs to. If there isn't one
 423     * (that is, if this is the front page course) returns null.
 424     */
 425    protected function magic_get_category() {
 426        $this->ensure_category_loaded();
 427        if (!empty($this->_categories)) {
 428            return reset($this->_categories);
 429        } else {
 430            return null;
 431        }
 432    }
 433
 434    /**
 435     * Please do not call this method directly, use the ->categories syntax. {@link moodle_page::__get()}.
 436     * @return array an array of all the categories the page course belongs to,
 437     * starting with the immediately containing category, and working out to
 438     * the top-level category. This may be the empty array if we are in the
 439     * front page course.
 440     */
 441    protected function magic_get_categories() {
 442        $this->ensure_categories_loaded();
 443        return $this->_categories;
 444    }
 445
 446    /**
 447     * Please do not call this method directly, use the ->context syntax. {@link moodle_page::__get()}.
 448     * @return context the main context to which this page belongs.
 449     */
 450    protected function magic_get_context() {
 451        if (is_null($this->_context)) {
 452            if (CLI_SCRIPT or NO_MOODLE_COOKIES) {
 453                // cli scripts work in system context, do not annoy devs with debug info
 454                // very few scripts do not use cookies, we can safely use system as default context there
 455            } else {
 456                debugging('Coding problem: $PAGE->context was not set. You may have forgotten '
 457                    .'to call require_login() or $PAGE->set_context(). The page may not display '
 458                    .'correctly as a result');
 459            }
 460            $this->_context = get_context_instance(CONTEXT_SYSTEM);
 461        }
 462        return $this->_context;
 463    }
 464
 465    /**
 466     * Please do not call this method directly, use the ->pagetype syntax. {@link moodle_page::__get()}.
 467     * @return string e.g. 'my-index' or 'mod-quiz-attempt'.
 468     */
 469    protected function magic_get_pagetype() {
 470        global $CFG;
 471        if (is_null($this->_pagetype) || isset($CFG->pagepath)) {
 472            $this->initialise_default_pagetype();
 473        }
 474        return $this->_pagetype;
 475    }
 476
 477    /**
 478     * Please do not call this method directly, use the ->pagetype syntax. {@link moodle_page::__get()}.
 479     * @return string The id to use on the body tag, uses {@link magic_get_pagetype()}.
 480     */
 481    protected function magic_get_bodyid() {
 482        return 'page-'.$this->pagetype;
 483    }
 484
 485    /**
 486     * Please do not call this method directly, use the ->pagelayout syntax. {@link moodle_page::__get()}.
 487     * @return string the general type of page this is. For example 'standard', 'popup', 'home'.
 488     *      Allows the theme to display things differently, if it wishes to.
 489     */
 490    protected function magic_get_pagelayout() {
 491        return $this->_pagelayout;
 492    }
 493
 494    /**
 495     * Please do not call this method directly, use the ->layout_tions syntax. {@link moodle_page::__get()}.
 496     * @return array returns arrys with options for layout file
 497     */
 498    protected function magic_get_layout_options() {
 499        return $this->_layout_options;
 500    }
 501
 502    /**
 503     * Please do not call this method directly, use the ->subpage syntax. {@link moodle_page::__get()}.
 504     * @return string The subpage identifier, if any.
 505     */
 506    protected function magic_get_subpage() {
 507        return $this->_subpage;
 508    }
 509
 510    /**
 511     * Please do not call this method directly, use the ->bodyclasses syntax. {@link moodle_page::__get()}.
 512     * @return string the class names to put on the body element in the HTML.
 513     */
 514    protected function magic_get_bodyclasses() {
 515        return implode(' ', array_keys($this->_bodyclasses));
 516    }
 517
 518    /**
 519     * Please do not call this method directly, use the ->title syntax. {@link moodle_page::__get()}.
 520     * @return string the title that should go in the <head> section of the HTML of this page.
 521     */
 522    protected function magic_get_title() {
 523        return $this->_title;
 524    }
 525
 526    /**
 527     * Please do not call this method directly, use the ->heading syntax. {@link moodle_page::__get()}.
 528     * @return string the main heading that should be displayed at the top of the <body>.
 529     */
 530    protected function magic_get_heading() {
 531        return $this->_heading;
 532    }
 533
 534    /**
 535     * Please do not call this method directly, use the ->heading syntax. {@link moodle_page::__get()}.
 536     * @return string The menu (or actions) to display in the heading
 537     */
 538    protected function magic_get_headingmenu() {
 539        return $this->_headingmenu;
 540    }
 541
 542    /**
 543     * Please do not call this method directly, use the ->docspath syntax. {@link moodle_page::__get()}.
 544     * @return string the path to the Moodle docs for this page.
 545     */
 546    protected function magic_get_docspath() {
 547        if (is_string($this->_docspath)) {
 548            return $this->_docspath;
 549        } else {
 550            return str_replace('-', '/', $this->pagetype);
 551        }
 552    }
 553
 554    /**
 555     * Please do not call this method directly, use the ->url syntax. {@link moodle_page::__get()}.
 556     * @return moodle_url the clean URL required to load the current page. (You
 557     * should normally use this in preference to $ME or $FULLME.)
 558     */
 559    protected function magic_get_url() {
 560        global $FULLME;
 561        if (is_null($this->_url)) {
 562            debugging('This page did not call $PAGE->set_url(...). Using '.s($FULLME), DEBUG_DEVELOPER);
 563            $this->_url = new moodle_url($FULLME);
 564            // Make sure the guessed URL cannot lead to dangerous redirects.
 565            $this->_url->remove_params('sesskey');
 566        }
 567        return new moodle_url($this->_url); // Return a clone for safety.
 568    }
 569
 570    /**
 571     * The list of alternate versions of this page.
 572     * @return array mime type => object with ->url and ->title.
 573     */
 574    protected function magic_get_alternateversions() {
 575        return $this->_alternateversions;
 576    }
 577
 578    /**
 579     * Please do not call this method directly, use the ->blocks syntax. {@link moodle_page::__get()}.
 580     * @return blocks_manager the blocks manager object for this page.
 581     */
 582    protected function magic_get_blocks() {
 583        global $CFG;
 584        if (is_null($this->_blocks)) {
 585            if (!empty($CFG->blockmanagerclass)) {
 586                $classname = $CFG->blockmanagerclass;
 587            } else {
 588                $classname = 'block_manager';
 589            }
 590            $this->_blocks = new $classname($this);
 591        }
 592        return $this->_blocks;
 593    }
 594
 595    /**
 596     * Please do not call this method directly, use the ->requires syntax. {@link moodle_page::__get()}.
 597     * @return page_requirements_manager tracks the JavaScript, CSS files, etc. required by this page.
 598     */
 599    protected function magic_get_requires() {
 600        global $CFG;
 601        if (is_null($this->_requires)) {
 602            $this->_requires = new page_requirements_manager();
 603        }
 604        return $this->_requires;
 605    }
 606
 607    /**
 608     * Please do not call this method directly, use the ->cacheable syntax. {@link moodle_page::__get()}.
 609     * @return bool can this page be cached by the user's browser.
 610     */
 611    protected function magic_get_cacheable() {
 612        return $this->_cacheable;
 613    }
 614
 615    /**
 616     * Please do not call this method directly, use the ->focuscontrol syntax. {@link moodle_page::__get()}.
 617     * @return string the id of the HTML element to be focused when the page has loaded.
 618     */
 619    protected function magic_get_focuscontrol() {
 620        return $this->_focuscontrol;
 621    }
 622
 623    /**
 624     * Please do not call this method directly, use the ->button syntax. {@link moodle_page::__get()}.
 625     * @return string the HTML to go where the Turn editing on button normally goes.
 626     */
 627    protected function magic_get_button() {
 628        return $this->_button;
 629    }
 630
 631    /**
 632     * Please do not call this method directly, use the ->theme syntax. {@link moodle_page::__get()}.
 633     * @return theme_config the initialised theme for this page.
 634     */
 635    protected function magic_get_theme() {
 636        if (is_null($this->_theme)) {
 637            $this->initialise_theme_and_output();
 638        }
 639        return $this->_theme;
 640    }
 641
 642    /**
 643     * Please do not call this method directly, use the ->devicetypeinuse syntax. {@link moodle_page::__get()}.
 644     * @return string The device type being used.
 645     */
 646    protected function magic_get_devicetypeinuse() {
 647        if (empty($this->_devicetypeinuse)) {
 648            $this->_devicetypeinuse = get_user_device_type();
 649        }
 650        return $this->_devicetypeinuse;
 651    }
 652
 653    /**
 654     * Please do not call this method directly, use the ->legacythemeinuse syntax. {@link moodle_page::__get()}.
 655     * @deprecated since 2.1
 656     * @return bool
 657     */
 658    protected function magic_get_legacythemeinuse() {
 659        debugging('$PAGE->legacythemeinuse is a deprecated property - please use $PAGE->devicetypeinuse and check if it is equal to legacy.', DEBUG_DEVELOPER);
 660        return ($this->devicetypeinuse == 'legacy');
 661    }
 662
 663    /**
 664     * Please do not call this method directly use the ->periodicrefreshdelay syntax
 665     * {@link moodle_page::__get()}
 666     * @return int The periodic refresh delay to use with meta refresh
 667     */
 668    protected function magic_get_periodicrefreshdelay() {
 669        return $this->_periodicrefreshdelay;
 670    }
 671
 672    /**
 673     * Please do not call this method directly use the ->opencontainers syntax. {@link moodle_page::__get()}
 674     * @return xhtml_container_stack tracks XHTML tags on this page that have been opened but not closed.
 675     *      mainly for internal use by the rendering code.
 676     */
 677    protected function magic_get_opencontainers() {
 678        if (is_null($this->_opencontainers)) {
 679            $this->_opencontainers = new xhtml_container_stack();
 680        }
 681        return $this->_opencontainers;
 682    }
 683
 684    /**
 685     * Return the navigation object
 686     * @return global_navigation
 687     */
 688    protected function magic_get_navigation() {
 689        if ($this->_navigation === null) {
 690            $this->_navigation = new global_navigation($this);
 691        }
 692        return $this->_navigation;
 693    }
 694
 695    /**
 696     * Return a navbar object
 697     * @return navbar
 698     */
 699    protected function magic_get_navbar() {
 700        if ($this->_navbar === null) {
 701            $this->_navbar = new navbar($this);
 702        }
 703        return $this->_navbar;
 704    }
 705
 706    /**
 707     * Returns the settings navigation object
 708     * @return settings_navigation
 709     */
 710    protected function magic_get_settingsnav() {
 711        if ($this->_settingsnav === null) {
 712            $this->_settingsnav = new settings_navigation($this);
 713            $this->_settingsnav->initialise();
 714        }
 715        return $this->_settingsnav;
 716    }
 717
 718    /**
 719     * PHP overloading magic to make the $PAGE->course syntax work by redirecting
 720     * it to the corresponding $PAGE->magic_get_course() method if there is one, and
 721     * throwing an exception if not.
 722     *
 723     * @param string $name property name
 724     * @return mixed
 725     */
 726    public function __get($name) {
 727        $getmethod = 'magic_get_' . $name;
 728        if (method_exists($this, $getmethod)) {
 729            return $this->$getmethod();
 730        } else {
 731            throw new coding_exception('Unknown property ' . $name . ' of $PAGE.');
 732        }
 733    }
 734
 735    /**
 736     * PHP overloading magic to catch obvious coding errors.
 737     *
 738     * This method has been created to catch obvious coding errors where the
 739     * developer has tried to set a page property using $PAGE->key = $value.
 740     * In the moodle_page class all properties must be set using the appropriate
 741     * $PAGE->set_something($value) method.
 742     *
 743     * @param string $name property name
 744     * @param mixed $value Value
 745     * @return void Throws exception if field not defined in page class
 746     */
 747    public function __set($name, $value) {
 748        if (method_exists($this, 'set_' . $name)) {
 749            throw new coding_exception('Invalid attempt to modify page object', "Use \$PAGE->set_$name() instead.");
 750        } else {
 751            throw new coding_exception('Invalid attempt to modify page object', "Unknown property $name");
 752        }
 753    }
 754
 755    // Other information getting methods ==========================================
 756
 757    /**
 758     * Returns instance of page renderer
 759     *
 760     * @param string $component name such as 'core', 'mod_forum' or 'qtype_multichoice'.
 761     * @param string $subtype optional subtype such as 'news' resulting to 'mod_forum_news'
 762     * @param string $target one of rendering target constants
 763     * @return renderer_base
 764     */
 765    public function get_renderer($component, $subtype = null, $target = null) {
 766        return $this->magic_get_theme()->get_renderer($this, $component, $subtype, $target);
 767    }
 768
 769    /**
 770     * Checks to see if there are any items on the navbar object
 771     *
 772     * @return bool true if there are, false if not
 773     */
 774    public function has_navbar() {
 775        if ($this->_navbar === null) {
 776            $this->_navbar = new navbar($this);
 777        }
 778        return $this->_navbar->has_items();
 779    }
 780
 781    /**
 782     * Should the current user see this page in editing mode.
 783     * That is, are they allowed to edit this page, and are they currently in
 784     * editing mode.
 785     * @return bool
 786     */
 787    public function user_is_editing() {
 788        global $USER;
 789        return !empty($USER->editing) && $this->user_allowed_editing();
 790    }
 791
 792    /**
 793     * Does the user have permission to edit blocks on this page.
 794     * @return bool
 795     */
 796    public function user_can_edit_blocks() {
 797        return has_capability($this->_blockseditingcap, $this->_context);
 798    }
 799
 800    /**
 801     * Does the user have permission to see this page in editing mode.
 802     * @return bool
 803     */
 804    public function user_allowed_editing() {
 805        if ($this->_legacypageobject) {
 806            return $this->_legacypageobject->user_allowed_editing();
 807        }
 808        return has_any_capability($this->all_editing_caps(), $this->_context);
 809    }
 810
 811    /**
 812     * Get a description of this page. Normally displayed in the footer in
 813     * developer debug mode.
 814     * @return string
 815     */
 816    public function debug_summary() {
 817        $summary = '';
 818        $summary .= 'General type: ' . $this->pagelayout . '. ';
 819        if (!during_initial_install()) {
 820            $summary .= 'Context ' . print_context_name($this->_context) . ' (context id ' . $this->_context->id . '). ';
 821        }
 822        $summary .= 'Page type ' . $this->pagetype .  '. ';
 823        if ($this->subpage) {
 824            'Sub-page ' . $this->subpage .  '. ';
 825        }
 826        return $summary;
 827    }
 828
 829    // Setter methods =============================================================
 830
 831    /**
 832     * Set the state. The state must be one of that STATE_... constants, and
 833     * the state is only allowed to advance one step at a time.
 834     *
 835     * @param integer $state The new state.
 836     */
 837    public function set_state($state) {
 838        if ($state != $this->_state + 1 || $state > self::STATE_DONE) {
 839            throw new coding_exception('Invalid state passed to moodle_page::set_state. We are in state ' .
 840                    $this->_state . ' and state ' . $state . ' was requested.');
 841        }
 842
 843        if ($state == self::STATE_PRINTING_HEADER) {
 844            $this->starting_output();
 845        }
 846
 847        $this->_state = $state;
 848    }
 849
 850    /**
 851     * Set the current course. This sets both $PAGE->course and $COURSE. It also
 852     * sets the right theme and locale.
 853     *
 854     * Normally you don't need to call this function yourself, require_login will
 855     * call it for you if you pass a $course to it. You can use this function
 856     * on pages that do need to call require_login().
 857     *
 858     * Sets $PAGE->context to the course context, if it is not already set.
 859     *
 860     * @param stdClass $course the course to set as the global course.
 861     */
 862    public function set_course($course) {
 863        global $COURSE, $PAGE;
 864
 865        if (empty($course->id)) {
 866            throw new coding_exception('$course passed to moodle_page::set_course does not look like a proper course object.');
 867        }
 868
 869        $this->ensure_theme_not_set();
 870
 871        if (!empty($this->_course->id) && $this->_course->id != $course->id) {
 872            $this->_categories = null;
 873        }
 874
 875        $this->_course = clone($course);
 876
 877        if ($this === $PAGE) {
 878            $COURSE = $this->_course;
 879            moodle_setlocale();
 880        }
 881
 882        if (!$this->_context) {
 883            $this->set_context(get_context_instance(CONTEXT_COURSE, $this->_course->id));
 884        }
 885    }
 886
 887    /**
 888     * Set the main context to which this page belongs.
 889     *
 890     * @param context $context a context object, normally obtained with get_context_instance.
 891     */
 892    public function set_context($context) {
 893        if ($context === null) {
 894            // extremely ugly hack which sets context to some value in order to prevent warnings,
 895            // use only for core error handling!!!!
 896            if (!$this->_context) {
 897                $this->_context = get_context_instance(CONTEXT_SYSTEM);
 898            }
 899            return;
 900        }
 901
 902        // ideally we should set context only once
 903        if (isset($this->_context)) {
 904            if ($context->id == $this->_context->id) {
 905                // fine - no change needed
 906            } else if ($this->_context->contextlevel == CONTEXT_SYSTEM or $this->_context->contextlevel == CONTEXT_COURSE) {
 907                // hmm - not ideal, but it might produce too many warnings due to the design of require_login
 908            } else if ($this->_context->contextlevel == CONTEXT_MODULE and $this->_context->id == get_parent_contextid($context)) {
 909                // hmm - most probably somebody did require_login() and after that set the block context
 910            } else {
 911                // we do not want devs to do weird switching of context levels on the fly,
 912                // because we might have used the context already such as in text filter in page title
 913                debugging('Coding problem: unsupported modification of PAGE->context from '.$this->_context->contextlevel.' to '.$context->contextlevel);
 914            }
 915        }
 916
 917        $this->_context = $context;
 918    }
 919
 920    /**
 921     * The course module that this page belongs to (if it does belong to one).
 922     *
 923     * @param stdClass|cm_info $cm a record from course_modules table or cm_info from get_fast_modinfo().
 924     * @param stdClass $course
 925     * @param stdClass $module
 926     * @return void
 927     */
 928    public function set_cm($cm, $course = null, $module = null) {
 929        global $DB;
 930
 931        if (!isset($cm->id) || !isset($cm->course)) {
 932            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.');
 933        }
 934
 935        if (!$this->_course || $this->_course->id != $cm->course) {
 936            if (!$course) {
 937                $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
 938            }
 939            if ($course->id != $cm->course) {
 940                throw new coding_exception('The course you passed to $PAGE->set_cm does not correspond to the $cm.');
 941            }
 942            $this->set_course($course);
 943        }
 944
 945        // make sure we have a $cm from get_fast_modinfo as this contains activity access details
 946        if (!($cm instanceof cm_info)) {
 947            $modinfo = get_fast_modinfo($this->_course);
 948            $cm = $modinfo->get_cm($cm->id);
 949        }
 950        $this->_cm = $cm;
 951
 952        // unfortunately the context setting is a mess, let's try to work around some common block problems and show some debug messages
 953        if (empty($this->_context) or $this->_context->contextlevel != CONTEXT_BLOCK) {
 954            $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 955            $this->set_context($context);
 956        }
 957
 958        if ($module) {
 959            $this->set_activity_record($module);
 960        }
 961    }
 962
 963    /**
 964     * Sets the activity record. This could be a row from the main table for a
 965     * module. For instance if the current module (cm) is a forum this should be a row
 966     * from the forum table.
 967     *
 968     * @param stdClass $module A row from the main database table for the module that this
 969     * page belongs to.
 970     * @return void
 971     */
 972    public function set_activity_record($module) {
 973        if (is_null($this->_cm)) {
 974            throw new coding_exception('You cannot call $PAGE->set_activity_record until after $PAGE->cm has been set.');
 975        }
 976        if ($module->id != $this->_cm->instance || $module->course != $this->_course->id) {
 977            throw new coding_exception('The activity record your are trying to set does not seem to correspond to the cm that has been set.');
 978        }
 979        $this->_module = $module;
 980    }
 981
 982    /**
 983     * Sets the pagetype to use for this page.
 984     *
 985     * Normally you do not need to set this manually, it is automatically created
 986     * from the script name. However, on some pages this is overridden.
 987     * For example the page type for course/view.php includes the course format,
 988     * for example 'course-view-weeks'. This gets used as the id attribute on
 989     * <body> and also for determining which blocks are displayed.
 990     *
 991     * @param string $pagetype e.g. 'my-index' or 'mod-quiz-attempt'.
 992     */
 993    public function set_pagetype($pagetype) {
 994        $this->_pagetype = $pagetype;
 995    }
 996
 997    /**
 998     * Sets the layout to use for this page.
 999     *
1000     * The page layout determines how the page will be displayed, things such as
1001     * block regions, content areas, etc are controlled by the layout.
1002     * The theme in use for the page will determine that the layout contains.
1003     *
1004     * This properly defaults to 'base', so you only need to call this function if
1005     * you want something different. The exact range of supported layouts is specified
1006     * in the standard theme.
1007     *
1008     * For an idea of the common page layouts see
1009     * {@link http://docs.moodle.org/dev/Themes_2.0#The_different_layouts_as_of_August_17th.2C_2010}
1010     * But please keep in mind that it may be (and normally is) out of date.
1011     * The only place to find an accurate up-to-date list of the page layouts
1012     * available for your version of Moodle is {@link theme/base/config.php}
1013     *
1014     * @param string $pagelayout the page layout this is. For example 'popup', 'home'.
1015     */
1016    public function set_pagelayout($pagelayout) {
1017        /**
1018         * Uncomment this to debug theme pagelayout issues like missing blocks.
1019         *
1020         * if (!empty($this->_wherethemewasinitialised) && $pagelayout != $this->_pagelayout) {
1021         *     debugging('Page layout has already been set and cannot be changed.', DEBUG_DEVELOPER);
1022         * }
1023         */
1024        $this->_pagelayout = $pagelayout;
1025    }
1026
1027    /**
1028     * If context->id and pagetype are not enough to uniquely identify this page,
1029     * then you can set a subpage id as well. For example, the tags page sets
1030     *
1031     * @param string $subpage an arbitrary identifier that, along with context->id
1032     *      and pagetype, uniquely identifies this page.
1033     */
1034    public function set_subpage($subpage) {
1035        if (empty($subpage)) {
1036            $this->_subpage = '';
1037        } else {
1038            $this->_subpage = $subpage;
1039        }
1040    }
1041
1042    /**
1043     * Adds a CSS class to the body tag of the page.
1044     *
1045     * @param string $class add this class name ot the class attribute on the body tag.
1046     */
1047    public function add_body_class($class) {
1048        if ($this->_state > self::STATE_BEFORE_HEADER) {
1049            throw new coding_exception('Cannot call moodle_page::add_body_class after output has been started.');
1050        }
1051        $this->_bodyclasses[$class] = 1;
1052    }
1053
1054    /**
1055     * Adds an array of body classes to the body tag of this page.
1056     *
1057     * @param array $classes this utility method calls add_body_class for each array element.
1058     */
1059    public function add_body_classes($classes) {
1060        foreach ($classes as $class) {
1061            $this->add_body_class($class);
1062        }
1063    }
1064
1065    /**
1066     * Sets the title for the page.
1067     * This is normally used within the title tag in the head of the page.
1068     *
1069     * @param string $title the title that should go in the <head> section of the HTML of this page.
1070     */
1071    public function set_title($title) {
1072        $title = format_string($title);
1073        $title = str_replace('"', '&quot;', $title);
1074        $this->_title = $title;
1075    }
1076
1077    /**
1078     * Sets the heading to use for the page.
1079     * This is normally used as the main heading at the top of the content.
1080     *
1081     * @param string $heading the main heading that should be displayed at the top of the <body>.
1082     */
1083    public function set_heading($heading) {
1084        $this->_heading = format_string($heading);
1085    }
1086
1087    /**
1088     * Sets some HTML to use next to the heading {@link moodle_page::set_heading()}
1089     *
1090     * @param string $menu The menu/content to show in the heading
1091     */
1092    public function set_headingmenu($menu) {
1093        $this->_headingmenu = $menu;
1094    }
1095
1096    /**
1097     * Set the course category this page belongs to manually.
1098     *
1099     * This automatically sets $PAGE->course to be the site course. You cannot
1100     * use this method if you have already set $PAGE->course - in that case,
1101     * the category must be the one that the course belongs to. This also
1102     * automatically sets the page context to the category context.
1103     *
1104     * @param integer $categoryid The id of the category to set.
1105     */
1106    public function set_category_by_id($categoryid) {
1107        global $SITE, $DB;
1108        if (!is_null($this->_course)) {
1109            throw new coding_exception('Attempt to manually set the course category when the course has been set. This is not allowed.');
1110        }
1111        if (is_array($this->_categories)) {
1112            throw new coding_exception('Course category has already been set. You are not allowed to change it.');
1113        }
1114        $this->ensure_theme_not_set();
1115        $this->set_course($SITE);
1116        $this->load_category($categoryid);
1117        $this->set_context(get_context_instance(CONTEXT_COURSECAT, $categoryid));
1118    }
1119
1120    /**
1121     * Set a different path to use for the 'Moodle docs for this page' link.
1122     *
1123     * By default, it uses the pagetype, which is normally the same as the
1124     * script name. So, for example, for mod/quiz/attempt.php, pagetype is
1125     * mod-quiz-attempt, and so docspath is mod/quiz/attempt.
1126     *
1127     * @param string $path the path to use at the end of the moodle docs URL.
1128     */
1129    public function set_docs_path($path) {
1130        $this->_docspath = $path;
1131    }
1132
1133    /**
1134     * You should call this method from every page to set the cleaned-up URL
1135     * that should be used to return to this page.
1136     *
1137     * Used, for example, by the blocks editing UI to know where to return the
1138     * user after an action.
1139     * For example, course/view.php does:
1140     *      $id = optional_param('id', 0, PARAM_INT);
1141     *      $PAGE->set_url('/course/view.php', array('id' => $id));
1142     *
1143     * @param moodle_url|string $url URL relative to $CFG->wwwroot or {@link moodle_url} instance
1144     * @param array $params parameters to add to the URL
1145     */
1146    public function set_url($url, array $params = null) {
1147        global $CFG;
1148
1149        if (is_string($url)) {
1150            if (strpos($url, 'http') === 0) {
1151                // ok
1152            } else if (strpos($url, '/') === 0) {
1153                // we have to use httpswwwroot here, because of loginhttps pages
1154                $url = $CFG->httpswwwroot . $url;
1155            } else {
1156                throw new coding_exception('Invalid parameter $url, has to be full url or in shortened form starting with /.');
1157            }
1158        }
1159
1160        $this->_url = new moodle_url($url, $params);
1161
1162        $fullurl = $this->_url->out_omit_querystring();
1163        if (strpos($fullurl, "$CFG->httpswwwroot/") !== 0) {
1164            debugging('Most probably incorrect set_page() url argument, it does not match the httpswwwroot!');
1165        }
1166        $shorturl = str_replace("$CFG->httpswwwroot/", '', $fullurl);
1167
1168        if (is_null($this->_pagetype)) {
1169            $this->initialise_default_pagetype($shorturl);
1170        }
1171        if (!is_null($this->_legacypageobject)) {
1172            $this->_legacypageobject->set_url($url, $params);
1173        }
1174    }
1175
1176    /**
1177     * Make sure page URL does not contain the given URL parameter.
1178     *
1179     * This should not be necessary if the script has called set_url properly.
1180     * However, in some situations like the block editing actions; when the URL
1181     * has been guessed, it will contain dangerous block-related actions.
1182     * Therefore, the blocks code calls this function to clean up such parameters
1183     * before doing any redirect.
1184     *
1185     * @param string $param the name of the parameter to make sure is not in the
1186     * page URL.
1187     */
1188    public function ensure_param_not_in_url($param) {
1189        $discard = $this->url; // Make sure $this->url is lazy-loaded;
1190        $this->_url->remove_params($param);
1191    }
1192
1193    /**
1194     * There can be alternate versions of some pages (for example an RSS feed version).
1195     * If such other version exist, call this method, and a link to the alternate
1196     * version will be included in the <head> of the page.
1197     *
1198     * @param string $title The title to give the alternate version.
1199     * @param string|moodle_url $url The URL of the alternate version.
1200     * @param string $mimetype The mime-type of the alternate version.
1201     */
1202    public function add_alternate_version($title, $url, $mimetype) {
1203        if ($this->_state > self::STATE_BEFORE_HEADER) {
1204            throw new coding_exception('Cannot call moodle_page::add_alternate_version after output has been started.');
1205        }
1206        $alt = new stdClass;
1207        $alt->title = $title;
1208        $alt->url = $url;
1209        $this->_alternateversions[$mimetype] = $alt;
1210    }
1211
1212    /**
1213     * Specify a form control should be focused when the page has loaded.
1214     *
1215     * @param string $controlid the id of the HTML element to be focused.
1216     */
1217    public function set_focuscontrol($controlid) {
1218        $this->_focuscontrol = $controlid;
1219    }
1220
1221    /**
1222     * Specify a fragment of HTML that goes where the 'Turn editing on' button normally goes.
1223     *
1224     * @param string $html the HTML to display there.
1225     */
1226    public function set_button($html) {
1227        $this->_button = $html;
1228    }
1229
1230    /**
1231     * Set the capability that allows users to edit blocks on this page.
1232     *
1233     * Normally the default of 'moodle/site:manageblocks' is used, but a few
1234     * pages like the My Moodle page need to use a different capability
1235     * like 'moodle/my:manageblocks'.
1236     *
1237     * @param string $capability a capability.
1238     */
1239    public function set_blocks_editing_capability($capability) {
1240        $this->_blockseditingcap = $capability;
1241    }
1242
1243    /**
1244     * Some pages let you turn editing on for reasons other than editing blocks.
1245     * If that is the case, you can pass other capabilities that let the user
1246     * edit this page here.
1247     *
1248     * @param string|array $capability either a capability, or an array of capabilities.
1249     */
1250    public function set_other_editing_capability($capability) {
1251        if (is_array($capability)) {
1252            $this->_othereditingcaps = array_unique($this->_othereditingcaps + $capability);
1253        } else {
1254            $this->_othereditingcaps[] = $capability;
1255        }
1256    }
1257
1258    /**
1259     * Sets whether the browser should cache this page or not.
1260     *
1261     * @return bool $cacheable can this page be cached by the user's browser.
1262     */
1263    public function set_cacheable($cacheable) {
1264        $this->_cacheable = $cacheable;
1265    }
1266
1267    /**
1268     * Sets the page to periodically refresh
1269     *
1270     * This function must be called before $OUTPUT->header has been called or
1271     * a coding exception will be thrown.
1272     *
1273     * @param int $delay Sets the delay before refreshing the page, if set to null
1274     *     refresh is cancelled
1275     */
1276    public function set_periodic_refresh_delay($delay=null) {
1277        if ($this->_state > self::STATE_BEFORE_HEADER) {
1278            throw new coding_exception('You cannot set a periodic refresh delay after the header has been printed');
1279        }
1280        if ($delay===null) {
1281            $this->_periodicrefreshdelay = null;
1282        } else if (is_int($delay)) {
1283            $this->_periodicrefreshdelay = $delay;
1284        }
1285    }
1286
1287    /**
1288     * Force this page to use a particular theme.
1289     *
1290     * Please use this cautiously.
1291     * It is only intended to be used by the themes selector admin page.
1292     *
1293     * @param string $themename the name of the theme to use.
1294     */
1295    pu…

Large files files are truncated, but you can click here to view the full file