CRM-14288 - Refactor and simplify relationship form
authorColeman Watts <coleman@civicrm.org>
Sat, 1 Mar 2014 03:01:55 +0000 (22:01 -0500)
committerColeman Watts <coleman@civicrm.org>
Sat, 1 Mar 2014 03:08:29 +0000 (22:08 -0500)
CRM/Contact/Form/Relationship.php
templates/CRM/Contact/Form/Relationship.tpl

index f4d7bd44ef558cffe3ad408e536108828ff240ac..f7bdb463c30f05a8ee96db9c08b5ebb07dd49c5d 100644 (file)
  */
 class CRM_Contact_Form_Relationship extends CRM_Core_Form {
 
-  /**
-   * max number of contacts we will display for a relationship
-   */
-  CONST MAX_RELATIONSHIPS = 50;
-
   /**
    * The relationship id, used when editing the relationship
    *
@@ -96,6 +91,21 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
    */
   protected $_allRelationshipNames;
 
+  /**
+   * @var bool
+   */
+  protected $_enabled;
+
+  /**
+   * @var bool
+   */
+  protected $_isCurrentEmployer;
+
+  /**
+   * @var string
+   */
+  protected $_contactType;
+
   /**
    * The relationship values if Updating relationship
    */
@@ -106,6 +116,11 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
    */
   protected $_caseId;
 
+  /**
+   * @var mixed
+   */
+  public $_cdType;
+
   function preProcess() {
     //custom data related code
     $this->_cdType = CRM_Utils_Array::value('type', $_GET);
@@ -117,6 +132,8 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
 
     $this->_contactId = $this->get('contactId');
 
+    $this->_contactType = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactId, 'contact_type');
+
     $this->_relationshipId = $this->get('id');
 
     $this->_rtype = CRM_Utils_Request::retrieve('rtype', 'String', $this);
@@ -125,8 +142,23 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
 
     $this->_display_name_a = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactId, 'display_name');
 
-    $this->assign('sort_name_a', $this->_display_name_a);
-    CRM_Utils_System::setTitle(ts('Relationships for') . ' ' . $this->_display_name_a);
+    $this->assign('display_name_a', $this->_display_name_a);
+
+    // Set page title based on action
+    switch ($this->_action) {
+      case CRM_Core_Action::VIEW:
+        CRM_Utils_System::setTitle(ts('View Relationship for %1', $this->_display_name_a));
+        break;
+      case CRM_Core_Action::ADD:
+        CRM_Utils_System::setTitle(ts('Add Relationship for %1', $this->_display_name_a));
+        break;
+      case CRM_Core_Action::UPDATE:
+        CRM_Utils_System::setTitle(ts('Edit Relationship for %1', $this->_display_name_a));
+        break;
+      case CRM_Core_Action::DELETE:
+        CRM_Utils_System::setTitle(ts('Delete Relationship for %1', $this->_display_name_a));
+        break;
+    }
 
     $this->_caseId = CRM_Utils_Request::retrieve('caseID', 'Integer', $this);
 
@@ -154,12 +186,22 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
     if (!$this->_rtype) {
       $this->_rtype = str_replace($this->_relationshipTypeId . '_', '', $this->_rtypeId);
     }
-    $this->assign('rtype', $this->_rtype);
 
+    //need to assign custom data type and subtype to the template - FIXME: explain why
+    $this->assign('customDataType', 'Relationship');
+    $this->assign('customDataSubType', $this->_relationshipTypeId);
+    $this->assign('entityID', $this->_relationshipId);
 
     //use name as it remain constant, CRM-3336
     $this->_allRelationshipNames = CRM_Core_PseudoConstant::relationshipType('name');
 
+    // Current employer?
+    if ($this->_action & CRM_Core_Action::UPDATE) {
+      if ($this->_allRelationshipNames[$this->_relationshipTypeId]["name_a_b"] == 'Employee of') {
+        $this->_isCurrentEmployer = $this->_values['contact_id_b'] == CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_values['contact_id_a'], 'employer_id');
+      }
+    }
+
     // when custom data is included in this page
     if (!empty($_POST['hidden_custom'])) {
       CRM_Custom_Form_CustomData::preProcess($this);
@@ -194,8 +236,14 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
         }
         $defaults['description'] = CRM_Utils_Array::value('description', $this->_values);
         $defaults['is_active'] = CRM_Utils_Array::value('is_active', $this->_values);
-        $defaults['is_permission_a_b'] = CRM_Utils_Array::value('is_permission_a_b', $this->_values);
-        $defaults['is_permission_b_a'] = CRM_Utils_Array::value('is_permission_b_a', $this->_values);
+
+        // The javascript on the form will swap these fields if it is a b_a relationship, so we compensate here
+        $defaults['is_permission_a_b'] = CRM_Utils_Array::value('is_permission_' . $this->_rtype, $this->_values);
+        $defaults['is_permission_b_a'] = CRM_Utils_Array::value('is_permission_' . strrev($this->_rtype), $this->_values);
+
+        $defaults['is_current_employer'] = $this->_isCurrentEmployer;
+
+        // Load info about the related contact
         $contact = new CRM_Contact_DAO_Contact();
         if ($this->_rtype == 'a_b' && $this->_values['contact_id_a'] == $this->_contactId) {
           $contact->id = $this->_values['contact_id_b'];
@@ -204,37 +252,22 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
           $contact->id = $this->_values['contact_id_a'];
         }
         if ($contact->find(TRUE)) {
+          $defaults['related_contact_id'] = $contact->id;
           $this->_display_name_b = $contact->display_name;
-          $this->assign('sort_name_b', $this->_display_name_b);
-
-          //is current employee/employer.
-          if ($this->_allRelationshipNames[$this->_relationshipTypeId]["name_{$this->_rtype}"] == 'Employee of' &&
-            $contact->id == CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactId, 'employer_id')
-          ) {
-            $defaults['is_current_employer'] = 1;
-            $this->_values['current_employee_id'] = $this->_contactId;
-            $this->_values['current_employer_id'] = $contact->id;
-          }
-          elseif ($this->_allRelationshipNames[$this->_relationshipTypeId]["name_{$this->_rtype}"] == 'Employer of' &&
-            $this->_contactId == $contact->employer_id
-          ) {
-            $defaults['is_current_employer'] = 1;
-            $this->_values['current_employee_id'] = $contact->id;
-            $this->_values['current_employer_id'] = $this->_contactId;
-          }
+          $this->assign('display_name_b', $this->_display_name_b);
         }
 
-        $relationshipID = $this->_values['id'];
-        $query          = "SELECT id, note FROM civicrm_note where entity_table = 'civicrm_relationship' and entity_id = $relationshipID  order by modified_date desc";
-        $dao            = new CRM_Core_DAO();
-        $dao->query($query);
-        if ($dao->fetch($query)) {
-          $defaults['note'] = $dao->note;
-        }
+        $noteParams = array(
+          'entity_id' => $this->_relationshipId,
+          'entity_table' => 'civicrm_relationship',
+          'limit' => 1,
+        );
+        $note = civicrm_api3('note' ,'getsingle', $noteParams);
+        $defaults['note'] = CRM_Utils_Array::value('note', $note);
       }
     }
     else {
-      $defaults['is_active'] = 1;
+      $defaults['is_active'] = $defaults['is_current_employer'] = 1;
       $defaults['relationship_type_id'] = $this->_rtypeId;
     }
 
@@ -254,17 +287,7 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
     }
 
     if (!($this->_action & CRM_Core_Action::DELETE)) {
-      $this->addRule('relationship_type_id', ts('Please select a relationship type.'), 'required');
-
-      // add a form rule only when creating a new relationship
-      // edit is severely limited, so add a simpleer form rule
-      if ($this->_action & CRM_Core_Action::ADD) {
-        $this->addFormRule(array('CRM_Contact_Form_Relationship', 'formRule'), $this);
-        $this->addFormRule(array('CRM_Contact_Form_Relationship', 'dateRule'));
-      }
-      elseif ($this->_action & CRM_Core_Action::UPDATE) {
-        $this->addFormRule(array('CRM_Contact_Form_Relationship', 'dateRule'));
-      }
+      $this->addFormRule(array('CRM_Contact_Form_Relationship', 'dateRule'));
     }
   }
 
@@ -279,10 +302,7 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
       return CRM_Custom_Form_CustomData::buildQuickForm($this);
     }
 
