Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/pagelib.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00029 defined('MOODLE_INTERNAL') || die();
00030 
00090 class moodle_page {
00092     const STATE_BEFORE_HEADER = 0;
00093     const STATE_PRINTING_HEADER = 1;
00094     const STATE_IN_BODY = 2;
00095     const STATE_DONE = 3;
00098 
00099 
00100     protected $_state = self::STATE_BEFORE_HEADER;
00101 
00102     protected $_course = null;
00103 
00108     protected $_cm = null;
00109 
00115     protected $_module = null;
00116 
00120     protected $_context = null;
00121 
00131     protected $_categories = null;
00132 
00133     protected $_bodyclasses = array();
00134 
00135     protected $_title = '';
00136 
00137     protected $_heading = '';
00138 
00139     protected $_pagetype = null;
00140 
00141     protected $_pagelayout = 'base';
00142 
00148     protected $_layout_options = array();
00149 
00150     protected $_subpage = '';
00151 
00152     protected $_docspath = null;
00153 
00155     protected $_legacyclass = null;
00156 
00157     protected $_url = null;
00158 
00159     protected $_alternateversions = array();
00160 
00161     protected $_blocks = null;
00162 
00163     protected $_requires = null;
00164 
00165     protected $_blockseditingcap = 'moodle/site:manageblocks';
00166 
00167     protected $_block_actions_done = false;
00168 
00169     protected $_othereditingcaps = array();
00170 
00171     protected $_cacheable = true;
00172 
00173     protected $_focuscontrol = '';
00174 
00175     protected $_button = '';
00176 
00177     protected $_theme = null;
00179     protected $_navigation = null;
00181     protected $_settingsnav = null;
00183     protected $_navbar = null;
00185     protected $_headingmenu = null;
00186 
00191     protected $_wherethemewasinitialised = null;
00192 
00194     protected $_opencontainers;
00195 
00202     protected $_periodicrefreshdelay = null;
00203 
00210     protected $_legacypageobject = null;
00211 
00217     protected $_legacybrowsers = array('MSIE' => 6.0);
00218 
00225     protected $_devicetypeinuse = null;
00226 
00227     protected $_https_login_required = false;
00228 
00229     protected $_popup_notification_allowed = true;
00230 
00234 
00242     protected function magic_get_state() {
00243         return $this->_state;
00244     }
00245 
00250     protected function magic_get_headerprinted() {
00251         return $this->_state >= self::STATE_IN_BODY;
00252     }
00253 
00262     protected function magic_get_course() {
00263         global $SITE;
00264         if (is_null($this->_course)) {
00265             return $SITE;
00266         }
00267         return $this->_course;
00268     }
00269 
00278     protected function magic_get_cm() {
00279         return $this->_cm;
00280     }
00281 
00288     protected function magic_get_activityrecord() {
00289         if (is_null($this->_module) && !is_null($this->_cm)) {
00290             $this->load_activity_record();
00291         }
00292         return $this->_module;
00293     }
00294 
00300     protected function magic_get_activityname() {
00301         if (is_null($this->_cm)) {
00302             return null;
00303         }
00304         return $this->_cm->modname;
00305     }
00306 
00312     protected function magic_get_category() {
00313         $this->ensure_category_loaded();
00314         if (!empty($this->_categories)) {
00315             return reset($this->_categories);
00316         } else {
00317             return null;
00318         }
00319     }
00320 
00328     protected function magic_get_categories() {
00329         $this->ensure_categories_loaded();
00330         return $this->_categories;
00331     }
00332 
00337     protected function magic_get_context() {
00338         if (is_null($this->_context)) {
00339             if (CLI_SCRIPT or NO_MOODLE_COOKIES) {
00340                 // cli scripts work in system context, do not annoy devs with debug info
00341                 // very few scripts do not use cookies, we can safely use system as default context there
00342             } else {
00343                 debugging('Coding problem: $PAGE->context was not set. You may have forgotten '
00344                     .'to call require_login() or $PAGE->set_context(). The page may not display '
00345                     .'correctly as a result');
00346             }
00347             $this->_context = get_context_instance(CONTEXT_SYSTEM);
00348         }
00349         return $this->_context;
00350     }
00351 
00356     protected function magic_get_pagetype() {
00357         global $CFG;
00358         if (is_null($this->_pagetype) || isset($CFG->pagepath)) {
00359             $this->initialise_default_pagetype();
00360         }
00361         return $this->_pagetype;
00362     }
00363 
00368     protected function magic_get_bodyid() {
00369         return 'page-'.$this->pagetype;
00370     }
00371 
00377     protected function magic_get_pagelayout() {
00378         return $this->_pagelayout;
00379     }
00380 
00385     protected function magic_get_layout_options() {
00386         return $this->_layout_options;
00387     }
00388 
00393     protected function magic_get_subpage() {
00394         return $this->_subpage;
00395     }
00396 
00401     protected function magic_get_bodyclasses() {
00402         return implode(' ', array_keys($this->_bodyclasses));
00403     }
00404 
00409     protected function magic_get_title() {
00410         return $this->_title;
00411     }
00412 
00417     protected function magic_get_heading() {
00418         return $this->_heading;
00419     }
00420 
00425     protected function magic_get_headingmenu() {
00426         return $this->_headingmenu;
00427     }
00428 
00433     protected function magic_get_docspath() {
00434         if (is_string($this->_docspath)) {
00435             return $this->_docspath;
00436         } else {
00437             return str_replace('-', '/', $this->pagetype);
00438         }
00439     }
00440 
00446     protected function magic_get_url() {
00447         global $FULLME;
00448         if (is_null($this->_url)) {
00449             debugging('This page did not call $PAGE->set_url(...). Using '.s($FULLME), DEBUG_DEVELOPER);
00450             $this->_url = new moodle_url($FULLME);
00451             // Make sure the guessed URL cannot lead to dangerous redirects.
00452             $this->_url->remove_params('sesskey');
00453         }
00454         return new moodle_url($this->_url); // Return a clone for safety.
00455     }
00456 
00461     protected function magic_get_alternateversions() {
00462         return $this->_alternateversions;
00463     }
00464 
00469     protected function magic_get_blocks() {
00470         global $CFG;
00471         if (is_null($this->_blocks)) {
00472             if (!empty($CFG->blockmanagerclass)) {
00473                 $classname = $CFG->blockmanagerclass;
00474             } else {
00475                 $classname = 'block_manager';
00476             }
00477             $this->_blocks = new $classname($this);
00478         }
00479         return $this->_blocks;
00480     }
00481 
00486     protected function magic_get_requires() {
00487         global $CFG;
00488         if (is_null($this->_requires)) {
00489             $this->_requires = new page_requirements_manager();
00490         }
00491         return $this->_requires;
00492     }
00493 
00498     protected function magic_get_cacheable() {
00499         return $this->_cacheable;
00500     }
00501 
00506     protected function magic_get_focuscontrol() {
00507         return $this->_focuscontrol;
00508     }
00509 
00514     protected function magic_get_button() {
00515         return $this->_button;
00516     }
00517 
00522     protected function magic_get_theme() {
00523         if (is_null($this->_theme)) {
00524             $this->initialise_theme_and_output();
00525         }
00526         return $this->_theme;
00527     }
00528 
00534     protected function magic_get_devicetypeinuse() {
00535         if (empty($this->_devicetypeinuse)) {
00536             $this->_devicetypeinuse = get_user_device_type();
00537         }
00538         return $this->_devicetypeinuse;
00539     }
00540 
00546     protected function magic_get_legacythemeinuse() {
00547         debugging('$PAGE->legacythemeinuse is a deprecated property - please use $PAGE->devicetypeinuse and check if it is equal to legacy.', DEBUG_DEVELOPER);
00548         return ($this->devicetypeinuse == 'legacy');
00549     }
00550 
00556     protected function magic_get_periodicrefreshdelay() {
00557         return $this->_periodicrefreshdelay;
00558     }
00559 
00565     protected function magic_get_opencontainers() {
00566         if (is_null($this->_opencontainers)) {
00567             $this->_opencontainers = new xhtml_container_stack();
00568         }
00569         return $this->_opencontainers;
00570     }
00571 
00576     protected function magic_get_navigation() {
00577         if ($this->_navigation === null) {
00578             $this->_navigation = new global_navigation($this);
00579         }
00580         return $this->_navigation;
00581     }
00582 
00587     protected function magic_get_navbar() {
00588         if ($this->_navbar === null) {
00589             $this->_navbar = new navbar($this);
00590         }
00591         return $this->_navbar;
00592     }
00593 
00598     protected function magic_get_settingsnav() {
00599         if ($this->_settingsnav === null) {
00600             $this->_settingsnav = new settings_navigation($this);
00601             $this->_settingsnav->initialise();
00602         }
00603         return $this->_settingsnav;
00604     }
00605 
00614     public function __get($name) {
00615         $getmethod = 'magic_get_' . $name;
00616         if (method_exists($this, $getmethod)) {
00617             return $this->$getmethod();
00618         } else {
00619             throw new coding_exception('Unknown property ' . $name . ' of $PAGE.');
00620         }
00621     }
00622 
00630     public function __set($name, $value) {
00631         if (method_exists($this, 'set_' . $name)) {
00632             throw new coding_exception('Invalid attempt to modify page object', "Use \$PAGE->set_$name() instead.");
00633         } else {
00634             throw new coding_exception('Invalid attempt to modify page object', "Unknown property $name");
00635         }
00636     }
00637 
00639 
00647     public function get_renderer($component, $subtype = null, $target = null) {
00648         return $this->magic_get_theme()->get_renderer($this, $component, $subtype, $target);
00649     }
00650 
00655     public function has_navbar() {
00656         if ($this->_navbar === null) {
00657             $this->_navbar = new navbar($this);
00658         }
00659         return $this->_navbar->has_items();
00660     }
00661 
00667     public function user_is_editing() {
00668         global $USER;
00669         return !empty($USER->editing) && $this->user_allowed_editing();
00670     }
00671 
00675     public function user_can_edit_blocks() {
00676         return has_capability($this->_blockseditingcap, $this->_context);
00677     }
00678 
00682     public function user_allowed_editing() {
00683         if ($this->_legacypageobject) {
00684             return $this->_legacypageobject->user_allowed_editing();
00685         }
00686         return has_any_capability($this->all_editing_caps(), $this->_context);
00687     }
00688 
00693     public function debug_summary() {
00694         $summary = '';
00695         $summary .= 'General type: ' . $this->pagelayout . '. ';
00696         if (!during_initial_install()) {
00697             $summary .= 'Context ' . print_context_name($this->_context) . ' (context id ' . $this->_context->id . '). ';
00698         }
00699         $summary .= 'Page type ' . $this->pagetype .  '. ';
00700         if ($this->subpage) {
00701             'Sub-page ' . $this->subpage .  '. ';
00702         }
00703         return $summary;
00704     }
00705 
00707 
00713     public function set_state($state) {
00714         if ($state != $this->_state + 1 || $state > self::STATE_DONE) {
00715             throw new coding_exception('Invalid state passed to moodle_page::set_state. We are in state ' .
00716                     $this->_state . ' and state ' . $state . ' was requested.');
00717         }
00718 
00719         if ($state == self::STATE_PRINTING_HEADER) {
00720             $this->starting_output();
00721         }
00722 
00723         $this->_state = $state;
00724     }
00725 
00738     public function set_course($course) {
00739         global $COURSE, $PAGE;
00740 
00741         if (empty($course->id)) {
00742             throw new coding_exception('$course passed to moodle_page::set_course does not look like a proper course object.');
00743         }
00744 
00745         $this->ensure_theme_not_set();
00746 
00747         if (!empty($this->_course->id) && $this->_course->id != $course->id) {
00748             $this->_categories = null;
00749         }
00750 
00751         $this->_course = clone($course);
00752 
00753         if ($this === $PAGE) {
00754             $COURSE = $this->_course;
00755             moodle_setlocale();
00756         }
00757 
00758         if (!$this->_context) {
00759             $this->set_context(get_context_instance(CONTEXT_COURSE, $this->_course->id));
00760         }
00761     }
00762 
00767     public function set_context($context) {
00768         if ($context === null) {
00769             // extremely ugly hack which sets context to some value in order to prevent warnings,
00770             // use only for core error handling!!!!
00771             if (!$this->_context) {
00772                 $this->_context = get_context_instance(CONTEXT_SYSTEM);
00773             }
00774             return;
00775         }
00776 
00777         // ideally we should set context only once
00778         if (isset($this->_context)) {
00779             if ($context->id == $this->_context->id) {
00780                 // fine - no change needed
00781             } else if ($this->_context->contextlevel == CONTEXT_SYSTEM or $this->_context->contextlevel == CONTEXT_COURSE) {
00782                 // hmm - not ideal, but it might produce too many warnings due to the design of require_login
00783             } else if ($this->_context->contextlevel == CONTEXT_MODULE and $this->_context->id == get_parent_contextid($context)) {
00784                 // hmm - most probably somebody did require_login() and after that set the block context
00785             } else {
00786                 // we do not want devs to do weird switching of context levels on the fly,
00787                 // because we might have used the context already such as in text filter in page title
00788                 debugging('Coding problem: unsupported modification of PAGE->context from '.$this->_context->contextlevel.' to '.$context->contextlevel);
00789             }
00790         }
00791 
00792         $this->_context = $context;
00793     }
00794 
00803     public function set_cm($cm, $course = null, $module = null) {
00804         global $DB;
00805 
00806         if (!isset($cm->id) || !isset($cm->course)) {
00807             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.');
00808         }
00809 
00810         if (!$this->_course || $this->_course->id != $cm->course) {
00811             if (!$course) {
00812                 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
00813             }
00814             if ($course->id != $cm->course) {
00815                 throw new coding_exception('The course you passed to $PAGE->set_cm does not correspond to the $cm.');
00816             }
00817             $this->set_course($course);
00818         }
00819 
00820         // make sure we have a $cm from get_fast_modinfo as this contains activity access details
00821         if (!($cm instanceof cm_info)) {
00822             $modinfo = get_fast_modinfo($this->_course);
00823             $cm = $modinfo->get_cm($cm->id);
00824         }
00825         $this->_cm = $cm;
00826 
00827         // unfortunately the context setting is a mess, let's try to work around some common block problems and show some debug messages
00828         if (empty($this->_context) or $this->_context->contextlevel != CONTEXT_BLOCK) {
00829             $context = get_context_instance(CONTEXT_MODULE, $cm->id);
00830             $this->set_context($context);
00831         }
00832 
00833         if ($module) {
00834             $this->set_activity_record($module);
00835         }
00836     }
00837 
00844     public function set_activity_record($module) {
00845         if (is_null($this->_cm)) {
00846             throw new coding_exception('You cannot call $PAGE->set_activity_record until after $PAGE->cm has been set.');
00847         }
00848         if ($module->id != $this->_cm->instance || $module->course != $this->_course->id) {
00849             throw new coding_exception('The activity record your are trying to set does not seem to correspond to the cm that has been set.');
00850         }
00851         $this->_module = $module;
00852     }
00853 
00862     public function set_pagetype($pagetype) {
00863         $this->_pagetype = $pagetype;
00864     }
00865 
00872     public function set_pagelayout($pagelayout) {
00880         $this->_pagelayout = $pagelayout;
00881     }
00882 
00889     public function set_subpage($subpage) {
00890         if (empty($subpage)) {
00891             $this->_subpage = '';
00892         } else {
00893             $this->_subpage = $subpage;
00894         }
00895     }
00896 
00900     public function add_body_class($class) {
00901         if ($this->_state > self::STATE_BEFORE_HEADER) {
00902             throw new coding_exception('Cannot call moodle_page::add_body_class after output has been started.');
00903         }
00904         $this->_bodyclasses[$class] = 1;
00905     }
00906 
00910     public function add_body_classes($classes) {
00911         foreach ($classes as $class) {
00912             $this->add_body_class($class);
00913         }
00914     }
00915 
00919     public function set_title($title) {
00920         $title = format_string($title);
00921         $title = str_replace('"', '&quot;', $title);
00922         $this->_title = $title;
00923     }
00924 
00928     public function set_heading($heading) {
00929         $this->_heading = format_string($heading);
00930     }
00931 
00935     public function set_headingmenu($menu) {
00936         $this->_headingmenu = $menu;
00937     }
00938 
00947     public function set_category_by_id($categoryid) {
00948         global $SITE, $DB;
00949         if (!is_null($this->_course)) {
00950             throw new coding_exception('Attempt to manually set the course category when the course has been set. This is not allowed.');
00951         }
00952         if (is_array($this->_categories)) {
00953             throw new coding_exception('Course category has already been set. You are not allowed to change it.');
00954         }
00955         $this->ensure_theme_not_set();
00956         $this->set_course($SITE);
00957         $this->load_category($categoryid);
00958         $this->set_context(get_context_instance(CONTEXT_COURSECAT, $categoryid));
00959     }
00960 
00968     public function set_docs_path($path) {
00969         $this->_docspath = $path;
00970     }
00971 
00982     public function set_url($url, array $params = null) {
00983         global $CFG;
00984 
00985         if (is_string($url)) {
00986             if (strpos($url, 'http') === 0) {
00987                 // ok
00988             } else if (strpos($url, '/') === 0) {
00989                 // we have to use httpswwwroot here, because of loginhttps pages
00990                 $url = $CFG->httpswwwroot . $url;
00991             } else {
00992                 throw new coding_exception('Invalid parameter $url, has to be full url or in shortened form starting with /.');
00993             }
00994         }
00995 
00996         $this->_url = new moodle_url($url, $params);
00997 
00998         $fullurl = $this->_url->out_omit_querystring();
00999         if (strpos($fullurl, "$CFG->httpswwwroot/") !== 0) {
01000             debugging('Most probably incorrect set_page() url argument, it does not match the httpswwwroot!');
01001         }
01002         $shorturl = str_replace("$CFG->httpswwwroot/", '', $fullurl);
01003 
01004         if (is_null($this->_pagetype)) {
01005             $this->initialise_default_pagetype($shorturl);
01006         }
01007         if (!is_null($this->_legacypageobject)) {
01008             $this->_legacypageobject->set_url($url, $params);
01009         }
01010     }
01011 
01024     public function ensure_param_not_in_url($param) {
01025         $discard = $this->url; // Make sure $this->url is lazy-loaded;
01026         $this->_url->remove_params($param);
01027     }
01028 
01038     public function add_alternate_version($title, $url, $mimetype) {
01039         if ($this->_state > self::STATE_BEFORE_HEADER) {
01040             throw new coding_exception('Cannot call moodle_page::add_alternate_version after output has been started.');
01041         }
01042         $alt = new stdClass;
01043         $alt->title = $title;
01044         $alt->url = $url;
01045         $this->_alternateversions[$mimetype] = $alt;
01046     }
01047 
01053     public function set_focuscontrol($controlid) {
01054         $this->_focuscontrol = $controlid;
01055     }
01056 
01062     public function set_button($html) {
01063         $this->_button = $html;
01064     }
01065 
01072     public function set_blocks_editing_capability($capability) {
01073         $this->_blockseditingcap = $capability;
01074     }
01075 
01082     public function set_other_editing_capability($capability) {
01083         if (is_array($capability)) {
01084             $this->_othereditingcaps = array_unique($this->_othereditingcaps + $capability);
01085         } else {
01086             $this->_othereditingcaps[] = $capability;
01087         }
01088     }
01089 
01093     public function set_cacheable($cacheable) {
01094         $this->_cacheable = $cacheable;
01095     }
01096 
01106     public function set_periodic_refresh_delay($delay=null) {
01107         if ($this->_state > self::STATE_BEFORE_HEADER) {
01108             throw new coding_exception('You cannot set a periodic refresh delay after the header has been printed');
01109         }
01110         if ($delay===null) {
01111             $this->_periodicrefreshdelay = null;
01112         } else if (is_int($delay)) {
01113             $this->_periodicrefreshdelay = $delay;
01114         }
01115     }
01116 
01124     public function force_theme($themename) {
01125         $this->ensure_theme_not_set();
01126         $this->_theme = theme_config::load($themename);
01127     }
01128 
01137     public function https_required() {
01138         global $CFG;
01139 
01140         if (!is_null($this->_url)) {
01141             throw new coding_exception('https_required() must be used before setting page url!');
01142         }
01143 
01144         $this->ensure_theme_not_set();
01145 
01146         $this->_https_login_required = true;
01147 
01148         if (!empty($CFG->loginhttps)) {
01149             $CFG->httpswwwroot = str_replace('http:', 'https:', $CFG->wwwroot);
01150         } else {
01151             $CFG->httpswwwroot = $CFG->wwwroot;
01152         }
01153     }
01154 
01161     public function verify_https_required() {
01162         global $CFG, $FULLME;
01163 
01164         if (is_null($this->_url)) {
01165             throw new coding_exception('verify_https_required() must be called after setting page url!');
01166         }
01167 
01168         if (!$this->_https_login_required) {
01169             throw new coding_exception('verify_https_required() must be called only after https_required()!');
01170         }
01171 
01172         if (empty($CFG->loginhttps)) {
01173             // https not required, so stop checking
01174             return;
01175         }
01176 
01177         if (strpos($this->_url, 'https://')) {
01178             // detect if incorrect PAGE->set_url() used, it is recommended to use root-relative paths there
01179             throw new coding_exception('Invalid page url specified, it must start with https:// for pages that set https_required()!');
01180         }
01181 
01182         if (!empty($CFG->sslproxy)) {
01183             // it does not make much sense to use sslproxy and loginhttps at the same time
01184             return;
01185         }
01186 
01187         // now the real test and redirect!
01188         // NOTE: do NOT use this test for detection of https on current page because this code is not compatible with SSL proxies,
01189         //       instead use strpos($CFG->httpswwwroot, 'https:') === 0
01190         if (strpos($FULLME, 'https:') !== 0) {
01191             // this may lead to infinite redirect on misconfigured sites, in that case use $CFG->loginhttps=0; in /config.php
01192             redirect($this->_url);
01193         }
01194     }
01195 
01198 
01203     protected function starting_output() {
01204         global $CFG;
01205 
01206         if (!during_initial_install()) {
01207             $this->blocks->load_blocks();
01208             if (empty($this->_block_actions_done)) {
01209                 $this->_block_actions_done = true;
01210                 if ($this->blocks->process_url_actions($this)) {
01211                     redirect($this->url->out(false));
01212                 }
01213             }
01214             $this->blocks->create_all_block_instances();
01215         }
01216 
01217         // If maintenance mode is on, change the page header.
01218         if (!empty($CFG->maintenance_enabled)) {
01219             $this->set_button('<a href="' . $CFG->wwwroot . '/' . $CFG->admin .
01220                     '/settings.php?section=maintenancemode">' . get_string('maintenancemode', 'admin') .
01221                     '</a> ' . $this->button);
01222 
01223             $title = $this->title;
01224             if ($title) {
01225                 $title .= ' - ';
01226             }
01227             $this->set_title($title . get_string('maintenancemode', 'admin'));
01228         } else {
01229             // Show the messaging popup if there are messages
01230             message_popup_window();
01231         }
01232 
01233         $this->initialise_standard_body_classes();
01234     }
01235 
01244     public function initialise_theme_and_output() {
01245         global $OUTPUT, $PAGE, $SITE;
01246 
01247         if (!empty($this->_wherethemewasinitialised)) {
01248             return;
01249         }
01250 
01251         if (!during_initial_install()) {
01252             // detect PAGE->context mess
01253             $this->magic_get_context();
01254         }
01255 
01256         if (!$this->_course && !during_initial_install()) {
01257             $this->set_course($SITE);
01258         }
01259 
01260         if (is_null($this->_theme)) {
01261             $themename = $this->resolve_theme();
01262             $this->_theme = theme_config::load($themename);
01263             $this->_layout_options = $this->_theme->pagelayout_options($this->pagelayout);
01264         }
01265 
01266         $this->_theme->setup_blocks($this->pagelayout, $this->blocks);
01267 
01268         if ($this === $PAGE) {
01269             $OUTPUT = $this->get_renderer('core');
01270         }
01271 
01272         $this->_wherethemewasinitialised = debug_backtrace();
01273     }
01274 
01282     protected function resolve_theme() {
01283         global $CFG, $USER, $SESSION;
01284 
01285         if (empty($CFG->themeorder)) {
01286             $themeorder = array('course', 'category', 'session', 'user', 'site');
01287         } else {
01288             $themeorder = $CFG->themeorder;
01289             // Just in case, make sure we always use the site theme if nothing else matched.
01290             $themeorder[] = 'site';
01291         }
01292 
01293         $mnetpeertheme = '';
01294         if (isloggedin() and isset($CFG->mnet_localhost_id) and $USER->mnethostid != $CFG->mnet_localhost_id) {
01295             require_once($CFG->dirroot.'/mnet/peer.php');
01296             $mnetpeer = new mnet_peer();
01297             $mnetpeer->set_id($USER->mnethostid);
01298             if ($mnetpeer->force_theme == 1 && $mnetpeer->theme != '') {
01299                 $mnetpeertheme = $mnetpeer->theme;
01300             }
01301         }
01302 
01303         foreach ($themeorder as $themetype) {
01304             switch ($themetype) {
01305                 case 'course':
01306                     if (!empty($CFG->allowcoursethemes) && !empty($this->_course->theme) && $this->devicetypeinuse == 'default') {
01307                         return $this->_course->theme;
01308                     }
01309 
01310                 case 'category':
01311                     if (!empty($CFG->allowcategorythemes) && $this->devicetypeinuse == 'default') {
01312                         $categories = $this->categories;
01313                         foreach ($categories as $category) {
01314                             if (!empty($category->theme)) {
01315                                 return $category->theme;
01316                             }
01317                         }
01318                     }
01319 
01320                 case 'session':
01321                     if (!empty($SESSION->theme)) {
01322                         return $SESSION->theme;
01323                     }
01324 
01325                 case 'user':
01326                     if (!empty($CFG->allowuserthemes) && !empty($USER->theme) && $this->devicetypeinuse == 'default') {
01327                         if ($mnetpeertheme) {
01328                             return $mnetpeertheme;
01329                         } else {
01330                             return $USER->theme;
01331                         }
01332                     }
01333 
01334                 case 'site':
01335                     if ($mnetpeertheme) {
01336                         return $mnetpeertheme;
01337                     }
01338                     // First try for the device the user is using.
01339                     $devicetheme = get_selected_theme_for_device_type($this->devicetypeinuse);
01340                     if (!empty($devicetheme)) {
01341                         return $devicetheme;
01342                     }
01343                     // Next try for the default device (as a fallback)
01344                     $devicetheme = get_selected_theme_for_device_type('default');
01345                     if (!empty($devicetheme)) {
01346                         return $devicetheme;
01347                     }
01348                     // The default device theme isn't set up - use the overall default theme.
01349                     return theme_config::DEFAULT_THEME;
01350             }
01351         }
01352     }
01353 
01354 
01363     protected function initialise_default_pagetype($script = null) {
01364         global $CFG, $SCRIPT;
01365 
01366         if (isset($CFG->pagepath)) {
01367             debugging('Some code appears to have set $CFG->pagepath. That was a horrible deprecated thing. ' .
01368                     'Don\'t do it! Try calling $PAGE->set_pagetype() instead.');
01369             $script = $CFG->pagepath;
01370             unset($CFG->pagepath);
01371         }
01372 
01373         if (is_null($script)) {
01374             $script = ltrim($SCRIPT, '/');
01375             $len = strlen($CFG->admin);
01376             if (substr($script, 0, $len) == $CFG->admin) {
01377                 $script = 'admin' . substr($script, $len);
01378             }
01379         }
01380 
01381         $path = str_replace('.php', '', $script);
01382         if (substr($path, -1) == '/') {
01383             $path .= 'index';
01384         }
01385 
01386         if (empty($path) || $path == 'index') {
01387             $this->_pagetype = 'site-index';
01388         } else {
01389             $this->_pagetype = str_replace('/', '-', $path);
01390         }
01391     }
01392 
01393     protected function initialise_standard_body_classes() {
01394         global $CFG, $USER;
01395 
01396         $pagetype = $this->pagetype;
01397         if ($pagetype == 'site-index') {
01398             $this->_legacyclass = 'course';
01399         } else if (substr($pagetype, 0, 6) == 'admin-') {
01400             $this->_legacyclass = 'admin';
01401         }
01402         $this->add_body_class($this->_legacyclass);
01403 
01404         $pathbits = explode('-', trim($pagetype));
01405         for ($i=1;$i<count($pathbits);$i++) {
01406             $this->add_body_class('path-'.join('-',array_slice($pathbits, 0, $i)));
01407         }
01408 
01409         $this->add_body_classes(get_browser_version_classes());
01410         $this->add_body_class('dir-' . get_string('thisdirection', 'langconfig'));
01411         $this->add_body_class('lang-' . current_language());
01412         $this->add_body_class('yui-skin-sam'); // Make YUI happy, if it is used.
01413         $this->add_body_class('yui3-skin-sam'); // Make YUI3 happy, if it is used.
01414         $this->add_body_class($this->url_to_class_name($CFG->wwwroot));
01415 
01416         $this->add_body_class('pagelayout-' . $this->_pagelayout); // extra class describing current page layout
01417 
01418         if (!during_initial_install()) {
01419             $this->add_body_class('course-' . $this->_course->id);
01420             $this->add_body_class('context-' . $this->_context->id);
01421         }
01422 
01423         if (!empty($this->_cm)) {
01424             $this->add_body_class('cmid-' . $this->_cm->id);
01425         }
01426 
01427         if (!empty($CFG->allowcategorythemes)) {
01428             $this->ensure_category_loaded();
01429             foreach ($this->_categories as $catid => $notused) {
01430                 $this->add_body_class('category-' . $catid);
01431             }
01432         } else {
01433             $catid = 0;
01434             if (is_array($this->_categories)) {
01435                 $catids = array_keys($this->_categories);
01436                 $catid = reset($catids);
01437             } else if (!empty($this->_course->category)) {
01438                 $catid = $this->_course->category;
01439             }
01440             if ($catid) {
01441                 $this->add_body_class('category-' . $catid);
01442             }
01443         }
01444 
01445         if (!isloggedin()) {
01446             $this->add_body_class('notloggedin');
01447         }
01448 
01449         if (!empty($USER->editing)) {
01450             $this->add_body_class('editing');
01451             if (optional_param('bui_moveid', false, PARAM_INT)) {
01452                $this->add_body_class('blocks-moving');
01453         }
01454         }
01455 
01456         if (!empty($CFG->blocksdrag)) {
01457             $this->add_body_class('drag');
01458         }
01459 
01460         if ($this->_devicetypeinuse != 'default') {
01461             $this->add_body_class($this->_devicetypeinuse . 'theme');
01462         }
01463     }
01464 
01465     protected function load_activity_record() {
01466         global $DB;
01467         if (is_null($this->_cm)) {
01468             return;
01469         }
01470         $this->_module = $DB->get_record($this->_cm->modname, array('id' => $this->_cm->instance));
01471     }
01472 
01473     protected function ensure_category_loaded() {
01474         if (is_array($this->_categories)) {
01475             return; // Already done.
01476         }
01477         if (is_null($this->_course)) {
01478             throw new coding_exception('Attempt to get the course category for this page before the course was set.');
01479         }
01480         if ($this->_course->category == 0) {
01481             $this->_categories = array();
01482         } else {
01483             $this->load_category($this->_course->category);
01484         }
01485     }
01486 
01487     protected function load_category($categoryid) {
01488         global $DB;
01489         $category = $DB->get_record('course_categories', array('id' => $categoryid));
01490         if (!$category) {
01491             throw new moodle_exception('unknowncategory');
01492         }
01493         $this->_categories[$category->id] = $category;
01494         $parentcategoryids = explode('/', trim($category->path, '/'));
01495         array_pop($parentcategoryids);
01496         foreach (array_reverse($parentcategoryids) as $catid) {
01497             $this->_categories[$catid] = null;
01498         }
01499     }
01500 
01501     protected function ensure_categories_loaded() {
01502         global $DB;
01503         $this->ensure_category_loaded();
01504         if (!is_null(end($this->_categories))) {
01505             return; // Already done.
01506         }
01507         $idstoload = array_keys($this->_categories);
01508         array_shift($idstoload);
01509         $categories = $DB->get_records_list('course_categories', 'id', $idstoload);
01510         foreach ($idstoload as $catid) {
01511             $this->_categories[$catid] = $categories[$catid];
01512         }
01513     }
01514 
01515     protected function ensure_theme_not_set() {
01516         if (!is_null($this->_theme)) {
01517             throw new coding_exception('The theme has already been set up for this page ready for output. ' .
01518                     'Therefore, you can no longer change the theme, or anything that might affect what ' .
01519                     'the current theme is, for example, the course.',
01520                     'Stack trace when the theme was set up: ' . format_backtrace($this->_wherethemewasinitialised));
01521         }
01522     }
01523 
01524     protected function url_to_class_name($url) {
01525         $bits = parse_url($url);
01526         $class = str_replace('.', '-', $bits['host']);
01527         if (!empty($bits['port'])) {
01528             $class .= '--' . $bits['port'];
01529         }
01530         if (!empty($bits['path'])) {
01531             $path = trim($bits['path'], '/');
01532             if ($path) {
01533                 $class .= '--' . str_replace('/', '-', $path);
01534             }
01535         }
01536         return $class;
01537     }
01538 
01539     protected function all_editing_caps() {
01540         $caps = $this->_othereditingcaps;
01541         $caps[] = $this->_blockseditingcap;
01542         return $caps;
01543     }
01544 
01546 
01551     public function get_type() {
01552         debugging('Call to deprecated method moodle_page::get_type. Please use $PAGE->pagetype instead.');
01553         return $this->get_pagetype();
01554     }
01555 
01560     function get_format_name() {
01561         return $this->get_pagetype();
01562     }
01563 
01568     public function get_courserecord() {
01569         debugging('Call to deprecated method moodle_page::get_courserecord. Please use $PAGE->course instead.');
01570         return $this->get_course();
01571     }
01572 
01577     public function get_legacyclass() {
01578         if (is_null($this->_legacyclass)) {
01579             $this->initialise_standard_body_classes();
01580         }
01581         debugging('Call to deprecated method moodle_page::get_legacyclass.');
01582         return $this->_legacyclass;
01583     }
01584 
01589     function blocks_get_positions() {
01590         debugging('Call to deprecated method moodle_page::blocks_get_positions. Use $PAGE->blocks->get_regions() instead.');
01591         return $this->blocks->get_regions();
01592     }
01593 
01598     function blocks_default_position() {
01599         debugging('Call to deprecated method moodle_page::blocks_default_position. Use $PAGE->blocks->get_default_region() instead.');
01600         return $this->blocks->get_default_region();
01601     }
01602 
01606     function blocks_get_default() {
01607         debugging('Call to deprecated method moodle_page::blocks_get_default. This method has no function any more.');
01608     }
01609 
01613     function blocks_move_position(&$instance, $move) {
01614         debugging('Call to deprecated method moodle_page::blocks_move_position. This method has no function any more.');
01615     }
01616 
01621     function url_get_parameters() {
01622         debugging('Call to deprecated method moodle_page::url_get_parameters. Use $this->url->params() instead.');
01623         return $this->url->params();
01624     }
01625 
01630     function url_get_path() {
01631         debugging('Call to deprecated method moodle_page::url_get_path. Use $this->url->out() instead.');
01632         return $this->url->out();
01633     }
01634 
01639     function url_get_full($extraparams = array()) {
01640         debugging('Call to deprecated method moodle_page::url_get_full. Use $this->url->out() instead.');
01641         return $this->url->out(true, $extraparams);
01642     }
01643 
01647     function set_legacy_page_object($pageobject) {
01648         return $this->_legacypageobject = $pageobject;
01649     }
01650 
01655     function print_header($_) {
01656         if (is_null($this->_legacypageobject)) {
01657             throw new coding_exception('You have called print_header on $PAGE when there is not a legacy page class present.');
01658         }
01659         debugging('You should not longer be doing print_header via a page class.', DEBUG_DEVELOPER);
01660         $args = func_get_args();
01661         call_user_func_array(array($this->_legacypageobject, 'print_header'), $args);
01662     }
01663 
01668     function get_id() {
01669         debugging('Call to deprecated method moodle_page::get_id(). It should not be necessary any more.', DEBUG_DEVELOPER);
01670         if (!is_null($this->_legacypageobject)) {
01671             return $this->_legacypageobject->get_id();
01672         }
01673         return 0;
01674     }
01675 
01680     function get_pageid() {
01681         debugging('Call to deprecated method moodle_page::get_pageid(). It should not be necessary any more.', DEBUG_DEVELOPER);
01682         if (!is_null($this->_legacypageobject)) {
01683             return $this->_legacypageobject->get_id();
01684         }
01685         return 0;
01686     }
01687 
01692     function get_modulerecord() {
01693         return $this->cm;
01694     }
01695 
01696     public function has_set_url() {
01697         return ($this->_url!==null);
01698     }
01699 
01700     public function set_block_actions_done($setting = true) {
01701         $this->_block_actions_done = $setting;
01702     }
01703 
01709     public function get_popup_notification_allowed() {
01710         return $this->_popup_notification_allowed;
01711     }
01712 
01718     public function set_popup_notification_allowed($allowed) {
01719         $this->_popup_notification_allowed = $allowed;
01720     }
01721 }
01722 
01729 function page_import_types($path) {
01730     global $CFG;
01731     debugging('Call to deprecated function page_import_types.', DEBUG_DEVELOPER);
01732 }
01733 
01741 function page_create_instance($instance) {
01742     global $PAGE;
01743     return page_create_object($PAGE->pagetype, $instance);
01744 }
01745 
01751 function page_create_object($type, $id = NULL) {
01752     global $CFG, $PAGE, $SITE, $ME;
01753     debugging('Call to deprecated function page_create_object.', DEBUG_DEVELOPER);
01754 
01755     $data = new stdClass;
01756     $data->pagetype = $type;
01757     $data->pageid = $id;
01758 
01759     $classname = page_map_class($type);
01760     if (!$classname) {
01761         return $PAGE;
01762     }
01763     $legacypage = new $classname;
01764     $legacypage->init_quick($data);
01765 
01766     $course = $PAGE->course;
01767     if ($course->id != $SITE->id) {
01768         $legacypage->set_course($course);
01769     } else {
01770         try {
01771             $category = $PAGE->category;
01772         } catch (coding_exception $e) {
01773             // Was not set before, so no need to try to set it again.
01774             $category = false;
01775         }
01776         if ($category) {
01777             $legacypage->set_category_by_id($category->id);
01778         } else {
01779             $legacypage->set_course($SITE);
01780         }
01781     }
01782 
01783     $legacypage->set_pagetype($type);
01784 
01785     $legacypage->set_url($ME);
01786     $PAGE->set_url(str_replace($CFG->wwwroot . '/', '', $legacypage->url_get_full()));
01787 
01788     $PAGE->set_pagetype($type);
01789     $PAGE->set_legacy_page_object($legacypage);
01790     return $PAGE;
01791 }
01792 
01798 function page_map_class($type, $classname = NULL) {
01799     global $CFG;
01800 
01801     static $mappings = array(
01802         PAGE_COURSE_VIEW => 'page_course',
01803     );
01804 
01805     if (!empty($type) && !empty($classname)) {
01806         $mappings[$type] = $classname;
01807     }
01808 
01809     if (!isset($mappings[$type])) {
01810         debugging('Page class mapping requested for unknown type: '.$type);
01811         return null;
01812     } else if (empty($classname) && !class_exists($mappings[$type])) {
01813         debugging('Page class mapping for id "'.$type.'" exists but class "'.$mappings[$type].'" is not defined');
01814         return null;
01815     }
01816 
01817     return $mappings[$type];
01818 }
01819 
01829 class page_base extends moodle_page {
01834     var $id             = NULL;
01835 
01837 
01838     // HTML OUTPUT SECTION
01839 
01840     // SELF-REPORTING SECTION
01841 
01842     // Simple stuff, do not override this.
01843     function get_id() {
01844         return $this->id;
01845     }
01846 
01847     // Initialize the data members of the parent class
01848     function init_quick($data) {
01849         $this->id   = $data->pageid;
01850     }
01851 
01852     function init_full() {
01853     }
01854 }
01855 
01867 class page_course extends page_base {
01868 }
01869 
01879 class page_generic_activity extends page_base {
01880     // Although this function is deprecated, it should be left here because
01881     // people upgrading legacy code need to copy it. See
01882     // http://docs.moodle.org/dev/Migrating_your_code_to_the_2.0_rendering_API
01883     function print_header($title, $morenavlinks = NULL, $bodytags = '', $meta = '') {
01884         global $USER, $CFG, $PAGE, $OUTPUT;
01885 
01886         $this->init_full();
01887         $replacements = array(
01888             '%fullname%' => format_string($this->activityrecord->name)
01889         );
01890         foreach ($replacements as $search => $replace) {
01891             $title = str_replace($search, $replace, $title);
01892         }
01893 
01894         $buttons = '<table><tr><td>'.$OUTPUT->update_module_button($this->modulerecord->id, $this->activityname).'</td>';
01895         if ($this->user_allowed_editing()) {
01896             $buttons .= '<td><form method="get" action="view.php"><div>'.
01897                 '<input type="hidden" name="id" value="'.$this->modulerecord->id.'" />'.
01898                 '<input type="hidden" name="edit" value="'.($this->user_is_editing()?'off':'on').'" />'.
01899                 '<input type="submit" value="'.get_string($this->user_is_editing()?'blockseditoff':'blocksediton').'" /></div></form></td>';
01900         }
01901         $buttons .= '</tr></table>';
01902 
01903         if (!empty($morenavlinks) && is_array($morenavlinks)) {
01904             foreach ($morenavlinks as $navitem) {
01905                 if (is_array($navitem) && array_key_exists('name', $navitem)) {
01906                     $link = null;
01907                     if (array_key_exists('link', $navitem)) {
01908                         $link = $navitem['link'];
01909                     }
01910                     $PAGE->navbar->add($navitem['name'], $link);
01911                 }
01912             }
01913         }
01914 
01915         $PAGE->set_title($title);
01916         $PAGE->set_heading($this->course->fullname);
01917         $PAGE->set_button($buttons);
01918         echo $OUTPUT->header();
01919     }
01920 }
 All Data Structures Namespaces Files Functions Variables Enumerations