]> git.mjollnir.org Git - moodle.git/commitdiff
moodle_page: MDL-12212 ->category and ->categories
authortjhunt <tjhunt>
Wed, 6 May 2009 08:46:05 +0000 (08:46 +0000)
committertjhunt <tjhunt>
Wed, 6 May 2009 08:46:05 +0000 (08:46 +0000)
admin/roles/assign.php
course/category.php
lib/moodlelib.php
lib/pagelib.php
lib/simpletest/testpagelib_moodlepage.php

index b7ada55b3daa937fbfb30198559b64d1565a1aa7..daa5d260f552a8da5ea760988e6ca8b7db4f9115 100755 (executable)
@@ -57,6 +57,7 @@
         print_error('wrongcontextid', 'error');
     }
     $isfrontpage = $context->contextlevel == CONTEXT_COURSE && $context->instanceid == SITEID;
+    $PAGE->set_context($context);
     $contextname = print_context_name($context);
 
     $inmeta = 0;
index 7129a805b7e1ba94160a4543b44eb4a523829f19..73f88ccbe5202f7a662463f603eaab7228b326ae 100644 (file)
         print_error("unknowcategory");
     }
 
-    if (!$context = get_context_instance(CONTEXT_COURSECAT, $id)) {
-        print_error("unknowcategory");
-    }
+    $PAGE->set_category_by_id($id);
+    $context = $PAGE->context;
+    $category = $PAGE->category;
 
-    if (!$category = $DB->get_record("course_categories", array("id"=>$id))) {
-        print_error("unknowcategory");
-    }
     if (!$category->visible) {
         require_capability('moodle/category:viewhiddencategories', $context);
     }
