CRM-15905 fix - API: problem sorting contacts on ID
[civicrm-core.git] / api / v3 / MailingAB.php
index 88cebb28b088fcfdf25feb410521d500317182d4..8685246a110a27da077123c78adce0bfcec4f559 100755 (executable)
@@ -1,8 +1,7 @@
 <?php
-
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.5                                                |
+ | CiviCRM version 4.6                                                |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2014                                |
  +--------------------------------------------------------------------+
@@ -24,7 +23,7 @@
  | GNU Affero General Public License or the licensing of CiviCRM,     |
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
-*/
+ */
 
 /**
  *
  * @subpackage API_MailingAB
  * @copyright CiviCRM LLC (c) 2004-2014
  * $Id$
- *
- */
-
-/**
- * Files required for this package
  */
 
 /**
- * Handle a create mailing ab testing
+ * Handle a create mailing ab testing.
  *
  * @param array $params
- * @param array $ids
  *
- * @return array API Success Array
+ * @return array
+ *   API Success Array
  */
 function civicrm_api3_mailing_a_b_create($params) {
   return _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__), $params);
@@ -57,9 +51,9 @@ function civicrm_api3_mailing_a_b_create($params) {
  * Handle a delete event.
  *
  * @param array $params
- * @param array $ids
  *
- * @return array API Success Array
+ * @return array
+ *   API Success Array
  */
 function civicrm_api3_mailing_a_b_delete($params) {
   return _civicrm_api3_basic_delete(_civicrm_api3_get_BAO(__FUNCTION__), $params);
@@ -69,106 +63,133 @@ function civicrm_api3_mailing_a_b_delete($params) {
  * Handle a get event.
  *
  * @param array $params
+ *
  * @return array
  */
 function civicrm_api3_mailing_a_b_get($params) {
   return _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params);
 }
 
-
 /**
- * Update recipients of A/B mail randomly based on group percentage selected.
+ * Adjust Metadata for submit action.
  *
- * @param array $params
- * @return array
- */
-function civicrm_api3_mailing_a_b_recipients_update($params) {
-  civicrm_api3_verify_mandatory($params,
-    'CRM_Mailing_DAO_MailingAB',
-    array('id'),
-    FALSE
-  );
-
-  $mailingAB = civicrm_api3('MailingAB', 'get', $params);
-  $mailingAB = $mailingAB['values'][$params['id']];
-
-  //update mailingC with include/exclude group id(s) provided
-  civicrm_api3('Mailing', 'create', array('id' => $mailingAB['mailing_id_c'], 'groups' =>  $params['groups']));
-  //update recipients for mailing_id_c
-  CRM_Mailing_BAO_Mailing::getRecipients($mailingAB['mailing_id_c'], $mailingAB['mailing_id_c'], NULL, NULL, TRUE);
-
-  //calculate total number of random recipients for mail C from group_percentage selected
-  $totalCount =  civicrm_api3('MailingRecipients', 'getcount', array('mailing_id' => $mailingAB['mailing_id_c']));
-  //we need at least 1 recipient for each test mailing, even if totalCount*group_percentage =~ 0
-  $totalSelected = max(1, round(($totalCount * $mailingAB['group_percentage'])/100));
-
-  foreach (array('mailing_id_a', 'mailing_id_b') as $columnName) {
-    CRM_Mailing_BAO_Recipients::updateRandomRecipients($mailingAB['mailing_id_c'], $mailingAB[$columnName], $totalSelected);
-  }
-
-  return civicrm_api3_create_success();
-}
-
-/**
- * Adjust Metadata for send_mail action
+ * The metadata is used for setting defaults, documentation & validation.
  *
- * The metadata is used for setting defaults, documentation & validation
- * @param array $params array or parameters determined by getfields
+ * @param array $params
+ *   Array or parameters determined by getfields.
  */
-function _civicrm_api3_mailing_a_b_send_mail_spec(&$params) {
-  $params['scheduled_date']['title'] = 'Scheduled Dated';
-  $params['scheduled_date']['api.default'] = 'now';
+function _civicrm_api3_mailing_a_b_submit_spec(&$params) {
+  $mailingFields = CRM_Mailing_DAO_Mailing::fields();
+  $mailingAbFields = CRM_Mailing_DAO_MailingAB::fields();
+  $spec['id'] = $mailingAbFields['id'];
+  $spec['status'] = $mailingAbFields['status'];
+  $spec['scheduled_date'] = $mailingFields['scheduled_date'];
+  $spec['approval_date'] = $mailingFields['approval_date'];
+  $spec['approval_status_id'] = $mailingFields['approval_status_id'];
+  $spec['approval_note'] = $mailingFields['approval_note'];
+  // Note: we'll pass through approval_* fields to the underlying mailing, but they may be ignored
+  // if the user doesn't have suitable permission. If separate approvals are required, they must be provided
+  // outside the A/B Test UI.
 }
 
 /**
- * Send A/B mail to A/B recipients respectively
+ * Send A/B mail to A/B recipients respectively.
  *
  * @param array $params
+ *
  * @return array
+ * @throws API_Exception
  */
-function civicrm_api3_mailing_a_b_send_mail($params) {
-  civicrm_api3_verify_mandatory($params,
-    'CRM_Mailing_DAO_MailingAB',
-    array('id'),
-    FALSE
-  );
+function civicrm_api3_mailing_a_b_submit($params) {
+  civicrm_api3_verify_mandatory($params, 'CRM_Mailing_DAO_MailingAB', array('id', 'status'));
+
+  if (!isset($params['scheduled_date']) && !isset($updateParams['approval_date'])) {
+    throw new API_Exception("Missing parameter scheduled_date and/or approval_date");
+  }
 
-  if ($params['scheduled_date'] == 'now') {
-    $params['scheduled_date'] = date('YmdHis');
+  $dao = new CRM_Mailing_DAO_MailingAB();
+  $dao->id = $params['id'];
+  if (!$dao->find(TRUE)) {
+    throw new API_Exception("Failed to locate A/B test by ID");
   }
-  else {
-    $params['scheduled_date'] = CRM_Utils_Date::processDate($params['scheduled_date'] . ' ' . $params['scheduled_date_time']);
+  if (empty($dao->mailing_id_a) || empty($dao->mailing_id_b) || empty($dao->mailing_id_c)) {
+    throw new API_Exception("Missing mailing IDs for A/B test");
   }
 
-  $mailingAB = civicrm_api3('MailingAB', 'get', array('id' => $params['id']));
-  $mailingAB = $mailingAB['values'][$params['id']];
+  $submitParams = CRM_Utils_Array::subset($params, array(
+    'scheduled_date',
+    'approval_date',
+    'approval_note',
+    'approval_status_id',
+  ));
 
-  foreach (array('mailing_id_a', 'mailing_id_b') as $columnName) {
-    $params['id'] = $mailingAB[$columnName];
-    civicrm_api3('Mailing', 'create', $params);
+  switch ($params['status']) {
+    case 'Testing':
+      if (!empty($dao->status) && $dao->status != 'Draft') {
+        throw new API_Exception("Cannot transition to state 'Testing'");
+      }
+      civicrm_api3('Mailing', 'submit', $submitParams + array(
+          'id' => $dao->mailing_id_a,
+          '_skip_evil_bao_auto_recipients_' => 0,
+        ));
+      civicrm_api3('Mailing', 'submit', $submitParams + array(
+          'id' => $dao->mailing_id_b,
+          '_skip_evil_bao_auto_recipients_' => 1,
+        ));
+      CRM_Mailing_BAO_MailingAB::distributeRecipients($dao);
+      break;
+
+    case 'Final':
+      if ($dao->status != 'Testing') {
+        throw new API_Exception("Cannot transition to state 'Final'");
+      }
+      civicrm_api3('Mailing', 'submit', $submitParams + array(
+          'id' => $dao->mailing_id_c,
+          '_skip_evil_bao_auto_recipients_' => 1,
+        ));
+      break;
+
+    default:
+      throw new API_Exception("Unrecognized submission status");
   }
 
-  return civicrm_api3_create_success();
+  return civicrm_api3('MailingAB', 'create', array(
+    'id' => $dao->id,
+    'status' => $params['status'],
+    'options' => array(
+      'reload' => 1,
+    ),
+  ));
 }
 
 /**
- * Adjust Metadata for graph_stats action
+ * Adjust Metadata for graph_stats action.
+ *
+ * The metadata is used for setting defaults, documentation & validation.
  *
- * The metadata is used for setting defaults, documentation & validation
- * @param array $params array or parameters determined by getfields
+ * @param array $params
+ *   Array or parameters determined by getfields.
  */
 function _civicrm_api3_mailing_a_b_graph_stats_spec(&$params) {
+  $params['criteria']['title'] = 'Criteria';
+  $params['criteria']['default'] = 'Open';
+  // mailing_ab_winner_criteria
+  $params['target_date']['title'] = 'Target Date';
+  $params['target_date']['type'] = CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME;
   $params['split_count']['title'] = 'Split Count';
   $params['split_count']['api.default'] = 6;
   $params['split_count_select']['title'] = 'Split Count Select';
   $params['split_count_select']['api.required'] = 1;
+  $params['target_url']['title'] = 'Target URL';
 }
 
 /**
- * Send graph detail for A/B tests mail
+ * Send graph detail for A/B tests mail.
  *
  * @param array $params
+ *
  * @return array
+ * @throws API_Exception
  */
 function civicrm_api3_mailing_a_b_graph_stats($params) {
   civicrm_api3_verify_mandatory($params,
@@ -177,59 +198,67 @@ function civicrm_api3_mailing_a_b_graph_stats($params) {
     FALSE
   );
 
-  $mailingAB = civicrm_api3('MailingAB', 'get', array('id' => $params['id']));
-  $mailingAB = $mailingAB['values'][$params['id']];
-
-  $optionGroupValue = civicrm_api3('OptionValue', 'get', array('option_group_name' => 'mailing_ab_winner_criteria', 'value' => $mailingAB['winner_criteria_id']));
-  $winningCriteria = $optionGroupValue['values'][$optionGroupValue['id']]['name'];
-
-  $declareWinnerDate = CRM_Utils_Date::processDate($mailingAB['declare_winning_time']);
+  $defaults = array(
+    'criteria' => 'Open',
+    'target_date' => CRM_Utils_Time::getTime('YmdHis'),
+    'split_count' => 6,
+    'split_count_select' => 1,
+  );
+  $params = array_merge($defaults, $params);
 
+  $mailingAB = civicrm_api3('MailingAB', 'getsingle', array('id' => $params['id']));
   $graphStats = array();
   $ABFormat = array('A' => 'mailing_id_a', 'B' => 'mailing_id_b');
 
   foreach ($ABFormat as $name => $column) {
-    switch ($winningCriteria) {
-      case 'Open':
-        $result = CRM_Mailing_Event_BAO_Opened::getRows($mailingAB['mailing_id_a'], NULL, TRUE, 0, 1, "civicrm_mailing_event_opened.time_stamp ASC");        $startDate = CRM_Utils_Date::processDate($result[0]['date']);
-        $dateDuration = round(round(strtotime($declareWinnerDate) - strtotime($startDate))/$params['split_count']);
+    switch (strtolower($params['criteria'])) {
+      case 'open':
+        $result = CRM_Mailing_Event_BAO_Opened::getRows($mailingAB['mailing_id_a'], NULL, TRUE, 0, 1, "civicrm_mailing_event_opened.time_stamp ASC");
+        $startDate = CRM_Utils_Date::processDate($result[0]['date']);
+        $targetDate = CRM_Utils_Date::processDate($params['target_date']);
+        $dateDuration = round(round(strtotime($targetDate) - strtotime($startDate)) / $params['split_count']);
         $toDate = strtotime($startDate) + ($dateDuration * $params['split_count_select']);
         $toDate = date('YmdHis', $toDate);
         $graphStats[$name] = array(
           $params['split_count_select'] => array(
             'count' => CRM_Mailing_Event_BAO_Opened::getTotalCount($mailingAB[$column], NULL, TRUE, $toDate),
-            'time' =>  CRM_Utils_Date::customFormat($toDate)
-          )
+            'time' => CRM_Utils_Date::customFormat($toDate),
+          ),
         );
         break;
-      case 'Total Unique Clicks':
+
+      case 'total unique clicks':
         $result = CRM_Mailing_Event_BAO_TrackableURLOpen::getRows($mailingAB['mailing_id_a'], NULL, TRUE, 0, 1, "civicrm_mailing_event_trackable_url_open.time_stamp ASC");
         $startDate = CRM_Utils_Date::processDate($result[0]['date']);
-        $dateDuration = round(abs(strtotime($declareWinnerDate) - strtotime($startDate))/$params['split_count']);
+        $targetDate = CRM_Utils_Date::processDate($params['target_date']);
+        $dateDuration = round(abs(strtotime($targetDate) - strtotime($startDate)) / $params['split_count']);
         $toDate = strtotime($startDate) + ($dateDuration * $params['split_count_select']);
         $toDate = date('YmdHis', $toDate);
         $graphStats[$name] = array(
           $params['split_count_select'] => array(
             'count' => CRM_Mailing_Event_BAO_TrackableURLOpen::getTotalCount($params['mailing_id'], NULL, FALSE, NULL, $toDate),
-            'time' =>  CRM_Utils_Date::customFormat($toDate)
-          )
+            'time' => CRM_Utils_Date::customFormat($toDate),
+          ),
         );
         break;
-      case 'Total Clicks on a particular link':
-        if (empty($params['url'])) {
-          throw new API_Exception("Provide url to get stats result for '{$winningCriteria}'");
+
+      case 'total clicks on a particular link':
+        if (empty($params['target_url'])) {
+          throw new API_Exception("Provide url to get stats result for total clicks on a particular link");
         }
-        $url_id = CRM_Mailing_BAO_TrackableURL::getTrackerURLId($mailingAB[$column], $params['url']);
+        // FIXME: doesn't make sense to get url_id mailing_id_(a|b) while getting start date in mailing_id_a
+        $url_id = CRM_Mailing_BAO_TrackableURL::getTrackerURLId($mailingAB[$column], $params['target_url']);
         $result = CRM_Mailing_Event_BAO_TrackableURLOpen::getRows($mailingAB['mailing_id_a'], NULL, FALSE, $url_id, 0, 1, "civicrm_mailing_event_trackable_url_open.time_stamp ASC");
         $startDate = CRM_Utils_Date::processDate($result[0]['date']);
-        $dateDuration = round(abs(strtotime($declareWinnerDate) - strtotime($startDate))/$params['split_count']);
+        $targetDate = CRM_Utils_Date::processDate($params['target_date']);
+        $dateDuration = round(abs(strtotime($targetDate) - strtotime($startDate)) / $params['split_count']);
         $toDate = strtotime($startDate) + ($dateDuration * $params['split_count_select']);
         $toDate = CRM_Utils_Date::processDate($toDate);
         $graphStats[$name] = array(
           $params['split_count_select'] => array(
             'count' => CRM_Mailing_Event_BAO_TrackableURLOpen::getTotalCount($params['mailing_id'], NULL, FALSE, $url_id, $toDate),
-            'time' =>  CRM_Utils_Date::customFormat($toDate)
-          )
+            'time' => CRM_Utils_Date::customFormat($toDate),
+          ),
         );
         break;
     }