CRM-15417 - Display deprecation notices in api output and api explorer
authorColeman Watts <coleman@civicrm.org>
Fri, 10 Oct 2014 02:52:14 +0000 (22:52 -0400)
committerColeman Watts <coleman@civicrm.org>
Mon, 13 Oct 2014 22:08:54 +0000 (18:08 -0400)
16 files changed:
Civi/API/Provider/ReflectionProvider.php
api/v3/ActivityType.php
api/v3/Case.php
api/v3/Constant.php
api/v3/Contact.php
api/v3/Entity.php
api/v3/Generic.php
api/v3/Generic/Getactions.php
api/v3/GroupContact.php
api/v3/Mailing.php
api/v3/MailingGroup.php
api/v3/Profile.php
api/v3/SurveyRespondant.php
api/v3/utils.php
templates/CRM/Admin/Page/APIExplorer.js
templates/CRM/Admin/Page/APIExplorer.tpl

index 676458faea696201e9196db6ec19609ea24dd0c1..24ec10d2f82387cf1636fa34247ea8759b3879c4 100644 (file)
@@ -63,7 +63,9 @@ class ReflectionProvider implements EventSubscriberInterface, ProviderInterface
   public function __construct($apiKernel) {
     $this->apiKernel = $apiKernel;
     $this->actions = array(
+      // FIXME: We really need to deal with the api's lack of uniformity wrt case (Entity or entity)
       'Entity' => array('get', 'getactions'),
+      'entity' => array('get', 'getactions'),
       '*' => array('getactions'), // 'getfields'
     );
   }
