CRM-10693 - AJAX - Standardize protocol for page, form, messages
authorColeman Watts <coleman@civicrm.org>
Sun, 17 Nov 2013 05:03:12 +0000 (21:03 -0800)
committerColeman Watts <coleman@civicrm.org>
Sun, 17 Nov 2013 05:03:12 +0000 (21:03 -0800)
12 files changed:
CRM/Contact/Form/Inline.php
CRM/Contact/Form/Inline/Address.php
CRM/Core/Form.php
CRM/Core/Page.php
CRM/Core/Page/AJAX.php
CRM/Core/QuickForm/Action/Display.php
CRM/Core/Session.php
js/Common.js
templates/CRM/Contact/Page/View/Summary.js
templates/CRM/Form/body.tpl
templates/CRM/common/snippet.tpl
templates/CRM/common/status.tpl

index 6a88ac5912213eda89299ee0bee444679043ca37..01289571a68d8ba2a2f2e3b68ec4f67678eeba8a 100644 (file)
@@ -140,14 +140,13 @@ abstract class CRM_Contact_Form_Inline extends CRM_Core_Form {
   }
 
   /**
-   * Final response from successful form submit
-   *
-   * @param response: array - data to send to the client
+   * Common function for all inline contact edit forms
+   * Prepares ajaxResponse
    *
    * @return void
    * @protected
    */
-  protected function response($response = array()) {
+  protected function response() {
     // Load changelog footer from template
     $smarty = CRM_Core_Smarty::singleton();
     $smarty->assign('contactId', $this->_contactId);
@@ -157,27 +156,16 @@ abstract class CRM_Contact_Form_Inline extends CRM_Core_Form {
       'contact_view_options', TRUE
     );
     $smarty->assign('changeLog', $viewOptions['log']);
-    $response = array_merge(
+    $this->ajaxResponse = array_merge(
       array(
-        'status' => 'save',
         'changeLog' => array(
          'count' => CRM_Contact_BAO_Contact::getCountComponent('log', $this->_contactId),
          'markup' => $smarty->fetch('CRM/common/contactFooter.tpl'),
         ),
       ),
-      $response,
+      $this->ajaxResponse,
       CRM_Contact_Form_Inline_Lock::getResponse($this->_contactId)
     );
-    $this->postProcessHook();
-    // CRM-11831 @see http://www.malsup.com/jquery/form/#file-upload
-    $xhr = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
-    if (!$xhr) {
-      echo '<textarea>';
-    }
-    echo json_encode($response);
-    if (!$xhr) {
-      echo '</textarea>';
-    }
-    CRM_Utils_System::civiExit();
+    // Note: Post hooks will be called by CRM_Core_Form::mainProcess
   }
 }
index 2b6bb6fb8e7073f80b367048082e606ff5196696..9e74ab31e28078154a78afe3de42921d40a346ef 100644 (file)
@@ -204,6 +204,7 @@ class CRM_Contact_Form_Inline_Address extends CRM_Contact_Form_Inline {
     $address = CRM_Core_BAO_Address::create($params, TRUE);
 
     $this->log();
-    $this->response(array('addressId' => $address[0]->id));
+    $this->ajaxResponse['addressId'] = $address[0]->id;
+    $this->response();
   }
 }
index 5e6f2c78d347653cad1174b3d155787ec0a18062..46f69b9d2ce0f8dfac7c0e2a6115ead4dfe898a6 100644 (file)
@@ -98,6 +98,13 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
    */
   static protected $_template;
 
