[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 18 /** 19 * Support for external API 20 * 21 * @package core_webservice 22 * @copyright 2009 Petr Skodak 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * Returns detailed function information 30 * 31 * @param string|object $function name of external function or record from external_function 32 * @param int $strictness IGNORE_MISSING means compatible mode, false returned if record not found, debug message if more found; 33 * MUST_EXIST means throw exception if no record or multiple records found 34 * @return stdClass description or false if not found or exception thrown 35 * @since Moodle 2.0 36 */ 37 function external_function_info($function, $strictness=MUST_EXIST) { 38 global $DB, $CFG; 39 40 if (!is_object($function)) { 41 if (!$function = $DB->get_record('external_functions', array('name'=>$function), '*', $strictness)) { 42 return false; 43 } 44 } 45 46 // First try class autoloading. 47 if (!class_exists($function->classname)) { 48 // Fallback to explicit include of externallib.php. 49 $function->classpath = empty($function->classpath) ? core_component::get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath; 50 if (!file_exists($function->classpath)) { 51 throw new coding_exception('Cannot find file with external function implementation'); 52 } 53 require_once($function->classpath); 54 if (!class_exists($function->classname)) { 55 throw new coding_exception('Cannot find external class'); 56 } 57 } 58 59 $function->parameters_method = $function->methodname.'_parameters'; 60 $function->returns_method = $function->methodname.'_returns'; 61 62 // make sure the implementaion class is ok 63 if (!method_exists($function->classname, $function->methodname)) { 64 throw new coding_exception('Missing implementation method of '.$function->classname.'::'.$function->methodname); 65 } 66 if (!method_exists($function->classname, $function->parameters_method)) { 67 throw new coding_exception('Missing parameters description'); 68 } 69 if (!method_exists($function->classname, $function->returns_method)) { 70 throw new coding_exception('Missing returned values description'); 71 } 72 73 // fetch the parameters description 74 $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method)); 75 if (!($function->parameters_desc instanceof external_function_parameters)) { 76 throw new coding_exception('Invalid parameters description'); 77 } 78 79 // fetch the return values description 80 $function->returns_desc = call_user_func(array($function->classname, $function->returns_method)); 81 // null means void result or result is ignored 82 if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) { 83 throw new coding_exception('Invalid return description'); 84 } 85 86 //now get the function description 87 //TODO MDL-31115 use localised lang pack descriptions, it would be nice to have 88 // easy to understand descriptions in admin UI, 89 // on the other hand this is still a bit in a flux and we need to find some new naming 90 // conventions for these descriptions in lang packs 91 $function->description = null; 92 $servicesfile = core_component::get_component_directory($function->component).'/db/services.php'; 93 if (file_exists($servicesfile)) { 94 $functions = null; 95 include($servicesfile); 96 if (isset($functions[$function->name]['description'])) { 97 $function->description = $functions[$function->name]['description']; 98 } 99 if (isset($functions[$function->name]['testclientpath'])) { 100 $function->testclientpath = $functions[$function->name]['testclientpath']; 101 } 102 } 103 104 return $function; 105 } 106 107 /** 108 * Exception indicating user is not allowed to use external function in the current context. 109 * 110 * @package core_webservice 111 * @copyright 2009 Petr Skodak 112 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 113 * @since Moodle 2.0 114 */ 115 class restricted_context_exception extends moodle_exception { 116 /** 117 * Constructor 118 * 119 * @since Moodle 2.0 120 */ 121 function __construct() { 122 parent::__construct('restrictedcontextexception', 'error'); 123 } 124 } 125 126 /** 127 * Base class for external api methods. 128 * 129 * @package core_webservice 130 * @copyright 2009 Petr Skodak 131 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 132 * @since Moodle 2.0 133 */ 134 class external_api { 135 136 /** @var stdClass context where the function calls will be restricted */ 137 private static $contextrestriction; 138 139 /** 140 * Set context restriction for all following subsequent function calls. 141 * 142 * @param stdClass $context the context restriction 143 * @since Moodle 2.0 144 */ 145 public static function set_context_restriction($context) { 146 self::$contextrestriction = $context; 147 } 148 149 /** 150 * This method has to be called before every operation 151 * that takes a longer time to finish! 152 * 153 * @param int $seconds max expected time the next operation needs 154 * @since Moodle 2.0 155 */ 156 public static function set_timeout($seconds=360) { 157 $seconds = ($seconds < 300) ? 300 : $seconds; 158 core_php_time_limit::raise($seconds); 159 } 160 161 /** 162 * Validates submitted function parameters, if anything is incorrect 163 * invalid_parameter_exception is thrown. 164 * This is a simple recursive method which is intended to be called from 165 * each implementation method of external API. 166 * 167 * @param external_description $description description of parameters 168 * @param mixed $params the actual parameters 169 * @return mixed params with added defaults for optional items, invalid_parameters_exception thrown if any problem found 170 * @since Moodle 2.0 171 */ 172 public static function validate_parameters(external_description $description, $params) { 173 if ($description instanceof external_value) { 174 if (is_array($params) or is_object($params)) { 175 throw new invalid_parameter_exception('Scalar type expected, array or object received.'); 176 } 177 178 if ($description->type == PARAM_BOOL) { 179 // special case for PARAM_BOOL - we want true/false instead of the usual 1/0 - we can not be too strict here ;-) 180 if (is_bool($params) or $params === 0 or $params === 1 or $params === '0' or $params === '1') { 181 return (bool)$params; 182 } 183 } 184 $debuginfo = 'Invalid external api parameter: the value is "' . $params . 185 '", the server was expecting "' . $description->type . '" type'; 186 return validate_param($params, $description->type, $description->allownull, $debuginfo); 187 188 } else if ($description instanceof external_single_structure) { 189 if (!is_array($params)) { 190 throw new invalid_parameter_exception('Only arrays accepted. The bad value is: \'' 191 . print_r($params, true) . '\''); 192 } 193 $result = array(); 194 foreach ($description->keys as $key=>$subdesc) { 195 if (!array_key_exists($key, $params)) { 196 if ($subdesc->required == VALUE_REQUIRED) { 197 throw new invalid_parameter_exception('Missing required key in single structure: '. $key); 198 } 199 if ($subdesc->required == VALUE_DEFAULT) { 200 try { 201 $result[$key] = self::validate_parameters($subdesc, $subdesc->default); 202 } catch (invalid_parameter_exception $e) { 203 //we are only interested by exceptions returned by validate_param() and validate_parameters() 204 //(in order to build the path to the faulty attribut) 205 throw new invalid_parameter_exception($key." => ".$e->getMessage() . ': ' .$e->debuginfo); 206 } 207 } 208 } else { 209 try { 210 $result[$key] = self::validate_parameters($subdesc, $params[$key]); 211 } catch (invalid_parameter_exception $e) { 212 //we are only interested by exceptions returned by validate_param() and validate_parameters() 213 //(in order to build the path to the faulty attribut) 214 throw new invalid_parameter_exception($key." => ".$e->getMessage() . ': ' .$e->debuginfo); 215 } 216 } 217 unset($params[$key]); 218 } 219 if (!empty($params)) { 220 throw new invalid_parameter_exception('Unexpected keys (' . implode(', ', array_keys($params)) . ') detected in parameter array.'); 221 } 222 return $result; 223 224 } else if ($description instanceof external_multiple_structure) { 225 if (!is_array($params)) { 226 throw new invalid_parameter_exception('Only arrays accepted. The bad value is: \'' 227 . print_r($params, true) . '\''); 228 } 229 $result = array(); 230 foreach ($params as $param) { 231 $result[] = self::validate_parameters($description->content, $param); 232 } 233 return $result; 234 235 } else { 236 throw new invalid_parameter_exception('Invalid external api description'); 237 } 238 } 239 240 /** 241 * Clean response 242 * If a response attribute is unknown from the description, we just ignore the attribute. 243 * If a response attribute is incorrect, invalid_response_exception is thrown. 244 * Note: this function is similar to validate parameters, however it is distinct because 245 * parameters validation must be distinct from cleaning return values. 246 * 247 * @param external_description $description description of the return values 248 * @param mixed $response the actual response 249 * @return mixed response with added defaults for optional items, invalid_response_exception thrown if any problem found 250 * @author 2010 Jerome Mouneyrac 251 * @since Moodle 2.0 252 */ 253 public static function clean_returnvalue(external_description $description, $response) { 254 if ($description instanceof external_value) { 255 if (is_array($response) or is_object($response)) { 256 throw new invalid_response_exception('Scalar type expected, array or object received.'); 257 } 258 259 if ($description->type == PARAM_BOOL) { 260 // special case for PARAM_BOOL - we want true/false instead of the usual 1/0 - we can not be too strict here ;-) 261 if (is_bool($response) or $response === 0 or $response === 1 or $response === '0' or $response === '1') { 262 return (bool)$response; 263 } 264 } 265 $debuginfo = 'Invalid external api response: the value is "' . $response . 266 '", the server was expecting "' . $description->type . '" type'; 267 try { 268 return validate_param($response, $description->type, $description->allownull, $debuginfo); 269 } catch (invalid_parameter_exception $e) { 270 //proper exception name, to be recursively catched to build the path to the faulty attribut 271 throw new invalid_response_exception($e->debuginfo); 272 } 273 274 } else if ($description instanceof external_single_structure) { 275 if (!is_array($response) && !is_object($response)) { 276 throw new invalid_response_exception('Only arrays/objects accepted. The bad value is: \'' . 277 print_r($response, true) . '\''); 278 } 279 280 // Cast objects into arrays. 281 if (is_object($response)) { 282 $response = (array) $response; 283 } 284 285 $result = array(); 286 foreach ($description->keys as $key=>$subdesc) { 287 if (!array_key_exists($key, $response)) { 288 if ($subdesc->required == VALUE_REQUIRED) { 289 throw new invalid_response_exception('Error in response - Missing following required key in a single structure: ' . $key); 290 } 291 if ($subdesc instanceof external_value) { 292 if ($subdesc->required == VALUE_DEFAULT) { 293 try { 294 $result[$key] = self::clean_returnvalue($subdesc, $subdesc->default); 295 } catch (invalid_response_exception $e) { 296 //build the path to the faulty attribut 297 throw new invalid_response_exception($key." => ".$e->getMessage() . ': ' . $e->debuginfo); 298 } 299 } 300 } 301 } else { 302 try { 303 $result[$key] = self::clean_returnvalue($subdesc, $response[$key]); 304 } catch (invalid_response_exception $e) { 305 //build the path to the faulty attribut 306 throw new invalid_response_exception($key." => ".$e->getMessage() . ': ' . $e->debuginfo); 307 } 308 } 309 unset($response[$key]); 310 } 311 312 return $result; 313 314 } else if ($description instanceof external_multiple_structure) { 315 if (!is_array($response)) { 316 throw new invalid_response_exception('Only arrays accepted. The bad value is: \'' . 317 print_r($response, true) . '\''); 318 } 319 $result = array(); 320 foreach ($response as $param) { 321 $result[] = self::clean_returnvalue($description->content, $param); 322 } 323 return $result; 324 325 } else { 326 throw new invalid_response_exception('Invalid external api response description'); 327 } 328 } 329 330 /** 331 * Makes sure user may execute functions in this context. 332 * 333 * @param stdClass $context 334 * @since Moodle 2.0 335 */ 336 protected static function validate_context($context) { 337 global $CFG; 338 339 if (empty($context)) { 340 throw new invalid_parameter_exception('Context does not exist'); 341 } 342 if (empty(self::$contextrestriction)) { 343 self::$contextrestriction = context_system::instance(); 344 } 345 $rcontext = self::$contextrestriction; 346 347 if ($rcontext->contextlevel == $context->contextlevel) { 348 if ($rcontext->id != $context->id) { 349 throw new restricted_context_exception(); 350 } 351 } else if ($rcontext->contextlevel > $context->contextlevel) { 352 throw new restricted_context_exception(); 353 } else { 354 $parents = $context->get_parent_context_ids(); 355 if (!in_array($rcontext->id, $parents)) { 356 throw new restricted_context_exception(); 357 } 358 } 359 360 if ($context->contextlevel >= CONTEXT_COURSE) { 361 list($context, $course, $cm) = get_context_info_array($context->id); 362 require_login($course, false, $cm, false, true); 363 } 364 } 365 366 /** 367 * Get context from passed parameters. 368 * The passed array must either contain a contextid or a combination of context level and instance id to fetch the context. 369 * For example, the context level can be "course" and instanceid can be courseid. 370 * 371 * See context_helper::get_all_levels() for a list of valid context levels. 372 * 373 * @param array $param 374 * @since Moodle 2.6 375 * @throws invalid_parameter_exception 376 * @return context 377 */ 378 protected static function get_context_from_params($param) { 379 $levels = context_helper::get_all_levels(); 380 if (!empty($param['contextid'])) { 381 return context::instance_by_id($param['contextid'], IGNORE_MISSING); 382 } else if (!empty($param['contextlevel']) && isset($param['instanceid'])) { 383 $contextlevel = "context_".$param['contextlevel']; 384 if (!array_search($contextlevel, $levels)) { 385 throw new invalid_parameter_exception('Invalid context level = '.$param['contextlevel']); 386 } 387 return $contextlevel::instance($param['instanceid'], IGNORE_MISSING); 388 } else { 389 // No valid context info was found. 390 throw new invalid_parameter_exception('Missing parameters, please provide either context level with instance id or contextid'); 391 } 392 } 393 } 394 395 /** 396 * Common ancestor of all parameter description classes 397 * 398 * @package core_webservice 399 * @copyright 2009 Petr Skodak 400 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 401 * @since Moodle 2.0 402 */ 403 abstract class external_description { 404 /** @var string Description of element */ 405 public $desc; 406 407 /** @var bool Element value required, null not allowed */ 408 public $required; 409 410 /** @var mixed Default value */ 411 public $default; 412 413 /** 414 * Contructor 415 * 416 * @param string $desc 417 * @param bool $required 418 * @param mixed $default 419 * @since Moodle 2.0 420 */ 421 public function __construct($desc, $required, $default) { 422 $this->desc = $desc; 423 $this->required = $required; 424 $this->default = $default; 425 } 426 } 427 428 /** 429 * Scalar value description class 430 * 431 * @package core_webservice 432 * @copyright 2009 Petr Skodak 433 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 434 * @since Moodle 2.0 435 */ 436 class external_value extends external_description { 437 438 /** @var mixed Value type PARAM_XX */ 439 public $type; 440 441 /** @var bool Allow null values */ 442 public $allownull; 443 444 /** 445 * Constructor 446 * 447 * @param mixed $type 448 * @param string $desc 449 * @param bool $required 450 * @param mixed $default 451 * @param bool $allownull 452 * @since Moodle 2.0 453 */ 454 public function __construct($type, $desc='', $required=VALUE_REQUIRED, 455 $default=null, $allownull=NULL_ALLOWED) { 456 parent::__construct($desc, $required, $default); 457 $this->type = $type; 458 $this->allownull = $allownull; 459 } 460 } 461 462 /** 463 * Associative array description class 464 * 465 * @package core_webservice 466 * @copyright 2009 Petr Skodak 467 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 468 * @since Moodle 2.0 469 */ 470 class external_single_structure extends external_description { 471 472 /** @var array Description of array keys key=>external_description */ 473 public $keys; 474 475 /** 476 * Constructor 477 * 478 * @param array $keys 479 * @param string $desc 480 * @param bool $required 481 * @param array $default 482 * @since Moodle 2.0 483 */ 484 public function __construct(array $keys, $desc='', 485 $required=VALUE_REQUIRED, $default=null) { 486 parent::__construct($desc, $required, $default); 487 $this->keys = $keys; 488 } 489 } 490 491 /** 492 * Bulk array description class. 493 * 494 * @package core_webservice 495 * @copyright 2009 Petr Skodak 496 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 497 * @since Moodle 2.0 498 */ 499 class external_multiple_structure extends external_description { 500 501 /** @var external_description content */ 502 public $content; 503 504 /** 505 * Constructor 506 * 507 * @param external_description $content 508 * @param string $desc 509 * @param bool $required 510 * @param array $default 511 * @since Moodle 2.0 512 */ 513 public function __construct(external_description $content, $desc='', 514 $required=VALUE_REQUIRED, $default=null) { 515 parent::__construct($desc, $required, $default); 516 $this->content = $content; 517 } 518 } 519 520 /** 521 * Description of top level - PHP function parameters. 522 * 523 * @package core_webservice 524 * @copyright 2009 Petr Skodak 525 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 526 * @since Moodle 2.0 527 */ 528 class external_function_parameters extends external_single_structure { 529 } 530 531 /** 532 * Generate a token 533 * 534 * @param string $tokentype EXTERNAL_TOKEN_EMBEDDED|EXTERNAL_TOKEN_PERMANENT 535 * @param stdClass|int $serviceorid service linked to the token 536 * @param int $userid user linked to the token 537 * @param stdClass|int $contextorid 538 * @param int $validuntil date when the token expired 539 * @param string $iprestriction allowed ip - if 0 or empty then all ips are allowed 540 * @return string generated token 541 * @author 2010 Jamie Pratt 542 * @since Moodle 2.0 543 */ 544 function external_generate_token($tokentype, $serviceorid, $userid, $contextorid, $validuntil=0, $iprestriction=''){ 545 global $DB, $USER; 546 // make sure the token doesn't exist (even if it should be almost impossible with the random generation) 547 $numtries = 0; 548 do { 549 $numtries ++; 550 $generatedtoken = md5(uniqid(rand(),1)); 551 if ($numtries > 5){ 552 throw new moodle_exception('tokengenerationfailed'); 553 } 554 } while ($DB->record_exists('external_tokens', array('token'=>$generatedtoken))); 555 $newtoken = new stdClass(); 556 $newtoken->token = $generatedtoken; 557 if (!is_object($serviceorid)){ 558 $service = $DB->get_record('external_services', array('id' => $serviceorid)); 559 } else { 560 $service = $serviceorid; 561 } 562 if (!is_object($contextorid)){ 563 $context = context::instance_by_id($contextorid, MUST_EXIST); 564 } else { 565 $context = $contextorid; 566 } 567 if (empty($service->requiredcapability) || has_capability($service->requiredcapability, $context, $userid)) { 568 $newtoken->externalserviceid = $service->id; 569 } else { 570 throw new moodle_exception('nocapabilitytousethisservice'); 571 } 572 $newtoken->tokentype = $tokentype; 573 $newtoken->userid = $userid; 574 if ($tokentype == EXTERNAL_TOKEN_EMBEDDED){ 575 $newtoken->sid = session_id(); 576 } 577 578 $newtoken->contextid = $context->id; 579 $newtoken->creatorid = $USER->id; 580 $newtoken->timecreated = time(); 581 $newtoken->validuntil = $validuntil; 582 if (!empty($iprestriction)) { 583 $newtoken->iprestriction = $iprestriction; 584 } 585 $DB->insert_record('external_tokens', $newtoken); 586 return $newtoken->token; 587 } 588 589 /** 590 * Create and return a session linked token. Token to be used for html embedded client apps that want to communicate 591 * with the Moodle server through web services. The token is linked to the current session for the current page request. 592 * It is expected this will be called in the script generating the html page that is embedding the client app and that the 593 * returned token will be somehow passed into the client app being embedded in the page. 594 * 595 * @param string $servicename name of the web service. Service name as defined in db/services.php 596 * @param int $context context within which the web service can operate. 597 * @return int returns token id. 598 * @since Moodle 2.0 599 */ 600 function external_create_service_token($servicename, $context){ 601 global $USER, $DB; 602 $service = $DB->get_record('external_services', array('name'=>$servicename), '*', MUST_EXIST); 603 return external_generate_token(EXTERNAL_TOKEN_EMBEDDED, $service, $USER->id, $context, 0); 604 } 605 606 /** 607 * Delete all pre-built services (+ related tokens) and external functions information defined in the specified component. 608 * 609 * @param string $component name of component (moodle, mod_assignment, etc.) 610 */ 611 function external_delete_descriptions($component) { 612 global $DB; 613 614 $params = array($component); 615 616 $DB->delete_records_select('external_tokens', 617 "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params); 618 $DB->delete_records_select('external_services_users', 619 "externalserviceid IN (SELECT id FROM {external_services} WHERE component = ?)", $params); 620 $DB->delete_records_select('external_services_functions', 621 "functionname IN (SELECT name FROM {external_functions} WHERE component = ?)", $params); 622 $DB->delete_records('external_services', array('component'=>$component)); 623 $DB->delete_records('external_functions', array('component'=>$component)); 624 } 625 626 /** 627 * Standard Moodle web service warnings 628 * 629 * @package core_webservice 630 * @copyright 2012 Jerome Mouneyrac 631 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 632 * @since Moodle 2.3 633 */ 634 class external_warnings extends external_multiple_structure { 635 636 /** 637 * Constructor 638 * 639 * @since Moodle 2.3 640 */ 641 public function __construct($itemdesc = 'item', $itemiddesc = 'item id', 642 $warningcodedesc = 'the warning code can be used by the client app to implement specific behaviour') { 643 644 parent::__construct( 645 new external_single_structure( 646 array( 647 'item' => new external_value(PARAM_TEXT, $itemdesc, VALUE_OPTIONAL), 648 'itemid' => new external_value(PARAM_INT, $itemiddesc, VALUE_OPTIONAL), 649 'warningcode' => new external_value(PARAM_ALPHANUM, $warningcodedesc), 650 'message' => new external_value(PARAM_TEXT, 651 'untranslated english message to explain the warning') 652 ), 'warning'), 653 'list of warnings', VALUE_OPTIONAL); 654 } 655 } 656 657 /** 658 * A pre-filled external_value class for text format. 659 * 660 * Default is FORMAT_HTML 661 * This should be used all the time in external xxx_params()/xxx_returns functions 662 * as it is the standard way to implement text format param/return values. 663 * 664 * @package core_webservice 665 * @copyright 2012 Jerome Mouneyrac 666 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 667 * @since Moodle 2.3 668 */ 669 class external_format_value extends external_value { 670 671 /** 672 * Constructor 673 * 674 * @param string $textfieldname Name of the text field 675 * @param int $required if VALUE_REQUIRED then set standard default FORMAT_HTML 676 * @since Moodle 2.3 677 */ 678 public function __construct($textfieldname, $required = VALUE_REQUIRED) { 679 680 $default = ($required == VALUE_DEFAULT) ? FORMAT_HTML : null; 681 682 $desc = $textfieldname . ' format (' . FORMAT_HTML . ' = HTML, ' 683 . FORMAT_MOODLE . ' = MOODLE, ' 684 . FORMAT_PLAIN . ' = PLAIN or ' 685 . FORMAT_MARKDOWN . ' = MARKDOWN)'; 686 687 parent::__construct(PARAM_INT, $desc, $required, $default); 688 } 689 } 690 691 /** 692 * Validate text field format against known FORMAT_XXX 693 * 694 * @param array $format the format to validate 695 * @return the validated format 696 * @throws coding_exception 697 * @since Moodle 2.3 698 */ 699 function external_validate_format($format) { 700 $allowedformats = array(FORMAT_HTML, FORMAT_MOODLE, FORMAT_PLAIN, FORMAT_MARKDOWN); 701 if (!in_array($format, $allowedformats)) { 702 throw new moodle_exception('formatnotsupported', 'webservice', '' , null, 703 'The format with value=' . $format . ' is not supported by this Moodle site'); 704 } 705 return $format; 706 } 707 708 /** 709 * Format the text to be returned properly as requested by the either the web service server, 710 * either by an internally call. 711 * The caller can change the format (raw, filter, file, fileurl) with the external_settings singleton 712 * All web service servers must set this singleton when parsing the $_GET and $_POST. 713 * 714 * @param string $text The content that may contain ULRs in need of rewriting. 715 * @param int $textformat The text format, by default FORMAT_HTML. 716 * @param int $contextid This parameter and the next two identify the file area to use. 717 * @param string $component 718 * @param string $filearea helps identify the file area. 719 * @param int $itemid helps identify the file area. 720 * @return array text + textformat 721 * @since Moodle 2.3 722 */ 723 function external_format_text($text, $textformat, $contextid, $component, $filearea, $itemid) { 724 global $CFG; 725 726 // Get settings (singleton). 727 $settings = external_settings::get_instance(); 728 729 if ($settings->get_fileurl()) { 730 require_once($CFG->libdir . "/filelib.php"); 731 $text = file_rewrite_pluginfile_urls($text, $settings->get_file(), $contextid, $component, $filearea, $itemid); 732 } 733 734 if (!$settings->get_raw()) { 735 $textformat = FORMAT_HTML; // Force format to HTML when not raw. 736 $text = format_text($text, $textformat, 737 array('noclean' => true, 'para' => false, 'filter' => $settings->get_filter())); 738 } 739 740 return array($text, $textformat); 741 } 742 743 /** 744 * Singleton to handle the external settings. 745 * 746 * We use singleton to encapsulate the "logic" 747 * 748 * @package core_webservice 749 * @copyright 2012 Jerome Mouneyrac 750 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 751 * @since Moodle 2.3 752 */ 753 class external_settings { 754 755 /** @var object the singleton instance */ 756 public static $instance = null; 757 758 /** @var boolean Should the external function return raw text or formatted */ 759 private $raw = false; 760 761 /** @var boolean Should the external function filter the text */ 762 private $filter = false; 763 764 /** @var boolean Should the external function rewrite plugin file url */ 765 private $fileurl = true; 766 767 /** @var string In which file should the urls be rewritten */ 768 private $file = 'webservice/pluginfile.php'; 769 770 /** 771 * Constructor - protected - can not be instanciated 772 */ 773 protected function __construct() { 774 } 775 776 /** 777 * Clone - private - can not be cloned 778 */ 779 private final function __clone() { 780 } 781 782 /** 783 * Return only one instance 784 * 785 * @return object 786 */ 787 public static function get_instance() { 788 if (self::$instance === null) { 789 self::$instance = new external_settings; 790 } 791 792 return self::$instance; 793 } 794 795 /** 796 * Set raw 797 * 798 * @param boolean $raw 799 */ 800 public function set_raw($raw) { 801 $this->raw = $raw; 802 } 803 804 /** 805 * Get raw 806 * 807 * @return boolean 808 */ 809 public function get_raw() { 810 return $this->raw; 811 } 812 813 /** 814 * Set filter 815 * 816 * @param boolean $filter 817 */ 818 public function set_filter($filter) { 819 $this->filter = $filter; 820 } 821 822 /** 823 * Get filter 824 * 825 * @return boolean 826 */ 827 public function get_filter() { 828 return $this->filter; 829 } 830 831 /** 832 * Set fileurl 833 * 834 * @param boolean $fileurl 835 */ 836 public function set_fileurl($fileurl) { 837 $this->fileurl = $fileurl; 838 } 839 840 /** 841 * Get fileurl 842 * 843 * @return boolean 844 */ 845 public function get_fileurl() { 846 return $this->fileurl; 847 } 848 849 /** 850 * Set file 851 * 852 * @param string $file 853 */ 854 public function set_file($file) { 855 $this->file = $file; 856 } 857 858 /** 859 * Get file 860 * 861 * @return string 862 */ 863 public function get_file() { 864 return $this->file; 865 } 866 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |