CRM-19690 - Mailing API - Encode and decode `template_options`
authorTim Otten <totten@civicrm.org>
Fri, 2 Dec 2016 18:24:02 +0000 (10:24 -0800)
committerTim Otten <totten@civicrm.org>
Tue, 20 Dec 2016 01:54:17 +0000 (17:54 -0800)
Present API consumers with a consistent, array-based interface for reading
and writing properties in a Mailing.

Suppose you're submitting a REST request to create a mailing.  The REST
request as a whole is encoded with JSON.  With the default API behavior, you
would need to double-encode the `template_options`, e.g. roughly

```
POST rest.php
  json_encode([
    entity => Mailing
    action => create
    params => [
      template_options => json_encode([...])
    ]
  ])
```

With this patch, you only need to encode the request once.

This parallels the approach used in CaseType API (for the XML `definition`
field).

api/v3/Mailing.php
tests/phpunit/api/v3/MailingTest.php

index c456276c75812afd459cdcc86f80189addb72f99..35d3f2fb4cda28ba286b8f9829246e21bdc31b1b 100644 (file)
@@ -43,6 +43,9 @@
  * @throws \Civi\API\Exception\UnauthorizedException
  */
 function civicrm_api3_mailing_create($params) {
+  if (isset($params['template_options']) && is_array($params['template_options'])) {
+    $params['template_options'] = $params['template_options'] === array() ? '{}' : json_encode($params['template_options']);
+  }
   if (CRM_Mailing_Info::workflowEnabled()) {
     // Note: 'schedule mailings' and 'approve mailings' can update certain fields, but can't create.
 
@@ -64,7 +67,8 @@ function civicrm_api3_mailing_create($params) {
     $safeParams = $params;
   }
   $safeParams['_evil_bao_validator_'] = 'CRM_Mailing_BAO_Mailing::checkSendable';
-  return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $safeParams);
+  $result = _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $safeParams);
+  return _civicrm_api3_mailing_get_formatResult($result);
 
 }
 
@@ -238,7 +242,27 @@ function civicrm_api3_mailing_delete($params) {
  * @return array
  */
 function civicrm_api3_mailing_get($params) {
-  return _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+  $result = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params);
+  return _civicrm_api3_mailing_get_formatResult($result);
+}
+
+/**
+ * Format definition.
+ *
+ * @param array $result
+ *
+ * @return array
+ * @throws \CRM_Core_Exception
+ */
+function _civicrm_api3_mailing_get_formatResult($result) {
+  if (isset($result['values']) && is_array($result['values'])) {
+    foreach ($result['values'] as $key => $caseType) {
+      if (isset($result['values'][$key]['template_options']) && is_string($result['values'][$key]['template_options'])) {
+        $result['values'][$key]['template_options'] = json_decode($result['values'][$key]['template_options'], TRUE);
+      }
+    }
+  }
+  return $result;
 }
 
 /**
index d8c65c17d6e0ea972153006cec76d637474a58e1..eb60ca10855c35b7acfb1949b661016dddd6afae 100644 (file)
@@ -93,6 +93,44 @@ class api_v3_MailingTest extends CiviUnitTestCase {
     $this->assertTrue(isset($types['values']['traditional']));
   }
 
+  /**
+   * The `template_options` field should be treated a JSON object.
+   *
+   * This test will create, read, and update the field.
+   */
+  public function testMailerCreateTemplateOptions() {
+    // 1. Create mailing with template_options.
+    $params = $this->_params;
+    $params['template_options'] = json_encode(array('foo' => 'bar_1'));
+    $createResult = $this->callAPISuccess('mailing', 'create', $params);
+    $id = $createResult['id'];
+    $this->assertDBQuery('{"foo":"bar_1"}', 'SELECT template_options FROM civicrm_mailing WHERE id = %1', array(
+      1 => array($id, 'Int'),
+    ));
+    $this->assertEquals('bar_1', $createResult['values'][$id]['template_options']['foo']);
+
+    // 2. Get mailing with template_options.
+    $getResult = $this->callAPISuccess('mailing', 'get', array(
+      'id' => $id,
+    ));
+    $this->assertEquals('bar_1', $getResult['values'][$id]['template_options']['foo']);
+    $getValueResult = $this->callAPISuccess('mailing', 'getvalue', array(
+      'id' => $id,
+      'return' => 'template_options',
+    ));
+    $this->assertEquals('bar_1', $getValueResult['foo']);
+
+    // 3. Update mailing with template_options.
+    $updateResult = $this->callAPISuccess('mailing', 'create', array(
+      'id' => $id,
+      'template_options' => array('foo' => 'bar_2'),
+    ));
+    $this->assertDBQuery('{"foo":"bar_2"}', 'SELECT template_options FROM civicrm_mailing WHERE id = %1', array(
+      1 => array($id, 'Int'),
+    ));
+    $this->assertEquals('bar_2', $updateResult['values'][$id]['template_options']['foo']);
+  }
+
   /**
    * The Mailing.create API supports magic properties "groups[include,enclude]" and "mailings[include,exclude]".
    * Make sure these work