-    $relTypeID = explode('_', $this->_rtypeId, 3);
-
     if ($this->_action & CRM_Core_Action::DELETE) {
-      $this->assign('id', $this->_relationshipId);
       $this->addButtons(array(
           array(
             'type' => 'next',
@@ -297,165 +317,84 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
       );
       return;
     }
-
-    $callAjax = $this->get('callAjax');
-
-    $searchRows = NULL;
-    if (!$callAjax) {
-      $searchRows = $this->get('searchRows');
-    }
-    else {
-
-      $this->addElement('hidden', 'store_contacts', '', array('id' => 'store_contacts'));
-      $sourceUrl = 'snippet=4&relType=' . $this->get('relType');
-      $sourceUrl .= '&relContact=' . $this->get('relContact');
-      $sourceUrl .= '&cid=' . $this->_contactId;
-
-      $this->assign('searchCount', TRUE);
-
-      // To handle employee of and employer of
-      if (!empty($this->_relationshipTypeId) &&
-        !empty($this->_rtype)
-      ) {
-        $sourceUrl .= '&typeName=' . $this->_allRelationshipNames[$this->_relationshipTypeId]["name_{$this->_rtype}"];
+    // Just in case custom data includes a rich text field
+    $this->assign('includeWysiwygEditor', TRUE);
+
+    // Select list
+    $relationshipList = CRM_Contact_BAO_Relationship::getContactRelationshipType($this->_contactId, $this->_rtype, $this->_relationshipId);
+
+    // Metadata needed on clientside
+    $contactTypes = CRM_Contact_BAO_ContactType::contactTypeInfo(TRUE);
+    $jsData = array();
+    // Filter it down to just what we need to keep the dom small
+    $whatWeWant = array_flip(array('contact_type_a', 'contact_type_b', 'contact_sub_type_a', 'contact_sub_type_b'));
+    foreach($this->_allRelationshipNames as $id => $vals) {
+      if ($vals['name_a_b'] === 'Employee of') {
+        $this->assign('employmentRelationship', $id);
+      }
+      if (isset($relationshipList["{$id}_a_b"]) || isset($relationshipList["{$id}_b_a"])) {
+        $jsData[$id] = array_filter(array_intersect_key($this->_allRelationshipNames[$id], $whatWeWant));
+        // Add user-friendly placeholder
+        foreach (array('a', 'b') as $x) {
+          $type = !empty($jsData[$id]["contact_sub_type_$x"]) ? $jsData[$id]["contact_sub_type_$x"] : CRM_Utils_Array::value("contact_type_$x", $jsData[$id]);
+          $jsData[$id]["placeholder_$x"] = $type ? ts('- select %1 -', array(strtolower($contactTypes[$type]['label']))) : ts('- select contact -');
+        }
       }
-      $this->assign('sourceUrl', CRM_Utils_System::url('civicrm/ajax/relationshipcontacts', $sourceUrl, FALSE, NULL, FALSE));
     }
+    $this->assign('relationshipData', $jsData);
 
-    $this->assign('callAjax', $callAjax);
-    $this->_callAjax = $callAjax;
-
-    $this->addElement('select',
+    $this->add(
+      'select',
       'relationship_type_id',
       ts('Relationship Type'),
-      array(
-        '' => ts('- select -')) +
-      CRM_Contact_BAO_Relationship::getContactRelationshipType($this->_contactId,
-        $this->_rtype,
-        $this->_relationshipId,
-        NULL, FALSE, 'label'
-      )
+      array( '' => ts('- select -')) + $relationshipList,
+      TRUE,
+      array('class' => 'crm-select2 huge')
     );
 
-    // add a ajax facility for searching contacts
-    $dataUrl = CRM_Utils_System::url('civicrm/ajax/search', 'reset=1', TRUE, NULL, FALSE);
-    $this->assign('dataUrl', $dataUrl);
-    CRM_Contact_Form_NewContact::buildQuickForm($this);
+    $label = $this->_action & CRM_Core_Action::ADD ? ts('Contact(s)') : ts('Contact');
+    $contactField = $this->addEntityRef('related_contact_id', $label, array('multiple' => TRUE, 'create' => TRUE), TRUE);
+    // This field cannot be updated
+    if ($this->_action & CRM_Core_Action::UPDATE) {
+      $contactField->freeze();
+    }
+
+    $this->add('checkbox', 'is_current_employer', $this->_contactType == 'Organization' ? ts('Current Employee') : ts('Current Employer'));
 
     $this->addDate('start_date', ts('Start Date'), FALSE, array('formatType' => 'searchDate'));
     $this->addDate('end_date', ts('End Date'), FALSE, array('formatType' => 'searchDate'));
-    $this->addElement('checkbox', 'is_active', ts('Enabled?'), NULL, NULL);
 
-    $this->addElement('checkbox', 'is_permission_a_b', ts('Permission for contact a to view and update information for contact b'), NULL);
-    $this->addElement('checkbox', 'is_permission_b_a', ts('permission for contact b to view and update information for contact a'), NULL);
+    $this->add('checkbox', 'is_active', ts('Enabled?'));
+
+    $this->add('checkbox', 'is_permission_a_b');
+    $this->add('checkbox', 'is_permission_b_a');
 
     $this->add('text', 'description', ts('Description'), CRM_Core_DAO::getAttribute('CRM_Contact_DAO_Relationship', 'description'));
 
     CRM_Contact_Form_Edit_Notes::buildQuickForm($this);
 
-    $searchCount = $this->get('searchCount');
-    $duplicateRelationship = $this->get('duplicateRelationship');
-    $searchDone = $this->get('searchDone');
-
-    $isEmployeeOf = $isEmployerOf = FALSE;
-    if (!empty($this->_relationshipTypeId) &&
-      !empty($this->_rtype)
-    ) {
-      if ($this->_allRelationshipNames[$this->_relationshipTypeId]["name_{$this->_rtype}"] == 'Employee of') {
-        $isEmployeeOf = TRUE;
-      }
-      elseif ($this->_allRelationshipNames[$this->_relationshipTypeId]["name_{$this->_rtype}"] == 'Employer of') {
-        $isEmployerOf = TRUE;
-      }
-    }
-
-    $employers = $checkBoxes = $employees = array();
-    if ($searchRows) {
-      foreach ($searchRows as $id => $row) {
-        $checkBoxes[$id] = $this->createElement('checkbox', $id, NULL, '');
-        if ($isEmployeeOf) {
-          $employers[$id] = $this->createElement('radio', NULL, $id, NULL, $id);
-        }
-        elseif ($isEmployerOf) {
-          $employees[$id] = $this->createElement('checkbox', $id, NULL, '');
-        }
-      }
-
-      $this->addGroup($checkBoxes, 'contact_check');
-      $this->assign('searchRows', $searchRows);
-    }
-
-    if ($isEmployeeOf) {
-      $this->assign('isEmployeeOf', $isEmployeeOf);
-      if (!$callAjax) {
-        $this->addGroup($employers, 'employee_of');
-      }
-    }
-    elseif ($isEmployerOf) {
-      $this->assign('isEmployerOf', $isEmployerOf);
-      if (!$callAjax) {
-        $this->addGroup($employees, 'employer_of');
-      }
-    }
-
-    if ($callAjax && ($isEmployeeOf || $isEmployerOf)) {
-      $this->addElement('hidden', 'store_employers', '', array('id' => 'store_employers'));
-    }
-
-    if ($this->_action & CRM_Core_Action::UPDATE) {
-      $this->addElement('checkbox', 'is_current_employer');
-    }
-
-    $this->assign('duplicateRelationship', $duplicateRelationship);
-    $this->assign('searchCount', $searchCount);
-    $this->assign('searchDone', $searchDone);
-
-    if ($this->get('contact_type')) {
-      $typeLabel = CRM_Contact_BAO_ContactType::getLabel($this->get('contact_type'));
-      $this->assign('contact_type', $this->get('contact_type'));
-      $this->assign('contact_type_display', $typeLabel);
-    }
-
-    if ($searchDone) {
-      $searchBtn = ts('Search Again');
+    if ($this->_action & CRM_Core_Action::VIEW) {
+      $this->addButtons(array(
+        array(
+          'type' => 'cancel',
+          'name' => ts('Done'),
+        ),
+      ));
     }
     else {
-      $searchBtn = ts('Search');
-    }
-    $this->addElement('submit', $this->getButtonName('refresh'), $searchBtn, array('class' => 'form-submit', 'id' => 'search-button'));
-    $this->addElement('submit', $this->getButtonName('refresh', 'save'), 'Quick Save', array('class' => 'form-submit', 'id' => 'quick-save'));
-    $this->addElement('submit', $this->getButtonName('cancel'), ts('Cancel'), array('class' => 'form-submit cancel'));
-
-    $this->addElement('submit', $this->getButtonName('refresh', 'savedetails'), 'Save Relationship', array('class' => 'form-submit hiddenElement', 'id' => 'details-save'));
-    $this->addElement('checkbox', 'add_current_employer', ts('Current Employer'), NULL);
-    $this->addElement('checkbox', 'add_current_employee', ts('Current Employee'), NULL);
-
-    //need to assign custom data type and subtype to the template
-    $this->assign('customDataType', 'Relationship');
-    $this->assign('customDataSubType', $this->_relationshipTypeId);
-    $this->assign('entityID', $this->_relationshipId);
-
-    // make this form an upload since we dont know if the custom data injected dynamically
-    // is of type file etc $uploadNames = $this->get(
-    // 'uploadNames' );
-    $buttonParams = array(
-      'type' => 'upload',
-      'name' => ts('Save Relationship'),
-      'isDefault' => TRUE,
-    );
-    if ($callAjax) {
-      $buttonParams['js'] = array('onclick' => ' submitAjaxData();');
-    }
-
-    $this->addButtons(array(
-      $buttonParams
-        ,
+      // make this form an upload since we don't know if the custom data injected dynamically is of type file etc.
+      $this->addButtons(array(
+        array(
+          'type' => 'upload',
+          'name' => ts('Save Relationship'),
+          'isDefault' => TRUE,
+        ),
         array(
           'type' => 'cancel',
           'name' => ts('Cancel'),
         ),
-      )
-    );
+      ));
+    }
   }
 
   /**
@@ -468,96 +407,49 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
   public function postProcess() {
     // store the submitted values in an array
     $params = $this->controller->exportValues($this->_name);
-    $quickSave = FALSE;
-    if (!empty($_POST['_qf_Relationship_refresh_save']) || !empty($_POST['_qf_Relationship_refresh_savedetails'])) {
-      $quickSave = TRUE;
-    }
-
-    $this->set('searchDone', 0);
-    $this->set('callAjax', FALSE);
-    if (!empty($_POST['_qf_Relationship_refresh']) || $quickSave) {
-      if (is_numeric($params['contact_select_id'][1])) {
-        if ($quickSave) {
-          $params['contact_check'] = array($params['contact_select_id'][1] => 1);
-        }
-      }
-      else {
-        $this->set('callAjax', TRUE);
-        $this->set('relType', $params['relationship_type_id']);
-        $this->set('relContact', $params['contact'][1]);
-        $quickSave = FALSE;
-      }
-      $this->set('searchDone', 1);
-      if (!$quickSave) {
-        return;
-      }
-    }
 
     // action is taken depending upon the mode
-    $ids = array();
-    $ids['contact'] = $this->_contactId;
-
-    // modify params for ajax call
-    $this->modifyParams($params);
-
     if ($this->_action & CRM_Core_Action::DELETE) {
       CRM_Contact_BAO_Relationship::del($this->_relationshipId);
       return;
     }
 
-    $relationshipTypeId = str_replace(array('_a_b', '_b_a'), array('', ''), $params['relationship_type_id']);
+    $ids = array('contact' => $this->_contactId);
+
+    // Boolean fields (checkboxes) are nonexistant when submitted if unchecked - cast them to boolean
+    // FIXME: Dear Quickform, this sucks.
+    $params['is_active'] = !empty($params['is_active']);
+    $params['is_permission_a_b'] = !empty($params['is_permission_a_b']);
+    $params['is_permission_b_a'] = !empty($params['is_permission_b_a']);
+
+
+    $relationshipTypeId = str_replace(array('_', 'a', 'b'), '', $params['relationship_type_id']);
     if ($this->_action & CRM_Core_Action::UPDATE) {
       $ids['relationship'] = $this->_relationshipId;
       $relation = CRM_Contact_BAO_Relationship::getContactIds($this->_relationshipId);
       $ids['contactTarget'] = ($relation->contact_id_a == $this->_contactId) ? $relation->contact_id_b : $relation->contact_id_a;
 
-      //if relationship type change and previously it was
-      //employer / emplyee relationship with current employer
-      //than clear the current employer. CRM-3235.
-
-      //make sure we has to have employer id before firing queries, CRM-7306
-      $employerId = CRM_Utils_Array::value('current_employee_id', $this->_values);
-      $isDisabled = TRUE;
-      if (!empty($params['is_active'])) {
-        $isDisabled = FALSE;
-      }
-      $relChanged = TRUE;
-      if ($relationshipTypeId == $this->_values['relationship_type_id']) {
-        $relChanged = FALSE;
-      }
-      if ($employerId && ($isDisabled || $relChanged)) {
-        CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($this->_values['current_employee_id']);
+      // if relationship type changes, relationship is disabled, or "current employer" is unchecked,
+      // clear the current employer. CRM-3235.
+      $isDisabled = !$params['is_active'] || !$params['is_current_employer'];
+      $relChanged = $relationshipTypeId != $this->_values['relationship_type_id'];
+      if ($this->_isCurrentEmployer && ($isDisabled || $relChanged)) {
+        CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($this->_values['contact_id_a']);
       }
 
-      //if field key doesn't exists in params that means the user has unchecked checkbox,
-      //hence fill FALSE to params
-      $params['is_active'] = $isDisabled ? FALSE : TRUE;
-      $params['is_permission_a_b'] = CRM_Utils_Array::value('is_permission_a_b', $params, FALSE);
-      $params['is_permission_b_a'] = CRM_Utils_Array::value('is_permission_b_a', $params, FALSE);
     }
-    elseif ($quickSave) {
-      if (!empty($params['add_current_employee']) &&
-        $this->_allRelationshipNames[$relationshipTypeId]['name_a_b'] == 'Employee of'
-      ) {
-        $params['employee_of'] = $params['contact_select_id'][1];
-      }
-      elseif (!empty($params['add_current_employer']) &&
-        $this->_allRelationshipNames[$relationshipTypeId]['name_b_a'] == 'Employer of'
-      ) {
-        $params['employer_of'] = array($params['contact_select_id'][1] => 1);
-      }
+    // Create mode - save 1 or more new relationships
+    else {
+      // Fill up this weird param with contact ids like the weird relationship bao expects
+      $params['contact_check'] = array_fill_keys(explode(',', $params['related_contact_id']), 1);
       if (!$this->_rtype) {
-        $this->_rtype = str_replace($relationshipTypeId . '_', '', $params['relationship_type_id']);
+        list(, $this->_rtype) = explode('_', $relationshipTypeId, 2);
       }
     }
-
-    if (!$params['note']) {
-      $params['note'] = 'null';
-    }
     $params['start_date'] = CRM_Utils_Date::processDate($params['start_date'], NULL, TRUE);
     $params['end_date'] = CRM_Utils_Date::processDate($params['end_date'], NULL, TRUE);
 
-    //special case to handle if all checkboxes are unchecked
+    // Process custom data
     $customFields = CRM_Core_BAO_CustomField::getFields('Relationship', FALSE, FALSE, $relationshipTypeId);
     $params['custom'] = CRM_Core_BAO_CustomField::postProcess(
       $params,
@@ -566,6 +458,7 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
       'Relationship'
     );
 
+    // Save relationships
     list($valid, $invalid, $duplicate, $saved, $relationshipIds) = CRM_Contact_BAO_Relationship::create($params, $ids);
 
     // if this is called from case view,
@@ -574,12 +467,11 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
       CRM_Case_BAO_Case::createCaseRoleActivity($this->_caseId, $relationshipIds, $params['contact_check'], $this->_contactId);
     }
 
-    $status = '';
     if ($valid) {
-      CRM_Core_Session::setStatus(ts('New relationship created.', array('count' => $valid, 'plural' => '%count new relationships created.')), ts('Saved'), 'success');
+      CRM_Core_Session::setStatus(ts('Relationship created.', array('count' => $valid, 'plural' => '%count relationships created.')), ts('Saved'), 'success');
     }
     if ($invalid) {
-      CRM_Core_Session::setStatus(ts('%count relationship record was not created due to an invalid target contact type.', array('count' => $invalid, 'plural' => '%count relationship records were not created due to invalid target contact types.')), ts('%count invalid relationship record', array('count' => $invalid, 'plural' => '%count invalid relationship records')));
+      CRM_Core_Session::setStatus(ts('%count relationship record was not created due to an invalid contact type.', array('count' => $invalid, 'plural' => '%count relationship records were not created due to invalid contact types.')), ts('%count invalid relationship record', array('count' => $invalid, 'plural' => '%count invalid relationship records')));
     }
     if ($duplicate) {
       CRM_Core_Session::setStatus(ts('One relationship was not created because it already exists.', array('count' => $duplicate, 'plural' => '%count relationships were not created because they already exist.')), ts('%count duplicate relationship', array('count' => $duplicate, 'plural' => '%count duplicate relationships')));
@@ -588,29 +480,29 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
       CRM_Core_Session::setStatus(ts('Relationship record has been updated.'), ts('Saved'), 'success');
     }
 
-    if (!empty($relationshipIds)) {
-      $note               = new CRM_Core_DAO_Note();
-      $note->entity_id    = $relationshipIds[0];
-      $note->entity_table = 'civicrm_relationship';
-      $noteIds            = array();
-      if ($note->find(TRUE)) {
-        $id = $note->id;
-        $noteIds['id'] = $id;
+    // Save notes
+    if ($this->action & CRM_Core_Action::UPDATE || $params['note']) {
+      foreach ($relationshipIds as $id) {
+        $noteParams = array(
+          'entity_id' => $id,
+          'entity_table' => 'civicrm_relationship',
+        );
+        $existing = civicrm_api3('note' ,'get', $noteParams);
+        if (!empty($existing['id'])) {
+          $noteParams['id'] = $existing['id'];
+        }
+        $noteParams['note'] = $params['note'];
+        $noteParams['contact_id'] = $this->_contactId;
+        if (!empty($existing['id']) || $params['note']) {
+          $action = $params['note'] ? 'create' : 'delete';
+          civicrm_api3('note', $action, $noteParams);
+        }
       }
-
-      $noteParams = array(
-        'entity_id' => $relationshipIds[0],
-        'entity_table' => 'civicrm_relationship',
-        'note' => $params['note'],
-        'contact_id' => $this->_contactId,
-      );
-      CRM_Core_BAO_Note::add($noteParams, $noteIds);
-
-      $params['relationship_ids'] = $relationshipIds;
     }
 
     // Membership for related contacts CRM-1657
     if (CRM_Core_Permission::access('CiviMember') && (!$duplicate)) {
+      $params['relationship_ids'] = $relationshipIds;
       if ($this->_action & CRM_Core_Action::ADD) {
         CRM_Contact_BAO_Relationship::relatedMemberships($this->_contactId,
           $params, $ids,
@@ -626,146 +518,16 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
         }
       }
     }
-    //handle current employee/employer relationship, CRM-3532
-    if ($this->_allRelationshipNames[$relationshipTypeId]["name_{$this->_rtype}"] == 'Employee of') {
-      $orgId = NULL;
-      if (!empty($params['employee_of'])) {
-        $orgId = $params['employee_of'];
-      }
-      elseif ($this->_action & CRM_Core_Action::UPDATE) {
-        if (!empty($params['is_current_employer']) && !empty($params['is_active'])) {
-          if (CRM_Utils_Array::value('contactTarget', $ids) !=
-            CRM_Utils_Array::value('current_employer_id', $this->_values)
-          ) {
-            $orgId = CRM_Utils_Array::value('contactTarget', $ids);
-          }
-        }
-        elseif (CRM_Utils_Array::value('contactTarget', $ids) ==
-          CRM_Utils_Array::value('current_employer_id', $this->_values)
-        ) {
-          //clear current employer.
-          CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($this->_contactId);
-        }
-      }
-
-      //set current employer
-      if ($orgId) {
-        $currentEmpParams[$this->_contactId] = $orgId;
-        CRM_Contact_BAO_Contact_Utils::setCurrentEmployer($currentEmpParams);
-      }
-    }
-    elseif ($this->_allRelationshipNames[$relationshipTypeId]["name_{$this->_rtype}"] == 'Employer of') {
-      $individualIds = array();
-      if (!empty($params['employer_of'])) {
-        $individualIds = array_keys($params['employer_of']);
-      }
-      elseif ($this->_action & CRM_Core_Action::UPDATE) {
-        if (!empty($params['is_current_employer'])) {
-          if (CRM_Utils_Array::value('contactTarget', $ids) !=
-            CRM_Utils_Array::value('current_employee_id', $this->_values)
-          ) {
-            $individualIds[] = CRM_Utils_Array::value('contactTarget', $ids);
-          }
-        }
-        elseif (CRM_Utils_Array::value('contactTarget', $ids) ==
-          CRM_Utils_Array::value('current_employee_id', $this->_values)
-        ) {
-          // clear current employee
-          CRM_Contact_BAO_Contact_Utils::clearCurrentEmployer($ids['contactTarget']);
-        }
-      }
-
-      //set current employee
-      if (!empty($individualIds)) {
-
-        //build the employee params.
-        foreach ($individualIds as $key => $Id) {
-          $currentEmpParams[$Id] = $this->_contactId;
-        }
-
-        CRM_Contact_BAO_Contact_Utils::setCurrentEmployer($currentEmpParams);
-      }
-    }
-    // Don't redirect in ajaxForm context
-    // FIXME: Perhaps changing the button type would avoid needing the redirect at allq
-    if ($quickSave && empty($_REQUEST['snippet'])) {
-      $session = CRM_Core_Session::singleton();
-      CRM_Utils_System::redirect($session->popUserContext());
-    }
-  }
-  //end of function
-
-  /**
-   * function for validation
-   *
-   * @param array $params (reference ) an assoc array of name/value pairs
-   *
-   * @return mixed true or array of errors
-   * @access public
-   * @static
-   */
-  static function formRule($params, $files, $form) {
-    // hack, no error check for refresh
-    if (!empty($_POST['_qf_Relationship_refresh']) || !empty($_POST['_qf_Relationship_refresh_save']) ||
-      CRM_Utils_Array::value('_qf_Relationship_refresh_savedetails', $_POST)
-    ) {
-      return TRUE;
-    }
-
-    $form->modifyParams($params);
-
-    $ids                 = array();
-    $session             = CRM_Core_Session::singleton();
-    $ids['contact']      = $form->get('contactId');
-    $ids['relationship'] = $form->get('relationshipId');
-
-    $errors = array();
-    $employerId = NULL;
-    if (!empty($params['contact_check']) && is_array($params['contact_check'])) {
-      foreach ($params['contact_check'] as $cid => $dontCare) {
-        $message = CRM_Contact_BAO_Relationship::checkValidRelationship($params, $ids, $cid);
-        if ($message) {
-          $errors['relationship_type_id'] = $message;
-          break;
-        }
-
-        if ($cid == CRM_Utils_Array::value('employee_of', $params)) {
-          $employerId = $cid;
-        }
-      }
-    }
-    else {
-      if ($form->_callAjax) {
-        $errors['store_contacts'] = ts('Select select at least one contact from Target Contact(s).');
-      }
-      else {
-        $errors['contact_check'] = ts('Please select at least one contact.');
-      }
-    }
-
-    if (!empty($params['employee_of']) &&
-      !$employerId
-    ) {
-      if ($form->_callAjax) {
-        $errors['store_employer'] = ts('Current employer should be one of the selected contacts.');
-      }
-      else {
-        $errors['employee_of'] = ts('Current employer should be one of the selected contacts.');
-      }
-    }
-
-    if (!empty($params['employer_of']) && !empty($params['contact_check']) &&
-      array_diff(array_keys($params['employer_of']), array_keys($params['contact_check']))
-    ) {
-      if ($form->_callAjax) {
-        $errors['store_employer'] = ts('Current employee should be among the selected contacts.');
-      }
-      else {
-        $errors['employer_of'] = ts('Current employee should be among the selected contacts.');
+    // Set current employee/employer relationship, CRM-3532
+    if ($params['is_current_employer'] && $this->_allRelationshipNames[$relationshipTypeId]["name_a_b"] == 'Employee of') {
+      $employerParams = array();
+      foreach ($relationshipIds as $id) {
+        // Fixme this is dumb why do we have to look this up again?
+        $rel = CRM_Contact_BAO_Relationship::getContactIds($id);
+        $employerParams[$rel->contact_id_a] = $rel->contact_id_b;
       }
+      CRM_Contact_BAO_Contact_Utils::setCurrentEmployer($employerParams);
     }
-
-    return empty($errors) ? TRUE : $errors;
   }
 
   /**
@@ -792,35 +554,5 @@ class CRM_Contact_Form_Relationship extends CRM_Core_Form {
     return empty($errors) ? TRUE : $errors;
   }
 
-  function modifyParams(&$params) {
-    if (!$this->_callAjax) {
-      return;
-    }
-
-    if (!empty($params['store_contacts'])) {
-      $storedContacts = array();
-      foreach (explode(',', $params['store_contacts']) as $value) {
-        if ($value) {
-          $storedContacts[$value] = 1;
-        }
-      }
-      $params['contact_check'] = $storedContacts;
-    }
-
-    if (!empty($params['store_employers'])) {
-      $employeeContacts = array();
-      foreach (explode(',', $params['store_employers']) as $value) {
-        if ($value) {
-          $employeeContacts[$value] = $value;
-        }
-      }
-      if ($this->_allRelationshipNames[$this->_relationshipTypeId]["name_{$this->_rtype}"] == 'Employee of') {
-        $params['employee_of'] = current($employeeContacts);
-      }
-      else {
-        $params['employer_of'] = $employeeContacts;
-      }
-    }
-  }
 }
 
index 05fb113600519359328596a36e3c8d3f1d657526..acaeeeb5a80adb56f546e5d28216e8be99255ead 100644 (file)
   {include file="CRM/Custom/Form/CustomData.tpl"}
 {else}
   {if $action eq 4 } {* action = view *}
-      <h3>{ts}View Relationship{/ts}</h3>
-        <div class="crm-block crm-content-block crm-relationship-view-block">
-        <table class="crm-info-panel">
-      {foreach from=$viewRelationship item="row"}
-            <tr>
-                <td class="label">{$row.relation}</td>
-                <td><a class="no-popup" href="{crmURL p='civicrm/contact/view' q="reset=1&cid=`$row.cid`"}">{$row.name}</a></td>
-            </tr>
-            {if $isCurrentEmployer}
-                <tr><td class="label">{ts}Current Employee?{/ts}</td><td>{ts}Yes{/ts}</td></tr>
-            {/if}
-            {if $row.start_date}
-                <tr><td class="label">{ts}Start Date{/ts}</td><td>{$row.start_date|crmDate}</td></tr>
-            {/if}
-            {if $row.end_date}
-                <tr><td class="label">{ts}End Date{/ts}</td><td>{$row.end_date|crmDate}</td></tr>
-            {/if}
-            {if $row.description}
-                <tr><td class="label">{ts}Description{/ts}</td><td>{$row.description}</td></tr>
-            {/if}
+    <div class="crm-block crm-content-block crm-relationship-view-block">
+      <table class="crm-info-panel">
+        {foreach from=$viewRelationship item="row"}
+          <tr>
+            <td class="label">{$row.relation}</td>
+            <td><a class="no-popup" href="{crmURL p='civicrm/contact/view' q="reset=1&cid=`$row.cid`"}">{$row.name}</a></td>
+          </tr>
+          {if $isCurrentEmployer}
+            <tr><td class="label">{ts}Current Employee?{/ts}</td><td>{ts}Yes{/ts}</td></tr>
+          {/if}
+          {if $row.start_date}
+            <tr><td class="label">{ts}Start Date{/ts}</td><td>{$row.start_date|crmDate}</td></tr>
+          {/if}
+          {if $row.end_date}
+            <tr><td class="label">{ts}End Date{/ts}</td><td>{$row.end_date|crmDate}</td></tr>
+          {/if}
+          {if $row.description}
+            <tr><td class="label">{ts}Description{/ts}</td><td>{$row.description}</td></tr>
+          {/if}
           {foreach from=$viewNote item="rec"}
-        {if $rec }
-          <tr><td class="label">{ts}Note{/ts}</td><td>{$rec}</td></tr>
-           {/if}
-            {/foreach}
-            {if $row.is_permission_a_b}
-                {if $row.rtype EQ 'a_b' AND $is_contact_id_a}
-                     <tr><td class="label">&nbsp;</td><td><strong>'{$displayName}'</strong> can view and update information for <strong>'{$row.display_name}'</strong></td></tr>
-                {else}
-                     <tr><td class="label">&nbsp;</td><td><strong>'{$row.display_name}'</strong> can view and update information for <strong>'{$displayName}'</strong></td></tr>
-                {/if}
-            {/if}
-            {if $row.is_permission_b_a}
-                 {if $row.rtype EQ 'a_b' AND $is_contact_id_a}
-                     <tr><td class="label">&nbsp;</td><td><strong>'{$row.display_name}'</strong> can view and update information for <strong>'{$displayName}'</strong></td></tr>
-                 {else}
-                     <tr><td class="label">&nbsp;</td><td><strong>'{$displayName}'</strong> can view and update information for <strong>'{$row.display_name}'</strong></td></tr>
-                 {/if}
+            {if $rec }
+              <tr><td class="label">{ts}Note{/ts}</td><td>{$rec}</td></tr>
             {/if}
-
-            <tr><td class="label">{ts}Status{/ts}</td><td>{if $row.is_active}{ts}Enabled{/ts} {else} {ts}Disabled{/ts}{/if}</td></tr>
+          {/foreach}
+          <tr>
+            <td class="label"><label>{ts}Permissions{/ts}</label></td>
+            <td>
+              {if $row.is_permission_a_b or $row.is_permission_b_a}
+                {if $row.is_permission_a_b}
+                  <div>
+                  {if $row.rtype EQ 'a_b' AND $is_contact_id_a}
+                    {ts 1=$displayName 2=$row.display_name}<strong>%1</strong> can view and update information about %2.{/ts}
+                  {else}
+                    {ts 1=$row.display_name 2=$displayName}<strong>%1</strong> can view and update information about %2.{/ts}
+                  {/if}
+                  </div>
+                {/if}
+                {if $row.is_permission_b_a}
+                  <div>
+                  {if $row.rtype EQ 'a_b' AND $is_contact_id_a}
+                    {ts 1=$row.display_name 2=$displayName}<strong>%1</strong> can view and update information about %2.{/ts}
+                  {else}
+                    {ts 1=$displayName 2=$row.display_name}<strong>%1</strong> can view and update information about %2.{/ts}
+                  {/if}
+                  </div>
+                {/if}
+              {else}
+                {ts}None{/ts}
+              {/if}
+            </td>
+          </tr>
+          <tr><td class="label">{ts}Status{/ts}</td><td>{if $row.is_active}{ts}Enabled{/ts}{else}{ts}Disabled{/ts}{/if}</td></tr>
         {/foreach}
-        </table>
-        {include file="CRM/Custom/Page/CustomDataView.tpl"}
-        <div class="crm-submit-buttons"><a class="button form-submit cancel" href="{crmURL p='civicrm/contact/view' q='action=browse&selectedChild=rel'}">{ts}Done{/ts}</a></div>
-        </div>
+      </table>
+      {include file="CRM/Custom/Page/CustomDataView.tpl"}
+    </div>
   {/if}
 
-  {if $action eq 2 | $action eq 1} {* add and update actions *}
-    {* Retrieve the ID for the Employee / Employer relationship type *}
-    {crmAPI var="employmentRelationship" entity="RelationshipType" action="getvalue" version="3" name_a_b="Employee of" return="id"}
-    <h3>{if $action eq 1}{ts}New Relationship{/ts}{else}{ts}Edit Relationship{/ts}{/if}</h3>
-    {literal}
-      <script type="text/javascript">
-        function setPermissionStatus( relTypeDirection ) {
-          var direction = relTypeDirection.split( '_' );
-          cj('#permision_a_b-' + direction[1] + '_' + direction[2] ).show( );
-          cj('#permision_a_b-' + direction[2] + '_' + direction[1] ).hide( );
-          cj('#permision_b_a-' + direction[1] + '_' + direction[2] ).show( );
-          cj('#permision_b_a-' + direction[2] + '_' + direction[1] ).hide( );
-        }
-      </script>
-    {/literal}
+  {if $action eq 2 or $action eq 1} {* add and update actions *}
     <div class="crm-block crm-form-block crm-relationship-form-block">
-            {if $action eq 1}
-                <div class="description">
-                    {ts}Select the relationship type. Then locate target contact(s) for this relationship by entering a partial name and selecting from the dropdown, or clicking 'Search'. If the target contact does not exist, you can create a new contact.{/ts}
-                </div>
-            {/if}
-            <table class="form-layout-compressed">
-             <tr class="crm-relationship-form-block-relationship_type_id">
-               <td class="label">{$form.relationship_type_id.label}</td><td>{$form.relationship_type_id.html}</td>
-            {if $action EQ 2} {* action = update *}
-                {literal}
-                <script type="text/javascript">
-                    var relType = 0;
-                    cj( function( ) {
-                        var relationshipType = cj('#relationship_type_id');
-                        relationshipType.change( function( ) {
-                            changeCustomData( 'Relationship' );
-                            currentEmployer( );
-                        });
-                        setPermissionStatus( relationshipType.val( ) );
-                    });
-                </script>
-                {/literal}
-                <td><label>{$sort_name_b}</label></td></tr>
-                <tr class="crm-relationship-form-block-is_current_employer">
-                  <td class="label">
-                     <span id="employee"><label>{ts}Current Employee?{/ts}</label></span>
-                     <span id="employer"><label>{ts}Current Employer?{/ts}</label></span>
-                  </td>
-                  <td id="current_employer">{$form.is_current_employer.html}</td>
-                </tr>
-             </table>
-            {else} {* action = add *}
-             </tr>
-             {include file="CRM/Contact/Form/NewContact.tpl" newContactCallback="afterCreateNew()"}
-             <tr class="crm-relationship-form-block-rel_contact">
-               <td colspan="2">
-                {literal}
-                  <script type="text/javascript">
-                    var relType = 0;
-                    cj( function( ) {
-                        enableDisableContactSelection( );
-                        createRelation( );
-                        var relationshipType = cj('#relationship_type_id');
-                        relationshipType.change( function() {
-                            enableDisableContactSelection( );
-                            cj('#relationship-refresh-save').hide();
-                            cj('#saveButtons').hide();
-                            createRelation( );
-                            changeCustomData( 'Relationship' );
-                            setPermissionStatus( cj(this).val( ) );
-                        });
-                        setPermissionStatus( relationshipType.val( ) );
-                    });
-
-                    function enableDisableContactSelection( ) {
-                        var relationshipTypeValue = cj('#relationship_type_id').val();
-                        var contactAutocomplete   = cj('#contact_1');
-
-                        //always reset field so that correct data url is linked
-                        contactAutocomplete.unautocomplete( );
-
-                        if ( relationshipTypeValue ) {
-                            cj('#profiles_1').prop('disabled', false);
-                            contactAutocomplete.prop('disabled', false);
-                            contactAutocomplete.addClass('ac_input');
-                            buildCreateNewSelect( 'profiles_1', relationshipTypeValue );
-                        } else {
-                            cj('#profiles_1').prop('disabled', true);
-                            contactAutocomplete.removeClass('ac_input');
-                            contactAutocomplete.prop('disabled', true);
-                        }
-                    }
-
-                    function afterCreateNew() {
-                      var relType    = cj('#relationship_type_id').val( );
-                      var contactSelected = cj('#contact_1').val( );
-                      if ( relType && contactSelected ) {
-                        cj('#relationship-refresh-save').show( );
-                        buildRelationFields( relType );
-                      }
-                    }
-
-                    function createRelation(  ) {
-                        var relType    = cj('#relationship_type_id').val( );
-                        var relContact = cj('#contact_1');
-                        if ( relType ) {
-                             var dataUrl = {/literal}'{crmURL p="civicrm/ajax/rest" h=0 q="className=CRM_Contact_Page_AJAX&fnName=getContactList&json=1&context=relationship&rel="}'{literal} + relType;
-                             relContact.autocomplete( dataUrl, { width : 200, selectFirst : false, matchContains: true, max: {/literal}{crmSetting name="search_autocomplete_count" group="Search Preferences"}{literal} });
-                             relContact.result(function( event, data ) {
-                                cj("input[name='contact_select_id[1]']").val(data[1]);
-                                cj('#relationship-refresh-save').show( );
-                                buildRelationFields( relType );
-                             });
-                        } else {
-                            relContact.unautocomplete( );
-                        }
-                    }
-
-                    function buildCreateNewSelect( selectID, relType ) {
-                        selectID = '#' + selectID;
-                        cj( selectID ).html('');
-                        var postUrl = "{/literal}{crmURL p='civicrm/ajax/relationshipContactTypeList' h=0}{literal}";
-                        cj.post( postUrl, { relType: relType },
-                            function ( response ) {
-                                cj( selectID ).get(0).add(new Option('{/literal}{ts escape="js"}- create new contact -{/ts}{literal}', ''));
-                                response = eval( response );
-                                for (i = 0; i < response.length; i++) {
-                                    cj( selectID ).get(0).add(new Option(response[i].name, response[i].value));
-                                }
-                            }
-                        );
-                    }
-
-          </script>
-                {/literal}
-               </td>
-             </tr>
-              </table>
-                <div class="crm-submit-buttons">
-                    <span id="relationship-refresh" class="crm-button crm-button-type-refresh crm-button_qf_Relationship_refresh">{$form._qf_Relationship_refresh.html}</span>
-                    <span id="relationship-refresh-save" class="crm-button crm-button-type-save crm-button_qf_Relationship_refresh_save" style="display:none">{$form._qf_Relationship_refresh_save.html}</span>
-                    <span class="crm-button crm-button-type-cancel crm-button_qf_Relationship_cancel">{$form._qf_Relationship_cancel.html}</span>
-                </div>
-                <div class="clear"></div>
-
-              {if $searchDone } {* Search button clicked *}
-                {if $searchCount || $callAjax}
-                    {if $searchRows || $callAjax} {* we got rows to display *}
-                        <fieldset id="searchResult"><legend>{ts}Mark Target Contact(s) for this Relationship{/ts}</legend>
-                        <div class="description">
-                            {ts}Mark the target contact(s) for this relationship if it appears below. Otherwise you may modify the search name above and click Search again.{/ts}
-                        </div>
-                        {strip}
-                  {if $callAjax}
-                      <div id="count_selected"> </div><br />
-                      {$form.store_contacts.html}
+      <table class="form-layout-compressed">
+        <tr class="crm-relationship-form-block-relationship_type_id">
+          <td class="label">{$form.relationship_type_id.label}</td>
+          <td>{$form.relationship_type_id.html}</td>
+        </tr>
+        <tr class="crm-relationship-form-block-related_contact_id">
+          <td class="label">{$form.related_contact_id.label}</td>
+          {* remove crm-select2 class - hack to prevent widget from being initialized so we can mess with it first *}
+          <td>{$form.related_contact_id.html|crmReplace:class:'crm-form-entityref'}</td>
+        </tr>
+        <tr class="crm-relationship-form-block-is_current_employer" style="display:none;">
+          <td class="label">{$form.is_current_employer.label}</td>
+          <td>{$form.is_current_employer.html}</td>
+        </tr>
+        <tr class="crm-relationship-form-block-start_date">
+          <td class="label">{$form.start_date.label}</td>
+          <td>{include file="CRM/common/jcalendar.tpl" elementName=start_date}<span>{$form.end_date.label} {include file="CRM/common/jcalendar.tpl" elementName=end_date}</span><br />
+            <span class="description">{ts}If this relationship has start and/or end dates, specify them here.{/ts}</span></td>
+        </tr>
+        <tr class="crm-relationship-form-block-description">
+          <td class="label">{$form.description.label}</td>
+          <td>{$form.description.html}</td>
+        </tr>
+        <tr class="crm-relationship-form-block-note">
+          <td class="label">{$form.note.label}</td>
+          <td>{$form.note.html}</td>
+        </tr>
+        <tr class="crm-relationship-form-block-is_permission_a_b">
+          {capture assign="contact_b"}{if $action eq 1}{ts}selected contact(s){/ts}{else}{$display_name_b}{/if}{/capture}
+          <td class="label"><label>{ts}Permissions{/ts}</label></td>
+          <td>
+            {$form.is_permission_a_b.html}
+            {ts 1=$display_name_a 2=$contact_b}<strong>%1</strong> can view and update information about %2.{/ts}
+          </td>
+        </tr>
+        <tr class="crm-relationship-form-block-is_permission_b_a">
+          <td class="label"></td>
+          <td>
+            {$form.is_permission_b_a.html}
+            {ts 1=$contact_b|ucfirst 2=$display_name_a}<strong>%1</strong> can view and update information about %2.{/ts}
+          </td>
+        </tr>
+        <tr class="crm-relationship-form-block-is_active">
+          <td class="label">{$form.is_active.label}</td>
+          <td>{$form.is_active.html}</td>
+        </tr>
+      </table>
+      <div id="customData"></div>
+      <div class="spacer"></div>
+    </div>
+  {/if}
+  {if ($action EQ 1) OR ($action EQ 2) }
+    {*include custom data js file - setting includeWysiwygEditor=TRUE because it's already been loaded*}
+    {include file="CRM/common/customData.tpl" includeWysiwygEditor=TRUE}
+    <script type="text/javascript">
+      {literal}
+      cj(function($) {
+        var
+          $form = $("form#{/literal}{$form.formName}{literal}"),
+          relationshipData = {/literal}{$relationshipData|@json_encode}{literal};
+        $('[name=relationship_type_id]', $form).change(function() {
+          var
+            val = $(this).val(),
+            $contactField = $('[name=related_contact_id][type=text].crm-form-entityref', $form);
+          if (!val && $contactField.length) {
+            $contactField
+              .prop('disabled', true)
+              .attr('placeholder', {/literal}'{ts escape='js'}- first select relationship type -{/ts}'{literal});
+            // Re-render select2 element
+            CRM.utils.buildSelect2Element.call($contactField);
+          }
+          else if (val) {
+            var
+              pieces = val.split('_'),
+              rType = pieces[0],
+              source = pieces[1], // a or b
+              target = pieces[2], // b or a
+              contact_type = relationshipData[rType]['contact_type_' + target],
+              contact_sub_type = relationshipData[rType]['contact_sub_type_' + target];
+            // ContactField only exists for ADD action, not update
+            if ($contactField.length) {
+              var
+                profiles = $.parseJSON($contactField.attr('data-create-links')),
+                placeholder = {/literal}'{ts escape='js' 1=%1}- select %1 -{/ts}'{literal},
+                params = {params: {}};
+              if (contact_type) {
+                profiles = _.where(profiles, {name: 'new_' + contact_type.toLowerCase()});
+                params.params.contact_type = contact_type;
+              }
+              if (contact_sub_type) {
+                params.params.contact_sub_type = contact_sub_type;
+                // Todo: pass sub-type to new contact profile otherwise relationship create will fail. Disabling it completely for now.
+                profiles = [];
+              }
+              $contactField
+                .val('')
+                .prop('disabled', false)
+                .data('create-links', profiles)
+                .data('api-params', params)
+                .attr('placeholder', relationshipData[rType]['placeholder_' + target]);
+
+              // Re-render select2 element
+              CRM.utils.buildSelect2Element.call($contactField);
+            }
 
-                      {if $isEmployeeOf || $isEmployerOf}
-                           {$form.store_employer.html}
-                      {/if}
-                      {include file="CRM/common/jsortable.tpl"  sourceUrl=$sourceUrl useAjax=1 callBack=1 }
-                  {/if}
+            // Show/hide employer field
+            $('.crm-relationship-form-block-is_current_employer', $form).toggle(rType === {/literal}'{$employmentRelationship}'{literal});
 
-                        <table id="rel-contacts" class="pagerDisplay">
-                      <thead>
-                                <tr class="columnheader">
-                                    <th id="nosort" class="contact_select">&nbsp;</th>
-                                    <th>{ts}Name{/ts}</th>
-                                {if $isEmployeeOf}<th id="nosort" class="current_employer">{ts}Current Employer?{/ts}</th>
-                                {elseif $isEmployerOf}<th id="nosort" class="current_employer">{ts}Current Employee?{/ts}</th>{/if}
-                                    <th>{ts}City{/ts}</th>
-                                    <th>{ts}State{/ts}</th>
-                                    <th>{ts}Email{/ts}</th>
-                                    <th>{ts}Phone{/ts}</th>
-                                </tr>
-                      </thead>
-                       <tbody>
-                      {if !$callAjax}
-                                {foreach from=$searchRows item=row}
-                                <tr class="{cycle values="odd-row,even-row"}">
-                                    <td class="contact_select">{$form.contact_check[$row.id].html}</td>
-                                    <td>{$row.type} {$row.name}</td>
-                                    {if $isEmployeeOf}<td>{$form.employee_of[$row.id].html}</td>
-                                    {elseif $isEmployerOf}<td>{$form.employer_of[$row.id].html}</td>{/if}
-                                    <td>{$row.city}</td>
-                                    <td>{$row.state}</td>
-                                    <td>{$row.email}</td>
-                                    <td>{$row.phone}</td>
-                                </tr>
-                                {/foreach}
-                      {else}
-                          <tr><td colspan="5" class="dataTables_empty">Loading data from server</td></tr>
-                      {/if}
-                      </tbody>
-                        </table>
-                        {/strip}
-                        </fieldset>
-                        <div class="spacer"></div>
-                    {else} {* too many results - we display only 50 *}
-                        {if $duplicateRelationship}
-                            {capture assign=infoTitle}{ts}Duplicate relationship.{/ts}{/capture}
-                            {capture assign=infoMessage}{ts}This relationship already exists.{/ts}{/capture}
-                        {else}
-                            {capture assign=infoTitle}{ts}Too many matching results.{/ts}{/capture}
-                            {capture assign=infoMessage}{ts}Please narrow your search by entering a more complete target contact name.{/ts}{/capture}
-                        {/if}
-                        {include file="CRM/common/info.tpl"}
-                    {/if}
-                {else} {* no valid matches for name + contact_type *}
-                        {capture assign=infoTitle}{ts}No matching results for{/ts}{/capture}
-                        {capture assign=infoMessage}<ul><li>{ts 1=$form.contact_1.value}Name like: %1{/ts}</li><li>{ts}Contact Type{/ts}: {$contact_type_display}</li></ul>{ts}Check your spelling, or try fewer letters for the target contact name.{/ts}{/capture}
-                        {include file="CRM/common/info.tpl"}
-                {/if} {* end if searchCount *}
-              {else}
-              {/if} {* end if searchDone *}
-        {/if} {* end action = add *}
+            // Swap the permission checkboxes to match selected relationship direction
+            $('#is_permission_a_b', $form).attr('name', 'is_permission_' + source + '_' + target);
+            $('#is_permission_b_a', $form).attr('name', 'is_permission_' + target + '_' + source);
 
-            <div id='saveElements'>
-                {if $action EQ 1}
-                <div id='addCurrentEmployer'>
-                   <table class="form-layout-compressed">
-                       <tr class="crm-relationship-form-block-add_current_employer">
-                         <td class="label">{$form.add_current_employer.label}</td>
-                         <td>{$form.add_current_employer.html}</td>
-                       </tr>
-                   </table>
-                </div>
-                <div id='addCurrentEmployee'>
-                   <table class="form-layout-compressed">
-                       <tr class="crm-relationship-form-block-add_current_employee">
-                         <td class="label">{$form.add_current_employee.label}</td>
-                         <td>{$form.add_current_employee.html}</td>
-                       </tr>
-                   </table>
-                </div>
-                {/if}
-                <table class="form-layout-compressed">
-                    <tr class="crm-relationship-form-block-start_date">
-                        <td class="label">{$form.start_date.label}</td>
-                        <td>{include file="CRM/common/jcalendar.tpl" elementName=start_date}</td></tr>
-                    <tr class="crm-relationship-form-block-end_date">
-                        <td class="label">{$form.end_date.label}</td>
-                        <td>{include file="CRM/common/jcalendar.tpl" elementName=end_date}<br />
-                        <span class="description">{ts}If this relationship has start and/or end dates, specify them here.{/ts}</span></td>
-                    </tr>
-                    <tr class="crm-relationship-form-block-description">
-                        <td class="label">{$form.description.label}</td>
-                        <td>{$form.description.html}</td>
-                    </tr>
-                    <tr class="crm-relationship-form-block-note">
-                        <td class="label">{$form.note.label}</td>
-                        <td>{$form.note.html}</td>
-                    </tr>
-                    <tr class="crm-relationship-form-block-is_permission_a_b">
-                        <td class="label"></td><td>{$form.is_permission_a_b.html}
-                        <span id='permision_a_b-a_b' class="hiddenElement">
-                            {if $action eq 1}
-                                <strong>'{$sort_name_a}'</strong> {ts}can view and update information for selected contact(s){/ts}
-                            {else}
-                                <strong>'{$sort_name_a}'</strong> {ts}can view and update information for {/ts} <strong>'{$sort_name_b}'</strong>
-                            {/if}
-                        </span>
-                        <span id='permision_a_b-b_a' class="hiddenElement">
-                            {if $action eq 1}
-                                <strong>{ts}Selected contact(s)</strong> can view and update information for {/ts} <strong>'{$sort_name_a}'</strong>
-                            {else}
-                                <strong>'{$sort_name_b}'</strong> {ts}can view and update information for {/ts} <strong>'{$sort_name_a}'</strong>
-                            {/if}
-                        </span>
-                        </td>
-                    </tr>
-                    <tr class="crm-relationship-form-block-is_permission_b_a">
-                        <td class="label"></td><td>{$form.is_permission_b_a.html}
-                        <span id='permision_b_a-b_a' class="hiddenElement">
-                            {if $action eq 1}
-                                <strong>'{$sort_name_a}'</strong> {ts}can view and update information for selected contact(s){/ts}
-                            {else}
-                                <strong>'{$sort_name_a}'</strong> {ts}can view and update information for {/ts} <strong>'{$sort_name_b}'</strong>
-                            {/if}
-                        </span>
-                        <span id='permision_b_a-a_b' class="hiddenElement">
-                            {if $action eq 1}
-                                <strong>{ts}Selected contact(s)</strong> can view and update information for {/ts} <strong>'{$sort_name_a}'</strong>
-                            {else}
-                                <strong>'{$sort_name_b}'</strong> {ts}can view and update information for {/ts} <strong>'{$sort_name_a}'</strong>
-                            {/if}
-                        </span>
-                        </td>
-                    </tr>
-                    <tr class="crm-relationship-form-block-is_active">
-                        <td class="label">{$form.is_active.label}</td>
-                        <td>{$form.is_active.html}</td>
-                    </tr>
-                </table>
-            </div>{* end of save element div *}
-        <div id="customData"></div>
-        <div class="spacer"></div>
-        <div class="crm-submit-buttons" id="saveButtons"> {include file="CRM/common/formButtons.tpl" location="bottom"}</div>
-        {if $action EQ 1}
-            <div class="crm-submit-buttons" id="saveDetails">
-            <span class="crm-button crm-button-type-save crm-button_qf_Relationship_refresh_savedetails">{$form._qf_Relationship_refresh_savedetails.html}</span>
-            <span class="crm-button crm-button-type-cancel crm-button_qf_Relationship_cancel">{$form._qf_Relationship_cancel.html}</span>
-            </div>
-        {/if}
-      </div> {* close main block div *}
+            CRM.buildCustomData('Relationship', rType);
+          }
+        }).change();
+      });
+      {/literal}
+    </script>
   {/if}
 
   {if $action eq 8}
-     <fieldset><legend>{ts}Delete Relationship{/ts}</legend>
-        <div class="status">
-            {capture assign=relationshipsString}{$currentRelationships.$id.relation}{ $disableRelationships.$id.relation} {$currentRelationships.$id.name}{ $disableRelationships.$id.name }{/capture}
-            {ts 1=$relationshipsString}Are you sure you want to delete the Relationship '%1'?{/ts}
-        </div>
-        <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
-    </fieldset>
+    <div class="status">
+      {ts}Are you sure you want to delete this Relationship?{/ts}
+    </div>
   {/if}
+  <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
 {/if} {* close of custom data else*}
 
-{if $callAjax}
-{literal}
-<script type="text/javascript">
-var contact_checked  = new Array();
-var employer_checked = new Array();
-var employer_holdelement = new Array();
-var countSelected = useEmployer = isRadio = 0;
-
-{/literal} {if $isEmployeeOf || $isEmployerOf} {literal}
-var storeElement  = 'store_employers';
-var employerClass = 'current_employer';
-useEmployer = 1;
-{/literal} {/if} {if $isEmployeeOf} {literal}
-isRadio = 1;
-{/literal} {/if} {literal}
-
-cj( function( ) {
-    // clear old data if any
-    cj('#store_contacts').val('');
-    if ( useEmployer ) {
-        cj('#store_employers').val('');
-    }
-
-    cj('.pagerDisplay').on('click', '.contact_select input', function () {
-        var valueSelected = cj(this).val();
-        if ( cj(this).prop('checked') ) {
-            contact_checked[valueSelected] =  valueSelected;
-            countSelected++;
-        } else if( contact_checked[valueSelected] ) {
-            delete contact_checked[valueSelected];
-            countSelected--;
-            if ( useEmployer && employer_holdelement[valueSelected] ) {
-                cj( employer_holdelement[valueSelected] ).prop('checked',false);
-                delete employer_checked[valueSelected];
-                delete employer_holdelement[valueSelected];
-            }
-        }
-        cj('#count_selected').html(countSelected +' Contacts selected.')
-    } );
-
-    if ( useEmployer ) {
-        cj('.pagerDisplay').on('click', '.'+ employerClass +' input', function () {
-            var valueSelected = cj(this).val();
-            if ( isRadio ) {
-                employer_checked = new Array();
-            }
-            if ( cj(this).prop('checked') ) {
-                // add validation to match with selected contacts
-                if( !contact_checked[valueSelected] ) {
-                    cj(this).crmError({/literal}'{ts escape="js"}Current employer / Current employee should be among the selected contacts.{/ts}'{literal});
-                    cj(this).prop('checked',false);
-                } else {
-                    employer_checked[valueSelected] = valueSelected;
-                    employer_holdelement[valueSelected] = this;
-                }
-
-            } else if ( employer_checked[valueSelected] ) {
-                delete employer_checked[valueSelected];
-                delete employer_holdelement[valueSelected];
-            }
-        } );
-    }
-
-});
-
-function checkSelected( ) {
-    cj('.pagerDisplay tbody tr .contact_select input').each( function( ) {
-        if ( contact_checked[cj(this).val()] ) {
-            cj(this).prop('checked',true);
-        }
-    });
-
-    if ( useEmployer ) {
-        // register new elements
-        employer_holdelement = new Array();
-        cj('.pagerDisplay tbody tr .'+ employerClass +' input').each( function( ) {
-            if ( employer_checked[cj(this).val()] ) {
-                cj(this).prop('checked',true);
-                employer_holdelement[cj(this).val()] = this;
-            }
-        });
-    }
-}
-
-function submitAjaxData() {
-  var total_checked = new Array();
-  cj.each(contact_checked, function (index, value) {
-    if (typeof value !== "undefined") {
-      total_checked.push(value);
-    }
-  });
-  contact_checked = total_checked;
-
-    cj('#store_contacts').val( contact_checked.toString() );
-    if ( useEmployer )  {
-        cj('#store_employers').val( employer_checked.toString() );
-    }
-    return true;
-}
-
-</script>
-{/literal}
-{/if}
-
-{if ($action EQ 1) OR ($action EQ 2) }
-{*include custom data js file*}
-{include file="CRM/common/customData.tpl"}
-{literal}
-<script type="text/javascript">
-
-{/literal} {if $searchRows} {literal}
-cj(".contact_select .form-checkbox").prop('checked',true);
-{/literal} {/if} {literal}
-
-{/literal} {if $action EQ 1}{literal}
-cj('#saveDetails').hide( );
-cj('#addCurrentEmployer').hide( );
-cj('#addCurrentEmployee').hide( );
-
-cj( function() {
-  if ( cj.browser.msie ) {
-       cj('#contact_1').keyup( function(e) {
-         if( e.keyCode == 9 || e.keyCode == 13 ) {
-            return false;
-       }
-         cj("input[name='contact_select_id[1]']").val('');
-         cj('#relationship-refresh').show( );
-         cj('#relationship-refresh-save').hide( );
-        });
-   } else {
-         cj('#contact_1').focus( function() {
-            cj("input[name='contact_select_id[1]']").val('');
-            cj('#relationship-refresh').show( );
-            cj('#relationship-refresh-save').hide( );
-         });
-   }
-});
-
-{/literal}{if $searchRows || $callAjax}{literal}
-  cj('#saveElements, #saveButtons').show();
-{/literal}{else}{literal}
-  cj('#saveElements, #saveButtons').hide();
-{/literal}{/if}{/if}{literal}
-
-cj( function( ) {
-    var relType = cj('#relationship_type_id').val( );
-    if ( relType ) {
-        var relTypeId = relType.split("_");
-        if (relTypeId) {
-            CRM.buildCustomData( 'Relationship', relTypeId[0]);
-        }
-    } else {
-        CRM.buildCustomData('Relationship');
-    }
-});
-
-function buildRelationFields( relType ) {
-    {/literal} {if $action EQ 1} {literal}
-    if ( relType ) {
-        var relTypeId = relType.split("_");
-        if ( relTypeId[0] == {/literal}{$employmentRelationship}{literal} ) {
-            if ( relTypeId[1] == 'a' ) {
-                cj('#addCurrentEmployee').show();
-                cj('#addCurrentEmployer').hide();
-            } else {
-                cj('#addCurrentEmployee').hide();
-                cj('#addCurrentEmployer').show();
-            }
-        } else {
-            cj('#addCurrentEmployee').hide();
-            cj('#addCurrentEmployer').hide();
-        }
-        cj('#relationship-refresh').hide();
-        cj('#relationship-refresh-save').show();
-        cj('#details-save').show();
-        cj('#saveElements').show();
-        cj('#saveDetails').show();
-        {/literal}{if $searchRows || $callAjax}{literal}
-        cj('#searchResult').hide();
-        {/literal}{/if}{literal}
-        cj('#saveButtons').hide();
-    }
-    {/literal}{/if}{literal}
-}
-
-function changeCustomData( cType ) {
-    {/literal}{if $action EQ 1} {literal}
-    cj('#customData').html('');
-    cj('#relationship-refresh').show();
-    cj('#saveElements').hide();
-    cj('#addCurrentEmployee').hide();
-    cj('#addCurrentEmployer').hide();
-    cj('#saveDetails').hide();
-    {/literal}{if $searchRows || $callAjax}{literal}
-    cj('#searchResult').hide();
-    {/literal}{/if}{literal}
-    {/literal}{/if} {literal}
-
-    var relType = cj('#relationship_type_id').val( );
-    if ( relType ) {
-        var relTypeId = relType.split("_");
-        if (relTypeId) {
-            CRM.buildCustomData( cType, relTypeId[0]);
-        }
-    } else {
-        CRM.buildCustomData( cType );
-    }
-}
-
-</script>
-{/literal}
-{/if}
-{if $action EQ 2}
-{literal}
-<script type="text/javascript">
-   currentEmployer( );
-   function currentEmployer( )
-   {
-      var relType = document.getElementById('relationship_type_id').value;
-      if ( relType == "{/literal}{$employmentRelationship}{literal}" + "_a_b" ) {
-           cj('#current_employer').show();
-           cj('#employee').show();
-           cj('#employer').hide();
-      } else if ( relType == "{/literal}{$employmentRelationship}{literal}" + "_b_a" ) {
-     cj('#current_employer').show();
-           cj('#employer').show();
-           cj('#employee').hide();
-      } else {
-           cj('#employer').hide();
-           cj('#employee').hide();
-     cj('#current_employer').hide();
-      }
-   }
-</script>
-{/literal}
-{/if}