@@ -99,12 +101,12 @@ class ReflectionProvider implements EventSubscriberInterface, ProviderInterface
    * {inheritdoc}
    */
   public function invoke($apiRequest) {
-    if ($apiRequest['entity'] == 'Entity' && $apiRequest['action'] == 'get') {
-      return civicrm_api3_create_success($this->apiKernel->getEntityNames($apiRequest['version']));
+    if (strtolower($apiRequest['entity']) == 'entity' && $apiRequest['action'] == 'get') {
+      return civicrm_api3_create_success($this->apiKernel->getEntityNames($apiRequest['version']), $apiRequest['params'], 'entity', 'get');
     }
     switch ($apiRequest['action']) {
       case 'getactions':
-        return civicrm_api3_create_success($this->apiKernel->getActionNames($apiRequest['version'], $apiRequest['entity']));
+        return civicrm_api3_create_success($this->apiKernel->getActionNames($apiRequest['version'], $apiRequest['entity']), $apiRequest['params'], $apiRequest['entity'], $apiRequest['action']);
 //      case 'getfields':
 //        return $this->doGetFields($apiRequest);
       default:
index 8a9328777e90b59af795bb6ad8e564b56cfeada8..2805c9b65d68a724b702ca409300c74e534de669 100644 (file)
 */
 
 /**
- * Definition of the ActivityType part of the CRM API.
- * More detailed documentation can be found
- * {@link http://objectledge.org/confluence/display/CRM/CRM+v1.0+Public+APIs
- * here}
+ * @deprecated
  *
  * @package CiviCRM_APIv3
  * @subpackage API_Activity
  *
  */
 
+/**
+ * @deprecated api notice
+ * @return string to indicate this entire api entity is deprecated
+ */
+function _civicrm_api3_activity_type_deprecation() {
+  return 'The activity_type api is deprecated. Please use the option_value api instead.';
+}
+
 /**
  * Function to retrieve activity types
  *
@@ -66,7 +71,7 @@ function civicrm_api3_activity_type_get($params) {
  *
  * @access public
  *
- * @deprecated - we will introduce OptionValue Create - plse consider helping with this if not done
+ * @deprecated - use option_value create
  */
 function civicrm_api3_activity_type_create($params) {
 
index 3f1f55acea24b0408fdf081a98ead3043ab1fa0c..d76b1afa240e0fe0644d36325c767709cce9dc02 100644 (file)
@@ -273,7 +273,18 @@ SELECT DISTINCT case_id
  * @return array
  */
 function civicrm_api3_case_activity_create($params) {
-  return civicrm_api3_activity_create($params);
+  require_once "api/v3/Activity.php";
+  return civicrm_api3_activity_create($params) + array(
+    'deprecated' => CRM_Utils_Array::value('activity_create', _civicrm_api3_case_deprecation()),
+  );
+}
+
+/**
+ * @deprecated api notice
+ * @return array of deprecated actions
+ */
+function _civicrm_api3_case_deprecation() {
+  return array('activity_create' => 'Case api "activity_create" action is deprecated. Use the activity api instead.');
 }
 
 /**
index 93fcfcb68f9a054f739aec73c1c41f301945956e..f242307ebcbc85576968f5822c89e82d852c317c 100644 (file)
  * @version $Id: Constant.php 30171 2010-10-14 09:11:27Z mover $
  */
 
+/**
+ * @deprecated api notice
+ * @return string to indicate this entire api entity is deprecated
+ */
+function _civicrm_api3_constant_deprecation() {
+  return 'The constant api is deprecated as of CiviCRM 4.4. Please use the getoptions api action instead.';
+}
+
 /**
  * @deprecated as of CiviCRM 4.4.
  * It's recommended to use the api getoptions action instead
@@ -117,12 +125,12 @@ function civicrm_api3_constant_get($params) {
       //@TODO XAV take out the param the COOKIE, Entity, Action and so there are only the "real param" in it
       //$values = call_user_func_array( array( $className, $name ), $params );
     }
-    return civicrm_api3_create_success($values, $params);
+    return civicrm_api3_create_success($values, $params, 'constant');
   }
   else{
     $values = call_user_func(array('CRM_Utils_PseudoConstant', 'getConstant'), $name);
     if(!empty($values)){
-      return civicrm_api3_create_success($values, $params);
+      return civicrm_api3_create_success($values, $params, 'constant');
     }
   }
   return civicrm_api3_create_error('Unknown civicrm constant or method not callable');
@@ -132,53 +140,55 @@ function civicrm_api3_constant_get($params) {
  * @param $params
  */
 function _civicrm_api3_constant_get_spec(&$params) {
-
+  $options = array(
+    'activityStatus',
+    'activityType',
+    'addressee',
+    'allGroup',
+    'country',
+    'countryIsoCode',
+    'county',
+    'currencyCode',
+    'currencySymbols',
+    'customGroup',
+    'emailGreeting',
+    'fromEmailAddress',
+    'gender',
+    'group',
+    'groupIterator',
+    'honor',
+    'IMProvider',
+    'individualPrefix',
+    'individualSuffix',
+    'locationType',
+    'locationVcardName',
+    'mailProtocol',
+    'mappingTypes',
+    'paymentInstrument',
+    'paymentProcessor',
+    'paymentProcessorType',
+    'pcm',
+    'phoneType',
+    'postalGreeting',
+    'priority',
+    'relationshipType',
+    'stateProvince',
+    'stateProvinceAbbreviation',
+    'stateProvinceForCountry',
+    'staticGroup',
+    'tag',
+    'tasks',
+    'ufGroup',
+    'visibility',
+    'worldRegion',
+    'wysiwygEditor',
+  );
   $params = (array
     ('name' => array(
       'title' => 'Constant Name',
+      'name' => 'name',
       'api.required' => 1,
-        'options' =>
-          'activityStatus',
-          'activityType',
-          'addressee',
-          'allGroup',
-          'country',
-          'countryIsoCode',
-          'county',
-          'currencyCode',
-          'currencySymbols',
-          'customGroup',
-          'emailGreeting',
-          'fromEmailAddress',
-          'gender',
-          'group',
-          'groupIterator',
-          'honor',
-          'IMProvider',
-          'individualPrefix',
-          'individualSuffix',
-          'locationType',
-          'locationVcardName',
-          'mailProtocol',
-          'mappingTypes',
-          'paymentInstrument',
-          'paymentProcessor',
-          'paymentProcessorType',
-          'pcm',
-          'phoneType',
-          'postalGreeting',
-          'priority',
-          'relationshipType',
-          'stateProvince',
-          'stateProvinceAbbreviation',
-          'stateProvinceForCountry',
-          'staticGroup',
-          'tag',
-          'tasks',
-          'ufGroup',
-          'visibility',
-          'worldRegion',
-          'wysiwygEditor',
+        'options' => array_combine($options, $options)
       ))
   );
 }
index bd8656691d6d6b36934a4969681b163062dbc78f..e287cb21e32d33b23e894fea5bba9ab7798a6fd7 100644 (file)
@@ -835,7 +835,15 @@ LIMIT    0, {$limit}
     }
   }
 
-  return civicrm_api3_create_success($contactList, $params);
+  return civicrm_api3_create_success($contactList, $params, 'contact', 'getquick');
+}
+
+/**
+ * @deprecated api notice
+ * @return array of deprecated actions
+ */
+function _civicrm_api3_contact_deprecation() {
+  return array('getquick' => 'The "getquick" action is deprecated in favor of "getlist".');
 }
 
 /**
index e0c30dbf80947f72b677e58f76899388f57578ca..204dd3ae01b4df23d8627681484cae0996292fff 100644 (file)
@@ -1,5 +1,22 @@
 <?php
 
+/**
+ * @deprecated api notice
+ * @param array entities
+ * @return array of deprecated api entities
+ */
+function _civicrm_api3_entity_deprecation($entities) {
+  $deprecated = array();
+  if (!empty($entities['values'])) {
+    foreach ($entities['values'] as $entity) {
+      if (is_string(_civicrm_api3_deprecation_check($entity))) {
+        $deprecated[] = $entity;
+      }
+    }
+  }
+  return $deprecated;
+}
+
 /**
  *  Placeholder function. This should never be called, as it doesn't have any meaning
  */
index a6559f39df2ffdfd4833b7fe1fccca0781b80d85..454353a575e165917dcf525e6d714cbec096882e 100644 (file)
@@ -133,7 +133,7 @@ function civicrm_api3_generic_getfields($apiRequest) {
     _civicrm_api3_generic_get_metadata_options($metadata, $apiRequest, $fieldname, $fieldSpec, $fieldsToResolve);
   }
 
-  $results[$entity][$action][$sequential] = civicrm_api3_create_success($metadata, $apiRequest['params'], NULL, 'getfields');
+  $results[$entity][$action][$sequential] = civicrm_api3_create_success($metadata, $apiRequest['params'], $entity, 'getfields');
   return $results[$entity][$action][$sequential];
 }
 
