427 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			427 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /*
 | |
|  +--------------------------------------------------------------------+
 | |
|  | CiviCRM version 4.7                                                |
 | |
|  +--------------------------------------------------------------------+
 | |
|  | Copyright CiviCRM LLC (c) 2004-2017                                |
 | |
|  +--------------------------------------------------------------------+
 | |
|  | This file is a part of CiviCRM.                                    |
 | |
|  |                                                                    |
 | |
|  | CiviCRM is free software; you can copy, modify, and distribute it  |
 | |
|  | under the terms of the GNU Affero General Public License           |
 | |
|  | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
 | |
|  |                                                                    |
 | |
|  | CiviCRM is distributed in the hope that it will be useful, but     |
 | |
|  | WITHOUT ANY WARRANTY; without even the implied warranty of         |
 | |
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
 | |
|  | See the GNU Affero General Public License for more details.        |
 | |
|  |                                                                    |
 | |
|  | You should have received a copy of the GNU Affero General Public   |
 | |
|  | License and the CiviCRM Licensing Exception along                  |
 | |
|  | with this program; if not, contact CiviCRM LLC                     |
 | |
|  | at info[AT]civicrm[DOT]org. If you have questions about the        |
 | |
|  | GNU Affero General Public License or the licensing of CiviCRM,     |
 | |
|  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
 | |
|  +--------------------------------------------------------------------+
 | |
|  */
 | |
| 
 | |
| define('API_V3_EXTENSION_DELIMITER', ',');
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * This provides an api interface for CiviCRM extension management.
 | |
|  *
 | |
|  * @package CiviCRM_APIv3
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Install an extension.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *   Input parameters.
 | |
|  *    - key: string, eg "com.example.myextension"
 | |
|  *    - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2")
 | |
|  *    - path: string, e.g. "/var/www/extensions/*"
 | |
|  *
 | |
|  * Using 'keys' should be more performant than making multiple API calls with 'key'
 | |
|  *
 | |
|  * @return array
 | |
|  */
 | |
