]> git.mjollnir.org Git - moodle.git/commitdiff
moodle_page: MDL-12212 ->cm and ->activityrecord fields
authortjhunt <tjhunt>
Wed, 6 May 2009 09:03:33 +0000 (09:03 +0000)
committertjhunt <tjhunt>
Wed, 6 May 2009 09:03:33 +0000 (09:03 +0000)
lib/adminlib.php
lib/pagelib.php
lib/simpletest/testpagelib_moodlepage.php

index b0a325883e053c34b2b7f1fba71bc2358117c41f..d086ce5c381a6347e1214fe78c8477babcbf226a 100644 (file)
@@ -3908,7 +3908,7 @@ function admin_externalpage_setup($section, $extrabutton = '',
     page_map_class(PAGE_ADMIN, 'page_admin');
     $PAGE = page_create_object(PAGE_ADMIN, 0); // there must be any constant id number
     $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM));
-    $PAGE->set_extra_button($extrabutton);
+    // $PAGE->set_extra_button($extrabutton); TODO
 
     $adminroot = admin_get_root(false, false); // settings not required for external pages
     $extpage = $adminroot->locate($section);
@@ -3916,6 +3916,7 @@ function admin_externalpage_setup($section, $extrabutton = '',
     if (!$actualurl) {
         $actualurl = $extpage->url;
     }
+    $PAGE->set_pagetype(null);
     $PAGE->set_url(str_replace($CFG->wwwroot . '/', '', $actualurl),
             array_merge($extraurlparams, array('section' => $section)));
 
index fdc9a21bfc2b58c0943561a052d5b8760588a269..2b744d8a1b894b7df7720db823a0c5ed707a3d9e 100644 (file)
@@ -54,6 +54,23 @@ class moodle_page {
 
     protected $_course = null;
 
+    /**
+     * If this page belongs to a module, this is the row from the course_modules
+     * table, as fetched by get_coursemodule_from_id or get_coursemodule_from_instance,
+     * so the extra modname and name fields are present.
+     */
+    protected $_cm = null;
+
+    /**
+     * If $_cm is not null, then this will hold the corresponding row from the
+     * modname table. For example, if $_cm->modname is 'quiz', this will be a
+     * row from the quiz table.
+     */
+    protected $_module = null;
+
+    /**
+     * The context that this page belongs to.
+     */
     protected $_context = null;
 
     /**
@@ -127,6 +144,42 @@ class moodle_page {
         return $this->_course;
     }
 
+    /**
+     * @return object the course_module that this page belongs to. Will be null
+     * if this page is not within a module. This is a full cm object, as loaded
+     * by get_coursemodule_from_id or get_coursemodule_from_instance,
+     * so the extra modname and name fields are present.
+     */
+    public function get_cm() {
+        return $this->_cm;
+    }
+
+    /**
+     * @return object the course_module that this page belongs to. Will be null
+     * if this page is not within a module. This is a full cm object, as loaded
+     * by get_coursemodule_from_id or get_coursemodule_from_instance,
+     * so the extra modname and name fields are present.
+     */
+    public function get_activityrecord() {
+        if (is_null($this->_module) && !is_null($this->_cm)) {
+            $this->load_activity_record();
+        }
+        return $this->_module;
+    }
+
+    /**
+     * @return object the course_module that this page belongs to. Will be null
+     * if this page is not within a module. This is a full cm object, as loaded
+     * by get_coursemodule_from_id or get_coursemodule_from_instance,
+     * so the extra modname and name fields are present.
+     */
+    public function get_activityname() {
+        if (is_null($this->_cm)) {
+            return null;
+        }
+        return $this->_cm->modname;
+    }
+
     /**
      * @return mixed the category that the page course belongs to. If there isn't one
      * (that is, if this is the front page course) returns null.
@@ -317,6 +370,50 @@ class moodle_page {
         $this->_context = $context;
     }
 
+    /**
+     * The course module that this page belongs to (if it does belong to one).
+     *
+     * @param objcet $cm a full cm objcet obtained from get_coursemodule_from_id or get_coursemodule_from_instance.
+     */
+    public function set_cm($cm, $course = null, $module = null) {
+        if (!isset($cm->name) || !isset($cm->modname)) {
+            throw new coding_exception('The $cm you set on $PAGE must have been obtained with get_coursemodule_from_id or get_coursemodule_from_instance. That is, the ->name and -> modname fields must be present and correct.');
+        }
+        $this->_cm = $cm;
+        if (!$this->_context) {
+            $this->set_context(get_context_instance(CONTEXT_MODULE, $cm->id));
+        }
+        if (!$this->_course || $this->_course->id != $cm->course) {
+            if (!$course) {
+                global $DB;
+                $course = $DB->get_record('course', array('id' => $cm->course));
+            }
+            if ($course->id != $cm->course) {
+                throw new coding_exception('The course you passed to $PAGE->set_cm does not seem to correspond to the $cm.');
+            }
+            $this->set_course($course);
+        }
+        if ($module) {
+            $this->set_activity_record($module);
+        }
+    }
+
+    /**
+     * @param $module a row from the main database table for the module that this
+     * page belongs to. For example, if ->cm is a forum, then you can pass the
+     * corresponding row from the forum table here if you have it (saves a database
+     * query sometimes).
+     */
+    public function set_activity_record($module) {
+        if (is_null($this->_cm)) {
+            throw new coding_exception('You cannot call $PAGE->set_activity_record until after $PAGE->cm has been set.');
+        }
+        if ($module->id != $this->_cm->instance || $module->course != $this->_course->id) {
+            throw new coding_exception('The activity record your are trying to set does not seem to correspond to the cm that has been set.');
+        }
+        $this->_module = $module;
+    }
+
     /**
      * @param string $pagetype e.g. 'my-index' or 'mod-quiz-attempt'. Normally
      * you do not need to set this manually, it is automatically created from the
@@ -396,6 +493,9 @@ class moodle_page {
         if (is_null($this->_pagetype)) {
             $this->initialise_default_pagetype($url);
         }
+        if (!is_null($this->_legacypageobject)) {
+            $this->_legacypageobject->set_url($url, $params);
+        }
     }
 
     /**
@@ -514,6 +614,14 @@ class moodle_page {
         }
     }
 
+    protected function load_activity_record() {
+        global $DB;
+        if (is_null($this->_cm)) {
+            return;
+        }
+        $this->_module = $DB->get_record($this->_cm->modname, array('id' => $this->_cm->instance));
+    }
+
     protected function ensure_category_loaded() {
         if (is_array($this->_categories)) {
             return; // Already done.
@@ -707,6 +815,14 @@ class moodle_page {
         }
         return 0;
     }
+
+    /**
+     * @deprecated since Moodle 2.0 - user $PAGE->cm instead.
+     * @return $this->cm;
+     */
+    function get_modulerecord() {
+        return $this->cm;
+    }
 }
 
 /** Stub implementation of the blocks_manager, to stop things from breaking too badly. */
@@ -748,12 +864,12 @@ function page_create_instance($instance) {
  * If you need custom behaviour, you should just set properties of that object.
  */
 function page_create_object($type, $id = NULL) {
-    global $CFG, $PAGE, $SITE;
+    global $CFG, $PAGE, $SITE, $ME;
     debugging('Call to deprecated function page_create_object.', DEBUG_DEVELOPER);
 
     $data = new stdClass;
     $data->pagetype = $type;
-    $data->pageid   = $id;
+    $data->pageid = $id;
 
     $classname = page_map_class($type);
     $legacypage = new $classname;
@@ -776,7 +892,9 @@ function page_create_object($type, $id = NULL) {
         }
     }
     $legacypage->set_pagetype($type);
-    $legacypage->set_url(str_replace($CFG->wwwroot . '/', '', $legacypage->url_get_full()));
+
+    $legacypage->set_url($ME);
+    $PAGE->set_url(str_replace($CFG->wwwroot . '/', '', $legacypage->url_get_full()));
 
     $PAGE->set_pagetype($type);
     $PAGE->set_legacy_page_object($legacypage);
@@ -817,37 +935,18 @@ function page_map_class($type, $classname = NULL) {
  * @package pages
  */
 class page_base extends moodle_page {
-    /**
-     * The string identifier for the type of page being described.
-     * @var string $type
-     */
-    var $type           = NULL;
-
     /**
      * The numeric identifier of the page being described.
      * @var int $id
      */
     var $id             = NULL;
 
-    /**
-     * Class bool to determine if the instance's full initialization has been completed.
-     * @var boolean $full_init_done
-     */
-    var $full_init_done = false;
-
 /// Class Functions
 
     // HTML OUTPUT SECTION
 
-    // We have absolutely no idea what derived pages are all about
-    function print_header($title, $morenavlinks=NULL) {
-        trigger_error('Page class does not implement method <strong>print_header()</strong>', E_USER_WARNING);
-        return;
-    }
-
     // SELF-REPORTING SECTION
 
-
     // Simple stuff, do not override this.
     function get_id() {
         return $this->id;
@@ -855,12 +954,10 @@ class page_base extends moodle_page {
 
     // Initialize the data members of the parent class
     function init_quick($data) {
-        $this->type = $data->pagetype;
         $this->id   = $data->pageid;
     }
 
     function init_full() {
-        $this->full_init_done = true;
     }
 }
 
@@ -871,39 +968,6 @@ class page_base extends moodle_page {
  * @package pages
  */
 class page_course extends page_base {
-    // Do any validation of the officially recognized bits of the data and forward to parent.
-    // Do NOT load up "expensive" resouces (e.g. SQL data) here!
-    function init_quick($data) {
-        if(empty($data->pageid) && !defined('ADMIN_STICKYBLOCKS')) {
-            print_error('cannotinitpage', 'debug', '', (object)array('name'=>'course', 'id'=>'?'));
-        }
-        parent::init_quick($data);
-    }
-
-    // Here you should load up all heavy-duty data for your page. Basically everything that
-    // does not NEED to be loaded for the class to make basic decisions should NOT be loaded
-    // in init_quick() and instead deferred here. Of course this function had better recognize
-    // $this->full_init_done to prevent wasteful multiple-time data retrieval.
-    function init_full() {
-        global $COURSE, $DB;
-
-        if($this->full_init_done) {
-            return;
-        }
-        if (empty($this->id)) {
-            $this->id = 0; // avoid db errors
-        }
-
-        $this->context = get_context_instance(CONTEXT_COURSE, $this->id);
-
-        // Preload - ensures that the context cache is populated
-        // in one DB query...
-        $this->childcontexts = get_child_contexts($this->context);
-
-        // Mark we're done
-        $this->full_init_done = true;
-    }
-
     // HTML OUTPUT SECTION
 
     // This function prints out the common part of the page's header.
@@ -999,29 +1063,6 @@ class page_course extends page_base {
  * @package pages
  */
 class page_generic_activity extends page_base {
-    var $activityname = NULL;
-    var $modulerecord = NULL;
-    var $activityrecord = NULL;
-
-    function init_full() {
-        global $DB;
-
-        if($this->full_init_done) {
-            return;
-        }
-        if(empty($this->activityname)) {
-            print_error('noactivityname', 'debug');
-        }
-        if (!$this->modulerecord = get_coursemodule_from_instance($this->activityname, $this->id)) {
-            print_error('cannotinitpager', 'debug', '', (object)array('name'=>$this->activityname, 'id'=>$this->id));
-        }
-        $this->activityrecord = $DB->get_record($this->activityname, array('id'=>$this->id));
-        if(empty($this->activityrecord)) {
-            print_error('cannotinitpager', 'debug', '', (object)array('name'=>$this->activityname, 'id'=>$this->id));
-        }
-        $this->full_init_done = true;
-    }
-
     function print_header($title, $morenavlinks = NULL, $bodytags = '', $meta = '') {
         global $USER, $CFG;
 
index 60f42cc371ee76d540a123494eefb4ff36f7d449..e6abd33ba0ac716d4dd01cdaa980c3336536eb63 100644 (file)
@@ -456,6 +456,207 @@ class moodle_page_categories_test extends UnitTestCaseUsingDatabase {
     }
 }
 
+/**
+ * Test functions that rely on the context table.
+ */
+class moodle_page_cm_test extends UnitTestCaseUsingDatabase {
+    protected $testpage;
+    protected $originalcourse;
+
+    public function setUp() {
+        global $COURSE, $SITE;
+        parent::setUp();
+        $this->originalcourse = $COURSE;
+        $this->testpage = new moodle_page();
+        $this->create_test_tables(array('course', 'context'), 'lib');
+        $this->create_test_table('forum', 'mod/forum');
+        $this->switch_to_test_db();
+
+        $context = new stdClass;
+        $context->contextlevel = CONTEXT_COURSE;
+        $context->instanceid = $SITE->id;
+        $context->path = 'not initialised';
+        $context->depth = '-1';
+        $this->testdb->insert_record('context', $context);
+    }
+
+    public function tearDown() {
+        global $COURSE;
+        $this->testpage = NULL;
+        $COURSE = $this->originalcourse;
+        parent::tearDown();
+    }
+
+    /** Creates an object with all the fields you would expect a $course object to have. */
+    protected function create_a_forum_with_context() {
+        $course = new stdClass;
+        $course->category = 2;
+        $course->fullname = 'Anonymous test course';
+        $course->shortname = 'ANON';
+        $course->summary = '';
+        $course->id = $this->testdb->insert_record('course', $course);
+
+        $forum = new stdClass;
+        $forum->course = $course->id;
+        $forum->name = 'Anonymouse test forum';
+        $forum->intro = '';
+        $forum->id = $this->testdb->insert_record('forum', $forum);
+
+        $cm = new stdClass;
+        $cm->id = -1;
+        $cm->course = $course->id;
+        $cm->instance = $forum->id;
+        $cm->modname = 'forum';
+        $cm->name = $forum->name;
+
+        $context = new stdClass;
+        $context->contextlevel = CONTEXT_MODULE;
+        $context->instanceid = $cm->id;
+        $context->path = 'not initialised';
+        $context->depth = '-1';
+        $this->testdb->insert_record('context', $context);
+
+        return array($cm, $course, $forum);
+    }
+
+    public function test_cm_null_initially() {
+        // Validate
+        $this->assertNull($this->testpage->cm);
+    }
+
+    public function test_set_cm() {
+        // Setup fixture
+        list($cm) = $this->create_a_forum_with_context();
+        // Exercise SUT
+        $this->testpage->set_cm($cm);
+        // Validate
+        $this->assert(new CheckSpecifiedFieldsExpectation($cm), $this->testpage->cm);
+    }
+
+    public function test_cannot_set_cm_without_name() {
+        // Setup fixture
+        list($cm) = $this->create_a_forum_with_context();
+        // Set expectation
+        $this->expectException();
+        // Exercise SUT
+        unset($cm->name);
+        $this->testpage->set_cm($cm);
+    }
+
+    public function test_cannot_set_cm_without_modname() {
+        // Setup fixture
+        list($cm) = $this->create_a_forum_with_context();
+        // Set expectation
+        $this->expectException();
+        // Exercise SUT
+        unset($cm->modname);
+        $this->testpage->set_cm($cm);
+    }
+
+    public function test_cannot_set_activity_record_before_cm() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        // Set expectation
+        $this->expectException();
+        // Exercise SUT
+        $this->testpage->set_activity_record($forum);
+    }
+
+    public function test_setting_cm_sets_context() {
+        // Setup fixture
+        list($cm) = $this->create_a_forum_with_context();
+        // Exercise SUT
+        $this->testpage->set_cm($cm);
+        // Validate
+        $expectedcontext = new stdClass;
+        $expectedcontext->contextlevel = CONTEXT_MODULE;
+        $expectedcontext->instanceid = $cm->id;
+        $this->assert(new CheckSpecifiedFieldsExpectation($expectedcontext), $this->testpage->context);
+    }
+
+    public function test_activity_record_loaded_if_not_set() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        // Exercise SUT
+        $this->testpage->set_cm($cm);
+        // Validate
+        $this->assert(new CheckSpecifiedFieldsExpectation($forum), $this->testpage->activityrecord);
+    }
+
+    public function test_set_activity_record() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        $this->testpage->set_cm($cm);
+        // Exercise SUT
+        $this->testpage->set_activity_record($forum);
+        // Validate
+        $this->assert(new CheckSpecifiedFieldsExpectation($forum), $this->testpage->activityrecord);
+    }
+
+    public function test_cannot_set_inconsistent_activity_record_course() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        $this->testpage->set_cm($cm);
+        // Set expectation
+        $this->expectException();
+        // Exercise SUT
+        $forum->course = -1;
+        $this->testpage->set_activity_record($forum);
+    }
+
+    public function test_cannot_set_inconsistent_activity_record_instance() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        $this->testpage->set_cm($cm);
+        // Set expectation
+        $this->expectException();
+        // Exercise SUT
+        $forum->id = -1;
+        $this->testpage->set_activity_record($forum);
+    }
+
+    public function test_settin_cm_sets_course() {
+        // Setup fixture
+        list($cm, $course) = $this->create_a_forum_with_context();
+        // Exercise SUT
+        $this->testpage->set_cm($cm);
+        // Validate
+        $this->assert(new CheckSpecifiedFieldsExpectation($course), $this->testpage->course);
+    }
+
+    public function test_set_cm_with_course_and_activity_no_db() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        $this->drop_test_table('forum');
+        $this->drop_test_table('course');
+        // Exercise SUT
+        $this->testpage->set_cm($cm, $course, $forum);
+        // Validate
+        $this->assert(new CheckSpecifiedFieldsExpectation($cm), $this->testpage->cm);
+        $this->assert(new CheckSpecifiedFieldsExpectation($course), $this->testpage->course);
+        $this->assert(new CheckSpecifiedFieldsExpectation($forum), $this->testpage->activityrecord);
+    }
+
+    public function test_cannot_set_cm_with_inconsistent_course() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        // Set expectation
+        $this->expectException();
+        // Exercise SUT
+        $cm->course = -1;
+        $this->testpage->set_cm($cm, $course);
+    }
+
+    public function test_get_activity_name() {
+        // Setup fixture
+        list($cm, $course, $forum) = $this->create_a_forum_with_context();
+        // Exercise SUT
+        $this->testpage->set_cm($cm, $course, $forum);
+        // Validate
+        $this->assertEqual('forum', $this->testpage->activityname);
+    }
+}
+
 /**
  * Test functions that affect filter_active table with contextid = $syscontextid.
  */