/** * Main function for processing the api request * and return the response * * @throws Exception when the api service class is missing * @throws RestException to send error response */ public function handle() { try { $this->init(); foreach ($this->filterClasses as $filterClass) { /** * @var iFilter */ $filterObj = new $filterClass(); $filterObj->restler = $this; if (!$filterObj instanceof iFilter) { throw new RestException(500, 'Filter Class ' . 'should implement iFilter'); } else { $ok = $filterObj->__isAllowed(); if (is_null($ok) && $filterObj instanceof iUseAuthentication) { //handle at authentication stage $this->filterObjects[] = $filterObj; continue; } throw new RestException(403); //Forbidden } } Util::setProperties(get_class($this->requestFormat), null, $this->requestFormat); $this->requestData = $this->getRequestData(); //parse defaults foreach ($_GET as $key => $value) { if (isset(Defaults::$aliases[$key])) { $_GET[Defaults::$aliases[$key]] = $value; unset($_GET[$key]); $key = Defaults::$aliases[$key]; } if (in_array($key, Defaults::$overridables)) { Defaults::setProperty($key, $value); } } $this->apiMethodInfo = $o = $this->mapUrlToMethod(); if (isset($o->metadata)) { foreach (Defaults::$fromComments as $key => $defaultsKey) { if (array_key_exists($key, $o->metadata)) { $value = $o->metadata[$key]; Defaults::setProperty($defaultsKey, $value); } } } $result = null; if (!isset($o->className)) { $this->handleError(404); } else { try { $accessLevel = max(Defaults::$apiAccessLevel, $o->accessLevel); if ($accessLevel || count($this->filterObjects)) { if (!count($this->authClasses)) { throw new RestException(401); } foreach ($this->authClasses as $authClass) { $authObj = Util::setProperties($authClass, $o->metadata); if (!method_exists($authObj, Defaults::$authenticationMethod)) { throw new RestException(500, 'Authentication Class ' . 'should implement iAuthenticate'); } elseif (!$authObj->{Defaults::$authenticationMethod}()) { throw new RestException(401); } } $this->authenticated = true; } } catch (RestException $e) { if ($accessLevel > 1) { //when it is not a hybrid api $this->handleError($e->getCode(), $e->getMessage()); } else { $this->authenticated = false; } } try { foreach ($this->filterObjects as $filterObj) { Util::setProperties(get_class($filterObj), $o->metadata, $filterObj); } $preProcess = '_' . $this->requestFormat->getExtension() . '_' . $o->methodName; $this->apiMethod = $o->methodName; $object = $this->apiClassInstance = null; // TODO:check if the api version requested is allowed by class if (Defaults::$autoValidationEnabled) { foreach ($o->metadata['param'] as $index => $param) { $info =& $param[CommentParser::$embeddedDataName]; if (!isset($info['validate']) || $info['validate'] != false) { if (isset($info['method'])) { if (!isset($object)) { $object = $this->apiClassInstance = Util::setProperties($o->className); } $info['apiClassInstance'] = $object; } //convert to instance of ValidationInfo $info = new ValidationInfo($param); $valid = Validator::validate($o->arguments[$index], $info); $o->arguments[$index] = $valid; } } } if (!isset($object)) { $object = $this->apiClassInstance = Util::setProperties($o->className); } if (method_exists($o->className, $preProcess)) { call_user_func_array(array($object, $preProcess), $o->arguments); } switch ($accessLevel) { case 3: //protected method $reflectionMethod = new ReflectionMethod($object, $o->methodName); $reflectionMethod->setAccessible(true); $result = $reflectionMethod->invokeArgs($object, $o->arguments); break; default: $result = call_user_func_array(array($object, $o->methodName), $o->arguments); } } catch (RestException $e) { $this->handleError($e->getCode(), $e->getMessage()); } } $this->sendData($result); } catch (RestException $e) { $this->handleError($e->getCode(), $e->getMessage()); } catch (\Exception $e) { $this->log[] = $e->getMessage(); if ($this->productionMode) { $this->handleError(500); } else { $this->handleError(500, $e->getMessage()); } } }
/** * Use this method to set value to a static properly of Defaults when * you want to make sure only proper values are taken in with the help of * validation * * @static * * @param string $name name of the static property * @param mixed $value value to set the property to * * @return bool */ public static function setProperty($name, $value) { if (!property_exists(__CLASS__, $name)) { return false; } if (@is_array(Defaults::$validation[$name])) { $info = new ValidationInfo(Defaults::$validation[$name]); $value = Validator::validate($value, $info); } Defaults::${$name} = $value; return true; }