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;
/**
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.
$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
if (is_null($this->_pagetype)) {
$this->initialise_default_pagetype($url);
}
+ if (!is_null($this->_legacypageobject)) {
+ $this->_legacypageobject->set_url($url, $params);
+ }
}
/**
}
}
+ 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.
}
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. */
* 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;
}
}
$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);
* @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;
// 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;
}
}
* @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.
* @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;
}
}
+/**
+ * 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.
*/