index 4c819c1d28827b51ca393988e3efae64c475e173..532ef40b620a78f3f6b84b92ad9b28058a31e00d 100644 (file)
@@ -1914,7 +1914,7 @@ function get_login_url($loginguest=false) {
  *             in order to keep redirects working properly. MDL-14495
  */
 function require_login($courseorid=0, $autologinguest=true, $cm=null, $setwantsurltome=true) {
-    global $CFG, $SESSION, $USER, $COURSE, $FULLME, $PAGE, $DB;
+    global $CFG, $SESSION, $USER, $COURSE, $FULLME, $PAGE, $SITE, $DB;
 
 /// setup global $COURSE, themes, language and locale
     if (!empty($courseorid)) {
index e511ec0d490b57dbff426044760a7a1438748e79..4995bb326044998b55180464bf1e39072d4267db 100644 (file)
@@ -56,6 +56,17 @@ class moodle_page {
 
     protected $_context = null;
 
+    /**
+     * This holds any categories that $_course belongs to, starting with the
+     * particular category it belongs to, and working out through any parent
+     * categories to the top level. These are loaded progressively, if neaded.
+     * There are three states. $_categories = null initially when nothing is
+     * loaded; $_categories = array($id => $cat, $parentid => null) when we have
+     * loaded $_course->category, but not any parents; and a complete array once
+     * everything is loaded.
+     */
+    protected $_categories = null;
+
     protected $_bodyclasses = array();
 
     protected $_pagetype = null;
@@ -98,6 +109,30 @@ class moodle_page {
         return $this->_course;
     }
 
+    /**
+     * @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.
+     */
+    public function get_category() {
+        $this->ensure_category_loaded();
+        if (!empty($this->_categories)) {
+            return reset($this->_categories);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @return array an array of all the categories the page course belongs to,
+     * starting with the immediately containing category, and working out to
+     * the top-level category. This may be the empty array if we are in the
+     * front page course.
+     */
+    public function get_categories() {
+        $this->ensure_categories_loaded();
+        return $this->_categories;
+    }
+
     /**
      * @return object the main context to which this page belongs.
      */
@@ -175,7 +210,7 @@ class moodle_page {
      * @param object the course to set as the global course.
      */
     public function set_course($course) {
-        global $COURSE, $SITE;
+        global $COURSE;
 
         if (empty($course->id)) {
             throw new coding_exception('$course passed to moodle_page::set_course does not look like a proper course object.');
@@ -192,6 +227,8 @@ class moodle_page {
             $this->set_context(get_context_instance(CONTEXT_COURSE, $this->_course->id));
         }
 
+        $this->_categories = null;
+
         moodle_setlocale();
         theme_setup();
     }
@@ -235,6 +272,27 @@ class moodle_page {
         }
     }
 
+    /**
+     * Set the course category this page belongs to manually. This automatically
+     * sets $PAGE->course to be the site coures. You cannot use this method if
+     * you have already set $PAGE->course - in that case, the category must be
+     * the one that the course belongs to. This also automatically sets the
+     * page context to the category context.
+     * @param integer $categoryid The id of the category to set.
+     */
+    public function set_category_by_id($categoryid) {
+        global $SITE, $DB;
+        if (!is_null($this->_course)) {
+            throw new coding_exception('Attempt to manually set the course category when the course has been set. This is not allowed.');
+        }
+        if (is_array($this->_categories)) {
+            throw new coding_exception('Course category has already been set. You are not allowed to change it.');
+        }
+        $this->set_course($SITE);
+        $this->load_category($categoryid);
+        $this->set_context(get_context_instance(CONTEXT_COURSECAT, $categoryid));
+    }
+
 /// Initialisation methods =====================================================
 /// These set various things up in a default way.
 
@@ -309,6 +367,48 @@ class moodle_page {
         }
     }
 
+    protected function ensure_category_loaded() {
+        if (is_array($this->_categories)) {
+            return; // Already done.
+        }
+        if (is_null($this->_course)) {
+            throw new coding_exception('Attempt to get the course category for this page before the course was set.');
+        }
+        if ($this->_course->category == 0) {
+            $this->_categories = array();
+        } else {
+            $this->load_category($this->_course->category);
+        }
+    }
+
+    protected function load_category($categoryid) {
+        global $DB;
+        $category = $DB->get_record('course_categories', array('id' => $categoryid));
+        if (!$category) {
+            throw new moodle_exception('unknowncategory');
+        }
+        $this->_categories[$category->id] = $category;
+        $parentcategoryids = explode('/', trim($category->path, '/'));
+        array_pop($parentcategoryids);
+        foreach (array_reverse($parentcategoryids) as $catid) {
+            $this->_categories[$catid] = null;
+        }
+    }
+
+    protected function ensure_categories_loaded() {
+        global $DB;
+        $this->ensure_category_loaded();
+        if (!is_null(end($this->_categories))) {
+            return; // Already done.
+        }
+        $idstoload = array_keys($this->_categories);
+        array_shift($idstoload);
+        $categories = $DB->get_records_list('course_categories', 'id', $idstoload);
+        foreach ($idstoload as $catid) {
+            $this->_categories[$catid] = $categories[$catid];
+        }
+    }
+
     protected function url_to_class_name($url) {
         $bits = parse_url($url);
         $class = str_replace('.', '-', $bits['host']);
index 623c6f521ccb259bb4ed57034c3f7cec9e622d88..cc798a0362a691f99d1927c8640a4d0a1d31d240 100644 (file)
@@ -124,6 +124,26 @@ class moodle_page_test extends UnitTestCase {
         $this->testpage->set_course($course);
     }
 
+    public function test_cannot_set_category_once_output_started() {
+        // Setup fixture
+        $this->testpage->set_state(moodle_page::STATE_PRINTING_HEADER);
+        // Set expectation.
+        $this->expectException();
+        // Exercise SUT
+        $this->testpage->set_category_by_id(123);
+    }
+
+    public function test_cannot_set_category_once_course_set() {
+        // Setup fixture
+        $course = $this->create_a_course();
+        $this->testpage->set_context(new stdClass); // Avoid trying to set the context.
+        $this->testpage->set_course($course);
+        // Set expectation.
+        $this->expectException();
+        // Exercise SUT
+        $this->testpage->set_category_by_id(123);
+    }
+
     public function test_set_state_normal_path() {
         $this->assertEqual(moodle_page::STATE_BEFORE_HEADER, $this->testpage->state);
 
@@ -230,14 +250,15 @@ class moodle_page_test extends UnitTestCase {
 }
 
 /**
- * Test functions that affect filter_active table with contextid = $syscontextid.
+ * Test functions that rely on the context table.
  */
-class moodle_page_with_db_test extends UnitTestCaseUsingDatabase {
+class moodle_page_with_context_table_test extends UnitTestCaseUsingDatabase {
     protected $testpage;
     protected $originalcourse;
 
     public function setUp() {
         global $COURSE;
+        parent::setUp();
         $this->originalcourse = $COURSE;
         $this->testpage = new moodle_page();
         $this->create_test_table('context', 'lib');
@@ -248,6 +269,7 @@ class moodle_page_with_db_test extends UnitTestCaseUsingDatabase {
         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. */
@@ -281,4 +303,90 @@ class moodle_page_with_db_test extends UnitTestCaseUsingDatabase {
         $this->assert(new CheckSpecifiedFieldsExpectation($expectedcontext), $this->testpage->context);
     }
 }
+
+/**
+ * Test functions that rely on the context table.
+ */
+class moodle_page_categories_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_categories', 'context'), 'lib');
+        $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_category_with_context($parentid = 0) {
+        if ($parentid) {
+            $parent = $this->testdb->get_record('course_categories', array('id' => $parentid));
+        } else {
+            $parent = new stdClass;
+            $parent->depth = 0;
+            $parent->path = '';
+        }
+        $cat = new stdClass;
+        $cat->name = 'Anonymous test category';
+        $cat->description = '';
+        $cat->parent = $parentid;
+        $cat->depth = $parent->depth + 1;
+        $cat->id = $this->testdb->insert_record('course_categories', $cat);
+        $cat->path = $parent->path . '/' . $cat->id;
+        $this->testdb->set_field('course_categories', 'path', $cat->path, array('id' => $cat->id));
+
+        $context = new stdClass;
+        $context->contextlevel = CONTEXT_COURSECAT;
+        $context->instanceid = $cat->id;
+        $context->path = 'not initialised';
+        $context->depth = '-1';
+        $this->testdb->insert_record('context', $context);
+
+        return $cat;
+    }
+
+    public function test_set_category_top_level() {
+        // Setup fixture
+        $cat = $this->create_a_category_with_context();
+        // Exercise SUT
+        $this->testpage->set_category_by_id($cat->id);
+        // Validate
+        $this->assert(new CheckSpecifiedFieldsExpectation($cat), $this->testpage->category);
+        $expectedcontext = new stdClass; // Test it sets the context.
+        $expectedcontext->contextlevel = CONTEXT_COURSECAT;
+        $expectedcontext->instanceid = $cat->id;
+        $this->assert(new CheckSpecifiedFieldsExpectation($expectedcontext), $this->testpage->context);
+    }
+
+    public function test_set_nested_categories() {
+        // Setup fixture
+        $topcat = $this->create_a_category_with_context();
+        $subcat = $this->create_a_category_with_context($topcat->id);
+        // Exercise SUT
+        $this->testpage->set_category_by_id($subcat->id);
+        // Validate
+        $categories = $this->testpage->categories;
+        $this->assertEqual(2, count($categories));
+        $this->assert(new CheckSpecifiedFieldsExpectation($topcat), array_pop($categories));
+        $this->assert(new CheckSpecifiedFieldsExpectation($subcat), array_pop($categories));
+    }
+}
+
 ?>