diff --git a/lib/accesslib.php b/lib/accesslib.php index 21ba4b40753..cc685fffc08 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -4426,237 +4426,6 @@ function role_change_permission($roleid, $context, $capname, $permission) { } -/** - * Context maintenance and helper methods. - * - * This is "extends context" is a bloody hack that tires to work around the deficiencies - * in the "protected" keyword in PHP, this helps us to hide all the internals of context - * level implementation from the rest of code, the code completion returns what developers need. - * - * Thank you Tim Hunt for helping me with this nasty trick. - * - * @author Petr Skoda - */ -class context_helper extends context { - - private static $alllevels = array( - CONTEXT_SYSTEM => 'context_system', - CONTEXT_USER => 'context_user', - CONTEXT_COURSECAT => 'context_coursecat', - CONTEXT_COURSE => 'context_course', - CONTEXT_MODULE => 'context_module', - CONTEXT_BLOCK => 'context_block', - ); - - /** - * Instance does not make sense here, only static use - */ - protected function __construct() { - } - - /** - * Returns a class name of the context level class - * - * @static - * @param int $contextlevel (CONTEXT_SYSTEM, etc.) - * @return string class name of the context class - */ - public static function get_class_for_level($contextlevel) { - if (isset(self::$alllevels[$contextlevel])) { - return self::$alllevels[$contextlevel]; - } else { - throw new coding_exception('Invalid context level specified'); - } - } - - /** - * Returns a list of all context levels - * - * @static - * @return array int=>string (level=>level class name) - */ - public static function get_all_levels() { - return self::$alllevels; - } - - /** - * Remove stale contexts that belonged to deleted instances. - * Ideally all code should cleanup contexts properly, unfortunately accidents happen... - * - * @static - * @return void - */ - public static function cleanup_instances() { - global $DB; - $sqls = array(); - foreach (self::$alllevels as $level=>$classname) { - $sqls[] = $classname::get_cleanup_sql(); - } - - $sql = implode(" UNION ", $sqls); - - // it is probably better to use transactions, it might be faster too - $transaction = $DB->start_delegated_transaction(); - - $rs = $DB->get_recordset_sql($sql); - foreach ($rs as $record) { - $context = context::create_instance_from_record($record); - $context->delete(); - } - $rs->close(); - - $transaction->allow_commit(); - } - - /** - * Create all context instances at the given level and above. - * - * @static - * @param int $contextlevel null means all levels - * @param bool $buildpaths - * @return void - */ - public static function create_instances($contextlevel = null, $buildpaths = true) { - foreach (self::$alllevels as $level=>$classname) { - if ($contextlevel and $level > $contextlevel) { - // skip potential sub-contexts - continue; - } - $classname::create_level_instances(); - if ($buildpaths) { - $classname::build_paths(false); - } - } - } - - /** - * Rebuild paths and depths in all context levels. - * - * @static - * @param bool $force false means add missing only - * @return void - */ - public static function build_all_paths($force = false) { - foreach (self::$alllevels as $classname) { - $classname::build_paths($force); - } - - // reset static course cache - it might have incorrect cached data - accesslib_clear_all_caches(true); - } - - /** - * Resets the cache to remove all data. - * @static - */ - public static function reset_caches() { - context::reset_caches(); - } - - /** - * Returns all fields necessary for context preloading from user $rec. - * - * This helps with performance when dealing with hundreds of contexts. - * - * @static - * @param string $tablealias context table alias in the query - * @return array (table.column=>alias, ...) - */ - public static function get_preload_record_columns($tablealias) { - return array("$tablealias.id"=>"ctxid", "$tablealias.path"=>"ctxpath", "$tablealias.depth"=>"ctxdepth", "$tablealias.contextlevel"=>"ctxlevel", "$tablealias.instanceid"=>"ctxinstance"); - } - - /** - * Returns all fields necessary for context preloading from user $rec. - * - * This helps with performance when dealing with hundreds of contexts. - * - * @static - * @param string $tablealias context table alias in the query - * @return string - */ - public static function get_preload_record_columns_sql($tablealias) { - return "$tablealias.id AS ctxid, $tablealias.path AS ctxpath, $tablealias.depth AS ctxdepth, $tablealias.contextlevel AS ctxlevel, $tablealias.instanceid AS ctxinstance"; - } - - /** - * Preloads context information from db record and strips the cached info. - * - * The db request has to contain all columns from context_helper::get_preload_record_columns(). - * - * @static - * @param stdClass $rec - * @return void (modifies $rec) - */ - public static function preload_from_record(stdClass $rec) { - context::preload_from_record($rec); - } - - /** - * Preload all contexts instances from course. - * - * To be used if you expect multiple queries for course activities... - * - * @static - * @param $courseid - */ - public static function preload_course($courseid) { - // Users can call this multiple times without doing any harm - if (isset(context::$cache_preloaded[$courseid])) { - return; - } - $coursecontext = context_course::instance($courseid); - $coursecontext->get_child_contexts(); - - context::$cache_preloaded[$courseid] = true; - } - - /** - * Delete context instance - * - * @static - * @param int $contextlevel - * @param int $instanceid - * @return void - */ - public static function delete_instance($contextlevel, $instanceid) { - global $DB; - - // double check the context still exists - if ($record = $DB->get_record('context', array('contextlevel'=>$contextlevel, 'instanceid'=>$instanceid))) { - $context = context::create_instance_from_record($record); - $context->delete(); - } else { - // we should try to purge the cache anyway - } - } - - /** - * Returns the name of specified context level - * - * @static - * @param int $contextlevel - * @return string name of the context level - */ - public static function get_level_name($contextlevel) { - $classname = context_helper::get_class_for_level($contextlevel); - return $classname::get_level_name(); - } - - /** - * not used - */ - public function get_url() { - } - - /** - * not used - */ - public function get_capabilities() { - } -} - - /** * Basic moodle context abstraction class. * @@ -5393,6 +5162,237 @@ abstract class context extends stdClass { } +/** + * Context maintenance and helper methods. + * + * This is "extends context" is a bloody hack that tires to work around the deficiencies + * in the "protected" keyword in PHP, this helps us to hide all the internals of context + * level implementation from the rest of code, the code completion returns what developers need. + * + * Thank you Tim Hunt for helping me with this nasty trick. + * + * @author Petr Skoda + */ +class context_helper extends context { + + private static $alllevels = array( + CONTEXT_SYSTEM => 'context_system', + CONTEXT_USER => 'context_user', + CONTEXT_COURSECAT => 'context_coursecat', + CONTEXT_COURSE => 'context_course', + CONTEXT_MODULE => 'context_module', + CONTEXT_BLOCK => 'context_block', + ); + + /** + * Instance does not make sense here, only static use + */ + protected function __construct() { + } + + /** + * Returns a class name of the context level class + * + * @static + * @param int $contextlevel (CONTEXT_SYSTEM, etc.) + * @return string class name of the context class + */ + public static function get_class_for_level($contextlevel) { + if (isset(self::$alllevels[$contextlevel])) { + return self::$alllevels[$contextlevel]; + } else { + throw new coding_exception('Invalid context level specified'); + } + } + + /** + * Returns a list of all context levels + * + * @static + * @return array int=>string (level=>level class name) + */ + public static function get_all_levels() { + return self::$alllevels; + } + + /** + * Remove stale contexts that belonged to deleted instances. + * Ideally all code should cleanup contexts properly, unfortunately accidents happen... + * + * @static + * @return void + */ + public static function cleanup_instances() { + global $DB; + $sqls = array(); + foreach (self::$alllevels as $level=>$classname) { + $sqls[] = $classname::get_cleanup_sql(); + } + + $sql = implode(" UNION ", $sqls); + + // it is probably better to use transactions, it might be faster too + $transaction = $DB->start_delegated_transaction(); + + $rs = $DB->get_recordset_sql($sql); + foreach ($rs as $record) { + $context = context::create_instance_from_record($record); + $context->delete(); + } + $rs->close(); + + $transaction->allow_commit(); + } + + /** + * Create all context instances at the given level and above. + * + * @static + * @param int $contextlevel null means all levels + * @param bool $buildpaths + * @return void + */ + public static function create_instances($contextlevel = null, $buildpaths = true) { + foreach (self::$alllevels as $level=>$classname) { + if ($contextlevel and $level > $contextlevel) { + // skip potential sub-contexts + continue; + } + $classname::create_level_instances(); + if ($buildpaths) { + $classname::build_paths(false); + } + } + } + + /** + * Rebuild paths and depths in all context levels. + * + * @static + * @param bool $force false means add missing only + * @return void + */ + public static function build_all_paths($force = false) { + foreach (self::$alllevels as $classname) { + $classname::build_paths($force); + } + + // reset static course cache - it might have incorrect cached data + accesslib_clear_all_caches(true); + } + + /** + * Resets the cache to remove all data. + * @static + */ + public static function reset_caches() { + context::reset_caches(); + } + + /** + * Returns all fields necessary for context preloading from user $rec. + * + * This helps with performance when dealing with hundreds of contexts. + * + * @static + * @param string $tablealias context table alias in the query + * @return array (table.column=>alias, ...) + */ + public static function get_preload_record_columns($tablealias) { + return array("$tablealias.id"=>"ctxid", "$tablealias.path"=>"ctxpath", "$tablealias.depth"=>"ctxdepth", "$tablealias.contextlevel"=>"ctxlevel", "$tablealias.instanceid"=>"ctxinstance"); + } + + /** + * Returns all fields necessary for context preloading from user $rec. + * + * This helps with performance when dealing with hundreds of contexts. + * + * @static + * @param string $tablealias context table alias in the query + * @return string + */ + public static function get_preload_record_columns_sql($tablealias) { + return "$tablealias.id AS ctxid, $tablealias.path AS ctxpath, $tablealias.depth AS ctxdepth, $tablealias.contextlevel AS ctxlevel, $tablealias.instanceid AS ctxinstance"; + } + + /** + * Preloads context information from db record and strips the cached info. + * + * The db request has to contain all columns from context_helper::get_preload_record_columns(). + * + * @static + * @param stdClass $rec + * @return void (modifies $rec) + */ + public static function preload_from_record(stdClass $rec) { + context::preload_from_record($rec); + } + + /** + * Preload all contexts instances from course. + * + * To be used if you expect multiple queries for course activities... + * + * @static + * @param $courseid + */ + public static function preload_course($courseid) { + // Users can call this multiple times without doing any harm + if (isset(context::$cache_preloaded[$courseid])) { + return; + } + $coursecontext = context_course::instance($courseid); + $coursecontext->get_child_contexts(); + + context::$cache_preloaded[$courseid] = true; + } + + /** + * Delete context instance + * + * @static + * @param int $contextlevel + * @param int $instanceid + * @return void + */ + public static function delete_instance($contextlevel, $instanceid) { + global $DB; + + // double check the context still exists + if ($record = $DB->get_record('context', array('contextlevel'=>$contextlevel, 'instanceid'=>$instanceid))) { + $context = context::create_instance_from_record($record); + $context->delete(); + } else { + // we should try to purge the cache anyway + } + } + + /** + * Returns the name of specified context level + * + * @static + * @param int $contextlevel + * @return string name of the context level + */ + public static function get_level_name($contextlevel) { + $classname = context_helper::get_class_for_level($contextlevel); + return $classname::get_level_name(); + } + + /** + * not used + */ + public function get_url() { + } + + /** + * not used + */ + public function get_capabilities() { + } +} + + /** * Basic context class * @author Petr Skoda (http://skodak.org)