|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00026 require_once 'Zend/Server/Interface.php'; 00027 00031 require_once 'Zend/Server/Reflection.php'; 00032 00036 require_once 'Zend/Server/Abstract.php'; 00037 00045 class Zend_Rest_Server implements Zend_Server_Interface 00046 { 00051 protected $_args = array(); 00052 00056 protected $_encoding = 'UTF-8'; 00057 00061 protected $_functions = array(); 00062 00066 protected $_headers = array(); 00067 00071 protected static $magicMethods = array( 00072 '__construct', 00073 '__destruct', 00074 '__get', 00075 '__set', 00076 '__call', 00077 '__sleep', 00078 '__wakeup', 00079 '__isset', 00080 '__unset', 00081 '__tostring', 00082 '__clone', 00083 '__set_state', 00084 ); 00085 00089 protected $_method; 00090 00094 protected $_reflection = null; 00095 00100 protected $_returnResponse = false; 00101 00105 public function __construct() 00106 { 00107 set_exception_handler(array($this, "fault")); 00108 $this->_reflection = new Zend_Server_Reflection(); 00109 } 00110 00117 public function setEncoding($encoding) 00118 { 00119 $this->_encoding = (string) $encoding; 00120 return $this; 00121 } 00122 00128 public function getEncoding() 00129 { 00130 return $this->_encoding; 00131 } 00132 00142 public static function lowerCase(&$value, &$key) 00143 { 00144 return $value = strtolower($value); 00145 } 00146 00159 public function returnResponse($flag = null) 00160 { 00161 if (null === $flag) { 00162 return $this->_returnResponse; 00163 } 00164 00165 $this->_returnResponse = ($flag) ? true : false; 00166 return $this; 00167 } 00168 00176 public function handle($request = false) 00177 { 00178 $this->_headers = array('Content-Type: text/xml'); 00179 if (!$request) { 00180 $request = $_REQUEST; 00181 } 00182 if (isset($request['method'])) { 00183 $this->_method = $request['method']; 00184 if (isset($this->_functions[$this->_method])) { 00185 if ($this->_functions[$this->_method] instanceof Zend_Server_Reflection_Function || $this->_functions[$this->_method] instanceof Zend_Server_Reflection_Method && $this->_functions[$this->_method]->isPublic()) { 00186 $request_keys = array_keys($request); 00187 array_walk($request_keys, array(__CLASS__, "lowerCase")); 00188 $request = array_combine($request_keys, $request); 00189 00190 $func_args = $this->_functions[$this->_method]->getParameters(); 00191 00192 $calling_args = array(); 00193 $missing_args = array(); 00194 foreach ($func_args as $arg) { 00195 if (isset($request[strtolower($arg->getName())])) { 00196 $calling_args[] = $request[strtolower($arg->getName())]; 00197 } elseif ($arg->isOptional()) { 00198 $calling_args[] = $arg->getDefaultValue(); 00199 } else { 00200 $missing_args[] = $arg->getName(); 00201 } 00202 } 00203 00204 foreach ($request as $key => $value) { 00205 if (substr($key, 0, 3) == 'arg') { 00206 $key = str_replace('arg', '', $key); 00207 $calling_args[$key] = $value; 00208 if (($index = array_search($key, $missing_args)) !== false) { 00209 unset($missing_args[$index]); 00210 } 00211 } 00212 } 00213 00214 // Sort arguments by key -- @see ZF-2279 00215 ksort($calling_args); 00216 00217 $result = false; 00218 if (count($calling_args) < count($func_args)) { 00219 require_once 'Zend/Rest/Server/Exception.php'; 00220 $result = $this->fault(new Zend_Rest_Server_Exception('Invalid Method Call to ' . $this->_method . '. Missing argument(s): ' . implode(', ', $missing_args) . '.'), 400); 00221 } 00222 00223 if (!$result && $this->_functions[$this->_method] instanceof Zend_Server_Reflection_Method) { 00224 // Get class 00225 $class = $this->_functions[$this->_method]->getDeclaringClass()->getName(); 00226 00227 if ($this->_functions[$this->_method]->isStatic()) { 00228 // for some reason, invokeArgs() does not work the same as 00229 // invoke(), and expects the first argument to be an object. 00230 // So, using a callback if the method is static. 00231 $result = $this->_callStaticMethod($class, $calling_args); 00232 } else { 00233 // Object method 00234 $result = $this->_callObjectMethod($class, $calling_args); 00235 } 00236 } elseif (!$result) { 00237 try { 00238 $result = call_user_func_array($this->_functions[$this->_method]->getName(), $calling_args); //$this->_functions[$this->_method]->invokeArgs($calling_args); 00239 } catch (Exception $e) { 00240 $result = $this->fault($e); 00241 } 00242 } 00243 } else { 00244 require_once "Zend/Rest/Server/Exception.php"; 00245 $result = $this->fault( 00246 new Zend_Rest_Server_Exception("Unknown Method '$this->_method'."), 00247 404 00248 ); 00249 } 00250 } else { 00251 require_once "Zend/Rest/Server/Exception.php"; 00252 $result = $this->fault( 00253 new Zend_Rest_Server_Exception("Unknown Method '$this->_method'."), 00254 404 00255 ); 00256 } 00257 } else { 00258 require_once "Zend/Rest/Server/Exception.php"; 00259 $result = $this->fault( 00260 new Zend_Rest_Server_Exception("No Method Specified."), 00261 404 00262 ); 00263 } 00264 00265 if ($result instanceof SimpleXMLElement) { 00266 $response = $result->asXML(); 00267 } elseif ($result instanceof DOMDocument) { 00268 $response = $result->saveXML(); 00269 } elseif ($result instanceof DOMNode) { 00270 $response = $result->ownerDocument->saveXML($result); 00271 } elseif (is_array($result) || is_object($result)) { 00272 $response = $this->_handleStruct($result); 00273 } else { 00274 $response = $this->_handleScalar($result); 00275 } 00276 00277 if (!$this->returnResponse()) { 00278 if (!headers_sent()) { 00279 foreach ($this->_headers as $header) { 00280 header($header); 00281 } 00282 } 00283 00284 echo $response; 00285 return; 00286 } 00287 00288 return $response; 00289 } 00290 00298 public function setClass($classname, $namespace = '', $argv = array()) 00299 { 00300 $this->_args = $argv; 00301 foreach ($this->_reflection->reflectClass($classname, $argv)->getMethods() as $method) { 00302 $this->_functions[$method->getName()] = $method; 00303 } 00304 } 00305 00312 protected function _handleStruct($struct) 00313 { 00314 $function = $this->_functions[$this->_method]; 00315 if ($function instanceof Zend_Server_Reflection_Method) { 00316 $class = $function->getDeclaringClass()->getName(); 00317 } else { 00318 $class = false; 00319 } 00320 00321 $method = $function->getName(); 00322 00323 $dom = new DOMDocument('1.0', $this->getEncoding()); 00324 if ($class) { 00325 $root = $dom->createElement($class); 00326 $method = $dom->createElement($method); 00327 $root->appendChild($method); 00328 } else { 00329 $root = $dom->createElement($method); 00330 $method = $root; 00331 } 00332 $root->setAttribute('generator', 'zend'); 00333 $root->setAttribute('version', '1.0'); 00334 $dom->appendChild($root); 00335 00336 $this->_structValue($struct, $dom, $method); 00337 00338 $struct = (array) $struct; 00339 if (!isset($struct['status'])) { 00340 $status = $dom->createElement('status', 'success'); 00341 $method->appendChild($status); 00342 } 00343 00344 return $dom->saveXML(); 00345 } 00346 00358 protected function _structValue($struct, DOMDocument $dom, DOMElement $parent) 00359 { 00360 $struct = (array) $struct; 00361 00362 foreach ($struct as $key => $value) { 00363 if ($value === false) { 00364 $value = 0; 00365 } elseif ($value === true) { 00366 $value = 1; 00367 } 00368 00369 if (ctype_digit((string) $key)) { 00370 $key = 'key_' . $key; 00371 } 00372 00373 if (is_array($value) || is_object($value)) { 00374 $element = $dom->createElement($key); 00375 $this->_structValue($value, $dom, $element); 00376 } else { 00377 $element = $dom->createElement($key); 00378 $element->appendChild($dom->createTextNode($value)); 00379 } 00380 00381 $parent->appendChild($element); 00382 } 00383 } 00384 00391 protected function _handleScalar($value) 00392 { 00393 $function = $this->_functions[$this->_method]; 00394 if ($function instanceof Zend_Server_Reflection_Method) { 00395 $class = $function->getDeclaringClass()->getName(); 00396 } else { 00397 $class = false; 00398 } 00399 00400 $method = $function->getName(); 00401 00402 $dom = new DOMDocument('1.0', $this->getEncoding()); 00403 if ($class) { 00404 $xml = $dom->createElement($class); 00405 $methodNode = $dom->createElement($method); 00406 $xml->appendChild($methodNode); 00407 } else { 00408 $xml = $dom->createElement($method); 00409 $methodNode = $xml; 00410 } 00411 $xml->setAttribute('generator', 'zend'); 00412 $xml->setAttribute('version', '1.0'); 00413 $dom->appendChild($xml); 00414 00415 if ($value === false) { 00416 $value = 0; 00417 } elseif ($value === true) { 00418 $value = 1; 00419 } 00420 00421 if (isset($value)) { 00422 $element = $dom->createElement('response'); 00423 $element->appendChild($dom->createTextNode($value)); 00424 $methodNode->appendChild($element); 00425 } else { 00426 $methodNode->appendChild($dom->createElement('response')); 00427 } 00428 00429 $methodNode->appendChild($dom->createElement('status', 'success')); 00430 00431 return $dom->saveXML(); 00432 } 00433 00443 public function fault($exception = null, $code = null) 00444 { 00445 if (isset($this->_functions[$this->_method])) { 00446 $function = $this->_functions[$this->_method]; 00447 } elseif (isset($this->_method)) { 00448 $function = $this->_method; 00449 } else { 00450 $function = 'rest'; 00451 } 00452 00453 if ($function instanceof Zend_Server_Reflection_Method) { 00454 $class = $function->getDeclaringClass()->getName(); 00455 } else { 00456 $class = false; 00457 } 00458 00459 if ($function instanceof Zend_Server_Reflection_Function_Abstract) { 00460 $method = $function->getName(); 00461 } else { 00462 $method = $function; 00463 } 00464 00465 $dom = new DOMDocument('1.0', $this->getEncoding()); 00466 if ($class) { 00467 $xml = $dom->createElement($class); 00468 $xmlMethod = $dom->createElement($method); 00469 $xml->appendChild($xmlMethod); 00470 } else { 00471 $xml = $dom->createElement($method); 00472 $xmlMethod = $xml; 00473 } 00474 $xml->setAttribute('generator', 'zend'); 00475 $xml->setAttribute('version', '1.0'); 00476 $dom->appendChild($xml); 00477 00478 $xmlResponse = $dom->createElement('response'); 00479 $xmlMethod->appendChild($xmlResponse); 00480 00481 if ($exception instanceof Exception) { 00482 $element = $dom->createElement('message'); 00483 $element->appendChild($dom->createTextNode($exception->getMessage())); 00484 $xmlResponse->appendChild($element); 00485 $code = $exception->getCode(); 00486 } elseif (($exception !== null) || 'rest' == $function) { 00487 $xmlResponse->appendChild($dom->createElement('message', 'An unknown error occured. Please try again.')); 00488 } else { 00489 $xmlResponse->appendChild($dom->createElement('message', 'Call to ' . $method . ' failed.')); 00490 } 00491 00492 $xmlMethod->appendChild($xmlResponse); 00493 $xmlMethod->appendChild($dom->createElement('status', 'failed')); 00494 00495 // Headers to send 00496 if ($code === null || (404 != $code)) { 00497 $this->_headers[] = 'HTTP/1.0 400 Bad Request'; 00498 } else { 00499 $this->_headers[] = 'HTTP/1.0 404 File Not Found'; 00500 } 00501 00502 return $dom; 00503 } 00504 00510 public function getHeaders() 00511 { 00512 return $this->_headers; 00513 } 00514 00521 public function addFunction($function, $namespace = '') 00522 { 00523 if (!is_array($function)) { 00524 $function = (array) $function; 00525 } 00526 00527 foreach ($function as $func) { 00528 if (is_callable($func) && !in_array($func, self::$magicMethods)) { 00529 $this->_functions[$func] = $this->_reflection->reflectFunction($func); 00530 } else { 00531 require_once 'Zend/Rest/Server/Exception.php'; 00532 throw new Zend_Rest_Server_Exception("Invalid Method Added to Service."); 00533 } 00534 } 00535 } 00536 00542 public function getFunctions() 00543 { 00544 return $this->_functions; 00545 } 00546 00553 public function loadFunctions($functions) 00554 { 00555 } 00556 00563 public function setPersistence($mode) 00564 { 00565 } 00566 00574 protected function _callStaticMethod($class, array $args) 00575 { 00576 try { 00577 $result = call_user_func_array(array($class, $this->_functions[$this->_method]->getName()), $args); 00578 } catch (Exception $e) { 00579 $result = $this->fault($e); 00580 } 00581 return $result; 00582 } 00583 00592 protected function _callObjectMethod($class, array $args) 00593 { 00594 try { 00595 if ($this->_functions[$this->_method]->getDeclaringClass()->getConstructor()) { 00596 $object = $this->_functions[$this->_method]->getDeclaringClass()->newInstanceArgs($this->_args); 00597 } else { 00598 $object = $this->_functions[$this->_method]->getDeclaringClass()->newInstance(); 00599 } 00600 } catch (Exception $e) { 00601 require_once 'Zend/Rest/Server/Exception.php'; 00602 throw new Zend_Rest_Server_Exception('Error instantiating class ' . $class . 00603 ' to invoke method ' . $this->_functions[$this->_method]->getName() . 00604 ' (' . $e->getMessage() . ') ', 00605 500, $e); 00606 } 00607 00608 try { 00609 $result = $this->_functions[$this->_method]->invokeArgs($object, $args); 00610 } catch (Exception $e) { 00611 $result = $this->fault($e); 00612 } 00613 00614 return $result; 00615 } 00616 }