Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
6a488035 TO |
2 | /* |
3 | +--------------------------------------------------------------------+ | |
81621fee | 4 | | CiviCRM version 4.7 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
1f4ea726 | 6 | | Copyright CiviCRM LLC (c) 2004-2017 | |
6a488035 TO |
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 | ||
c490a46a CW |
28 | define('API_V3_EXTENSION_DELIMITER', ','); |
29 | ||
30 | ||
6a488035 | 31 | /** |
244bbdd8 | 32 | * This provides an api interface for CiviCRM extension management. |
6a488035 TO |
33 | * |
34 | * @package CiviCRM_APIv3 | |
6a488035 TO |
35 | */ |
36 | ||
37 | /** | |
dc64d047 | 38 | * Install an extension. |
6a488035 | 39 | * |
cf470720 TO |
40 | * @param array $params |
41 | * Input parameters. | |
e5f24f02 CW |
42 | * - key: string, eg "com.example.myextension" |
43 | * - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2") | |
44 | * | |
45 | * Using 'keys' should be more performant than making multiple API calls with 'key' | |
6a488035 | 46 | * |
a6c01b45 | 47 | * @return array |
6a488035 TO |
48 | */ |
49 | function civicrm_api3_extension_install($params) { | |
82b474af | 50 | $keys = _civicrm_api3_getKeys($params); |
dbb0dbe6 | 51 | if (!$keys) { |
6a488035 TO |
52 | return civicrm_api3_create_success(); |
53 | } | |
54 | ||
55 | try { | |
56 | CRM_Extension_System::singleton()->getManager()->install($keys); | |
0db6c3e1 TO |
57 | } |
58 | catch (CRM_Extension_Exception $e) { | |
6a488035 TO |
59 | return civicrm_api3_create_error($e->getMessage()); |
60 | } | |
61 | ||
62 | return civicrm_api3_create_success(); | |
63 | } | |
64 | ||
e5f24f02 CW |
65 | /** |
66 | * Spec function for getfields | |
67 | * @param $fields | |
68 | */ | |
69 | function _civicrm_api3_extension_install_spec(&$fields) { | |
70 | $fields['keys'] = array( | |
71 | 'title' => 'Extension Key(s)', | |
72 | 'api.required' => 1, | |
73 | 'api.aliases' => array('key'), | |
74 | 'type' => CRM_Utils_Type::T_STRING, | |
75 | 'description' => 'Fully qualified name of one or more extensions', | |
76 | ); | |
77 | } | |
78 | ||
9a477d10 | 79 | /** |
d1b0d05e | 80 | * Upgrade an extension - runs upgrade_N hooks and system.flush. |
9a477d10 | 81 | * |
a6c01b45 | 82 | * @return array |
72b3a70c | 83 | * API result |
9a477d10 FG |
84 | */ |
85 | function civicrm_api3_extension_upgrade() { | |
86 | CRM_Core_Invoke::rebuildMenuAndCaches(TRUE); | |
87 | $queue = CRM_Extension_Upgrades::createQueue(); | |
88 | $runner = new CRM_Queue_Runner(array( | |
89 | 'title' => 'Extension Upgrades', | |
90 | 'queue' => $queue, | |
91 | 'errorMode' => CRM_Queue_Runner::ERROR_ABORT, | |
92 | )); | |
93 | ||
94 | try { | |
95 | $result = $runner->runAll(); | |
0db6c3e1 TO |
96 | } |
97 | catch (CRM_Extension_Exception $e) { | |
9a477d10 FG |
98 | return civicrm_api3_create_error($e->getMessage()); |
99 | } | |
100 | ||
101 | if ($result === TRUE) { | |
102 | return civicrm_api3_create_success(); | |
0db6c3e1 TO |
103 | } |
104 | else { | |
9a477d10 FG |
105 | return $result; |
106 | } | |
107 | } | |
108 | ||
6a488035 | 109 | /** |
dc64d047 | 110 | * Enable an extension. |
6a488035 | 111 | * |
cf470720 TO |
112 | * @param array $params |
113 | * Input parameters. | |
e5f24f02 CW |
114 | * - key: string, eg "com.example.myextension" |
115 | * - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2") | |
116 | * | |
117 | * Using 'keys' should be more performant than making multiple API calls with 'key' | |
6a488035 | 118 | * |
a6c01b45 | 119 | * @return array |
6a488035 TO |
120 | */ |
121 | function civicrm_api3_extension_enable($params) { | |
82b474af | 122 | $keys = _civicrm_api3_getKeys($params); |
6a488035 TO |
123 | if (count($keys) == 0) { |
124 | return civicrm_api3_create_success(); | |
125 | } | |
126 | ||
127 | CRM_Extension_System::singleton()->getManager()->enable($keys); | |
128 | return civicrm_api3_create_success(); | |
129 | } | |
130 | ||
e5f24f02 CW |
131 | /** |
132 | * Spec function for getfields | |
133 | * @param $fields | |
134 | */ | |
135 | function _civicrm_api3_extension_enable_spec(&$fields) { | |
136 | _civicrm_api3_extension_install_spec($fields); | |
137 | } | |
138 | ||
6a488035 | 139 | /** |
9d32e6f7 | 140 | * Disable an extension. |
6a488035 | 141 | * |
cf470720 TO |
142 | * @param array $params |
143 | * Input parameters. | |
e5f24f02 CW |
144 | * - key: string, eg "com.example.myextension" |
145 | * - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2") | |
146 | * | |
147 | * Using 'keys' should be more performant than making multiple API calls with 'key' | |
6a488035 | 148 | * |
a6c01b45 | 149 | * @return array |
6a488035 TO |
150 | */ |
151 | function civicrm_api3_extension_disable($params) { | |
82b474af | 152 | $keys = _civicrm_api3_getKeys($params); |
6a488035 TO |
153 | if (count($keys) == 0) { |
154 | return civicrm_api3_create_success(); | |
155 | } | |
156 | ||
157 | CRM_Extension_System::singleton()->getManager()->disable($keys); | |
158 | return civicrm_api3_create_success(); | |
159 | } | |
160 | ||
e5f24f02 CW |
161 | /** |
162 | * Spec function for getfields | |
163 | * @param $fields | |
164 | */ | |
165 | function _civicrm_api3_extension_disable_spec(&$fields) { | |
166 | _civicrm_api3_extension_install_spec($fields); | |
167 | } | |
168 | ||
6a488035 | 169 | /** |
dc64d047 | 170 | * Uninstall an extension. |
6a488035 | 171 | * |
cf470720 TO |
172 | * @param array $params |
173 | * Input parameters. | |
e5f24f02 CW |
174 | * - key: string, eg "com.example.myextension" |
175 | * - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2") | |
176 | * | |
177 | * Using 'keys' should be more performant than making multiple API calls with 'key' | |
178 | * | |
179 | * @todo: removeFiles as optional param | |
6a488035 | 180 | * |
a6c01b45 | 181 | * @return array |
6a488035 TO |
182 | */ |
183 | function civicrm_api3_extension_uninstall($params) { | |
82b474af | 184 | $keys = _civicrm_api3_getKeys($params); |
6a488035 TO |
185 | if (count($keys) == 0) { |
186 | return civicrm_api3_create_success(); | |
187 | } | |
188 | ||
6a488035 TO |
189 | CRM_Extension_System::singleton()->getManager()->uninstall($keys); |
190 | return civicrm_api3_create_success(); | |
191 | } | |
192 | ||
e5f24f02 CW |
193 | /** |
194 | * Spec function for getfields | |
195 | * @param $fields | |
196 | */ | |
197 | function _civicrm_api3_extension_uninstall_spec(&$fields) { | |
198 | _civicrm_api3_extension_install_spec($fields); | |
199 | //$fields['removeFiles'] = array( | |
200 | // 'title' => 'Remove files', | |
201 | // 'description' => 'Whether to remove the source tree. Default FALSE.', | |
202 | // 'type' => CRM_Utils_Type::T_BOOLEAN, | |
203 | //); | |
204 | } | |
205 | ||
6a488035 | 206 | /** |
dc64d047 | 207 | * Download and install an extension. |
6a488035 | 208 | * |
cf470720 TO |
209 | * @param array $params |
210 | * Input parameters. | |
244bbdd8 CW |
211 | * - key: string, eg "com.example.myextension" |
212 | * - url: string eg "http://repo.com/myextension-1.0.zip" | |
6a488035 | 213 | * |
77b97be7 | 214 | * @throws API_Exception |
a6c01b45 | 215 | * @return array |
72b3a70c | 216 | * API result |
6a488035 TO |
217 | */ |
218 | function civicrm_api3_extension_download($params) { | |
6c552737 TO |
219 | if (!array_key_exists('url', $params)) { |
220 | if (!CRM_Extension_System::singleton()->getBrowser()->isEnabled()) { | |
e5f24f02 | 221 | throw new API_Exception('Automatic downloading is disabled. Try adding parameter "url"'); |
6a488035 TO |
222 | } |
223 | if ($reqs = CRM_Extension_System::singleton()->getBrowser()->checkRequirements()) { | |
224 | $first = array_shift($reqs); | |
225 | throw new API_Exception($first['message']); | |
226 | } | |
227 | if ($info = CRM_Extension_System::singleton()->getBrowser()->getExtension($params['key'])) { | |
228 | if ($info->downloadUrl) { | |
229 | $params['url'] = $info->downloadUrl; | |
230 | } | |
231 | } | |
232 | } | |
233 | ||
6c552737 | 234 | if (!array_key_exists('url', $params)) { |
6a488035 TO |
235 | throw new API_Exception('Cannot resolve download url for extension. Try adding parameter "url"'); |
236 | } | |
237 | ||
238 | foreach (CRM_Extension_System::singleton()->getDownloader()->checkRequirements() as $requirement) { | |
239 | return civicrm_api3_create_error($requirement['message']); | |
240 | } | |
241 | ||
6c552737 | 242 | if (!CRM_Extension_System::singleton()->getDownloader()->download($params['key'], $params['url'])) { |
6a488035 TO |
243 | return civicrm_api3_create_error('Download failed - ZIP file is unavailable or malformed'); |
244 | } | |
245 | CRM_Extension_System::singleton()->getCache()->flush(); | |
246 | CRM_Extension_System::singleton(TRUE); | |
c62449ca TO |
247 | if (CRM_Utils_Array::value('install', $params, TRUE)) { |
248 | CRM_Extension_System::singleton()->getManager()->install(array($params['key'])); | |
249 | } | |
6a488035 TO |
250 | |
251 | return civicrm_api3_create_success(); | |
252 | } | |
253 | ||
e5f24f02 CW |
254 | /** |
255 | * Spec function for getfields | |
256 | * @param $fields | |
257 | */ | |
258 | function _civicrm_api3_extension_download_spec(&$fields) { | |
259 | $fields['key'] = array( | |
260 | 'title' => 'Extension Key', | |
261 | 'api.required' => 1, | |
262 | 'type' => CRM_Utils_Type::T_STRING, | |
263 | 'description' => 'Fully qualified name of the extension', | |
264 | ); | |
265 | $fields['url'] = array( | |
266 | 'title' => 'Download URL', | |
267 | 'type' => CRM_Utils_Type::T_STRING, | |
268 | 'description' => 'Optional as the system can determine the url automatically for public extensions', | |
269 | ); | |
c62449ca TO |
270 | $fields['install'] = array( |
271 | 'title' => 'Auto-install', | |
272 | 'type' => CRM_Utils_Type::T_STRING, | |
273 | 'description' => 'Automatically install the downloaded extension', | |
274 | 'api.default' => TRUE, | |
275 | ); | |
e5f24f02 CW |
276 | } |
277 | ||
6a488035 | 278 | /** |
dc64d047 | 279 | * Download and install an extension. |
6a488035 | 280 | * |
cf470720 TO |
281 | * @param array $params |
282 | * Input parameters. | |
244bbdd8 CW |
283 | * - local: bool, whether to rescan local filesystem (default: TRUE) |
284 | * - remote: bool, whether to rescan remote repository (default: TRUE) | |
6a488035 | 285 | * |
a6c01b45 | 286 | * @return array |
72b3a70c | 287 | * API result |
6a488035 TO |
288 | */ |
289 | function civicrm_api3_extension_refresh($params) { | |
6a488035 TO |
290 | $system = CRM_Extension_System::singleton(TRUE); |
291 | ||
292 | if ($params['local']) { | |
293 | $system->getManager()->refresh(); | |
294 | $system->getManager()->getStatuses(); // force immediate scan | |
295 | } | |
296 | ||
297 | if ($params['remote']) { | |
298 | if ($system->getBrowser()->isEnabled() && empty($system->getBrowser()->checkRequirements)) { | |
299 | $system->getBrowser()->refresh(); | |
300 | $system->getBrowser()->getExtensions(); // force immediate download | |
301 | } | |
302 | } | |
303 | ||
304 | return civicrm_api3_create_success(); | |
305 | } | |
306 | ||
e5f24f02 CW |
307 | /** |
308 | * Spec function for getfields | |
309 | * @param $fields | |
310 | */ | |
311 | function _civicrm_api3_extension_refresh_spec(&$fields) { | |
312 | $fields['local'] = array( | |
313 | 'title' => 'Rescan Local', | |
314 | 'api.default' => 1, | |
315 | 'type' => CRM_Utils_Type::T_BOOLEAN, | |
316 | 'description' => 'Whether to rescan the local filesystem (default TRUE)', | |
317 | ); | |
318 | $fields['remote'] = array( | |
319 | 'title' => 'Rescan Remote', | |
320 | 'api.default' => 1, | |
321 | 'type' => CRM_Utils_Type::T_BOOLEAN, | |
322 | 'description' => 'Whether to rescan the remote repository (default TRUE)', | |
323 | ); | |
324 | } | |
325 | ||
6a488035 | 326 | /** |
d1b0d05e | 327 | * Get a list of available extensions. |
6a488035 | 328 | * |
c490a46a | 329 | * @param array $params |
77b97be7 | 330 | * |
a6c01b45 | 331 | * @return array |
72b3a70c | 332 | * API result |
6a488035 TO |
333 | */ |
334 | function civicrm_api3_extension_get($params) { | |
df4848b8 TS |
335 | $full_names = _civicrm_api3_getKeys($params, 'full_name'); |
336 | $keys = _civicrm_api3_getKeys($params, 'key'); | |
337 | $keys = array_merge($full_names, $keys); | |
6a488035 | 338 | $statuses = CRM_Extension_System::singleton()->getManager()->getStatuses(); |
517dfba8 | 339 | $mapper = CRM_Extension_System::singleton()->getMapper(); |
6a488035 | 340 | $result = array(); |
c36fe5b0 | 341 | $id = 0; |
6a488035 | 342 | foreach ($statuses as $key => $status) { |
517dfba8 AS |
343 | try { |
344 | $obj = $mapper->keyToInfo($key); | |
345 | } | |
346 | catch (CRM_Extension_Exception $ex) { | |
347 | CRM_Core_Session::setStatus(ts('Failed to read extension (%1). Please refresh the extension list.', array(1 => $key))); | |
348 | continue; | |
349 | } | |
350 | $info = CRM_Extension_System::createExtendedInfo($obj); | |
c36fe5b0 | 351 | $info['id'] = $id++; // backward compatibility with indexing scheme |
df4848b8 | 352 | if (!empty($keys)) { |
d4c44c70 SL |
353 | if (in_array($key, $keys)) { |
354 | $result[] = $info; | |
355 | } | |
356 | } | |
357 | else { | |
358 | $result[] = $info; | |
359 | } | |
6a488035 | 360 | } |
9776f417 | 361 | $options = _civicrm_api3_get_options_from_params($params); |
525ccb68 TS |
362 | $returnFields = !empty($options['return']) ? $options['return'] : array(); |
363 | if (!in_array('id', $returnFields)) { | |
364 | $returnFields = array_merge($returnFields, array('id')); | |
365 | } | |
d4c44c70 | 366 | return _civicrm_api3_basic_array_get('Extension', $params, $result, 'id', $returnFields); |
6a488035 TO |
367 | } |
368 | ||
c74a6c8f AS |
369 | /** |
370 | * Get a list of remotely available extensions. | |
371 | * | |
372 | * @param array $params | |
373 | * | |
374 | * @return array | |
375 | * API result | |
376 | */ | |
377 | function civicrm_api3_extension_getremote($params) { | |
378 | $extensions = CRM_Extension_System::singleton()->getBrowser()->getExtensions(); | |
379 | $result = array(); | |
380 | $id = 0; | |
381 | foreach ($extensions as $key => $obj) { | |
382 | $info = array(); | |
383 | $info['id'] = $id++; // backward compatibility with indexing scheme | |
384 | $info = array_merge($info, (array) $obj); | |
385 | $result[] = $info; | |
386 | } | |
387 | return _civicrm_api3_basic_array_get('Extension', $params, $result, 'id', CRM_Utils_Array::value('return', $params, array())); | |
388 | } | |
389 | ||
6a488035 | 390 | /** |
d1b0d05e | 391 | * Determine the list of extension keys. |
6a488035 | 392 | * |
cf470720 | 393 | * @param array $params |
df4848b8 | 394 | * @param string $key |
dbb0dbe6 | 395 | * API request params with 'keys'. |
d1b0d05e | 396 | * |
a6c01b45 | 397 | * @return array |
6a488035 | 398 | */ |
82b474af | 399 | function _civicrm_api3_getKeys($params, $key = 'keys') { |
83f51f6a TS |
400 | if (isset($params[$key])) { |
401 | if (is_array($params[$key])) { | |
402 | return $params[$key]; | |
403 | } | |
404 | if ($params[$key] == '') { | |
405 | return array(); | |
406 | } | |
407 | return explode(API_V3_EXTENSION_DELIMITER, $params[$key]); | |
6f59c19b TS |
408 | } |
409 | else { | |
dbb0dbe6 | 410 | return array(); |
6a488035 TO |
411 | } |
412 | } |