Avoid CiviCRM running full drupal cache flush, as this results in CiviCRM clobbering...
[civicrm-core.git] / Civi / API / Kernel.php
index eb17709aaf820417015fe2fd755354b6260974b8..9f224965fd22c6ae6bcdbbbf91108525e442aec3 100644 (file)
@@ -1,9 +1,9 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.4                                                |
+ | CiviCRM version 4.6                                                |
  +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2013                                |
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
  +--------------------------------------------------------------------+
  | This file is a part of CiviCRM.                                    |
  |                                                                    |
@@ -23,7 +23,7 @@
  | GNU Affero General Public License or the licensing of CiviCRM,     |
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
-*/
+ */
 namespace Civi\API;
 
 use Civi\API\Event\AuthorizeEvent;
@@ -34,11 +34,9 @@ use Civi\API\Event\RespondEvent;
 use Civi\API\Provider\ProviderInterface;
 
 /**
- *
  * @package Civi
- * @copyright CiviCRM LLC (c) 2004-2013
+ * @copyright CiviCRM LLC (c) 2004-2015
  */
-
 class Kernel {
 
   /**
@@ -52,22 +50,25 @@ class Kernel {
   protected $apiProviders;
 
   /**
-   * @param $dispatcher
+   * @param \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
+   *   The event dispatcher which receives kernel events.
    * @param array $apiProviders
+   *   Array of ProviderInterface.
    */
-  function __construct($dispatcher, $apiProviders = array()) {
+  public function __construct($dispatcher, $apiProviders = array()) {
     $this->apiProviders = $apiProviders;
     $this->dispatcher = $dispatcher;
   }
 
   /**
    * @param string $entity
-   *   type of entities to deal with
+   *   Type of entities to deal with.
    * @param string $action
-   *   create, get, delete or some special action name.
+   *   Create, get, delete or some special action name.
    * @param array $params
-   *   array to be passed to function
-   * @param null $extra
+   *   Array to be passed to API function.
+   * @param mixed $extra
+   *   Who knows.
    *
    * @return array|int
    */
@@ -98,13 +99,15 @@ class Kernel {
       return $this->formatResult($apiRequest, $apiResponse);
     }
     catch (\Exception $e) {
-      $this->dispatcher->dispatch(Events::EXCEPTION, new ExceptionEvent($e, $apiProvider, $apiRequest));
+      $this->dispatcher->dispatch(Events::EXCEPTION, new ExceptionEvent($e, $apiProvider, $apiRequest, $this));
 
       if ($e instanceof \PEAR_Exception) {
         $err = $this->formatPearException($e, $apiRequest);
-      } elseif ($e instanceof \API_Exception) {
+      }
+      elseif ($e instanceof \API_Exception) {
         $err = $this->formatApiException($e, $apiRequest);
-      } else {
+      }
+      else {
         $err = $this->formatException($e, $apiRequest);
       }
 
@@ -112,8 +115,41 @@ class Kernel {
     }
   }
 
+  /**
+   * Determine if a hypothetical API call would be authorized.
+   *
+   * @param string $entity
+   *   Type of entities to deal with.
+   * @param string $action
+   *   Create, get, delete or some special action name.
+   * @param array $params
+   *   Array to be passed to function.
+   * @param mixed $extra
+   *   Who knows.
+   * @return bool
+   *   TRUE if authorization would succeed.
+   * @throws \Exception
+   */
+  public function runAuthorize($entity, $action, $params, $extra = NULL) {
+    $apiProvider = NULL;
+    $apiRequest = Request::create($entity, $action, $params, $extra);
+
+    try {
+      $this->boot();
+      list($apiProvider, $apiRequest) = $this->resolve($apiRequest);
+      $this->authorize($apiProvider, $apiRequest);
+      return TRUE;
+    }
+    catch (\Civi\API\Exception\UnauthorizedException $e) {
+      return FALSE;
+    }
+  }
+
+  /**
+   * Bootstrap - Load basic dependencies.
+   */
   public function boot() {
-    require_once ('api/v3/utils.php');
+    require_once 'api/v3/utils.php';
     require_once 'api/Exception.php';
     _civicrm_api3_initialize();
   }
@@ -122,12 +158,14 @@ class Kernel {
    * Determine which, if any, service will execute the API request.
    *
    * @param array $apiRequest
+   *   The full description of the API request.
    * @throws Exception\NotImplementedException
    * @return array
+   *   Array(0 => ProviderInterface, 1 => array).
    */
   public function resolve($apiRequest) {
     /** @var ResolveEvent $resolveEvent */
-    $resolveEvent = $this->dispatcher->dispatch(Events::RESOLVE, new ResolveEvent($apiRequest));
+    $resolveEvent = $this->dispatcher->dispatch(Events::RESOLVE, new ResolveEvent($apiRequest, $this));
     $apiRequest = $resolveEvent->getApiRequest();
     if (!$resolveEvent->getApiProvider()) {
       throw new \Civi\API\Exception\NotImplementedException("API (" . $apiRequest['entity'] . ", " . $apiRequest['action'] . ") does not exist (join the API team and implement it!)");
@@ -139,12 +177,14 @@ class Kernel {
    * Determine if the API request is allowed (under current policy)
    *
    * @param ProviderInterface $apiProvider
+   *   The API provider responsible for executing the request.
    * @param array $apiRequest
+   *   The full description of the API request.
    * @throws Exception\UnauthorizedException
    */
   public function authorize($apiProvider, $apiRequest) {
     /** @var AuthorizeEvent $event */
-    $event = $this->dispatcher->dispatch(Events::AUTHORIZE, new AuthorizeEvent($apiProvider, $apiRequest));
+    $event = $this->dispatcher->dispatch(Events::AUTHORIZE, new AuthorizeEvent($apiProvider, $apiRequest, $this));
     if (!$event->isAuthorized()) {
       throw new \Civi\API\Exception\UnauthorizedException("Authorization failed");
     }
@@ -154,12 +194,14 @@ class Kernel {
    * Allow third-party code to manipulate the API request before execution.
    *
    * @param ProviderInterface $apiProvider
+   *   The API provider responsible for executing the request.
    * @param array $apiRequest
+   *   The full description of the API request.
    * @return mixed
    */
   public function prepare($apiProvider, $apiRequest) {
     /** @var PrepareEvent $event */
-    $event = $this->dispatcher->dispatch(Events::PREPARE, new PrepareEvent($apiProvider, $apiRequest));
+    $event = $this->dispatcher->dispatch(Events::PREPARE, new PrepareEvent($apiProvider, $apiRequest, $this));
     return $event->getApiRequest();
   }
 
@@ -167,19 +209,24 @@ class Kernel {
    * Allow third-party code to manipulate the API response after execution.
    *
    * @param ProviderInterface $apiProvider
+   *   The API provider responsible for executing the request.
    * @param array $apiRequest
+   *   The full description of the API request.
    * @param array $result
+   *   The response to return to the client.
    * @return mixed
    */
   public function respond($apiProvider, $apiRequest, $result) {
     /** @var RespondEvent $event */
-    $event = $this->dispatcher->dispatch(Events::RESPOND, new RespondEvent($apiProvider, $apiRequest, $result));
+    $event = $this->dispatcher->dispatch(Events::RESPOND, new RespondEvent($apiProvider, $apiRequest, $result, $this));
     return $event->getResponse();
   }
 
   /**
    * @param int $version
-   * @return array<string>
+   *   API version.
+   * @return array
+   *   Array<string>.
    */
   public function getEntityNames($version) {
     // Question: Would it better to eliminate $this->apiProviders and just use $this->dispatcher?
@@ -195,8 +242,11 @@ class Kernel {
 
   /**
    * @param int $version
+   *   API version.
    * @param string $entity
-   * @return array<string>
+   *   API entity.
+   * @return array
+   *   Array<string>
    */
   public function getActionNames($version, $entity) {
     // Question: Would it better to eliminate $this->apiProviders and just use $this->dispatcher?
@@ -212,8 +262,11 @@ class Kernel {
 
   /**
    * @param \Exception $e
+   *   An unhandled exception.
    * @param array $apiRequest
-   * @return array (API response)
+   *   The full description of the API request.
+   * @return array
+   *   API response.
    */
   public function formatException($e, $apiRequest) {
     $data = array();
@@ -225,8 +278,11 @@ class Kernel {
 
   /**
    * @param \API_Exception $e
+   *   An unhandled exception.
    * @param array $apiRequest
-   * @return array (API response)
+   *   The full description of the API request.
+   * @return array
+   *   (API response)
    */
   public function formatApiException($e, $apiRequest) {
     $data = $e->getExtraParams();
@@ -244,8 +300,11 @@ class Kernel {
 
   /**
    * @param \PEAR_Exception $e
+   *   An unhandled exception.
    * @param array $apiRequest
-   * @return array (API response)
+   *   The full description of the API request.
+   * @return array
+   *   API response.
    */
   public function formatPearException($e, $apiRequest) {
     $data = array();
@@ -272,20 +331,26 @@ class Kernel {
 
   /**
    * @param string $msg
+   *   Descriptive error message.
    * @param array $data
+   *   Error data.
    * @param array $apiRequest
-   * @param mixed $code doesn't appear to be used
+   *   The full description of the API request.
+   * @param mixed $code
+   *   Doesn't appear to be used.
    *
    * @throws \API_Exception
-   * @return array <type>
+   * @return array
+   *   Array<type>.
    */
-  function createError($msg, $data, $apiRequest, $code = NULL) {
+  public function createError($msg, $data, $apiRequest, $code = NULL) {
     // FIXME what to do with $code?
     if ($msg == 'DB Error: constraint violation' || substr($msg, 0, 9) == 'DB Error:' || $msg == 'DB Error: already exists') {
       try {
         $fields = _civicrm_api3_api_getfields($apiRequest);
         _civicrm_api3_validate_fields($apiRequest['entity'], $apiRequest['action'], $apiRequest['params'], $fields, TRUE);
-      } catch (\Exception $e) {
+      }
+      catch (\Exception $e) {
         $msg = $e->getMessage();
       }
     }
@@ -302,7 +367,9 @@ class Kernel {
 
   /**
    * @param array $apiRequest
+   *   The full description of the API request.
    * @param array $result
+   *   The response to return to the client.
    * @return mixed
    */
   public function formatResult($apiRequest, $result) {
@@ -328,6 +395,7 @@ class Kernel {
 
   /**
    * @param array $apiProviders
+   *   Array<ProviderInterface>.
    * @return Kernel
    */
   public function setApiProviders($apiProviders) {
@@ -337,6 +405,7 @@ class Kernel {
 
   /**
    * @param ProviderInterface $apiProvider
+   *   The API provider responsible for executing the request.
    * @return Kernel
    */
   public function registerApiProvider($apiProvider) {
@@ -356,10 +425,12 @@ class Kernel {
 
   /**
    * @param \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
+   *   The event dispatcher which receives kernel events.
    * @return Kernel
    */
   public function setDispatcher($dispatcher) {
     $this->dispatcher = $dispatcher;
     return $this;
   }
+
 }