index e3520c13a273ae4fa9fe44437f50c8ce044f87e6..89c7d43fe0138345b71bf1c05c5b66048e03f858 100644 (file)
@@ -36,5 +36,5 @@ function civicrm_api3_generic_getActions($apiRequest) {
   civicrm_api3_verify_mandatory($apiRequest, NULL, array('entity'));
   $mfp = \Civi\Core\Container::singleton()->get('magic_function_provider');
   $actions = $mfp->getActionNames($apiRequest['version'], $apiRequest['entity']);
-  return civicrm_api3_create_success($actions);
+  return civicrm_api3_create_success($actions, $apiRequest['params'], $apiRequest['entity'], 'getactions');
 }
index aa6429880774e295ea23b8c4da6c2d5a51fe2170..83282fde0e2913c622cba2b8056bdcd1db1a78e2 100644 (file)
@@ -236,3 +236,15 @@ function civicrm_api3_group_contact_update_status($params) {
   return TRUE;
 }
 
+/**
+ * @deprecated api notice
+ * @return array of deprecated actions
+ */
+function _civicrm_api3_group_contact_deprecation() {
+  return array(
+    'delete' => 'GroupContact "delete" action is deprecated in favor of "create".',
+    'pending' => 'GroupContact "pending" action is deprecated in favor of "create".',
+    'update_status' => 'GroupContact "update_status" action is deprecated in favor of "create".',
+  );
+}
+
index 62bac6e3089cbdd572d37c2df411c8c797327dc5..74f7d8fc9ed6ccb48554e35705abb085b02b77e4 100644 (file)
@@ -145,6 +145,14 @@ function civicrm_api3_mailing_event_confirm($params) {
   return civicrm_api('mailing_event_confirm', 'create', $params);
 }
 
+/**
+ * @deprecated api notice
+ * @return array of deprecated actions
+ */
+function _civicrm_api3_mailing_deprecation() {
+  return array('event_confirm' => 'Mailing api "event_confirm" action is deprecated. Use the mailing_event_confirm api instead.');
+}
+
 /**
  * Handle a reply event
  *
index c042a393cf9b19100f8966c34b7b1c1583974998..490a793649977ea20a54e6d7042ca4abf32cdfdd 100644 (file)
  *
  */
 
