dirroot.'/webservice/lib.php'); class webservicehelper { /** @var \context_system */ private static $systemcontext = null; private static $validated_contexts = []; /** * Test for capability in the given context for the current user and throw a \webservice_access_exception if not * Note: The context is not validate * @param array|string $capability One or more capabilities to be tested OR wise (if one capability is given, the function passes) * @param \context $context The context in which to check for the capability. * @throws \webservice_access_exception If none of the capabilities provided are given to the current user * @return boolean */ public static function has_capabilities($capability,$context){ if($context == null){ $context = \context_system::instance(); } if(is_array($capability)){ //TODO: replace this by accesslib function \has_any_capability() foreach($capability as $cap){ if(has_capability($cap,$context)){ return true; } } } elseif(has_capability($capability,$context)){ return true; } } /** * Test if the current user has a certain capability in any of the categories they have access to * @param string $capability The capability to scan for in the categories * @param \core_course_category $parent The parent category to use as a scanning base. Used in recursing Leave empty if calling this function * @return boolean */ public static function has_capability_in_any_category($capability,\core_course_category $parent=null){ // List the categories in which the user has a specific capability $list = []; // initialize parent if needed if($parent == null){ $parent = \core_course_category::user_top(); if(has_capability($capability,$parent->get_context())){ $list[] = $parent; } } $children = $parent->get_children(); // Since the change for a category permission is greatest at the lower levels, // we scan in two stages, to focus the search more on the lower levels instead of diving deep into the first category // Stage one (surface check): check all children for the capability foreach($children as $child){ // Check if we should add this category if(has_capability($capability,$child->get_context())){ return true; } } // Stage two (deep dive): recurse into the child categories foreach($children as $child){ if($child->get_children_count() > 0){ if(self::has_capability_in_any_category($capability,$child)){ return true; } } } return false; } /** * Test for capability in the given context for the current user and throw a \webservice_access_exception if not * @param array|string $capability One or more capabilities to be tested OR wise (if one capability is given, the function passes) * @param \context $context The context in which to check for the capability. Leave empty to use the system context. * @param bool $validate Validate the context before checking capabilities * @throws \webservice_access_exception If none of the capabilities provided are given to the current user */ public static function require_capabilities($capability,$context=null,$validate=true){ if($validate) { \external_api::validate_context($context); } if(! static::has_capabilities($capability,$context)){ throw new \webservice_access_exception("The capability {$capability} is required on this context ({$context->get_context_name()})"); } } /** * Find and validate a given context by id * @param int $contextid The id of the context * @return \context The found context by id * @throws \InvalidArgumentException When the context is not found */ public static function find_context($contextid): \context{ if(isset($contextid) && is_int($contextid) && $contextid > 0){ if(!in_array($contextid,self::$validated_contexts)){ // Cache the context and make sure it is only validated once... try{ $context = \context::instance_by_id($contextid); } catch(\dml_missing_record_exception $x){ throw new \InvalidArgumentException("Context {$contextid} not available"); // Just throw it up again. catch is included here to make sure we know it throws this exception } // Validate the found context \external_api::validate_context($context); self::$validated_contexts[$contextid] = $context; } return self::$validated_contexts[$contextid]; } else{ return static::system_context(); // This function ensures the system context is validated just once this call } } /** * Return the validated system context (validation happens only once for this call) * @return \context_system The system context, validated to use as this context */ public static function system_context(): \context_system { if(!isset(static::$systemcontext)){ static::$systemcontext = \context_system::instance(); \external_api::validate_context(static::$systemcontext); } return static::$systemcontext; } }