Commit | Line | Data |
---|---|---|
0f643fb2 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | CiviCRM version 4.4 | | |
5 | +--------------------------------------------------------------------+ | |
6 | | Copyright CiviCRM LLC (c) 2004-2013 | | |
7 | +--------------------------------------------------------------------+ | |
8 | | This file is a part of CiviCRM. | | |
9 | | | | |
10 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
11 | | under the terms of the GNU Affero General Public License | | |
12 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
13 | | | | |
14 | | CiviCRM is distributed in the hope that it will be useful, but | | |
15 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
16 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
17 | | See the GNU Affero General Public License for more details. | | |
18 | | | | |
19 | | You should have received a copy of the GNU Affero General Public | | |
20 | | License and the CiviCRM Licensing Exception along | | |
21 | | with this program; if not, contact CiviCRM LLC | | |
22 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
23 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
24 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
25 | +--------------------------------------------------------------------+ | |
26 | */ | |
27 | namespace Civi\API; | |
28 | ||
132ec342 TO |
29 | use Civi\API\Event\AuthorizeEvent; |
30 | use Civi\API\Event\PrepareEvent; | |
31 | use Civi\API\Event\ExceptionEvent; | |
787604ff | 32 | use Civi\API\Event\ResolveEvent; |
132ec342 TO |
33 | use Civi\API\Event\RespondEvent; |
34 | ||
0f643fb2 TO |
35 | /** |
36 | * | |
37 | * @package Civi | |
38 | * @copyright CiviCRM LLC (c) 2004-2013 | |
39 | */ | |
40 | ||
41 | class Kernel { | |
42 | ||
43 | /** | |
44 | * @var \Symfony\Component\EventDispatcher\EventDispatcher | |
45 | */ | |
46 | protected $dispatcher; | |
47 | ||
48 | /** | |
49 | * @var array<APIProviderInterface> | |
50 | */ | |
51 | protected $apiProviders; | |
52 | ||
53 | function __construct($dispatcher, $apiProviders = array()) { | |
54 | $this->apiProviders = $apiProviders; | |
55 | $this->dispatcher = $dispatcher; | |
56 | } | |
57 | ||
58 | /** | |
59 | * @param string $entity | |
60 | * type of entities to deal with | |
61 | * @param string $action | |
62 | * create, get, delete or some special action name. | |
63 | * @param array $params | |
64 | * array to be passed to function | |
65 | * @param null $extra | |
66 | * | |
67 | * @return array|int | |
68 | */ | |
69 | public function run($entity, $action, $params, $extra) { | |
787604ff TO |
70 | /** |
71 | * @var $apiProvider \Civi\API\Provider\ProviderInterface|NULL | |
72 | */ | |
73 | $apiProvider = NULL; | |
74 | ||
61c8f96f | 75 | $apiRequest = $this->createRequest($entity, $action, $params, $extra); |
0f643fb2 | 76 | |
0f643fb2 | 77 | try { |
0f643fb2 TO |
78 | if (!is_array($params)) { |
79 | throw new \API_Exception('Input variable `params` is not an array', 2000); | |
80 | } | |
132ec342 TO |
81 | |
82 | $this->boot(); | |
0f643fb2 | 83 | $errorScope = \CRM_Core_TemporaryErrorScope::useException(); |
132ec342 | 84 | |
787604ff TO |
85 | $resolveEvent = $this->dispatcher->dispatch(Events::RESOLVE, new ResolveEvent($apiRequest)); |
86 | $apiRequest = $resolveEvent->getApiRequest(); | |
87 | $apiProvider = $resolveEvent->getApiProvider(); | |
88 | if (!$apiProvider) { | |
89 | throw new \API_Exception("API (" . $apiRequest['entity'] . ", " . $apiRequest['action'] . ") does not exist (join the API team and implement it!)"); | |
132ec342 TO |
90 | } |
91 | ||
787604ff TO |
92 | if (! $this->dispatcher->dispatch(Events::AUTHORIZE, new AuthorizeEvent($apiProvider, $apiRequest))->isAuthorized()) { |
93 | throw new \API_Exception("Authorization failed", 'unauthorized'); | |
0f643fb2 TO |
94 | } |
95 | ||
787604ff TO |
96 | $apiRequest = $this->dispatcher->dispatch(Events::PREPARE, new PrepareEvent($apiProvider, $apiRequest))->getApiRequest(); |
97 | $result = $apiProvider->invoke($apiRequest); | |
98 | ||
0f643fb2 TO |
99 | if (\CRM_Utils_Array::value('is_error', $result, 0) == 0) { |
100 | _civicrm_api_call_nested_api($apiRequest['params'], $result, $apiRequest['action'], $apiRequest['entity'], $apiRequest['version']); | |
101 | } | |
132ec342 | 102 | |
787604ff | 103 | $responseEvent = $this->dispatcher->dispatch(Events::RESPOND, new RespondEvent($apiProvider, $apiRequest, $result)); |
143ed725 | 104 | return $this->formatResult($apiRequest, $responseEvent->getResponse()); |
0f643fb2 TO |
105 | } |
106 | catch (\Exception $e) { | |
787604ff | 107 | $this->dispatcher->dispatch(Events::EXCEPTION, new ExceptionEvent($e, $apiProvider, $apiRequest)); |
91798b7a | 108 | |
91798b7a TO |
109 | if ($e instanceof \PEAR_Exception) { |
110 | $err = $this->formatPearException($e, $apiRequest); | |
111 | } elseif ($e instanceof \API_Exception) { | |
112 | $err = $this->formatApiException($e, $apiRequest); | |
113 | } else { | |
114 | $err = $this->formatException($e, $apiRequest); | |
0f643fb2 | 115 | } |
91798b7a | 116 | |
143ed725 | 117 | return $this->formatResult($apiRequest, $err); |
0f643fb2 TO |
118 | } |
119 | ||
120 | } | |
132ec342 | 121 | |
61c8f96f TO |
122 | /** |
123 | * Create a formatted/normalized request object. | |
124 | * | |
125 | * @param string $entity | |
126 | * @param string $action | |
127 | * @param array $params | |
128 | * @param mixed $extra | |
129 | * @return array the request descriptor | |
130 | */ | |
131 | public function createRequest($entity, $action, $params, $extra) { | |
132 | $apiRequest = array(); | |
133 | $apiRequest['entity'] = \CRM_Utils_String::munge($entity); | |
134 | $apiRequest['action'] = \CRM_Utils_String::munge($action); | |
135 | $apiRequest['version'] = civicrm_get_api_version($params); | |
136 | $apiRequest['params'] = $params; | |
137 | $apiRequest['extra'] = $extra; | |
138 | $apiRequest['fields'] = NULL; | |
139 | return $apiRequest; | |
140 | } | |
141 | ||
132ec342 TO |
142 | public function boot() { |
143 | require_once ('api/v3/utils.php'); | |
144 | require_once 'api/Exception.php'; | |
145 | _civicrm_api3_initialize(); | |
146 | } | |
91798b7a TO |
147 | |
148 | /** | |
149 | * @param \Exception $e | |
150 | * @param array $apiRequest | |
151 | * @return array (API response) | |
152 | */ | |
153 | public function formatException($e, $apiRequest) { | |
154 | $data = array(); | |
155 | if (!empty($apiRequest['params']['debug'])) { | |
156 | $data['trace'] = $e->getTraceAsString(); | |
157 | } | |
158 | return civicrm_api3_create_error($e->getMessage(), $data, $apiRequest, $e->getCode()); | |
159 | } | |
160 | ||
161 | /** | |
162 | * @param \API_Exception $e | |
163 | * @param array $apiRequest | |
164 | * @return array (API response) | |
165 | */ | |
166 | public function formatApiException($e, $apiRequest) { | |
167 | $data = $e->getExtraParams(); | |
168 | $data['entity'] = \CRM_Utils_Array::value('entity', $apiRequest); | |
169 | $data['action'] = \CRM_Utils_Array::value('action', $apiRequest); | |
170 | ||
171 | if (\CRM_Utils_Array::value('debug', \CRM_Utils_Array::value('params', $apiRequest)) | |
172 | && empty($data['trace']) // prevent recursion | |
173 | ) { | |
174 | $data['trace'] = $e->getTraceAsString(); | |
175 | } | |
176 | ||
177 | return civicrm_api3_create_error($e->getMessage(), $data, $apiRequest, $e->getCode()); | |
178 | } | |
179 | ||
180 | /** | |
181 | * @param \PEAR_Exception $e | |
182 | * @param array $apiRequest | |
183 | * @return array (API response) | |
184 | */ | |
185 | public function formatPearException($e, $apiRequest) { | |
186 | $data = array(); | |
187 | $error = $e->getCause(); | |
188 | if ($error instanceof \DB_Error) { | |
189 | $data["error_code"] = \DB::errorMessage($error->getCode()); | |
190 | $data["sql"] = $error->getDebugInfo(); | |
191 | } | |
192 | if (!empty($apiRequest['params']['debug'])) { | |
193 | if (method_exists($e, 'getUserInfo')) { | |
194 | $data['debug_info'] = $error->getUserInfo(); | |
195 | } | |
196 | if (method_exists($e, 'getExtraData')) { | |
197 | $data['debug_info'] = $data + $error->getExtraData(); | |
198 | } | |
199 | $data['trace'] = $e->getTraceAsString(); | |
200 | } | |
201 | else { | |
202 | $data['tip'] = "add debug=1 to your API call to have more info about the error"; | |
203 | } | |
204 | ||
205 | return civicrm_api3_create_error($e->getMessage(), $data, $apiRequest); | |
206 | } | |
143ed725 TO |
207 | |
208 | /** | |
209 | * @return mixed | |
210 | */ | |
211 | public function formatResult($apiRequest, $result) { | |
212 | if (isset($apiRequest, $apiRequest['params'])) { | |
213 | if (isset($apiRequest['params']['format.is_success']) && $apiRequest['params']['format.is_success'] == 1) { | |
214 | return (empty($result['is_error'])) ? 1 : 0; | |
215 | } | |
216 | ||
217 | if (!empty($apiRequest['params']['format.only_id']) && isset($result['id'])) { | |
218 | // FIXME dispatch | |
219 | return $result['id']; | |
220 | } | |
221 | } | |
222 | return $result; | |
223 | } | |
0f643fb2 | 224 | } |