+/**
+ * @deprecated api notice
+ * @return string to indicate this entire api entity is deprecated
+ */
+function _civicrm_api3_mailing_group_deprecation() {
+  return 'The mailing_group api is deprecated. Use the mailing_event apis instead.';
+}
+
 /**
  * Handle an unsubscribe event
  * @deprecated
@@ -108,6 +116,6 @@ function civicrm_api3_mailing_group_getfields($params) {
     unset($field['pseudoconstant']);
   }
 
-  return civicrm_api3_create_success($fields);
+  return civicrm_api3_create_success($fields, $params, 'mailing_group');
 }
 
index 04eb4314571e3d32ef296733ed39ab6eeedd00fd..7553d0765fc75a6d515dfc8a1e05bb4be440584e 100644 (file)
@@ -732,3 +732,14 @@ function _civicrm_api3_profile_appendaliases($values, $entity) {
   }
   return $values;
 }
+
+/**
+ * @deprecated api notice
+ * @return array of deprecated actions
+ */
+function _civicrm_api3_profile_deprecation() {
+  return array(
+    'set' => 'Profile api "set" action is deprecated in favor of "submit".',
+    'apply' => 'Profile api "apply" action is deprecated in favor of "submit".',
+  );
+}
index b81ca55af5ac95abf85451840b29028c459d7161..381a6dd1fa5365060971b119f76ae601cea8ba8b 100644 (file)
  * @subpackage API_Survey
  */
 
+/**
+ * @deprecated api notice
+ * @return string to indicate this entire api entity is deprecated
+ */
+function _civicrm_api3_survey_respondant_deprecation() {
+  return 'The survey_respondant api is not currently supported.';
+}
+
 /**
  * Get the list of signatories
  *
index 37d232a6e878cb259a212efb39b04da108d65cde..4ad728ec4980850a234e57a64580d76a0591267f 100644 (file)
@@ -164,7 +164,7 @@ function civicrm_api3_create_success($values = 1, $params = array(), $entity = N
   $result = array();
   $result['is_error'] = 0;
   //lets set the ['id'] field if it's not set & we know what the entity is
-  if (is_array($values) && !empty($entity)) {
+  if (is_array($values) && !empty($entity) && $action != 'getfields') {
     foreach ($values as $key => $item) {
       if (empty($item['id']) && !empty($item[$entity . "_id"])) {
         $values[$key]['id'] = $item[$entity . "_id"];
@@ -233,11 +233,27 @@ function civicrm_api3_create_success($values = 1, $params = array(), $entity = N
   }
   if(!empty($params['options']['metadata'])) {
     // we've made metadata an array but only supporting 'fields' atm
-    if(in_array('fields', (array) $params['options']['metadata'])) {
+    if(in_array('fields', (array) $params['options']['metadata']) && $action !== 'getfields') {
       $fields = civicrm_api3($entity, 'getfields', array('action' => substr($action, 0, 3) == 'get' ? 'get' : 'create'));
       $result['metadata']['fields'] = $fields['values'];
     }
   }
+  // Report deprecations
+  $deprecated = _civicrm_api3_deprecation_check($entity, $result);
+  // Always report "update" action as deprecated
+  if (!is_string($deprecated) && ($action == 'getactions' || $action == 'update')) {
+    $deprecated = ((array) $deprecated) + array('update' => 'The "update" action is deprecated. Use "create" with an id instead.');
+  }
+  if ($deprecated) {
+    // Metadata-level deprecations or wholesale entity deprecations
+    if ($entity == 'entity' || $action == 'getactions' || is_string($deprecated)) {
+      $result['deprecated'] = $deprecated;
+    }
+    // Action-specific deprecations
+    elseif (!empty($deprecated[$action])) {
+      $result['deprecated'] = $deprecated[$action];
+    }
+  }
   return array_merge($result, $extraReturnValues);
 }
 
@@ -1954,3 +1970,19 @@ function _civicrm_api3_api_resolve_alias($entity, $fieldName) {
   }
   return FALSE;
 }
+
+/**
+ * @param string $entity
+ * @param array $result
+ */
+function _civicrm_api3_deprecation_check($entity, $result = array()) {
+  $apiFile = 'api/v3/' . _civicrm_api_get_camel_name($entity) . '.php';
+  if (CRM_Utils_File::isIncludable($apiFile)) {
+    require_once $apiFile;
+  }
+  $entity = _civicrm_api_get_entity_name_from_camel($entity);
+  $fnName = "_civicrm_api3_{$entity}_deprecation";
+  if (function_exists($fnName)) {
+    return $fnName($result);
+  }
+}
index 729d7c6d4ebe6214208bdef75d4406cdd63136d7..39ec4f6e6a26277aa305d1e47c8aa3003c65a38a 100644 (file)
@@ -2,7 +2,7 @@
   var
     entity,
     action,