| function civicrm_api3_extension_install($params) {
 | |
|   $keys = _civicrm_api3_getKeys($params);
 | |
|   if (!$keys) {
 | |
|     return civicrm_api3_create_success();
 | |
|   }
 | |
| 
 | |
|   try {
 | |
|     $manager = CRM_Extension_System::singleton()->getManager();
 | |
|     $manager->install($manager->findInstallRequirements($keys));
 | |
|   }
 | |
|   catch (CRM_Extension_Exception $e) {
 | |
|     return civicrm_api3_create_error($e->getMessage());
 | |
|   }
 | |
| 
 | |
|   return civicrm_api3_create_success();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Spec function for getfields
 | |
|  * @param $fields
 | |
|  */
 | |
| function _civicrm_api3_extension_install_spec(&$fields) {
 | |
|   $fields['keys'] = array(
 | |
|     'title' => 'Extension Key(s)',
 | |
|     'api.aliases' => array('key'),
 | |
|     'type' => CRM_Utils_Type::T_STRING,
 | |
|     'description' => 'Fully qualified name of one or more extensions',
 | |
|   );
 | |
|   $fields['path'] = array(
 | |
|     'title' => 'Extension Path',
 | |
|     'type' => CRM_Utils_Type::T_STRING,
 | |
|     'description' => 'The path to the extension. May use wildcard ("*").',
 | |
|   );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Upgrade an extension - runs upgrade_N hooks and system.flush.
 | |
|  *
 | |
|  * @return array
 | |
|  *   API result
 | |
|  */
 | |
| function civicrm_api3_extension_upgrade() {
 | |
|   CRM_Core_Invoke::rebuildMenuAndCaches(TRUE);
 | |
|   $queue = CRM_Extension_Upgrades::createQueue();
 | |
|   $runner = new CRM_Queue_Runner(array(
 | |
|     'title' => 'Extension Upgrades',
 | |
|     'queue' => $queue,
 | |
|     'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
 | |
|   ));
 | |
| 
 | |
|   try {
 | |
|     $result = $runner->runAll();
 | |
|   }
 | |
|   catch (CRM_Extension_Exception $e) {
 | |
|     return civicrm_api3_create_error($e->getMessage());
 | |
|   }
 | |
| 
 | |
|   if ($result === TRUE) {
 | |
|     return civicrm_api3_create_success();
 | |
|   }
 | |
|   else {
 | |
|     return $result;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Enable an extension.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *   Input parameters.
 | |
|  *    - key: string, eg "com.example.myextension"
 | |
|  *    - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2")
 | |
|  *    - path: string, e.g. "/var/www/vendor/foo/myext" or "/var/www/vendor/*"
 | |
|  *
 | |
|  * Using 'keys' should be more performant than making multiple API calls with 'key'
 | |
|  *
 | |
|  * @return array
 | |
|  */
 | |
| function civicrm_api3_extension_enable($params) {
 | |
|   $keys = _civicrm_api3_getKeys($params);
 | |
|   if (count($keys) == 0) {
 | |
|     return civicrm_api3_create_success();
 | |
|   }
 | |
| 
 | |
|   $manager = CRM_Extension_System::singleton()->getManager();
 | |
|   $manager->enable($manager->findInstallRequirements($keys));
 | |
|   return civicrm_api3_create_success();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Spec function for getfields
 | |
|  * @param $fields
 | |
|  */
 | |
| function _civicrm_api3_extension_enable_spec(&$fields) {
 | |
|   _civicrm_api3_extension_install_spec($fields);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Disable an extension.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *   Input parameters.
 | |
|  *    - key: string, eg "com.example.myextension"
 | |
|  *    - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2")
 | |
|  *    - path: string, e.g. "/var/www/vendor/foo/myext" or "/var/www/vendor/*"
 | |
|  *
 | |
|  * Using 'keys' should be more performant than making multiple API calls with 'key'
 | |
|  *
 | |
|  * @return array
 | |
|  */
 | |
| function civicrm_api3_extension_disable($params) {
 | |
|   $keys = _civicrm_api3_getKeys($params);
 | |
|   if (count($keys) == 0) {
 | |
|     return civicrm_api3_create_success();
 | |
|   }
 | |
| 
 | |
|   CRM_Extension_System::singleton()->getManager()->disable($keys);
 | |
|   return civicrm_api3_create_success();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Spec function for getfields
 | |
|  * @param $fields
 | |
|  */
 | |
| function _civicrm_api3_extension_disable_spec(&$fields) {
 | |
|   _civicrm_api3_extension_install_spec($fields);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Uninstall an extension.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *   Input parameters.
 | |
|  *    - key: string, eg "com.example.myextension"
 | |
|  *    - keys: array of string, eg array("com.example.myextension1", "com.example.myextension2")
 | |
|  *    - path: string, e.g. "/var/www/vendor/foo/myext" or "/var/www/vendor/*"
 | |
|  *
 | |
|  * Using 'keys' should be more performant than making multiple API calls with 'key'
 | |
|  *
 | |
|  * @todo: removeFiles as optional param
 | |
|  *
 | |
|  * @return array
 | |
|  */
 | |
| function civicrm_api3_extension_uninstall($params) {
 | |
|   $keys = _civicrm_api3_getKeys($params);
 | |
|   if (count($keys) == 0) {
 | |
|     return civicrm_api3_create_success();
 | |
|   }
 | |
| 
 | |
|   CRM_Extension_System::singleton()->getManager()->uninstall($keys);
 | |
|   return civicrm_api3_create_success();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Spec function for getfields
 | |
|  * @param $fields
 | |
|  */
 | |
| function _civicrm_api3_extension_uninstall_spec(&$fields) {
 | |
|   _civicrm_api3_extension_install_spec($fields);
 | |
|   //$fields['removeFiles'] = array(
 | |
|   //  'title' => 'Remove files',
 | |
|   //  'description' => 'Whether to remove the source tree. Default FALSE.',
 | |
|   //  'type' => CRM_Utils_Type::T_BOOLEAN,
 | |
|   //);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Download and install an extension.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *   Input parameters.
 | |
|  *   - key: string, eg "com.example.myextension"
 | |
|  *   - url: string eg "http://repo.com/myextension-1.0.zip"
 | |
|  *
 | |
|  * @throws API_Exception
 | |
|  * @return array
 | |
|  *   API result
 | |
|  */
 | |
| function civicrm_api3_extension_download($params) {
 | |
|   if (!array_key_exists('url', $params)) {
 | |
|     if (!CRM_Extension_System::singleton()->getBrowser()->isEnabled()) {
 | |
|       throw new API_Exception('Automatic downloading is disabled. Try adding parameter "url"');
 | |
|     }
 | |
|     if ($reqs = CRM_Extension_System::singleton()->getBrowser()->checkRequirements()) {
 | |
|       $first = array_shift($reqs);
 | |
|       throw new API_Exception($first['message']);
 | |
|     }
 | |
|     if ($info = CRM_Extension_System::singleton()->getBrowser()->getExtension($params['key'])) {
 | |
|       if ($info->downloadUrl) {
 | |
|         $params['url'] = $info->downloadUrl;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!array_key_exists('url', $params)) {
 | |
|     throw new API_Exception('Cannot resolve download url for extension. Try adding parameter "url"');
 | |
|   }
 | |
| 
 | |
|   foreach (CRM_Extension_System::singleton()->getDownloader()->checkRequirements() as $requirement) {
 | |
|     return civicrm_api3_create_error($requirement['message']);
 | |
|   }
 | |
| 
 | |
|   if (!CRM_Extension_System::singleton()->getDownloader()->download($params['key'], $params['url'])) {
 | |
|     return civicrm_api3_create_error('Download failed - ZIP file is unavailable or malformed');
 | |
|   }
 | |
|   CRM_Extension_System::singleton()->getCache()->flush();
 | |
|   CRM_Extension_System::singleton(TRUE);
 | |
|   if (CRM_Utils_Array::value('install', $params, TRUE)) {
 | |
|     CRM_Extension_System::singleton()->getManager()->install(array($params['key']));
 | |
|   }
 | |
| 
 | |
|   return civicrm_api3_create_success();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Spec function for getfields
 | |
|  * @param $fields
 | |
|  */
 | |
| function _civicrm_api3_extension_download_spec(&$fields) {
 | |
|   $fields['key'] = array(
 | |
|     'title' => 'Extension Key',
 | |
|     'api.required' => 1,
 | |
|     'type' => CRM_Utils_Type::T_STRING,
 | |
|     'description' => 'Fully qualified name of the extension',
 | |
|   );
 | |
|   $fields['url'] = array(
 | |
|     'title' => 'Download URL',
 | |
|     'type' => CRM_Utils_Type::T_STRING,
 | |
|     'description' => 'Optional as the system can determine the url automatically for public extensions',
 | |
|   );
 | |
|   $fields['install'] = array(
 | |
|     'title' => 'Auto-install',
 | |
|     'type' => CRM_Utils_Type::T_STRING,
 | |
|     'description' => 'Automatically install the downloaded extension',
 | |
|     'api.default' => TRUE,
 | |
|   );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Download and install an extension.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *   Input parameters.
 | |
|  *   - local: bool, whether to rescan local filesystem (default: TRUE)
 | |
|  *   - remote: bool, whether to rescan remote repository (default: TRUE)
 | |
|  *
 | |
|  * @return array
 | |
|  *   API result
 | |
|  */
 | |
| function civicrm_api3_extension_refresh($params) {
 | |
|   $system = CRM_Extension_System::singleton(TRUE);
 | |
| 
 | |
|   if ($params['local']) {
 | |
|     $system->getManager()->refresh();
 | |
|     $system->getManager()->getStatuses(); // force immediate scan
 | |
|   }
 | |
| 
 | |
|   if ($params['remote']) {
 | |
|     if ($system->getBrowser()->isEnabled() && empty($system->getBrowser()->checkRequirements)) {
 | |
|       $system->getBrowser()->refresh();
 | |
|       $system->getBrowser()->getExtensions(); // force immediate download
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return civicrm_api3_create_success();
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Spec function for getfields
 | |
|  * @param $fields
 | |
|  */
 | |
| function _civicrm_api3_extension_refresh_spec(&$fields) {
 | |
|   $fields['local'] = array(
 | |
|     'title' => 'Rescan Local',
 | |
|     'api.default' => 1,
 | |
|     'type' => CRM_Utils_Type::T_BOOLEAN,
 | |
|     'description' => 'Whether to rescan the local filesystem (default TRUE)',
 | |
|   );
 | |
|   $fields['remote'] = array(
 | |
|     'title' => 'Rescan Remote',
 | |
|     'api.default' => 1,
 | |
|     'type' => CRM_Utils_Type::T_BOOLEAN,
 | |
|     'description' => 'Whether to rescan the remote repository (default TRUE)',
 | |
|   );
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get a list of available extensions.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *
 | |
|  * @return array
 | |
|  *   API result
 | |
|  */
 | |
| function civicrm_api3_extension_get($params) {
 | |
|   $full_names = _civicrm_api3_getKeys($params, 'full_name');
 | |
|   $keys = _civicrm_api3_getKeys($params, 'key');
 | |
|   $keys = array_merge($full_names, $keys);
 | |
|   $statuses = CRM_Extension_System::singleton()->getManager()->getStatuses();
 | |
|   $mapper = CRM_Extension_System::singleton()->getMapper();
 | |
|   $result = array();
 | |
|   $id = 0;
 | |
|   foreach ($statuses as $key => $status) {
 | |
|     try {
 | |
|       $obj = $mapper->keyToInfo($key);
 | |
|     }
 | |
|     catch (CRM_Extension_Exception $ex) {
 | |
|       CRM_Core_Session::setStatus(ts('Failed to read extension (%1). Please refresh the extension list.', array(1 => $key)));
 | |
|       continue;
 | |
|     }
 | |
|     $info = CRM_Extension_System::createExtendedInfo($obj);
 | |
|     $info['id'] = $id++; // backward compatibility with indexing scheme
 | |
|     if (!empty($keys)) {
 | |
|       if (in_array($key, $keys)) {
 | |
|         $result[] = $info;
 | |
|       }
 | |
|     }
 | |
|     else {
 | |
|       $result[] = $info;
 | |
|     }
 | |
|   }
 | |
|   $options = _civicrm_api3_get_options_from_params($params);
 | |
|   $returnFields = !empty($options['return']) ? $options['return'] : array();
 | |
|   if (!in_array('id', $returnFields)) {
 | |
|     $returnFields = array_merge($returnFields, array('id'));
 | |
|   }
 | |
|   return _civicrm_api3_basic_array_get('Extension', $params, $result, 'id', $returnFields);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Get a list of remotely available extensions.
 | |
|  *
 | |
|  * @param array $params
 | |
|  *
 | |
|  * @return array
 | |
|  *   API result
 | |
|  */
 | |
| function civicrm_api3_extension_getremote($params) {
 | |
|   $extensions = CRM_Extension_System::singleton()->getBrowser()->getExtensions();
 | |
|   $result = array();
 | |
|   $id = 0;
 | |
|   foreach ($extensions as $key => $obj) {
 | |
|     $info = array();
 | |
|     $info['id'] = $id++; // backward compatibility with indexing scheme
 | |
|     $info = array_merge($info, (array) $obj);
 | |
|     $result[] = $info;
 | |
|   }
 | |
|   return _civicrm_api3_basic_array_get('Extension', $params, $result, 'id', CRM_Utils_Array::value('return', $params, array()));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Determine the list of extension keys.
 | |
|  *
 | |
|  * @param array $params
 | |
|  * @param string $key
 | |
|  *   API request params with 'keys' or 'path'.
 | |
|  *   - keys: A comma-delimited list of extension names
 | |
|  *   - path: An absolute directory path. May append '*' to match all sub-directories.
 | |
|  *
 | |
|  * @return array
 | |
|  */
 | |
| function _civicrm_api3_getKeys($params, $key = 'keys') {
 | |
|   if ($key == 'path') {
 | |
|     return CRM_Extension_System::singleton()->getMapper()->getKeysByPath($params['path']);
 | |
|   }
 | |
|   if (isset($params[$key])) {
 | |
|     if (is_array($params[$key])) {
 | |
|       return $params[$key];
 | |
|     }
 | |
|     if ($params[$key] == '') {
 | |
|       return array();
 | |
|     }
 | |
|     return explode(API_V3_EXTENSION_DELIMITER, $params[$key]);
 | |
|   }
 | |
|   else {
 | |
|     return array();
 | |
|   }
 | |
| }
 |