+  /**
+   * What to return to the client if in ajax mode (snippet=6)
+   *
+   * @var array
+   */
+  public $ajaxResponse = array();
+
   /**
    * constants for attributes for various form elements
    * attempt to standardize on the number of variations that we
@@ -159,6 +166,8 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
     if (!isset(self::$_template)) {
       self::$_template = CRM_Core_Smarty::singleton();
     }
+
+    $this->assign('snippet', (int) CRM_Utils_Array::value('snippet', $_REQUEST));
   }
 
   static function generateID() {
@@ -259,8 +268,14 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
    */
   function mainProcess() {
     $this->postProcess();
-
     $this->postProcessHook();
+
+    // Respond with JSON if in AJAX context
+    if (!empty($_REQUEST['snippet']) && $_REQUEST['snippet'] == CRM_Core_Smarty::PRINT_JSON) {
+      $this->ajaxResponse['buttonName'] = str_replace('_qf_' . $this->getAttribute('id') . '_', '', $this->controller->getButtonName());
+      $this->ajaxResponse['action'] = $this->_action;
+      CRM_Core_Page_AJAX::returnJsonResponse($this->ajaxResponse);
+    }
   }
 
   /**
index 95ff5575788cfb1e070f0ae980556e11bebddec3..1ba8b8f326946877227300f02694d79f03928907 100644 (file)
@@ -124,9 +124,10 @@ class CRM_Core_Page {
     }
 
     if (isset($_REQUEST['snippet']) && $_REQUEST['snippet']) {
-      if ($_REQUEST['snippet'] == 3) {
+      if ($_REQUEST['snippet'] == CRM_Core_Smarty::PRINT_PDF) {
         $this->_print = CRM_Core_Smarty::PRINT_PDF;
       }
+      // FIXME - why does this number not match the constant?
       else if ($_REQUEST['snippet'] == 5) {
         $this->_print = CRM_Core_Smarty::PRINT_NOFORM;
       }
index 8c7eff678c0fa32c89eab56ddc3db535bd8124ab..fa720eb8699d12227f77536254767ee13c430a0f 100644 (file)
@@ -162,5 +162,36 @@ class CRM_Core_Page_AJAX {
         return FALSE;
     }
   }
+
+  /**
+   * Outputs the CiviCRM standard json-formatted page/form response
+   * @param array|string $response
+   */
+  static function returnJsonResponse($response) {
+    // Allow lazy callers to not wrap content in an array
+    if (is_string($response)) {
+      $response = array('content' => $response);
+    }
+    $session = CRM_Core_Session::singleton();
+    $response += array(
+      'status' => 'success',
+      'userContext' => htmlspecialchars_decode($session->readUserContext()),
+    );
+    // crmMessages will be automatically handled by our client-side ajax preprocessor @see Common.js
+    if ($session->getStatus(FALSE)) {
+      $response['crmMessages'] = $session->getStatus(TRUE);
+    }
+
+    // CRM-11831 @see http://www.malsup.com/jquery/form/#file-upload
+    $xhr = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
+    if (!$xhr) {
+      echo '<textarea>';
+    }
+    echo json_encode($response);
+    if (!$xhr) {
+      echo '</textarea>';
+    }
+    CRM_Utils_System::civiExit();
+  }
 }
 
