[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Zend Framework 4 * 5 * LICENSE 6 * 7 * This source file is subject to the new BSD license that is bundled 8 * with this package in the file LICENSE.txt. 9 * It is also available through the world-wide-web at this URL: 10 * http://framework.zend.com/license/new-bsd 11 * If you did not receive a copy of the license and are unable to 12 * obtain it through the world-wide-web, please send an email 13 * to [email protected] so we can send you a copy immediately. 14 * 15 * @category Zend 16 * @package Zend_Amf 17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 18 * @license http://framework.zend.com/license/new-bsd New BSD License 19 * @version $Id$ 20 */ 21 22 /** @see Zend_Server_Interface */ 23 require_once 'Zend/Server/Interface.php'; 24 25 /** @see Zend_Server_Reflection */ 26 require_once 'Zend/Server/Reflection.php'; 27 28 /** @see Zend_Amf_Constants */ 29 require_once 'Zend/Amf/Constants.php'; 30 31 /** @see Zend_Amf_Value_MessageBody */ 32 require_once 'Zend/Amf/Value/MessageBody.php'; 33 34 /** @see Zend_Amf_Value_MessageHeader */ 35 require_once 'Zend/Amf/Value/MessageHeader.php'; 36 37 /** @see Zend_Amf_Value_Messaging_CommandMessage */ 38 require_once 'Zend/Amf/Value/Messaging/CommandMessage.php'; 39 40 /** @see Zend_Loader_PluginLoader */ 41 require_once 'Zend/Loader/PluginLoader.php'; 42 43 /** @see Zend_Amf_Parse_TypeLoader */ 44 require_once 'Zend/Amf/Parse/TypeLoader.php'; 45 46 /** @see Zend_Auth */ 47 require_once 'Zend/Auth.php'; 48 /** 49 * An AMF gateway server implementation to allow the connection of the Adobe Flash Player to 50 * Zend Framework 51 * 52 * @todo Make the reflection methods cache and autoload. 53 * @package Zend_Amf 54 * @subpackage Server 55 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) 56 * @license http://framework.zend.com/license/new-bsd New BSD License 57 */ 58 class Zend_Amf_Server implements Zend_Server_Interface 59 { 60 /** 61 * Array of dispatchables 62 * @var array 63 */ 64 protected $_methods = array(); 65 66 /** 67 * Array of classes that can be called without being explicitly loaded 68 * 69 * Keys are class names. 70 * 71 * @var array 72 */ 73 protected $_classAllowed = array(); 74 75 /** 76 * Loader for classes in added directories 77 * @var Zend_Loader_PluginLoader 78 */ 79 protected $_loader; 80 81 /** 82 * @var bool Production flag; whether or not to return exception messages 83 */ 84 protected $_production = true; 85 86 /** 87 * Request processed 88 * @var null|Zend_Amf_Request 89 */ 90 protected $_request = null; 91 92 /** 93 * Class to use for responses 94 * @var null|Zend_Amf_Response 95 */ 96 protected $_response; 97 98 /** 99 * Dispatch table of name => method pairs 100 * @var array 101 */ 102 protected $_table = array(); 103 104 /** 105 * 106 * @var bool session flag; whether or not to add a session to each response. 107 */ 108 protected $_session = false; 109 110 /** 111 * Namespace allows all AMF calls to not clobber other php session variables 112 * @var Zend_Session_NameSpace default session namespace zend_amf 113 */ 114 protected $_sesionNamespace = 'zend_amf'; 115 116 /** 117 * Set the default session.name if php_ 118 * @var string 119 */ 120 protected $_sessionName = 'PHPSESSID'; 121 122 /** 123 * Authentication handler object 124 * 125 * @var Zend_Amf_Auth_Abstract 126 */ 127 protected $_auth; 128 /** 129 * ACL handler object 130 * 131 * @var Zend_Acl 132 */ 133 protected $_acl; 134 /** 135 * The server constructor 136 */ 137 public function __construct() 138 { 139 Zend_Amf_Parse_TypeLoader::setResourceLoader(new Zend_Loader_PluginLoader(array("Zend_Amf_Parse_Resource" => "Zend/Amf/Parse/Resource"))); 140 } 141 142 /** 143 * Set authentication adapter 144 * 145 * @param Zend_Amf_Auth_Abstract $auth 146 * @return Zend_Amf_Server 147 */ 148 public function setAuth(Zend_Amf_Auth_Abstract $auth) 149 { 150 $this->_auth = $auth; 151 return $this; 152 } 153 /** 154 * Get authentication adapter 155 * 156 * @return Zend_Amf_Auth_Abstract 157 */ 158 public function getAuth() 159 { 160 return $this->_auth; 161 } 162 163 /** 164 * Set ACL adapter 165 * 166 * @param Zend_Acl $acl 167 * @return Zend_Amf_Server 168 */ 169 public function setAcl(Zend_Acl $acl) 170 { 171 $this->_acl = $acl; 172 return $this; 173 } 174 /** 175 * Get ACL adapter 176 * 177 * @return Zend_Acl 178 */ 179 public function getAcl() 180 { 181 return $this->_acl; 182 } 183 184 /** 185 * Set production flag 186 * 187 * @param bool $flag 188 * @return Zend_Amf_Server 189 */ 190 public function setProduction($flag) 191 { 192 $this->_production = (bool) $flag; 193 return $this; 194 } 195 196 /** 197 * Whether or not the server is in production 198 * 199 * @return bool 200 */ 201 public function isProduction() 202 { 203 return $this->_production; 204 } 205 206 /** 207 * @param namespace of all incoming sessions defaults to Zend_Amf 208 * @return Zend_Amf_Server 209 */ 210 public function setSession($namespace = 'Zend_Amf') 211 { 212 require_once 'Zend/Session.php'; 213 $this->_session = true; 214 $this->_sesionNamespace = new Zend_Session_Namespace($namespace); 215 return $this; 216 } 217 218 /** 219 * Whether of not the server is using sessions 220 * @return bool 221 */ 222 public function isSession() 223 { 224 return $this->_session; 225 } 226 227 /** 228 * Check if the ACL allows accessing the function or method 229 * 230 * @param string|object $object Object or class being accessed 231 * @param string $function Function or method being accessed 232 * @return unknown_type 233 */ 234 protected function _checkAcl($object, $function) 235 { 236 if(!$this->_acl) { 237 return true; 238 } 239 if($object) { 240 $class = is_object($object)?get_class($object):$object; 241 if(!$this->_acl->has($class)) { 242 require_once 'Zend/Acl/Resource.php'; 243 $this->_acl->add(new Zend_Acl_Resource($class)); 244 } 245 $call = array($object, "initAcl"); 246 if(is_callable($call) && !call_user_func($call, $this->_acl)) { 247 // if initAcl returns false, no ACL check 248 return true; 249 } 250 } else { 251 $class = null; 252 } 253 254 $auth = Zend_Auth::getInstance(); 255 if($auth->hasIdentity()) { 256 $role = $auth->getIdentity()->role; 257 } else { 258 if($this->_acl->hasRole(Zend_Amf_Constants::GUEST_ROLE)) { 259 $role = Zend_Amf_Constants::GUEST_ROLE; 260 } else { 261 require_once 'Zend/Amf/Server/Exception.php'; 262 throw new Zend_Amf_Server_Exception("Unauthenticated access not allowed"); 263 } 264 } 265 if($this->_acl->isAllowed($role, $class, $function)) { 266 return true; 267 } else { 268 require_once 'Zend/Amf/Server/Exception.php'; 269 throw new Zend_Amf_Server_Exception("Access not allowed"); 270 } 271 } 272 273 /** 274 * Get PluginLoader for the Server 275 * 276 * @return Zend_Loader_PluginLoader 277 */ 278 protected function getLoader() 279 { 280 if(empty($this->_loader)) { 281 require_once 'Zend/Loader/PluginLoader.php'; 282 $this->_loader = new Zend_Loader_PluginLoader(); 283 } 284 return $this->_loader; 285 } 286 287 /** 288 * Loads a remote class or method and executes the function and returns 289 * the result 290 * 291 * @param string $method Is the method to execute 292 * @param mixed $param values for the method 293 * @return mixed $response the result of executing the method 294 * @throws Zend_Amf_Server_Exception 295 */ 296 protected function _dispatch($method, $params = null, $source = null) 297 { 298 if($source) { 299 if(($mapped = Zend_Amf_Parse_TypeLoader::getMappedClassName($source)) !== false) { 300 $source = $mapped; 301 } 302 } 303 $qualifiedName = empty($source) ? $method : $source.".".$method; 304 305 if (!isset($this->_table[$qualifiedName])) { 306 // if source is null a method that was not defined was called. 307 if ($source) { 308 $className = str_replace(".", "_", $source); 309 if(class_exists($className, false) && !isset($this->_classAllowed[$className])) { 310 require_once 'Zend/Amf/Server/Exception.php'; 311 throw new Zend_Amf_Server_Exception('Can not call "' . $className . '" - use setClass()'); 312 } 313 try { 314 $this->getLoader()->load($className); 315 } catch (Exception $e) { 316 require_once 'Zend/Amf/Server/Exception.php'; 317 throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e); 318 } 319 // Add the new loaded class to the server. 320 $this->setClass($className, $source); 321 } else { 322 require_once 'Zend/Amf/Server/Exception.php'; 323 throw new Zend_Amf_Server_Exception('Method "' . $method . '" does not exist'); 324 } 325 } 326 327 $info = $this->_table[$qualifiedName]; 328 $argv = $info->getInvokeArguments(); 329 330 if (0 < count($argv)) { 331 $params = array_merge($params, $argv); 332 } 333 334 if ($info instanceof Zend_Server_Reflection_Function) { 335 $func = $info->getName(); 336 $this->_checkAcl(null, $func); 337 $return = call_user_func_array($func, $params); 338 } elseif ($info instanceof Zend_Server_Reflection_Method) { 339 // Get class 340 $class = $info->getDeclaringClass()->getName(); 341 if ('static' == $info->isStatic()) { 342 // for some reason, invokeArgs() does not work the same as 343 // invoke(), and expects the first argument to be an object. 344 // So, using a callback if the method is static. 345 $this->_checkAcl($class, $info->getName()); 346 $return = call_user_func_array(array($class, $info->getName()), $params); 347 } else { 348 // Object methods 349 try { 350 $object = $info->getDeclaringClass()->newInstance(); 351 } catch (Exception $e) { 352 require_once 'Zend/Amf/Server/Exception.php'; 353 throw new Zend_Amf_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $info->getName() . ': '.$e->getMessage(), 621, $e); 354 } 355 $this->_checkAcl($object, $info->getName()); 356 $return = $info->invokeArgs($object, $params); 357 } 358 } else { 359 require_once 'Zend/Amf/Server/Exception.php'; 360 throw new Zend_Amf_Server_Exception('Method missing implementation ' . get_class($info)); 361 } 362 363 return $return; 364 } 365 366 /** 367 * Handles each of the 11 different command message types. 368 * 369 * A command message is a flex.messaging.messages.CommandMessage 370 * 371 * @see Zend_Amf_Value_Messaging_CommandMessage 372 * @param Zend_Amf_Value_Messaging_CommandMessage $message 373 * @return Zend_Amf_Value_Messaging_AcknowledgeMessage 374 */ 375 protected function _loadCommandMessage(Zend_Amf_Value_Messaging_CommandMessage $message) 376 { 377 require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; 378 switch($message->operation) { 379 case Zend_Amf_Value_Messaging_CommandMessage::DISCONNECT_OPERATION : 380 case Zend_Amf_Value_Messaging_CommandMessage::CLIENT_PING_OPERATION : 381 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); 382 break; 383 case Zend_Amf_Value_Messaging_CommandMessage::LOGIN_OPERATION : 384 $data = explode(':', base64_decode($message->body)); 385 $userid = $data[0]; 386 $password = isset($data[1])?$data[1]:""; 387 if(empty($userid)) { 388 require_once 'Zend/Amf/Server/Exception.php'; 389 throw new Zend_Amf_Server_Exception('Login failed: username not supplied'); 390 } 391 if(!$this->_handleAuth($userid, $password)) { 392 require_once 'Zend/Amf/Server/Exception.php'; 393 throw new Zend_Amf_Server_Exception('Authentication failed'); 394 } 395 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); 396 break; 397 case Zend_Amf_Value_Messaging_CommandMessage::LOGOUT_OPERATION : 398 if($this->_auth) { 399 Zend_Auth::getInstance()->clearIdentity(); 400 } 401 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); 402 break; 403 default : 404 require_once 'Zend/Amf/Server/Exception.php'; 405 throw new Zend_Amf_Server_Exception('CommandMessage::' . $message->operation . ' not implemented'); 406 break; 407 } 408 return $return; 409 } 410 411 /** 412 * Create appropriate error message 413 * 414 * @param int $objectEncoding Current AMF encoding 415 * @param string $message Message that was being processed when error happened 416 * @param string $description Error description 417 * @param mixed $detail Detailed data about the error 418 * @param int $code Error code 419 * @param int $line Error line 420 * @return Zend_Amf_Value_Messaging_ErrorMessage|array 421 */ 422 protected function _errorMessage($objectEncoding, $message, $description, $detail, $code, $line) 423 { 424 $return = null; 425 switch ($objectEncoding) { 426 case Zend_Amf_Constants::AMF0_OBJECT_ENCODING : 427 return array ( 428 'description' => ($this->isProduction ()) ? '' : $description, 429 'detail' => ($this->isProduction ()) ? '' : $detail, 430 'line' => ($this->isProduction ()) ? 0 : $line, 431 'code' => $code 432 ); 433 case Zend_Amf_Constants::AMF3_OBJECT_ENCODING : 434 require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php'; 435 $return = new Zend_Amf_Value_Messaging_ErrorMessage ( $message ); 436 $return->faultString = $this->isProduction () ? '' : $description; 437 $return->faultCode = $code; 438 $return->faultDetail = $this->isProduction () ? '' : $detail; 439 break; 440 } 441 return $return; 442 } 443 444 /** 445 * Handle AMF authentication 446 * 447 * @param string $userid 448 * @param string $password 449 * @return boolean 450 */ 451 protected function _handleAuth( $userid, $password) 452 { 453 if (!$this->_auth) { 454 return true; 455 } 456 $this->_auth->setCredentials($userid, $password); 457 $auth = Zend_Auth::getInstance(); 458 $result = $auth->authenticate($this->_auth); 459 if ($result->isValid()) { 460 if (!$this->isSession()) { 461 $this->setSession(); 462 } 463 return true; 464 } else { 465 // authentication failed, good bye 466 require_once 'Zend/Amf/Server/Exception.php'; 467 throw new Zend_Amf_Server_Exception( 468 "Authentication failed: " . join("\n", 469 $result->getMessages()), $result->getCode()); 470 } 471 472 } 473 474 /** 475 * Takes the deserialized AMF request and performs any operations. 476 * 477 * @todo should implement and SPL observer pattern for custom AMF headers 478 * @todo DescribeService support 479 * @param Zend_Amf_Request $request 480 * @return Zend_Amf_Response 481 * @throws Zend_Amf_server_Exception|Exception 482 */ 483 protected function _handle(Zend_Amf_Request $request) 484 { 485 // Get the object encoding of the request. 486 $objectEncoding = $request->getObjectEncoding(); 487 488 // create a response object to place the output from the services. 489 $response = $this->getResponse(); 490 491 // set response encoding 492 $response->setObjectEncoding($objectEncoding); 493 494 $responseBody = $request->getAmfBodies(); 495 496 $handleAuth = false; 497 if ($this->_auth) { 498 $headers = $request->getAmfHeaders(); 499 if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) && 500 isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) { 501 $handleAuth = true; 502 } 503 } 504 505 // Iterate through each of the service calls in the AMF request 506 foreach($responseBody as $body) 507 { 508 try { 509 if ($handleAuth) { 510 if ($this->_handleAuth( 511 $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, 512 $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) { 513 // use RequestPersistentHeader to clear credentials 514 $response->addAmfHeader( 515 new Zend_Amf_Value_MessageHeader( 516 Zend_Amf_Constants::PERSISTENT_HEADER, 517 false, 518 new Zend_Amf_Value_MessageHeader( 519 Zend_Amf_Constants::CREDENTIALS_HEADER, 520 false, null))); 521 $handleAuth = false; 522 } 523 } 524 525 if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) { 526 // AMF0 Object Encoding 527 $targetURI = $body->getTargetURI(); 528 $message = ''; 529 530 // Split the target string into its values. 531 $source = substr($targetURI, 0, strrpos($targetURI, '.')); 532 533 if ($source) { 534 // Break off method name from namespace into source 535 $method = substr(strrchr($targetURI, '.'), 1); 536 $return = $this->_dispatch($method, $body->getData(), $source); 537 } else { 538 // Just have a method name. 539 $return = $this->_dispatch($targetURI, $body->getData()); 540 } 541 } else { 542 // AMF3 read message type 543 $message = $body->getData(); 544 if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) { 545 // async call with command message 546 $return = $this->_loadCommandMessage($message); 547 } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) { 548 require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; 549 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); 550 $return->body = $this->_dispatch($message->operation, $message->body, $message->source); 551 } else { 552 // Amf3 message sent with netConnection 553 $targetURI = $body->getTargetURI(); 554 555 // Split the target string into its values. 556 $source = substr($targetURI, 0, strrpos($targetURI, '.')); 557 558 if ($source) { 559 // Break off method name from namespace into source 560 $method = substr(strrchr($targetURI, '.'), 1); 561 $return = $this->_dispatch($method, $body->getData(), $source); 562 } else { 563 // Just have a method name. 564 $return = $this->_dispatch($targetURI, $body->getData()); 565 } 566 } 567 } 568 $responseType = Zend_AMF_Constants::RESULT_METHOD; 569 } catch (Exception $e) { 570 $return = $this->_errorMessage($objectEncoding, $message, 571 $e->getMessage(), $e->getTraceAsString(),$e->getCode(), $e->getLine()); 572 $responseType = Zend_AMF_Constants::STATUS_METHOD; 573 } 574 575 $responseURI = $body->getResponseURI() . $responseType; 576 $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $return); 577 $response->addAmfBody($newBody); 578 } 579 // Add a session header to the body if session is requested. 580 if($this->isSession()) { 581 $currentID = session_id(); 582 $joint = "?"; 583 if(isset($_SERVER['QUERY_STRING'])) { 584 if(!strpos($_SERVER['QUERY_STRING'], $currentID) !== FALSE) { 585 if(strrpos($_SERVER['QUERY_STRING'], "?") !== FALSE) { 586 $joint = "&"; 587 } 588 } 589 } 590 591 // create a new AMF message header with the session id as a variable. 592 $sessionValue = $joint . $this->_sessionName . "=" . $currentID; 593 $sessionHeader = new Zend_Amf_Value_MessageHeader(Zend_Amf_Constants::URL_APPEND_HEADER, false, $sessionValue); 594 $response->addAmfHeader($sessionHeader); 595 } 596 597 // serialize the response and return serialized body. 598 $response->finalize(); 599 } 600 601 /** 602 * Handle an AMF call from the gateway. 603 * 604 * @param null|Zend_Amf_Request $request Optional 605 * @return Zend_Amf_Response 606 */ 607 public function handle($request = null) 608 { 609 // Check if request was passed otherwise get it from the server 610 if (is_null($request) || !$request instanceof Zend_Amf_Request) { 611 $request = $this->getRequest(); 612 } else { 613 $this->setRequest($request); 614 } 615 if ($this->isSession()) { 616 // Check if a session is being sent from the amf call 617 if (isset($_COOKIE[$this->_sessionName])) { 618 session_id($_COOKIE[$this->_sessionName]); 619 } 620 } 621 622 // Check for errors that may have happend in deserialization of Request. 623 try { 624 // Take converted PHP objects and handle service call. 625 // Serialize to Zend_Amf_response for output stream 626 $this->_handle($request); 627 $response = $this->getResponse(); 628 } catch (Exception $e) { 629 // Handle any errors in the serialization and service calls. 630 require_once 'Zend/Amf/Server/Exception.php'; 631 throw new Zend_Amf_Server_Exception('Handle error: ' . $e->getMessage() . ' ' . $e->getLine(), 0, $e); 632 } 633 634 // Return the Amf serialized output string 635 return $response; 636 } 637 638 /** 639 * Set request object 640 * 641 * @param string|Zend_Amf_Request $request 642 * @return Zend_Amf_Server 643 */ 644 public function setRequest($request) 645 { 646 if (is_string($request) && class_exists($request)) { 647 $request = new $request(); 648 if (!$request instanceof Zend_Amf_Request) { 649 require_once 'Zend/Amf/Server/Exception.php'; 650 throw new Zend_Amf_Server_Exception('Invalid request class'); 651 } 652 } elseif (!$request instanceof Zend_Amf_Request) { 653 require_once 'Zend/Amf/Server/Exception.php'; 654 throw new Zend_Amf_Server_Exception('Invalid request object'); 655 } 656 $this->_request = $request; 657 return $this; 658 } 659 660 /** 661 * Return currently registered request object 662 * 663 * @return null|Zend_Amf_Request 664 */ 665 public function getRequest() 666 { 667 if (null === $this->_request) { 668 require_once 'Zend/Amf/Request/Http.php'; 669 $this->setRequest(new Zend_Amf_Request_Http()); 670 } 671 672 return $this->_request; 673 } 674 675 /** 676 * Public access method to private Zend_Amf_Server_Response reference 677 * 678 * @param string|Zend_Amf_Server_Response $response 679 * @return Zend_Amf_Server 680 */ 681 public function setResponse($response) 682 { 683 if (is_string($response) && class_exists($response)) { 684 $response = new $response(); 685 if (!$response instanceof Zend_Amf_Response) { 686 require_once 'Zend/Amf/Server/Exception.php'; 687 throw new Zend_Amf_Server_Exception('Invalid response class'); 688 } 689 } elseif (!$response instanceof Zend_Amf_Response) { 690 require_once 'Zend/Amf/Server/Exception.php'; 691 throw new Zend_Amf_Server_Exception('Invalid response object'); 692 } 693 $this->_response = $response; 694 return $this; 695 } 696 697 /** 698 * get a reference to the Zend_Amf_response instance 699 * 700 * @return Zend_Amf_Server_Response 701 */ 702 public function getResponse() 703 { 704 if (null === ($response = $this->_response)) { 705 require_once 'Zend/Amf/Response/Http.php'; 706 $this->setResponse(new Zend_Amf_Response_Http()); 707 } 708 return $this->_response; 709 } 710 711 /** 712 * Attach a class or object to the server 713 * 714 * Class may be either a class name or an instantiated object. Reflection 715 * is done on the class or object to determine the available public 716 * methods, and each is attached to the server as and available method. If 717 * a $namespace has been provided, that namespace is used to prefix 718 * AMF service call. 719 * 720 * @param string|object $class 721 * @param string $namespace Optional 722 * @param mixed $arg Optional arguments to pass to a method 723 * @return Zend_Amf_Server 724 * @throws Zend_Amf_Server_Exception on invalid input 725 */ 726 public function setClass($class, $namespace = '', $argv = null) 727 { 728 if (is_string($class) && !class_exists($class)){ 729 require_once 'Zend/Amf/Server/Exception.php'; 730 throw new Zend_Amf_Server_Exception('Invalid method or class'); 731 } elseif (!is_string($class) && !is_object($class)) { 732 require_once 'Zend/Amf/Server/Exception.php'; 733 throw new Zend_Amf_Server_Exception('Invalid method or class; must be a classname or object'); 734 } 735 736 $argv = null; 737 if (2 < func_num_args()) { 738 $argv = array_slice(func_get_args(), 2); 739 } 740 741 // Use the class name as the name space by default. 742 743 if ($namespace == '') { 744 $namespace = is_object($class) ? get_class($class) : $class; 745 } 746 747 $this->_classAllowed[is_object($class) ? get_class($class) : $class] = true; 748 749 $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace); 750 $this->_buildDispatchTable(); 751 752 return $this; 753 } 754 755 /** 756 * Attach a function to the server 757 * 758 * Additional arguments to pass to the function at dispatch may be passed; 759 * any arguments following the namespace will be aggregated and passed at 760 * dispatch time. 761 * 762 * @param string|array $function Valid callback 763 * @param string $namespace Optional namespace prefix 764 * @return Zend_Amf_Server 765 * @throws Zend_Amf_Server_Exception 766 */ 767 public function addFunction($function, $namespace = '') 768 { 769 if (!is_string($function) && !is_array($function)) { 770 require_once 'Zend/Amf/Server/Exception.php'; 771 throw new Zend_Amf_Server_Exception('Unable to attach function'); 772 } 773 774 $argv = null; 775 if (2 < func_num_args()) { 776 $argv = array_slice(func_get_args(), 2); 777 } 778 779 $function = (array) $function; 780 foreach ($function as $func) { 781 if (!is_string($func) || !function_exists($func)) { 782 require_once 'Zend/Amf/Server/Exception.php'; 783 throw new Zend_Amf_Server_Exception('Unable to attach function'); 784 } 785 $this->_methods[] = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace); 786 } 787 788 $this->_buildDispatchTable(); 789 return $this; 790 } 791 792 793 /** 794 * Creates an array of directories in which services can reside. 795 * TODO: add support for prefixes? 796 * 797 * @param string $dir 798 */ 799 public function addDirectory($dir) 800 { 801 $this->getLoader()->addPrefixPath("", $dir); 802 } 803 804 /** 805 * Returns an array of directories that can hold services. 806 * 807 * @return array 808 */ 809 public function getDirectory() 810 { 811 return $this->getLoader()->getPaths(""); 812 } 813 814 /** 815 * (Re)Build the dispatch table 816 * 817 * The dispatch table consists of a an array of method name => 818 * Zend_Server_Reflection_Function_Abstract pairs 819 * 820 * @return void 821 */ 822 protected function _buildDispatchTable() 823 { 824 $table = array(); 825 foreach ($this->_methods as $key => $dispatchable) { 826 if ($dispatchable instanceof Zend_Server_Reflection_Function_Abstract) { 827 $ns = $dispatchable->getNamespace(); 828 $name = $dispatchable->getName(); 829 $name = empty($ns) ? $name : $ns . '.' . $name; 830 831 if (isset($table[$name])) { 832 require_once 'Zend/Amf/Server/Exception.php'; 833 throw new Zend_Amf_Server_Exception('Duplicate method registered: ' . $name); 834 } 835 $table[$name] = $dispatchable; 836 continue; 837 } 838 839 if ($dispatchable instanceof Zend_Server_Reflection_Class) { 840 foreach ($dispatchable->getMethods() as $method) { 841 $ns = $method->getNamespace(); 842 $name = $method->getName(); 843 $name = empty($ns) ? $name : $ns . '.' . $name; 844 845 if (isset($table[$name])) { 846 require_once 'Zend/Amf/Server/Exception.php'; 847 throw new Zend_Amf_Server_Exception('Duplicate method registered: ' . $name); 848 } 849 $table[$name] = $method; 850 continue; 851 } 852 } 853 } 854 $this->_table = $table; 855 } 856 857 858 859 /** 860 * Raise a server fault 861 * 862 * Unimplemented 863 * 864 * @param string|Exception $fault 865 * @return void 866 */ 867 public function fault($fault = null, $code = 404) 868 { 869 } 870 871 /** 872 * Returns a list of registered methods 873 * 874 * Returns an array of dispatchables (Zend_Server_Reflection_Function, 875 * _Method, and _Class items). 876 * 877 * @return array 878 */ 879 public function getFunctions() 880 { 881 return $this->_table; 882 } 883 884 /** 885 * Set server persistence 886 * 887 * Unimplemented 888 * 889 * @param mixed $mode 890 * @return void 891 */ 892 public function setPersistence($mode) 893 { 894 } 895 896 /** 897 * Load server definition 898 * 899 * Unimplemented 900 * 901 * @param array $definition 902 * @return void 903 */ 904 public function loadFunctions($definition) 905 { 906 } 907 908 /** 909 * Map ActionScript classes to PHP classes 910 * 911 * @param string $asClass 912 * @param string $phpClass 913 * @return Zend_Amf_Server 914 */ 915 public function setClassMap($asClass, $phpClass) 916 { 917 require_once 'Zend/Amf/Parse/TypeLoader.php'; 918 Zend_Amf_Parse_TypeLoader::setMapping($asClass, $phpClass); 919 return $this; 920 } 921 922 /** 923 * List all available methods 924 * 925 * Returns an array of method names. 926 * 927 * @return array 928 */ 929 public function listMethods() 930 { 931 return array_keys($this->_table); 932 } 933 }
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 |