CRM-16632 - Fix calculation of contribution fees
[civicrm-core.git] / CRM / Profile / Form.php
index 95c44a49dc4280629e79e8d9b2b54d91647a9f44..cf276a1c374b9e15d1361a6f229ec24dc3954d5f 100644 (file)
@@ -3,7 +3,7 @@
  +--------------------------------------------------------------------+
  | CiviCRM version 4.6                                                |
  +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2014                                |
+ | Copyright CiviCRM LLC (c) 2004-2015                                |
  +--------------------------------------------------------------------+
  | This file is a part of CiviCRM.                                    |
  |                                                                    |
  | GNU Affero General Public License or the licensing of CiviCRM,     |
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
-*/
+ */
 
 /**
  *
  * @package CRM
- * @copyright CiviCRM LLC (c) 2004-2014
+ * @copyright CiviCRM LLC (c) 2004-2015
  * $Id$
  *
  */
 class CRM_Profile_Form extends CRM_Core_Form {
   const
     MODE_REGISTER = 1,
-    MODE_SEARCH   = 2,
-    MODE_CREATE   = 4,
-    MODE_EDIT     = 8;
+    MODE_SEARCH = 2,
+    MODE_CREATE = 4,
+    MODE_EDIT = 8;
 
   protected $_mode;
 
   protected $_skipPermission = FALSE;
 
   /**
-   * The contact id that we are editing
+   * The contact id that we are editing.
    *
    * @var int
    */
   protected $_id;
 
   /**
-   * The group id that we are editing
+   * The group id that we are editing.
    *
    * @var int
    */
@@ -72,45 +72,51 @@ class CRM_Profile_Form extends CRM_Core_Form {
   protected $_ufGroup = array('name' => 'unknown');
 
   /**
-   * The group id that we are passing in url
+   * The group id that we are passing in url.
    *
    * @var int
    */
   public $_grid;
 
   /**
-   * Name of button for saving matching contacts
+   * Name of button for saving matching contacts.
    * @var
    */
   protected $_duplicateButtonName;
   /**
-   * The title of the category we are editing
+   * The title of the category we are editing.
    *
    * @var string
    */
   protected $_title;
 
   /**
-   * The fields needed to build this form
+   * The fields needed to build this form.
    *
    * @var array
    */
   public $_fields;
 
   /**
-   * To store contact details
+   * store contact details.
    *
    * @var array
    */
   protected $_contact;
 
   /**
-   * Do we allow updates of the contact
+   * Do we allow updates of the contact.
    *
    * @var int
    */
   public $_isUpdateDupe = 0;
 
+  /**
+   * Dedupe using a specific rule (CRM-6131).
+   * Not currently exposed in profile settings, but can be set in a buildForm hook.
+   */
+  public $_ruleGroupID = NULL;
+
   public $_isAddCaptcha = FALSE;
 
   protected $_isPermissionedChecksum = FALSE;
@@ -123,7 +129,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
   protected $_context;
 
   /**
-   * THe contact type for registration case
+   * THe contact type for registration case.
    *
    * @var string
    */
@@ -145,7 +151,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
   protected $_isContactActivityProfile = FALSE;
 
   /**
-   * Activity Id connected to the profile
+   * Activity Id connected to the profile.
    *
    * @var string
    */
@@ -174,7 +180,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
   protected $_customGroupId = NULL;
 
   protected $_currentUserID = NULL;
-  protected $_session       = NULL;
+  protected $_session = NULL;
 
   /**
    * Pre processing work done here.
@@ -184,13 +190,12 @@ class CRM_Profile_Form extends CRM_Core_Form {
    * @param
    *
    * @return void
-   *
    */
   public function preProcess() {
-    $this->_id         = $this->get('id');
+    $this->_id = $this->get('id');
     $this->_profileIds = $this->get('profileIds');
-    $this->_grid       = CRM_Utils_Request::retrieve('grid', 'Integer', $this);
-    $this->_context    = CRM_Utils_Request::retrieve('context', 'String', $this);
+    $this->_grid = CRM_Utils_Request::retrieve('grid', 'Integer', $this);
+    $this->_context = CRM_Utils_Request::retrieve('context', 'String', $this);
 
     //unset from session when $_GET doesn't have it
     //except when the form is submitted
@@ -215,7 +220,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
       }
 
       if ($this->_multiRecord &&
-          !in_array($this->_multiRecord, array(CRM_Core_Action::UPDATE, CRM_Core_Action::ADD, CRM_Core_Action::DELETE))) {
+        !in_array($this->_multiRecord, array(CRM_Core_Action::UPDATE, CRM_Core_Action::ADD, CRM_Core_Action::DELETE))
+      ) {
         CRM_Core_Error::fatal(ts('Proper action not specified for this custom value record profile'));
       }
     }
@@ -309,17 +315,20 @@ class CRM_Profile_Form extends CRM_Core_Form {
         if ($this->_multiRecord) {
           if ($this->_multiRecord != CRM_Core_Action::ADD) {
             $this->_recordId = CRM_Utils_Request::retrieve('recordId', 'Positive', $this);
-          } else {
+          }
+          else {
             $this->_recordId = NULL;
             $this->set('recordId', NULL);
           }
           //record id is neccessary for _multiRecord view and update/edit action
           if (!$this->_recordId
-              && ($this->_multiRecord == CRM_Core_Action::UPDATE || $this->_multiRecord == CRM_Core_Action::DELETE)) {
+            && ($this->_multiRecord == CRM_Core_Action::UPDATE || $this->_multiRecord == CRM_Core_Action::DELETE)
+          ) {
             CRM_Core_Error::fatal(ts('The requested Profile (gid=%1) requires record id while performing this action',
               array(1 => $this->_gid)
             ));
-          } elseif (empty($this->_multiRecordFields)) {
+          }
+          elseif (empty($this->_multiRecordFields)) {
             CRM_Core_Error::fatal(ts('No Multi-Record Fields configured for this profile (gid=%1)',
               array(1 => $this->_gid)
             ));
@@ -339,7 +348,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
 
             if (array_key_exists($this->_recordId, $getValues)) {
               $this->_recordExists = TRUE;
-            } else {
+            }
+            else {
               $this->_recordExists = FALSE;
               if ($this->_multiRecord & CRM_Core_Action::UPDATE) {
                 CRM_Core_Session::setStatus(ts('Note: The record %1 doesnot exists. Upon save a new record will be create', array(1 => $this->_recordId)), ts('Record doesnot exist'), 'alert');
@@ -353,8 +363,13 @@ class CRM_Profile_Form extends CRM_Core_Form {
             }
           }
 
-        } elseif (!empty($this->_multiRecordFields)
-           && (!$this->_multiRecord || !in_array($this->_multiRecord, array(CRM_Core_Action::DELETE, CRM_Core_Action::UPDATE)) )) {
+        }
+        elseif (!empty($this->_multiRecordFields)
+          && (!$this->_multiRecord || !in_array($this->_multiRecord, array(
+                CRM_Core_Action::DELETE,
+                CRM_Core_Action::UPDATE,
+              )))
+        ) {
           CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'js/crm.livePage.js', 1, 'html-header');
           //multirecord listing page
           $multiRecordFieldListing = TRUE;
@@ -391,7 +406,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
       if ($this->_multiRecord && !empty($this->_multiRecordFields)) {
         $this->_fields = $this->_multiRecordFields;
         $this->_multiRecordProfile = TRUE;
-      } elseif ($this->_multiRecord && empty($this->_multiRecordFields)) {
+      }
+      elseif ($this->_multiRecord && empty($this->_multiRecordFields)) {
         CRM_Core_Session::setStatus(ts('This feature is not currently available.'), ts('Sorry'), 'error');
         CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm', 'reset=1'));
       }
@@ -454,7 +470,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
         $defaultValues = CRM_Core_BAO_CustomValueTable::getEntityValues($this->_id, NULL, $fieldIds, TRUE);
         if ($this->_recordExists == TRUE) {
           $defaultValues = $defaultValues[$this->_recordId];
-        } else {
+        }
+        else {
           $defaultValues = NULL;
         }
       }
@@ -472,7 +489,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
                 $this->_mode,
                 $value
               );
-            } else {
+            }
+            else {
               $this->_defaults[$name] = "";
             }
           }
