From: Tim Otten Date: Fri, 28 Mar 2014 04:45:16 +0000 (-0700) Subject: CRM-14370 - API Kernel - Move dispatch into helpers X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=5fda6437b5f005ad616356b2414d36394a0d12ca;p=civicrm-core.git CRM-14370 - API Kernel - Move dispatch into helpers Also: Use constants for error codes --- diff --git a/Civi/API/Kernel.php b/Civi/API/Kernel.php index 69f96b8da9..e5c098f9be 100644 --- a/Civi/API/Kernel.php +++ b/Civi/API/Kernel.php @@ -31,6 +31,7 @@ use Civi\API\Event\PrepareEvent; use Civi\API\Event\ExceptionEvent; use Civi\API\Event\ResolveEvent; use Civi\API\Event\RespondEvent; +use Civi\API\Provider\ProviderInterface; /** * @@ -46,7 +47,7 @@ class Kernel { protected $dispatcher; /** - * @var array + * @var array */ protected $apiProviders; @@ -84,26 +85,17 @@ class Kernel { $this->boot(); $errorScope = \CRM_Core_TemporaryErrorScope::useException(); - $resolveEvent = $this->dispatcher->dispatch(Events::RESOLVE, new ResolveEvent($apiRequest)); - $apiRequest = $resolveEvent->getApiRequest(); - $apiProvider = $resolveEvent->getApiProvider(); - if (!$apiProvider) { - throw new \API_Exception("API (" . $apiRequest['entity'] . ", " . $apiRequest['action'] . ") does not exist (join the API team and implement it!)"); - } - - if (! $this->dispatcher->dispatch(Events::AUTHORIZE, new AuthorizeEvent($apiProvider, $apiRequest))->isAuthorized()) { - throw new \API_Exception("Authorization failed", 'unauthorized'); - } - - $apiRequest = $this->dispatcher->dispatch(Events::PREPARE, new PrepareEvent($apiProvider, $apiRequest))->getApiRequest(); + list($apiProvider, $apiRequest) = $this->resolve($apiRequest); + $this->authorize($apiProvider, $apiRequest); + $apiRequest = $this->prepare($apiProvider, $apiRequest); $result = $apiProvider->invoke($apiRequest); if (\CRM_Utils_Array::value('is_error', $result, 0) == 0) { _civicrm_api_call_nested_api($apiRequest['params'], $result, $apiRequest['action'], $apiRequest['entity'], $apiRequest['version']); } - $responseEvent = $this->dispatcher->dispatch(Events::RESPOND, new RespondEvent($apiProvider, $apiRequest, $result)); - return $this->formatResult($apiRequest, $responseEvent->getResponse()); + $apiResponse = $this->respond($apiProvider, $apiRequest, $result); + return $this->formatResult($apiRequest, $apiResponse); } catch (\Exception $e) { $this->dispatcher->dispatch(Events::EXCEPTION, new ExceptionEvent($e, $apiProvider, $apiRequest)); @@ -231,6 +223,61 @@ class Kernel { _civicrm_api3_initialize(); } + /** + * Determine which, if any, service will execute the API request. + * + * @param $apiRequest + * @return array + * @throws \API_Exception + */ + public function resolve($apiRequest) { + $resolveEvent = $this->dispatcher->dispatch(Events::RESOLVE, new ResolveEvent($apiRequest)); + $apiRequest = $resolveEvent->getApiRequest(); + if (!$resolveEvent->getApiProvider()) { + throw new \API_Exception("API (" . $apiRequest['entity'] . ", " . $apiRequest['action'] . ") does not exist (join the API team and implement it!)", \API_Exception::NOT_IMPLEMENTED); + } + return array($resolveEvent->getApiProvider(), $apiRequest); + } + + /** + * Determine if the API request is allowed (under current policy) + * + * @param ProviderInterface $apiProvider + * @param array $apiRequest + * @throws \API_Exception + */ + public function authorize($apiProvider, $apiRequest) { + $event = $this->dispatcher->dispatch(Events::AUTHORIZE, new AuthorizeEvent($apiProvider, $apiRequest)); + if (!$event->isAuthorized()) { + throw new \API_Exception("Authorization failed", \API_Exception::UNAUTHORIZED); + } + } + + /** + * Allow third-party code to manipulate the API request before execution. + * + * @param ProviderInterface $apiProvider + * @param array $apiRequest + * @return mixed + */ + public function prepare($apiProvider, $apiRequest) { + $event = $this->dispatcher->dispatch(Events::PREPARE, new PrepareEvent($apiProvider, $apiRequest)); + return $event->getApiRequest(); + } + + /** + * Allow third-party code to manipulate the API response after execution. + * + * @param ProviderInterface $apiProvider + * @param array $apiRequest + * @param array $result + * @return mixed + */ + public function respond($apiProvider, $apiRequest, $result) { + $event = $this->dispatcher->dispatch(Events::RESPOND, new RespondEvent($apiProvider, $apiRequest, $result)); + return $event->getResponse(); + } + /** * @param \Exception $e * @param array $apiRequest diff --git a/api/Exception.php b/api/Exception.php index 254ab3752d..48d89e7572 100644 --- a/api/Exception.php +++ b/api/Exception.php @@ -21,6 +21,9 @@ */ class API_Exception extends Exception { + const UNAUTHORIZED = 'unauthorized'; + const NOT_IMPLEMENTED = 'not-found'; + private $extraParams = array(); public function __construct($message, $error_code = 0, $extraParams = array(),Exception $previous = null) { if (is_numeric ($error_code)) // using int for error code "old way") @@ -44,7 +47,9 @@ class API_Exception extends Exception return array( 2000 => '$params was not an array', 2001 => 'Invalid Value for Date field', - 2100 => 'String value is longer than permitted length' + 2100 => 'String value is longer than permitted length', + self::UNAUTHORIZED => 'Unauthorized', + self::NOT_IMPLEMENTED => 'Entity or method is not implemented', ); } }