2023-05-17 21:19:14 +02:00
< ? php
2023-08-24 23:02:41 +02:00
// This file is part of the Studyplan plugin for Moodle
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
/**
*
* @ package local_treestudyplan
* @ copyright 2023 P . M . Kuipers
* @ license https :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
2023-05-17 21:19:14 +02:00
namespace local_treestudyplan\local\helpers ;
2023-08-17 23:28:48 +02:00
require_once ( $CFG -> dirroot . '/webservice/lib.php' );
2023-05-17 21:19:14 +02:00
class webservicehelper {
/** @var \context_system */
private static $systemcontext = null ;
2023-08-25 09:33:42 +02:00
private static $validatedcontexts = [];
2023-05-17 21:19:14 +02:00
/**
2023-08-24 23:02:41 +02:00
* Test for capability in the given context for the current user and throw a \webservice_access_exception if not
2023-05-17 21:19:14 +02:00
* 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
2023-08-24 23:02:41 +02:00
* @ return boolean
2023-05-17 21:19:14 +02:00
*/
2023-08-24 23:02:41 +02:00
public static function has_capabilities ( $capability , $context ) {
2023-05-17 21:19:14 +02:00
2023-08-24 23:02:41 +02:00
if ( $context == null ) {
2023-05-17 21:19:14 +02:00
$context = \context_system :: instance ();
}
2023-08-24 23:02:41 +02:00
if ( is_array ( $capability )) {
//TODO: replace this by accesslib function \has_any_capability().
foreach ( $capability as $cap ) {
if ( has_capability ( $cap , $context )) {
2023-05-17 21:19:14 +02:00
return true ;
}
}
2023-08-24 23:09:20 +02:00
} else if ( has_capability ( $capability , $context )) {
2023-05-17 21:19:14 +02:00
return true ;
}
}
2023-08-17 07:51:04 +02:00
/**
* 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
2023-08-24 23:02:41 +02:00
* @ return boolean
2023-08-17 07:51:04 +02:00
*/
2023-08-24 23:02:41 +02:00
public static function has_capability_in_any_category ( $capability , \core_course_category $parent = null ) {
2023-08-17 07:51:04 +02:00
2023-08-24 23:02:41 +02:00
// List the categories in which the user has a specific capability.
2023-08-17 07:51:04 +02:00
$list = [];
2023-08-25 09:44:34 +02:00
// Initialize parent if needed.
2023-08-24 23:02:41 +02:00
if ( $parent == null ) {
2023-08-17 07:51:04 +02:00
$parent = \core_course_category :: user_top ();
2023-08-24 23:02:41 +02:00
if ( has_capability ( $capability , $parent -> get_context ())) {
2023-08-17 07:51:04 +02:00
$list [] = $parent ;
}
}
2023-08-24 23:02:41 +02:00
2023-08-17 07:51:04 +02:00
$children = $parent -> get_children ();
2023-08-24 23:02:41 +02:00
// Since the change for a category permission is greatest at the lower levels,.
2023-08-25 09:44:34 +02:00
// We scan in two stages, to focus the search more on the lower levels instead of diving deep into the first category.
2023-08-24 23:02:41 +02:00
// 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 ())) {
2023-08-17 07:51:04 +02:00
return true ;
2023-08-24 23:02:41 +02:00
}
2023-08-17 23:28:48 +02:00
}
2023-08-24 23:02:41 +02:00
// 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 )) {
2023-08-17 23:28:48 +02:00
return true ;
2023-08-17 07:51:04 +02:00
}
}
}
return false ;
}
2023-05-17 21:19:14 +02:00
/**
2023-08-24 23:02:41 +02:00
* Test for capability in the given context for the current user and throw a \webservice_access_exception if not
2023-05-17 21:19:14 +02:00
* @ 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
*/
2023-08-24 23:02:41 +02:00
public static function require_capabilities ( $capability , $context = null , $validate = true ) {
if ( $validate ) {
\external_api :: validate_context ( $context );
2023-05-17 21:19:14 +02:00
}
2023-08-24 23:02:41 +02:00
if ( ! static :: has_capabilities ( $capability , $context )) {
2023-05-17 21:19:14 +02:00
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 {
2023-08-24 23:02:41 +02:00
if ( isset ( $contextid ) && is_int ( $contextid ) && $contextid > 0 ) {
2023-08-25 09:33:42 +02:00
if ( ! in_array ( $contextid , self :: $validatedcontexts )) { // Cache the context and make sure it is only validated once...
2023-08-24 23:09:20 +02:00
try {
2023-05-17 21:19:14 +02:00
$context = \context :: instance_by_id ( $contextid );
}
2023-08-24 23:02:41 +02:00
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.
2023-05-17 21:19:14 +02:00
}
2023-08-24 23:02:41 +02:00
// Validate the found context.
2023-05-17 21:19:14 +02:00
\external_api :: validate_context ( $context );
2023-08-25 09:33:42 +02:00
self :: $validatedcontexts [ $contextid ] = $context ;
2023-05-17 21:19:14 +02:00
}
2023-08-25 09:33:42 +02:00
return self :: $validatedcontexts [ $contextid ];
2023-08-24 23:09:20 +02:00
} else {
2023-08-24 23:02:41 +02:00
return static :: system_context (); // This function ensures the system context is validated just once this call.
2023-05-17 21:19:14 +02:00
}
}
2023-08-24 23:02:41 +02:00
/**
2023-05-17 21:19:14 +02:00
* 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 {
2023-08-24 23:02:41 +02:00
if ( ! isset ( static :: $systemcontext )) {
2023-05-17 21:19:14 +02:00
static :: $systemcontext = \context_system :: instance ();
\external_api :: validate_context ( static :: $systemcontext );
}
return static :: $systemcontext ;
}
}