@@ -480,8 +498,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
           if ($htmlType == 'File') {
             $entityId = $this->_id;
             if (CRM_Utils_Array::value('field_type', $field) == 'Activity' &&
-                $this->_activityId
-                ) {
+              $this->_activityId
+            ) {
               $entityId = $this->_activityId;
             }
             $url = CRM_Core_BAO_CustomField::getFileURL($entityId, $key);
@@ -490,10 +508,10 @@ class CRM_Profile_Form extends CRM_Core_Form {
               $customFiles[$name]['displayURL'] = ts("Attached File") . ": {$url['file_url']}";
 
               $deleteExtra = ts("Are you sure you want to delete attached file?");
-              $fileId      = $url['file_id'];
-              $deleteURL   = CRM_Utils_System::url('civicrm/file',
-                             "reset=1&id={$fileId}&eid=$entityId&fid={$key}&action=delete"
-                           );
+              $fileId = $url['file_id'];
+              $deleteURL = CRM_Utils_System::url('civicrm/file',
+                "reset=1&id={$fileId}&eid=$entityId&fid={$key}&action=delete"
+              );
               $text = ts("Delete Attached File");
               $customFiles[$field['name']]['deleteURL'] = "<a href=\"{$deleteURL}\" onclick = \"if (confirm( ' $deleteExtra ' )) this.href+='&amp;confirmed=1'; else return false;\">$text</a>";
 
@@ -509,8 +527,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
         if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) {
           $htmlType = $field['html_type'];
           if ((!isset($this->_defaults[$name]) || $htmlType == 'File') &&
-              (CRM_Utils_Array::value('field_type', $field) != 'Activity')
-              ) {
+            (CRM_Utils_Array::value('field_type', $field) != 'Activity')
+          ) {
             CRM_Core_BAO_CustomField::setProfileDefaults($customFieldID,
               $name,
               $this->_defaults,
@@ -530,9 +548,9 @@ class CRM_Profile_Form extends CRM_Core_Form {
               $customFiles[$field['name']]['displayURL'] = ts("Attached File") . ": {$url['file_url']}";
 
               $deleteExtra = ts("Are you sure you want to delete attached file?");
-              $fileId      = $url['file_id'];
-              $deleteURL   = CRM_Utils_System::url('civicrm/file',
-                 "reset=1&id={$fileId}&eid=$entityId&fid={$customFieldID}&action=delete"
+              $fileId = $url['file_id'];
+              $deleteURL = CRM_Utils_System::url('civicrm/file',
+                "reset=1&id={$fileId}&eid=$entityId&fid={$customFieldID}&action=delete"
               );
               $text = ts("Delete Attached File");
               $customFiles[$field['name']]['deleteURL'] = "<a href=\"{$deleteURL}\" onclick = \"if (confirm( ' $deleteExtra ' )) this.href+='&amp;confirmed=1'; else return false;\">$text</a>";
@@ -576,7 +594,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
   }
 
   /**
-   * Build the form object
+   * Build the form object.
    *
    * @return void
    */
@@ -637,7 +655,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
 
       if ($this->_id) {
         $contactTypes = CRM_Contact_BAO_Contact::getContactTypes($this->_id);
-        $contactType  = $contactTypes[0];
+        $contactType = $contactTypes[0];
 
         array_shift($contactTypes);
         $contactSubtypes = $contactTypes;
@@ -655,18 +673,17 @@ class CRM_Profile_Form extends CRM_Core_Form {
         ) {
           $return = TRUE;
           if (!$statusMessage) {
-            $statusMessage =
-              ts("This profile is configured for contact type '%1'. It cannot be used to edit contacts of other types.",
+            $statusMessage = ts("This profile is configured for contact type '%1'. It cannot be used to edit contacts of other types.",
                 array(1 => $profileSubType ? $profileSubType : $profileType));
           }
         }
       }
 
       if (
-        in_array(
-          $profileType,
-          array("Membership", "Participant", "Contribution")
-        )
+      in_array(
+        $profileType,
+        array("Membership", "Participant", "Contribution")
+      )
       ) {
         $return = TRUE;
         if (!$statusMessage) {
@@ -717,7 +734,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
     if (!$this->_currentUserID) {
       $defaultLocationType = CRM_Core_BAO_LocationType::getDefault();
       $primaryLocationType = $defaultLocationType->id;
-      $anonUser            = TRUE;
+      $anonUser = TRUE;
     }
     $this->assign('anonUser', $anonUser);
 
@@ -764,7 +781,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
       if ($this->_currentUserID) {
         $this->_isAddCaptcha = FALSE;
       }
-      else if (!$this->_isAddCaptcha && !empty($addCaptcha)) {
+      elseif (!$this->_isAddCaptcha && !empty($addCaptcha)) {
         $this->_isAddCaptcha = TRUE;
       }
 
@@ -825,7 +842,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
   }
 
   /**
-   * Validate profile and provided activity Id
+   * Validate profile and provided activity Id.
    *
    * @param int $activityId
    * @param int $contactId
@@ -865,7 +882,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
   }
 
   /**
-   * Global form rule
+   * Global form rule.
    *
    * @param array $fields
    *   The input form values.
@@ -874,8 +891,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
    * @param CRM_Core_Form $form
    *   The form object.
    *
-   * @return true if no errors, else array of errors
-   * @static
+   * @return bool|array
+   *   true if no errors, else array of errors
    */
   public static function formRule($fields, $files, $form) {
     CRM_Utils_Hook::validateProfile($form->_ufGroup['name']);
@@ -935,7 +952,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
       $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams,
         $ctype,
         $ruleType,
-        $exceptions
+        $exceptions,
+        $form->_ruleGroupID
       );
       if ($ids) {
         if ($form->_isUpdateDupe == 2) {
@@ -951,17 +969,26 @@ class CRM_Profile_Form extends CRM_Core_Form {
             $contactLinks = CRM_Contact_BAO_Contact_Utils::formatContactIDSToLinks($ids, TRUE, TRUE);
 
             $duplicateContactsLinks = '<div class="matching-contacts-found">';
-            $duplicateContactsLinks .= ts('One matching contact was found. ', array('count' => count($contactLinks['rows']), 'plural' => '%count matching contacts were found.<br />'));
+            $duplicateContactsLinks .= ts('One matching contact was found. ', array(
+                'count' => count($contactLinks['rows']),
+                'plural' => '%count matching contacts were found.<br />',
+              ));
             if ($contactLinks['msg'] == 'view') {
-              $duplicateContactsLinks .= ts('You can View the existing contact.', array('count' => count($contactLinks['rows']), 'plural' => 'You can View the existing contacts.'));
+              $duplicateContactsLinks .= ts('You can View the existing contact.', array(
+                  'count' => count($contactLinks['rows']),
+                  'plural' => 'You can View the existing contacts.',
+                ));
             }
             else {
-              $duplicateContactsLinks .= ts('You can View or Edit the existing contact.', array('count' => count($contactLinks['rows']), 'plural' => 'You can View or Edit the existing contacts.'));
+              $duplicateContactsLinks .= ts('You can View or Edit the existing contact.', array(
+                  'count' => count($contactLinks['rows']),
+                  'plural' => 'You can View or Edit the existing contacts.',
+                ));
             }
             $duplicateContactsLinks .= '</div>';
             $duplicateContactsLinks .= '<table class="matching-contacts-actions">';
             $row = '';
-            for ($i = 0; $i < sizeof($contactLinks['rows']); $i++) {
+            for ($i = 0; $i < count($contactLinks['rows']); $i++) {
               $row .= '  <tr>   ';
               $row .= '    <td class="matching-contacts-name"> ';
               $row .= $contactLinks['rows'][$i]['display_name'];
@@ -1007,8 +1034,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
           if ($stateProvinceDAO->country_id != $countryId) {
             // country mismatch hence display error
             $stateProvinces = CRM_Core_PseudoConstant::stateProvince();
-            $countries      = CRM_Core_PseudoConstant::country();
-            $errors[$key]   = "State/Province " . $stateProvinces[$stateProvinceId] . " is not part of " . $countries[$countryId] . ". It belongs to " . $countries[$stateProvinceDAO->country_id] . ".";
+            $countries = CRM_Core_PseudoConstant::country();
+            $errors[$key] = "State/Province " . $stateProvinces[$stateProvinceId] . " is not part of " . $countries[$countryId] . ". It belongs to " . $countries[$stateProvinceDAO->country_id] . ".";
           }
         }
       }
@@ -1026,8 +1053,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
           if ($countyDAO->state_province_id != $stateProvinceId) {
             // state province mismatch hence display error
             $stateProvinces = CRM_Core_PseudoConstant::stateProvince();
-            $counties       = CRM_Core_PseudoConstant::county();
-            $errors[$key]   = "County " . $counties[$countyId] . " is not part of " . $stateProvinces[$stateProvinceId] . ". It belongs to " . $stateProvinces[$countyDAO->state_province_id] . ".";
+            $counties = CRM_Core_PseudoConstant::county();
+            $errors[$key] = "County " . $counties[$countyId] . " is not part of " . $stateProvinces[$stateProvinceId] . ". It belongs to " . $stateProvinces[$countyDAO->state_province_id] . ".";
           }
         }
       }
@@ -1065,9 +1092,9 @@ class CRM_Profile_Form extends CRM_Core_Form {
           if ($tableName = CRM_Utils_Array::value('table_name', $returnValues)) {
             $sql = "DELETE FROM {$tableName} WHERE id = %1 AND entity_id = %2";
             $sqlParams = array(
-                          1 => array($this->_recordId, 'Integer'),
-                          2 => array($this->_id, 'Integer')
-                         );
+              1 => array($this->_recordId, 'Integer'),
+              2 => array($this->_id, 'Integer'),
+            );
             CRM_Core_DAO::executeQuery($sql, $sqlParams);
             CRM_Core_Session::setStatus(ts('Your record has been deleted.'), ts('Deleted'), 'success');
           }
@@ -1094,8 +1121,9 @@ class CRM_Profile_Form extends CRM_Core_Form {
       $details = $contactDetails[0][$this->_id];
     }
     if (!(!empty($details['addressee_id']) || !empty($details['email_greeting_id']) ||
-        CRM_Utils_Array::value('postal_greeting_id', $details)
-      )) {
+      CRM_Utils_Array::value('postal_greeting_id', $details)
+    )
+    ) {
 
       $profileType = CRM_Core_BAO_UFField::getProfileType($this->_gid);
       //Though Profile type is contact we need
@@ -1299,8 +1327,8 @@ class CRM_Profile_Form extends CRM_Core_Form {
         CRM_Core_Error::debug_log_message("Rolling back transaction as CMSUser Create failed in Profile_Form for contact " . $params['contactID']);
         $transaction->rollback();
         return CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/profile/create',
-            'reset=1&gid=' . $this->_gid
-          ));
+          'reset=1&gid=' . $this->_gid
+        ));
       }
     }
 
@@ -1333,7 +1361,7 @@ class CRM_Profile_Form extends CRM_Core_Form {
   }
 
   /**
-   * Use the form name to create the tpl file name
+   * Use the form name to create the tpl file name.
    *
    * @return string
    */
@@ -1358,4 +1386,5 @@ class CRM_Profile_Form extends CRM_Core_Form {
     $fileName = $this->checkTemplateFileExists('extra.');
     return $fileName ? $fileName : parent::overrideExtraTemplateFileName();
   }
+
 }