index b02bd4f32badaa0d2a8b0c1038acc88e4d5ebba2..14c76669c6e11cbd556ccea3abd4ab55552efb32 100644 (file)
@@ -115,8 +115,8 @@ class CRM_Core_QuickForm_Action_Display extends CRM_Core_QuickForm_Action {
     $template = CRM_Core_Smarty::singleton();
     $form = $page->toSmarty();
 
+    // Deprecated - use snippet=6 instead of json=1
     $json = CRM_Utils_Request::retrieve('json', 'Boolean', CRM_Core_DAO::$_nullObject);
-
     if ($json) {
       echo json_encode($form);
       CRM_Utils_System::civiExit();
@@ -158,16 +158,11 @@ class CRM_Core_QuickForm_Action_Display extends CRM_Core_QuickForm_Action {
 
     if ($controller->_QFResponseType == 'json') {
       $response = array('content' => $html);
-      // CRM-11831 @see http://www.malsup.com/jquery/form/#file-upload
-      $xhr = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
-      if (!$xhr) {
-        echo '<textarea>';
-      }
-      echo json_encode($response);
-      if (!$xhr) {
-        echo '</textarea>';
+      if (!empty($form['errors'])) {
+        $response['status'] = 'form_error';
+        $response['errors'] = $form['errors'];
       }
-      CRM_Utils_System::civiExit();
+      CRM_Core_Page_AJAX::returnJsonResponse($response);
     }
 
     if ($print) {
index d667b837255c79ecd173a89864e1ebdd24a48b7c..7eb7b716298f0225ea29d2c1ecd848f678c0c927 100644 (file)
@@ -509,7 +509,7 @@ class CRM_Core_Session {
         'text' => $text,
         'title' => $title,
         'type' => $type,
-        'options' => $options ? json_encode($options) : NULL,
+        'options' => $options ? $options : NULL,
       );
     }
   }
index e5d14fef7f37005db8ebaf423dc1a317059f2d91..21dca3559eb8042dd686f3a7637a30034d21bd27 100644 (file)
@@ -820,6 +820,22 @@ CRM.validate = CRM.validate || {
     });
   }
 
+  // Preprocess all cj ajax calls to display messages
+  $(document).ajaxSuccess(function(event, xhr, settings) {
+    try {
+      if ((!settings.dataType || settings.dataType == 'json') && xhr.responseText) {
+        var response = $.parseJSON(xhr.responseText);
+        if (typeof(response.crmMessages) == 'object') {
+          $.each(response.crmMessages, function(n, msg) {
+            CRM.alert(msg.text, msg.title, msg.type, msg.options);
+          })
+        }
+      }
+    }
+    // Suppress errors
+    catch (e) {}
+  });
+
   $(function () {
     if ($('#crm-notification-container').length) {
       // Initialize notifications
index 82a46c4ce61345951aced76ef770106257e0c25e..dc91dc66492ed6744a9e4ebede94d353fd0c4181 100644 (file)
@@ -44,7 +44,7 @@
   function requestHandler(response) {
     var o = $('div.crm-inline-edit.form');
 
-    if (response.status == 'save' || response.status == 'cancel') {
+    if (response.status == 'success' || response.status == 'cancel') {
       o.trigger('crmFormSuccess', [response]);
       $('.crm-inline-edit-container').addClass('crm-edit-ready');
       var data = o.data('edit-params');
index 2221e69457a19080e11e21fcb68e58be30386b67..01ef1b845de2992e91b0a325ae8020a0097fb8e6 100644 (file)
@@ -33,7 +33,7 @@
   <div>{$form.hidden}</div>
 {/if}
 
-{if $suppressForm and count($form.errors) gt 0}
+{if $snippet neq 6 and !$suppressForm and count($form.errors) gt 0}
    <div class="messages crm-error">
        <div class="icon red-icon alert-icon"></div>
      {ts}Please correct the following errors in the form fields below:{/ts}
index cb71658916f9f43a35d58f6f1c9d7653d1d193fc..5ec59a3807052475d3a415fdaa9746e328ac327c 100644 (file)
     {else}
     <div class="crm-container-snippet" bgColor="white">
 
-    {* Check for Status message for the page (stored in session->getStatus). Status is cleared on retrieval. *}
-    {include file="CRM/common/status.tpl"}
+    {* Display Status messages unless we are outputting json. *}
+    {if $smarty.get.snippet neq 6}
+      {include file="CRM/common/status.tpl"}
+    {/if}
 
     <!-- .tpl file invoked: {$tplFile}. Call via form.tpl if we have a form in the page. -->
     {if !empty($isForm)}
index bae44e517c812c9efe9797200b0ddc4fa3759fbc..f42dd5b7f7d364633b77b157c1e31d4fc8e0aef1 100644 (file)
@@ -33,6 +33,6 @@
     {else}
       {assign var="infoType" value=$statItem.type}
     {/if}
-    {include file="CRM/common/info.tpl" infoTitle=$statItem.title infoMessage=$statItem.text infoOptions=$statItem.options}
+    {include file="CRM/common/info.tpl" infoTitle=$statItem.title infoMessage=$statItem.text infoOptions=$statItem.options|@json_encode}
   {/foreach}
 {/if}