-    actions = ['get'],
+    actions = {values: ['get']},
     fields = [],
     getFieldData = {},
     options = {},
@@ -77,7 +77,7 @@
   /**
    * Fetch fields for entity+action
    */
-  function getFields() {
+  function getFields(changedElement) {
     var required = [];
     fields = [];
     options = getFieldData = {};
           }
         }
       });
+      if ($(changedElement).is('#api-entity') && data.deprecated) {
+        CRM.alert(data.deprecated, entity + ' Deprecated');
+      }
       showFields(required);
       if (action === 'get' || action === 'getsingle') {
         showReturn();
     if (entity) {
       $('#api-action').addClass('loading');
       CRM.api3(entity, 'getactions').done(function(data) {
-        actions = data.values || ['get'];
+        actions = data;
         populateActions();
       });
     } else {
-      actions = ['get'];
+      actions = {values: ['get']};
       populateActions();
     }
   }
 
+  function renderAction(option) {
+    if (actions.deprecated && actions.deprecated[option.id]) {
+      return '<span class="strikethrough">' + option.text + '</span>';
+    }
+    return option.text;
+  }
+
   /**
    * Called after getActions to populate action list
    * @param el
   function populateActions(el) {
     var val = $('#api-action').val();
     $('#api-action').removeClass('loading').select2({
-      data: _.transform(actions, function(ret, item) {ret.push({text: item, id: item})})
+      data: _.transform(actions.values, function(ret, item) {ret.push({text: item, id: item})}),
+      formatSelection: renderAction,
+      formatResult: renderAction
     });
     // If previously selected action is not available, set it to 'get' if possible
-    if (_.indexOf(actions, val) < 0) {
-      $('#api-action').select2('val', _.indexOf(actions, 'get') < 0 ? actions[0] : 'get', true);
+    if (_.indexOf(actions.values, val) < 0) {
+      $('#api-action').select2('val', _.indexOf(actions.values, 'get') < 0 ? actions.values[0] : 'get', true);
+    }
+  }
+
+  function onChangeAction(action) {
+    if (actions.deprecated && actions.deprecated[action]) {
+      CRM.alert(actions.deprecated[action], action + ' deprecated');
     }
   }
 
   }
 
   $(document).ready(function() {
+    $('#api-entity').crmSelect2({
+      // Add strikethough class to selection to indicate deprecated apis
+      formatSelection: function(option) {
+        return $(option.element).hasClass('strikethrough') ? '<span class="strikethrough">' + option.text + '</span>' : option.text;
+      }
+    });
     $('form#api-explorer')
       .on('change', '#api-entity, #api-action', function() {
         entity = $('#api-entity').val();
+        action = $('#api-action').val();
         if ($(this).is('#api-entity')) {
           getActions();
+        } else {
+          onChangeAction(action);
         }
-        action = $('#api-action').val();
         if (entity && action) {
           $('#api-params').html('<tr><td colspan="4" class="crm-loading-element"></td></tr>');
           $('#api-params-table thead').show();
-          getFields();
+          getFields(this);
           buildParams();
         } else {
           $('#api-params, #api-generated pre').empty();
index 6fbf0306d6376d151fb63b24546fcac0487b388a..35630105d89ca43e372c23a758eae524bc87a551 100644 (file)
 
 <form id="api-explorer">
   <label for="api-entity">{ts}Entity{/ts}:</label>
-  <select class="crm-form-select crm-select2" id="api-entity" name="entity">
+  <select class="crm-form-select" id="api-entity" name="entity">
     <option value="" selected="selected">{ts}Choose{/ts}...</option>
     {crmAPI entity="Entity" action="get" var="entities" version=3}
     {foreach from=$entities.values item=entity}
-      <option value="{$entity}">{$entity}</option>
+      <option value="{$entity}" {if !empty($entities.deprecated) && in_array($entity, $entities.deprecated)}class="strikethrough"{/if}>
+        {$entity}
+      </option>
     {/foreach}
   </select>
   &nbsp;&nbsp;