Merge pull request #12725 from civicrm/5.5
authorSeamus Lee <seamuslee001@gmail.com>
Fri, 24 Aug 2018 20:42:13 +0000 (06:42 +1000)
committerGitHub <noreply@github.com>
Fri, 24 Aug 2018 20:42:13 +0000 (06:42 +1000)
5.5

126 files changed:
CRM/ACL/API.php
CRM/ACL/BAO/ACL.php
CRM/ACL/BAO/EntityRole.php
CRM/ACL/Form/WordPress/Permissions.php
CRM/Activity/BAO/Activity.php
CRM/Activity/Page/AJAX.php
CRM/Activity/Selector/Activity.php
CRM/Badge/BAO/Layout.php
CRM/Campaign/BAO/Campaign.php
CRM/Campaign/BAO/Survey.php
CRM/Campaign/Selector/Search.php
CRM/Case/BAO/Case.php
CRM/Case/Form/Activity.php
CRM/Contact/BAO/ContactType.php
CRM/Contact/BAO/Group.php
CRM/Contact/BAO/Query.php
CRM/Contact/BAO/RelationshipType.php
CRM/Contact/Form/Search/Custom/ContribSYBNT.php
CRM/Contact/Form/Task.php
CRM/Contact/Form/Task/EmailCommon.php
CRM/Contact/Selector.php
CRM/Contribute/BAO/ContributionPage.php
CRM/Contribute/BAO/Premium.php
CRM/Contribute/Form/AbstractEditPayment.php
CRM/Contribute/Form/AdditionalPayment.php
CRM/Contribute/Form/Contribution/Confirm.php
CRM/Core/BAO/ActionSchedule.php
CRM/Core/BAO/CustomField.php
CRM/Core/BAO/CustomGroup.php
CRM/Core/BAO/Job.php
CRM/Core/BAO/LocationType.php
CRM/Core/BAO/MessageTemplate.php
CRM/Core/BAO/Navigation.php
CRM/Core/BAO/OptionGroup.php
CRM/Core/BAO/OptionValue.php
CRM/Core/BAO/Setting.php
CRM/Core/BAO/UFField.php
CRM/Core/BAO/UFGroup.php
CRM/Core/BAO/UFMatch.php
CRM/Core/DAO/AllCoreTables.php
CRM/Core/DAO/OptionValue.php
CRM/Core/DAO/PrevNextCache.php
CRM/Core/Payment.php
CRM/Core/Payment/PayPalImpl.php
CRM/Core/Permission.php
CRM/Core/Permission/Backdrop.php
CRM/Core/Permission/Base.php
CRM/Core/Permission/Drupal.php
CRM/Core/Permission/Drupal6.php
CRM/Core/Permission/Drupal8.php
CRM/Core/Permission/Joomla.php
CRM/Core/Permission/Soap.php
CRM/Core/Permission/UnitTests.php
CRM/Core/Permission/WordPress.php
CRM/Core/PrevNextCache/Interface.php
CRM/Core/PrevNextCache/Sql.php
CRM/Core/Resources.php
CRM/Event/BAO/Event.php
CRM/Event/BAO/ParticipantStatusType.php
CRM/Event/Form/ManageEvent/Repeat.php
CRM/Event/Form/Participant.php
CRM/Event/Page/EventInfo.php
CRM/Export/BAO/Export.php
CRM/Export/BAO/ExportProcessor.php
CRM/Financial/BAO/FinancialAccount.php
CRM/Financial/BAO/PaymentProcessor.php
CRM/Financial/BAO/PaymentProcessorType.php
CRM/Financial/Form/SalesTaxTrait.php [new file with mode: 0644]
CRM/Mailing/BAO/Component.php
CRM/Member/BAO/MembershipStatus.php
CRM/Member/BAO/MembershipType.php
CRM/Member/Form.php
CRM/Member/Form/Membership.php
CRM/Member/Form/MembershipRenewal.php
CRM/PCP/BAO/PCP.php
CRM/Price/BAO/PriceField.php
CRM/Price/BAO/PriceFieldValue.php
CRM/Price/BAO/PriceSet.php
CRM/Report/BAO/ReportInstance.php
CRM/Report/Form.php
CRM/Report/Form/Contact/CurrentEmployer.php
CRM/Report/Form/Contribute/Detail.php
CRM/Report/Form/Member/Detail.php
CRM/Report/Form/Pledge/Pbnp.php
CRM/Upgrade/Incremental/General.php
CRM/Upgrade/Incremental/php/FiveSix.php [new file with mode: 0644]
CRM/Upgrade/Incremental/sql/5.6.alpha1.mysql.tpl [new file with mode: 0644]
CRM/Upgrade/Snapshot/V4p2/Price/BAO/Field.php
CRM/Upgrade/Snapshot/V4p2/Price/BAO/FieldValue.php
CRM/Upgrade/Snapshot/V4p2/Price/BAO/Set.php
CRM/Utils/Check/Component/Env.php
CRM/Utils/Hook.php
CRM/Utils/Money.php
CRM/Utils/System/Drupal.php
CRM/Utils/System/Drupal8.php
CRM/Utils/System/DrupalBase.php
CRM/Utils/System/Joomla.php
Civi/Token/TokenCompatSubscriber.php
api/v3/PaymentProcessor.php
api/v3/PaymentProcessorType.php
api/v3/Setting.php
composer.json
composer.lock
css/civicrmNavigation.css
css/contactSummary.css
css/joomla.css
js/AlternateContactSelector.js
js/Common.js
js/crm.datepicker.js [new file with mode: 0644]
js/crm.drupal7.js [moved from js/crm.drupal.js with 59% similarity]
js/crm.drupal8.js [new file with mode: 0644]
karma.conf.js
sql/civicrm_generated.mysql
templates/CRM/Case/Form/CaseView.tpl
templates/CRM/Contact/Page/View/Summary.js
templates/CRM/Report/Form/Tabs/Developer.tpl
templates/CRM/common/navigation.js.tpl
tests/phpunit/CRM/Core/ComposerConfigTest.php
tests/phpunit/CRM/Event/BAO/EventPermissionsTest.php [new file with mode: 0644]
tests/phpunit/CRM/Export/BAO/ExportTest.php
tests/phpunit/CRM/Member/Form/MembershipTest.php
tests/phpunit/CRM/Utils/MoneyTest.php
tests/phpunit/E2E/Core/PrevNextTest.php [new file with mode: 0644]
xml/schema/Core/OptionValue.xml
xml/schema/Core/PrevNextCache.xml
xml/version.xml

index b3eacfc3f0f0f408e31feb22472a9425bf00cbe6..b317fde85f27a462211fc15d316b35abbe0120f7 100644 (file)
@@ -113,18 +113,18 @@ class CRM_ACL_API {
       }
     }
 
-    // first see if the contact has edit / view all contacts
-    if (CRM_Core_Permission::check('edit all contacts') ||
-      ($type == self::VIEW && CRM_Core_Permission::check('view all contacts'))
-    ) {
-      return $deleteClause;
-    }
-
     if (!$contactID) {
       $contactID = CRM_Core_Session::getLoggedInContactID();
     }
     $contactID = (int) $contactID;
 
+    // first see if the contact has edit / view all permission
+    if (CRM_Core_Permission::check('edit all contacts', $contactID) ||
+      ($type == self::VIEW && CRM_Core_Permission::check('view all contacts', $contactID))
+    ) {
+      return $deleteClause;
+    }
+
     $where = implode(' AND ',
       array(
         CRM_ACL_BAO_ACL::whereClause($type,
index 15221f74565ead4bc8a0177ce0147f34df3c4c6a..2723f0f61e8eced30a4468ada4bdf7cb0de0e934 100644 (file)
@@ -680,8 +680,8 @@ SELECT $acl.*
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     // note this also resets any ACL cache
@@ -777,7 +777,7 @@ SELECT g.*
         $staticGroupIDs = array();
         $cachedGroupIDs = array();
         while ($dao->fetch()) {
-          // currently operation is restrcited to VIEW/EDIT
+          // currently operation is restricted to VIEW/EDIT
           if ($dao->where_clause) {
             if ($dao->select_tables) {
               $tmpTables = array();
index 757edce1cf10123c1b43a3dbe2ecbf56432f5c3a..42dd9167bc995efd481cc4ad53051c7f00c45826 100644 (file)
@@ -80,8 +80,8 @@ class CRM_ACL_BAO_EntityRole extends CRM_ACL_DAO_EntityRole {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_ACL_DAO_EntityRole', $id, 'is_active', $is_active);
index 8310106827ac2c3d360bd5bfe00edcea55439ec8..580886435761a7242c0d34ed47ad10ad13fa6592 100644 (file)
@@ -191,7 +191,7 @@ class CRM_ACL_Form_WordPress_Permissions extends CRM_Core_Form {
 
     CRM_Core_Session::setStatus("", ts('Wordpress Access Control Updated'), "success");
 
-    // rebuild the menus to comply with the new permisssions/capabilites
+    // rebuild the menus to comply with the new permissions/capabilites
     CRM_Core_Invoke::rebuildMenuAndCaches();
 
     CRM_Utils_System::redirect('admin.php?page=CiviCRM&q=civicrm/admin/access&reset=1');
index e7921e83cc40d91876cb563fbe7bc6feb410088e..f0b149731d447fe624cfb285ee1a23b3b0b9f206 100644 (file)
@@ -780,7 +780,7 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
         continue;
       }
 
-      $isBulkActivity = (!$bulkActivityTypeID || ($bulkActivityTypeID != $activity['activity_type_id']));
+      $isBulkActivity = (!$bulkActivityTypeID || ($bulkActivityTypeID === $activity['activity_type_id']));
       foreach ($mappingParams as $apiKey => $expectedName) {
         if (in_array($apiKey, array('assignee_contact_name', 'target_contact_name'))) {
           $activities[$id][$expectedName] = CRM_Utils_Array::value($apiKey, $activity, array());
@@ -2880,7 +2880,7 @@ INNER JOIN  civicrm_option_group grp ON ( grp.id = val.option_group_id AND grp.n
     }
 
     // Get contact activities.
-    $activities = CRM_Activity_BAO_Activity::deprecatedGetActivities($params);
+    $activities = CRM_Activity_BAO_Activity::getActivities($params);
 
     // Add total.
     $params['total'] = CRM_Activity_BAO_Activity::deprecatedGetActivitiesCount($params);
@@ -2950,19 +2950,19 @@ INNER JOIN  civicrm_option_group grp ON ( grp.id = val.option_group_id AND grp.n
         }
         elseif (isset($values['target_contact_counter']) && $values['target_contact_counter']) {
           $activity['target_contact_name'] = '';
-          foreach ($values['target_contact_name'] as $tcID => $tcName) {
-            $targetTypeImage = "";
-            $targetLink = CRM_Utils_System::href($tcName, 'civicrm/contact/view', "reset=1&cid={$tcID}");
-            if ($showContactOverlay) {
-              $targetTypeImage = CRM_Contact_BAO_Contact_Utils::getImage(
-                CRM_Contact_BAO_Contact::getContactType($tcID),
-                FALSE,
-                $tcID);
-              $activity['target_contact_name'] .= "<div>$targetTypeImage  $targetLink";
-            }
-            else {
-              $activity['target_contact_name'] .= $targetLink;
-            }
+          $firstTargetName = reset($values['target_contact_name']);
+          $firstTargetContactID = key($values['target_contact_name']);
+
+          $targetLink = CRM_Utils_System::href($firstTargetName, 'civicrm/contact/view', "reset=1&cid={$firstTargetContactID}");
+          if ($showContactOverlay) {
+            $targetTypeImage = CRM_Contact_BAO_Contact_Utils::getImage(
+              CRM_Contact_BAO_Contact::getContactType($firstTargetContactID),
+              FALSE,
+              $firstTargetContactID);
+            $activity['target_contact_name'] .= "<div>$targetTypeImage  $targetLink";
+          }
+          else {
+            $activity['target_contact_name'] .= $targetLink;
           }
 
           if ($extraCount = $values['target_contact_counter'] - 1) {
index 63d342f291178d4ab0ace57142157fb3b262bf44..4a53288813e26499bc25a0d86d354b681c7d4ff6 100644 (file)
@@ -302,8 +302,8 @@ class CRM_Activity_Page_AJAX {
     $mainActivity->activity_date_time = $actDateTime;
     // Make sure this is current revision.
     $mainActivity->is_current_revision = TRUE;
-    // Drop all relations.
-    $mainActivity->parent_id = $mainActivity->original_id = NULL;
+    $mainActivity->original_id = $otherActivity->id;
+    $otherActivity->is_current_revision = FALSE;
 
     $mainActivity->save();
     $mainActivityId = $mainActivity->id;
@@ -327,7 +327,6 @@ class CRM_Activity_Page_AJAX {
           1 => $params['caseID'],
         )) . ' ' . $otherActivity->subject;
       }
-      $otherActivity->activity_date_time = $actDateTime;
       $otherActivity->save();
 
       $caseActivity->free();
index 8182c6409cf52f491db92bf17f3e633e6c72c1e6..9c279843ea913d5d29b33526525185a1ef2e78fd 100644 (file)
@@ -393,7 +393,7 @@ class CRM_Activity_Selector_Activity extends CRM_Core_Selector_Base implements C
       'sort' => $sort,
     );
     $config = CRM_Core_Config::singleton();
-    $rows = CRM_Activity_BAO_Activity::deprecatedGetActivities($params);
+    $rows = CRM_Activity_BAO_Activity::getActivities($params);
 
     if (empty($rows)) {
       return $rows;
index 1c5ce8021952440623d7fd47ccb0642fc3257e38..db9dd0de0b456bf3e6382e4980314af25145158d 100644 (file)
@@ -70,9 +70,8 @@ class CRM_Badge_BAO_Layout extends CRM_Core_DAO_PrintLabel {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
-   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_PrintLabel', $id, 'is_active', $is_active);
index 8345d7fac404bcc4256c24c8989928de0f68706c..7cc0e111c8b770cfdfef755c1f07bd1d7d4453b5 100644 (file)
@@ -551,8 +551,8 @@ INNER JOIN  civicrm_group grp ON ( grp.id = campgrp.entity_id )
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return CRM_Campaign_DAO_Campaign|null
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Campaign_DAO_Campaign', $id, 'is_active', $is_active);
index df9b49022b8318bf037a85598343c53b97485343..a7e9f8ea08ecffb97fed939cfb8206b64e4a07ac 100644 (file)
@@ -391,8 +391,8 @@ SELECT  survey.id    as id,
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Campaign_DAO_Survey', $id, 'is_active', $is_active);
index 28c2b15b6d7961c6899021582a5765012b16e5fc..535a78349547fb580b15f66e9ba8123cdb56d2d0 100644 (file)
@@ -282,7 +282,7 @@ class CRM_Campaign_Selector_Search extends CRM_Core_Selector_Base implements CRM
       );
       list($select, $from) = explode(' FROM ', $sql);
       $selectSQL = "
-      SELECT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.display_name
+      SELECT '$cacheKey', contact_a.id, contact_a.display_name
 FROM {$from}
 ";
 
index 0d5f1d10c4277a1961579e630248970dff16ed40..797867c23e8a923d94b116e3358c8da52e8aca94 100644 (file)
@@ -909,15 +909,13 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c
    *
    * @param null $context
    * @param int $userID
-   * @param null $type
+   * @param null $type (deprecated)
    *
    * @return array
    *   Array of case activities
    *
    */
   public static function getCaseActivity($caseID, &$params, $contactID, $context = NULL, $userID = NULL, $type = NULL) {
-    $values = array();
-
     $activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
     $assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
     $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
@@ -1088,9 +1086,6 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c
       CRM_Activity_BAO_Activity::getStatusesByType(CRM_Activity_BAO_Activity::CANCELLED)
     );
 
-    $contactViewUrl = CRM_Utils_System::url("civicrm/contact/view", "reset=1&cid=", FALSE, NULL, FALSE);
-    $hasViewContact = CRM_Core_Permission::giveMeAllACLs();
-
     if (!$userID) {
       $session = CRM_Core_Session::singleton();
       $userID = $session->get('userID');
@@ -1112,75 +1107,74 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c
         continue;
       }
 
-      $caseActivity['DT_RowId'] = $caseActivityId;
+      $caseActivities[$caseActivityId]['DT_RowId'] = $caseActivityId;
       //Add classes to the row, via DataTables syntax
-      $caseActivity['DT_RowClass'] = "crm-entity status-id-$dao->status";
+      $caseActivities[$caseActivityId]['DT_RowClass'] = "crm-entity status-id-$dao->status";
 
       if (CRM_Utils_Array::crmInArray($dao->status, $compStatusValues)) {
-        $caseActivity['DT_RowClass'] .= " status-completed";
+        $caseActivities[$caseActivityId]['DT_RowClass'] .= " status-completed";
       }
       else {
         if (CRM_Utils_Date::overdue($dao->display_date)) {
-          $caseActivity['DT_RowClass'] .= " status-overdue";
+          $caseActivities[$caseActivityId]['DT_RowClass'] .= " status-overdue";
         }
         else {
-          $caseActivity['DT_RowClass'] .= " status-scheduled";
+          $caseActivities[$caseActivityId]['DT_RowClass'] .= " status-scheduled";
         }
       }
 
       if (!empty($dao->priority)) {
         if ($dao->priority == CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'priority_id', 'Urgent')) {
-          $caseActivity['DT_RowClass'] .= " priority-urgent ";
+          $caseActivities[$caseActivityId]['DT_RowClass'] .= " priority-urgent ";
         }
         elseif ($dao->priority == CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'priority_id', 'Low')) {
-          $caseActivity['DT_RowClass'] .= " priority-low ";
+          $caseActivities[$caseActivityId]['DT_RowClass'] .= " priority-low ";
         }
       }
 
       //Add data to the row for inline editing, via DataTable syntax
-      $caseActivity['DT_RowAttr'] = array();
-      $caseActivity['DT_RowAttr']['data-entity'] = 'activity';
-      $caseActivity['DT_RowAttr']['data-id'] = $caseActivityId;
+      $caseActivities[$caseActivityId]['DT_RowAttr'] = array();
+      $caseActivities[$caseActivityId]['DT_RowAttr']['data-entity'] = 'activity';
+      $caseActivities[$caseActivityId]['DT_RowAttr']['data-id'] = $caseActivityId;
 
       //Activity Date and Time
-      $caseActivity['activity_date_time'] = CRM_Utils_Date::customFormat($dao->display_date);
+      $caseActivities[$caseActivityId]['activity_date_time'] = CRM_Utils_Date::customFormat($dao->display_date);
 
       //Activity Subject
-      $caseActivity['subject'] = $dao->subject;
+      $caseActivities[$caseActivityId]['subject'] = $dao->subject;
 
       //Activity Type
-      $caseActivity['type'] = (!empty($activityTypes[$dao->type]['icon']) ? '<span class="crm-i ' . $activityTypes[$dao->type]['icon'] . '"></span> ' : '')
+      $caseActivities[$caseActivityId]['type'] = (!empty($activityTypes[$dao->type]['icon']) ? '<span class="crm-i ' . $activityTypes[$dao->type]['icon'] . '"></span> ' : '')
         . $activityTypes[$dao->type]['label'];
 
-      //Activity Target (With)
-      $targetContact = '';
-      if (isset($dao->target_contact_id)) {
-        $targetContact = $dao->target_contact_name;
-        if ($hasViewContact) {
-          $targetContact = '<a href="' . $contactViewUrl . $dao->target_contact_id . '">' . $dao->target_contact_name . '</a>';
+      // Activity Target (With Contact) (There can be more than one)
+      $targetContact = self::formatContactLink($dao->target_contact_id, $dao->target_contact_name);
+      if (empty($caseActivities[$caseActivityId]['target_contact_name'])) {
+        $caseActivities[$caseActivityId]['target_contact_name'] = $targetContact;
+      }
+      else {
+        if (strpos($caseActivities[$caseActivityId]['target_contact_name'], $targetContact) === FALSE) {
+          $caseActivities[$caseActivityId]['target_contact_name'] .= '; ' . $targetContact;
         }
       }
-      $caseActivity['target_contact_name'] = $targetContact;
 
-      //Activity Source Contact (Reporter)
-      $sourceContact = $dao->source_contact_name;
-      if ($hasViewContact) {
-        $sourceContact = '<a href="' . $contactViewUrl . $dao->source_contact_id . '">' . $dao->source_contact_name . '</a>';
-      }
-      $caseActivity['source_contact_name'] = $sourceContact;
+      // Activity Source Contact (Reporter) (There can only be one)
+      $sourceContact = self::formatContactLink($dao->source_contact_id, $dao->source_contact_name);
+      $caseActivities[$caseActivityId]['source_contact_name'] = $sourceContact;
 
-      //Activity Assignee. CRM-4485.
-      $assigneeContact = '';
-      if (isset($dao->assignee_contact_id)) {
-        $assigneeContact = $dao->assignee_contact_name;
-        if ($hasViewContact) {
-          $assigneeContact = '<a href="' . $contactViewUrl . $dao->assignee_contact_id . '">' . $dao->assignee_contact_name . '</a>';
+      // Activity Assignee (There can be more than one)
+      $assigneeContact = self::formatContactLink($dao->assignee_contact_id, $dao->assignee_contact_name);
+      if (empty($caseActivities[$caseActivityId]['assignee_contact_name'])) {
+        $caseActivities[$caseActivityId]['assignee_contact_name'] = $assigneeContact;
+      }
+      else {
+        if (strpos($caseActivities[$caseActivityId]['assignee_contact_name'], $assigneeContact) === FALSE) {
+          $caseActivities[$caseActivityId]['assignee_contact_name'] .= '; ' . $assigneeContact;
         }
       }
-      $caseActivity['assignee_contact_name'] = $assigneeContact;
 
       //Activity Status
-      $caseActivity['status_id'] = $activityStatuses[$dao->status];
+      $caseActivities[$caseActivityId]['status_id'] = $activityStatuses[$dao->status];
 
       // FIXME: Why are we not using CRM_Core_Action for these links? This is too much manual work and likely to get out-of-sync with core markup.
       $url = "";
@@ -1204,7 +1198,7 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c
       }
       elseif (!$caseDeleted) {
         $url = ' <a ' . $css . ' href="' . $restoreUrl . $additionalUrl . '">' . ts('Restore') . '</a>';
-        $caseActivity['status_id'] = $caseActivity['status_id'] . '<br /> (deleted)';
+        $caseActivities[$caseActivityId]['status_id'] = $caseActivities[$caseActivityId]['status_id'] . '<br /> (deleted)';
       }
 
       //check for operations.
@@ -1217,24 +1211,46 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c
       // if there are file attachments we will return how many and, if only one, add a link to it
       if (!empty($dao->attachment_ids)) {
         $attachmentIDs = array_unique(explode(',', $dao->attachment_ids));
-        $caseActivity['no_attachments'] = count($attachmentIDs);
+        $caseActivities[$caseActivityId]['no_attachments'] = count($attachmentIDs);
         $url .= implode(' ', CRM_Core_BAO_File::paperIconAttachment('civicrm_activity', $caseActivityId));
       }
 
-      $caseActivity['links'] = $url;
-
-      array_push($caseActivities, $caseActivity);
+      $caseActivities[$caseActivityId]['links'] = $url;
     }
     $dao->free();
 
     $caseActivitiesDT = array();
-    $caseActivitiesDT['data'] = $caseActivities;
+    $caseActivitiesDT['data'] = array_values($caseActivities);
     $caseActivitiesDT['recordsTotal'] = $caseCount;
     $caseActivitiesDT['recordsFiltered'] = $caseCount;
 
     return $caseActivitiesDT;
   }
 
+  /**
+   * Helper function to generate a formatted contact link/name for display in the Case activities tab
+   *
+   * @param $contactId
+   * @param $contactName
+   *
+   * @return string
+   */
+  private static function formatContactLink($contactId, $contactName) {
+    if (empty($contactId)) {
+      return NULL;
+    }
+
+    $hasViewContact = CRM_Contact_BAO_Contact_Permission::allow($contactId);
+
+    if ($hasViewContact) {
+      $contactViewUrl = CRM_Utils_System::url("civicrm/contact/view", "reset=1&cid={$contactId}");
+      return "<a href=\"{$contactViewUrl}\">" . $contactName . "</a>";
+    }
+    else {
+      return $contactName;
+    }
+  }
+
   /**
    * Get Case Related Contacts.
    *
index d12b8716cc5b242a7b3e442ce97dd654b2d67d1d..7fd6f54d7de6e32d2f0d21cc21ef1eeca86ba13a 100644 (file)
@@ -178,10 +178,9 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity {
                 $atArray,
                 $this->_currentUserId
               );
-              $activities = array_keys($activities);
-              $activities = $activities[0];
+              $activityId = CRM_Utils_Array::first(array_keys($activities['data']));
               $editUrl = CRM_Utils_System::url('civicrm/case/activity',
-                "reset=1&cid={$this->_currentlyViewedContactId}&caseid={$caseId}&action=update&id={$activities}"
+                "reset=1&cid={$this->_currentlyViewedContactId}&caseid={$caseId}&action=update&id={$activityId}"
               );
             }
             CRM_Core_Error::statusBounce(ts("You can not add another '%1' activity to this case. %2",
index cb13346f556a1bd91fa98d7b7010b056757c2b17..d7a211ebac47f93b8f1dd82af3677c586fb37843 100644 (file)
@@ -694,8 +694,8 @@ WHERE name = %1";
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     $params = array('id' => $id);
index 8c08654256d78acd477d7017d4c70506a31a3d0b..a5374fe7a68f22a222d37627518621b6b9e49773 100644 (file)
@@ -539,8 +539,8 @@ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group {
    * @param bool $isActive
    *   Value we want to set the is_active field.
    *
-   * @return CRM_Core_DAO|null
-   *   DAO object on success, NULL otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $isActive) {
     return CRM_Core_DAO::setFieldValue('CRM_Contact_DAO_Group', $id, 'is_active', $isActive);
index f515564998a6e3e6a4b7added11863b1b46f8a52..57643ede2677b99a55f8c1474a4c7f0d7dc59fdc 100644 (file)
@@ -2235,6 +2235,7 @@ class CRM_Contact_BAO_Query {
       $this->_qill[$grouping][] = "$field[title] $op \"$value\"";
     }
     elseif ($name === 'email_greeting') {
+      CRM_Core_Error::deprecatedFunctionWarning('pass in email_greeting_id or email_greeting_display');
       $filterCondition = array('greeting_type' => 'email_greeting');
       $this->optionValueQuery(
         $name, $op, $value, $grouping,
@@ -2244,6 +2245,7 @@ class CRM_Contact_BAO_Query {
       );
     }
     elseif ($name === 'postal_greeting') {
+      CRM_Core_Error::deprecatedFunctionWarning('pass in postal_greeting_id or postal_greeting_display');
       $filterCondition = array('greeting_type' => 'postal_greeting');
       $this->optionValueQuery(
         $name, $op, $value, $grouping,
@@ -2253,6 +2255,7 @@ class CRM_Contact_BAO_Query {
       );
     }
     elseif ($name === 'addressee') {
+      CRM_Core_Error::deprecatedFunctionWarning('pass in addressee_id or addressee_display');
       $filterCondition = array('greeting_type' => 'addressee');
       $this->optionValueQuery(
         $name, $op, $value, $grouping,
@@ -5965,8 +5968,8 @@ AND   displayRelType.is_active = 1
       }
     }
     else {
-      // LOWER roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
-      $wc = self::caseImportant($op) ? "LOWER({$field['where']})" : "{$field['where']}";
+      CRM_Core_Error::deprecatedFunctionWarning('pass $ids to this method');
+      $wc = "{$field['where']}";
     }
     if (in_array($name, $pseudoFields)) {
       if (!in_array($name, array('gender_id', 'prefix_id', 'suffix_id', 'communication_style_id'))) {
index 55e32582ff55d1cabff8f0c9803338754c3a1e12..346131b9f3ddb1c07a0a8a36efdd65f571076617 100644 (file)
@@ -68,8 +68,8 @@ class CRM_Contact_BAO_RelationshipType extends CRM_Contact_DAO_RelationshipType
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Contact_DAO_RelationshipType', $id, 'is_active', $is_active);
index cf2b1e950be59178278235c38f703c3025eb27f8..8a8703800d5d339fc36bf1e587e4da6689d7ff77 100644 (file)
@@ -404,7 +404,7 @@ AND      c.receive_date < {$this->start_date_1}
    * @param array $formValues
    *
    */
-  public static function formatSavedSearchFields(&$formValues) {
+  public static function formatSavedSearchFields($formValues) {
     $dateFields = array(
       'start_date_1',
       'end_date_1',
@@ -418,6 +418,8 @@ AND      c.receive_date < {$this->start_date_1}
         $formValues[$element] = date('Y-m-d', strtotime($value));
       }
     }
+
+    return $formValues;
   }
 
 }
index 369d59451367e91e50fcc22c2e7d603842640ff8..2c03f1e7233ccee2b35fb90e6d7a3a889fa575c7 100644 (file)
@@ -165,9 +165,6 @@ class CRM_Contact_Form_Task extends CRM_Core_Form_Task {
     if ((CRM_Utils_Array::value('radio_ts', self::$_searchFormValues) == 'ts_all') ||
       ($form->_task == CRM_Contact_Task::SAVE_SEARCH)
     ) {
-      $sortByCharacter = $form->get('sortByCharacter');
-      $cacheKey = ($sortByCharacter && $sortByCharacter != 'all') ? "{$cacheKey}_alphabet" : $cacheKey;
-
       // since we don't store all contacts in prevnextcache, when user selects "all" use query to retrieve contacts
       // rather than prevnext cache table for most of the task actions except export where we rebuild query to fetch
       // final result set
index 3f12ee333a4d11a9239ff9eb8255c803978c2b7a..889adc25abb2f752ea2b142d2f981e8e5510db01 100644 (file)
@@ -89,7 +89,11 @@ class CRM_Contact_Form_Task_EmailCommon {
     }
 
     $form->_emails = $fromEmailValues;
+    $defaults = array();
     $form->_fromEmails = $fromEmailValues;
+    if (!Civi::settings()->get('allow_mail_from_logged_in_contact')) {
+      $defaults['from_email_address'] = current(CRM_Core_BAO_Domain::getNameAndEmail(FALSE, TRUE));
+    }
     if (is_numeric(key($form->_fromEmails))) {
       // Add signature
       $defaultEmail = civicrm_api3('email', 'getsingle', array('id' => key($form->_fromEmails)));
@@ -100,8 +104,8 @@ class CRM_Contact_Form_Task_EmailCommon {
       if (!empty($defaultEmail['signature_text'])) {
         $defaults['text_message'] = "\n\n--\n" . $defaultEmail['signature_text'];
       }
-      $form->setDefaults($defaults);
     }
+    $form->setDefaults($defaults);
   }
 
   /**
index 066e4a4476fd22a14557c37bc9f35f32aa960cb2..f048612ab7116eb803f6c86ded746d321315ddd2 100644 (file)
@@ -903,7 +903,6 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     $countRow = Civi::service('prevnext')->getCount($cacheKey);
     // $sortByCharacter triggers a refresh in the prevNext cache
     if ($sortByCharacter && $sortByCharacter != 'all') {
-      $cacheKey .= "_alphabet";
       $this->fillupPrevNextCache($sort, $cacheKey, 0, max(self::CACHE_SIZE, $pageSize));
     }
     elseif (($firstRecord + $pageSize) >= $countRow) {
@@ -1039,7 +1038,7 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     // the other alternative of running the FULL query will just be incredibly inefficient
     // and slow things down way too much on large data sets / complex queries
 
-    $selectSQL = "SELECT DISTINCT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.sort_name";
+    $selectSQL = "SELECT DISTINCT '$cacheKey', contact_a.id, contact_a.sort_name";
 
     $sql = str_replace(array("SELECT contact_a.id as contact_id", "SELECT contact_a.id as id"), $selectSQL, $sql);
     try {
index 0197f65cdcbfc50962151ca824ce34bd1d746cd1..c8a63a5adcda062816338e7f949878b043b61164 100644 (file)
@@ -74,8 +74,8 @@ class CRM_Contribute_BAO_ContributionPage extends CRM_Contribute_DAO_Contributio
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_ContributionPage', $id, 'is_active', $is_active);
index a7db1d5efd48f604cc84d6f87509bdca837b4060..5a8063925e85e8d3954071cd69068fcd0ea31246 100644 (file)
@@ -74,8 +74,8 @@ class CRM_Contribute_BAO_Premium extends CRM_Contribute_DAO_Premium {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Premium', $id, 'premiums_active ', $is_active);
index 62295f1c70ca7db182413be80c62fe7e7cac52be..9e59495c619241253100f6422578fb684f702b4a 100644 (file)
@@ -46,6 +46,9 @@
  *
  */
 class CRM_Contribute_Form_AbstractEditPayment extends CRM_Contact_Form_Task {
+
+  use CRM_Financial_Form_SalesTaxTrait;
+
   public $_mode;
 
   public $_action;
index 075206d6928222679d8cd8d21fd17392a8b1953a..d05088c118cc4ac7c535002a0b47767457a2a595 100644 (file)
@@ -174,7 +174,7 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
       $defaults['total_amount'] = CRM_Utils_Money::format(abs($this->_refund), NULL, NULL, TRUE);
     }
     elseif ($this->_owed) {
-      $defaults['total_amount'] = number_format($this->_owed, 2);
+      $defaults['total_amount'] = CRM_Utils_Money::formatLocaleNumericRoundedForDefaultCurrency($this->_owed);
     }
 
     // Set $newCredit variable in template to control whether link to credit card mode is included
index a8b19f13e04ff52b36a2ae67470eb159a6713071..78a08ea421eee0ce2242fc2caed97b816c82f126 100644 (file)
@@ -1842,7 +1842,7 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
    *
    * Ie the membership block supports a separate transactions AND the contribution form has been configured for a
    * contribution
-   * transaction AND a membership transaction AND the payment processor supports double financial transactions (ie. NOT doTransferPayment style)
+   * transaction AND a membership transaction AND the payment processor supports double financial transactions (ie. NOT doTransferCheckout style)
    *
    * @param int $formID
    * @param bool $amountBlockActiveOnForm
index e783523e0a003616cb5ace50f0f168e87fdc36cb..b7cb0b2c3f7118592edba146aedfcac423842c20 100644 (file)
@@ -259,8 +259,8 @@ FROM civicrm_action_schedule cas
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_ActionSchedule', $id, 'is_active', $is_active);
index 8dd1a491fc3acb6a9f5d95e0bd2cdbe26faa3693..6fc3fe7d49e7b014b058d60f7e2da1a98afe97e7 100644 (file)
@@ -363,8 +363,8 @@ class CRM_Core_BAO_CustomField extends CRM_Core_DAO_CustomField {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
 
index 17d089d656ec96947024d6072cc881795970830e..f4b61a577722c92001815064b75be7b8f994f1a9 100644 (file)
@@ -253,8 +253,8 @@ class CRM_Core_BAO_CustomGroup extends CRM_Core_DAO_CustomGroup {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     // reset the cache
index a67ffaa5b07f852b00472ad51a2d54f9b1b7680f..dfd28028a0e52b3d531853a4d0768f3ccc67ce5a 100644 (file)
@@ -90,9 +90,8 @@ class CRM_Core_BAO_Job extends CRM_Core_DAO_Job {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
-   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_Job', $id, 'is_active', $is_active);
index d75cb632f18fa942d15b1f38bc1edbe7486bbed3..6362f126aaa355674b73c7e76bc4751d7fd9fc2b 100644 (file)
@@ -76,9 +76,8 @@ class CRM_Core_BAO_LocationType extends CRM_Core_DAO_LocationType {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
-   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_LocationType', $id, 'is_active', $is_active);
index 871ca35427d77a8f9c2639e67a7e5921b262fe74..9d2b002aacb47a656edda85d4a6315f3fd5e82d9 100644 (file)
@@ -66,8 +66,8 @@ class CRM_Core_BAO_MessageTemplate extends CRM_Core_DAO_MessageTemplate {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, NULL otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_MessageTemplate', $id, 'is_active', $is_active);
index 9b5f50a00c5350acea1780ec7773e962127e0607..e08778fc8b322a50adfceed9a0e1dee8451fa0c5 100644 (file)
@@ -50,8 +50,8 @@ class CRM_Core_BAO_Navigation extends CRM_Core_DAO_Navigation {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return CRM_Core_DAO_Navigation|NULL
-   *   DAO object on success, NULL otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_Navigation', $id, 'is_active', $is_active);
@@ -493,8 +493,9 @@ FROM civicrm_navigation WHERE domain_id = $domainID";
     $config = CRM_Core_Config::singleton();
 
     $makeLink = FALSE;
-    if (isset($url) && $url) {
-      if (substr($url, 0, 4) !== 'http') {
+    if (!empty($url)) {
+      // Skip processing fully-formed urls
+      if (substr($url, 0, 4) !== 'http' && $url[0] !== '/') {
         //CRM-7656 --make sure to separate out url path from url params,
         //as we'r going to validate url path across cross-site scripting.
         $parsedUrl = parse_url($url);
index bbabcef8bd42e1fcc265e20d6e3a3159b2749375..4c1ccc9dfb9a856dd54afd4bbd7b435a108224f6 100644 (file)
@@ -69,8 +69,8 @@ class CRM_Core_BAO_OptionGroup extends CRM_Core_DAO_OptionGroup {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_OptionGroup', $id, 'is_active', $is_active);
index 98a331c6f4422edd1ea37c66fb8604af845005ec..5c3c2dfd26c5d6c4b519390f5c40815c769b4ee0 100644 (file)
@@ -151,8 +151,8 @@ class CRM_Core_BAO_OptionValue extends CRM_Core_DAO_OptionValue {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_OptionValue', $id, 'is_active', $is_active);
index 96a8b7d414bfbe1e9f63cbb1584a0683f8678f9c..5b891898022ddaa41b42e5a334d3140a7681125f 100644 (file)
@@ -103,7 +103,7 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
   }
 
   /**
-   * Store multiple items in the setting table.
+   * Get multiple items from the setting table.
    *
    * @param array $params
    *   (required) An api formatted array of keys and values.
index e3ce7a46b557c23ee8dc17f1dcd5fe2450f9e860..9629d21e1a536717554805027aab06c8e88bbe9e 100644 (file)
@@ -158,8 +158,8 @@ class CRM_Core_BAO_UFField extends CRM_Core_DAO_UFField {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     //check if custom data profile field is disabled
index 4434d2b43952de7445a4a3feb75f899ce72b1254..8e294147d973d9fb27f7cb57584fba617607f932 100644 (file)
@@ -116,8 +116,8 @@ class CRM_Core_BAO_UFGroup extends CRM_Core_DAO_UFGroup {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   CRM_Core_DAO_UFGroup object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $id, 'is_active', $is_active);
index a781b645873d603d23d2782cc3cf74a047bad3f1..a3581258433012f4fad3724b6c17f6200b4c397a 100644 (file)
@@ -51,10 +51,12 @@ class CRM_Core_BAO_UFMatch extends CRM_Core_DAO_UFMatch {
     }
     $dao = new CRM_Core_DAO_UFMatch();
     $dao->copyValues($params);
+    // Fixme: this function cannot update records
     if (!$dao->find(TRUE)) {
       $dao->save();
+      Civi::$statics[__CLASS__][$params['domain_id']][(int) $dao->contact_id] = (int) $dao->uf_id;
+      CRM_Utils_Hook::post($hook, 'UFMatch', $dao->id, $dao);
     }
-    CRM_Utils_Hook::post($hook, 'UFMatch', $dao->id, $dao);
     return $dao;
   }
 
@@ -468,8 +470,11 @@ AND    domain_id    = %4
     $ufmatch = new CRM_Core_DAO_UFMatch();
 
     $ufmatch->uf_id = $ufID;
-    $ufmatch->domain_id = CRM_Core_Config::domainID();
+    $ufmatch->domain_id = $domainId = CRM_Core_Config::domainID();
     $ufmatch->delete();
+
+    // Flush cache
+    Civi::$statics[__CLASS__][$domainId] = [];
   }
 
   /**
@@ -478,20 +483,29 @@ AND    domain_id    = %4
    * @param int $ufID
    *   Id of UF for which related contact_id is required.
    *
-   * @return int
+   * @return int|NULL
    *   contact_id on success, null otherwise
    */
   public static function getContactId($ufID) {
-    if (!isset($ufID)) {
+    if (!$ufID) {
       return NULL;
     }
+    $domainId = CRM_Core_Config::domainID();
 
+    if (!isset(Civi::$statics[__CLASS__][$domainId])) {
+      Civi::$statics[__CLASS__][$domainId] = [];
+    }
+    $contactId = array_search($ufID, Civi::$statics[__CLASS__][$domainId]);
+    if ($contactId) {
+      return $contactId;
+    }
     $ufmatch = new CRM_Core_DAO_UFMatch();
-
     $ufmatch->uf_id = $ufID;
-    $ufmatch->domain_id = CRM_Core_Config::domainID();
+    $ufmatch->domain_id = $domainId;
     if ($ufmatch->find(TRUE)) {
-      return (int ) $ufmatch->contact_id;
+      $contactId = (int) $ufmatch->contact_id;
+      Civi::$statics[__CLASS__][$domainId][$contactId] = (int) $ufID;
+      return $contactId;
     }
     return NULL;
   }
@@ -502,22 +516,26 @@ AND    domain_id    = %4
    * @param int $contactID
    *   ID of the contact for which related uf_id is required.
    *
-   * @return int
+   * @return int|NULL
    *   uf_id of the given contact_id on success, null otherwise
    */
   public static function getUFId($contactID) {
-    if (!isset($contactID)) {
+    if (!$contactID) {
       return NULL;
     }
-    $domain = CRM_Core_BAO_Domain::getDomain();
-    $ufmatch = new CRM_Core_DAO_UFMatch();
+    $domainId = CRM_Core_Config::domainID();
+    $contactID = (int) $contactID;
 
-    $ufmatch->contact_id = $contactID;
-    $ufmatch->domain_id = $domain->id;
-    if ($ufmatch->find(TRUE)) {
-      return $ufmatch->uf_id;
+    if (empty(Civi::$statics[__CLASS__][$domainId]) || !array_key_exists($contactID, Civi::$statics[__CLASS__][$domainId])) {
+      Civi::$statics[__CLASS__][$domainId][$contactID] = NULL;
+      $ufmatch = new CRM_Core_DAO_UFMatch();
+      $ufmatch->contact_id = $contactID;
+      $ufmatch->domain_id = $domainId;
+      if ($ufmatch->find(TRUE)) {
+        Civi::$statics[__CLASS__][$domainId][$contactID] = (int) $ufmatch->uf_id;
+      }
     }
-    return NULL;
+    return Civi::$statics[__CLASS__][$domainId][$contactID];
   }
 
   /**
index 6be5be07f763499ac0ec58febc8a082e08e2518f..2bfbf0aeeb9ccc43092bc65d1a5e949b0fe0badd 100644 (file)
@@ -126,7 +126,7 @@ class CRM_Core_DAO_AllCoreTables {
   /**
    * Modify indices to account for localization options.
    *
-   * @param CRM_Core_DAO $class DAO class
+   * @param string $class DAO class
    * @param array $originalIndices index definitions before localization
    *
    * @return array
index dbf7059bb18280c8f0e52c33975fbf350fc376fc..ba11ef224af76d93bd6aa8429a4c7a4c1ff0cc76 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/OptionValue.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:8cf699b034cbd9d7b8fe0a69250a79ba)
+ * (GenCodeChecksum:c2177ac5574657232c71d57dbf7e0e55)
  */
 
 /**
@@ -395,6 +395,10 @@ class CRM_Core_DAO_OptionValue extends CRM_Core_DAO {
           'entity' => 'OptionValue',
           'bao' => 'CRM_Core_BAO_OptionValue',
           'localizable' => 0,
+          'pseudoconstant' => [
+            'optionGroupName' => 'visibility',
+            'optionEditPath' => 'civicrm/admin/options/visibility',
+          ]
         ],
         'icon' => [
           'name' => 'icon',
index bc01e75e1c94aa855dd6001fdc924ce627906786..c55e0b7369d278760ec1790abcbcf6e853052b82 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/PrevNextCache.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:cfce4435348e53ba9941ce5ed223c05b)
+ * (GenCodeChecksum:5e4976ab94ea074a01a14e9eb0dde913)
  */
 
 /**
@@ -127,7 +127,7 @@ class CRM_Core_DAO_PrevNextCache extends CRM_Core_DAO {
           'type' => CRM_Utils_Type::T_INT,
           'title' => ts('Prev Next Entity ID 2'),
           'description' => 'FK to entity table specified in entity_table column.',
-          'required' => TRUE,
+          'required' => FALSE,
           'table_name' => 'civicrm_prevnext_cache',
           'entity' => 'PrevNextCache',
           'bao' => 'CRM_Core_BAO_PrevNextCache',
index b686cd8501a36f70b3b0e90f1e6566abda1749be..13f506bcd118e2627c14e1fe5cb51e63362b139b 100644 (file)
@@ -1153,7 +1153,7 @@ abstract class CRM_Core_Payment {
   }
 
   /**
-   * Process payment - this function wraps around both doTransferPayment and doDirectPayment.
+   * Process payment - this function wraps around both doTransferCheckout and doDirectPayment.
    *
    * The function ensures an exception is thrown & moves some of this logic out of the form layer and makes the forms
    * more agnostic.
index 8ab1bbec3a72056eb575540aabfd24a98813578a..e5cd28035117c78ae3960b62cf390f52153ce76d 100644 (file)
@@ -478,7 +478,7 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment {
   }
 
   /**
-   * Process payment - this function wraps around both doTransferPayment and doDirectPayment.
+   * Process payment - this function wraps around both doTransferCheckout and doDirectPayment.
    *
    * The function ensures an exception is thrown & moves some of this logic out of the form layer and makes the forms
    * more agnostic.
index a532a4a2c4d2a679c89a55be794bbbe5e55462e6..49d003dd62c4ddddd00f70c8bdf1862b210629f7 100644 (file)
@@ -83,9 +83,11 @@ class CRM_Core_Permission {
 
   /**
    * Given a permission string or array, check for access requirements
-   * @param mixed $permissions
+   * @param string|array $permissions
    *   The permission to check as an array or string -see examples.
-   *   arrays
+   *
+   * @param int $contactId
+   *   Contact id to check permissions for. Defaults to current logged-in user.
    *
    *  Ex 1
    *
@@ -117,15 +119,20 @@ class CRM_Core_Permission {
    * @return bool
    *   true if yes, else false
    */
-  public static function check($permissions) {
+  public static function check($permissions, $contactId = NULL) {
     $permissions = (array) $permissions;
+    $userId = NULL;
+    if ($contactId) {
+      $userId = CRM_Core_BAO_UFMatch::getUFId($contactId);
+    }
 
+    /** @var CRM_Core_Permission_Temp $tempPerm */
     $tempPerm = CRM_Core_Config::singleton()->userPermissionTemp;
 
     foreach ($permissions as $permission) {
       if (is_array($permission)) {
         foreach ($permission as $orPerm) {
-          if (self::check($orPerm)) {
+          if (self::check($orPerm, $contactId)) {
             //one of our 'or' permissions has succeeded - stop checking this permission
             return TRUE;
           }
@@ -135,9 +142,9 @@ class CRM_Core_Permission {
       }
       else {
         // This is an individual permission
-        $granted = CRM_Core_Config::singleton()->userPermissionClass->check($permission);
+        $granted = CRM_Core_Config::singleton()->userPermissionClass->check($permission, $userId);
         // Call the permission_check hook to permit dynamic escalation (CRM-19256)
-        CRM_Utils_Hook::permission_check($permission, $granted);
+        CRM_Utils_Hook::permission_check($permission, $granted, $contactId);
         if (
           !$granted
           && !($tempPerm && $tempPerm->check($permission))
index f6a0d6f330ab45035ff9024bfd2a552d63ac213e..3d40db218ec20d3caeb294e630d76850f9609d8f 100644 (file)
@@ -68,12 +68,12 @@ class CRM_Core_Permission_Backdrop extends CRM_Core_Permission_DrupalBase {
    * @param string $str
    *   The permission to check.
    *
-   * @param int $contactID
+   * @param int $userId
    *
    * @return bool
    *   true if yes, else false
    */
-  public function check($str, $contactID = NULL) {
+  public function check($str, $userId = NULL) {
     $str = $this->translatePermission($str, 'Drupal', array(
       'view user account' => 'access user profiles',
       'administer users' => 'administer users',
@@ -85,7 +85,11 @@ class CRM_Core_Permission_Backdrop extends CRM_Core_Permission_DrupalBase {
       return TRUE;
     }
     if (function_exists('user_access')) {
-      return user_access($str) ? TRUE : FALSE;
+      $account = NULL;
+      if ($userId) {
+        $account = user_load($userId);
+      }
+      return user_access($str, $account);
     }
     return TRUE;
   }
index c1a48cc49ce4f0b709e8ea836ed1b9e436f2cb9a..be286cafbdb949f84d5ec77463cbf3917d0ebb3a 100644 (file)
@@ -157,9 +157,10 @@ class CRM_Core_Permission_Base {
    *
    * @param string $str
    *   The permission to check.
+   * @param int $userId
    *
    */
-  public function check($str) {
+  public function check($str, $userId = NULL) {
     //no default behaviour
   }
 
index 45ebe56fe1497a3dea4cdcd8a017d712ca333511..03b8ed6eda22c87a47831bd9161207b336bc78a0 100644 (file)
@@ -68,12 +68,12 @@ class CRM_Core_Permission_Drupal extends CRM_Core_Permission_DrupalBase {
    * @param string $str
    *   The permission to check.
    *
-   * @param int $contactID
+   * @param int $userId
    *
    * @return bool
    *   true if yes, else false
    */
-  public function check($str, $contactID = NULL) {
+  public function check($str, $userId = NULL) {
     $str = $this->translatePermission($str, 'Drupal', array(
       'view user account' => 'access user profiles',
       'administer users' => 'administer users',
@@ -85,7 +85,11 @@ class CRM_Core_Permission_Drupal extends CRM_Core_Permission_DrupalBase {
       return TRUE;
     }
     if (function_exists('user_access')) {
-      return user_access($str) ? TRUE : FALSE;
+      $account = NULL;
+      if ($userId) {
+        $account = user_load($userId);
+      }
+      return user_access($str, $account);
     }
     return TRUE;
   }
index 93ddf08a4c53cfce610adb20755441233dff38d4..9aaa4ffc02173a0c8dd676e21ccb62dd3ea0538a 100644 (file)
@@ -67,12 +67,12 @@ class CRM_Core_Permission_Drupal6 extends CRM_Core_Permission_DrupalBase {
    * @param string $str
    *   The permission to check.
    *
-   * @param int $contactID
+   * @param int $userId
    *
    * @return bool
    *   true if yes, else false
    */
-  public function check($str, $contactID = NULL) {
+  public function check($str, $userId = NULL) {
     $str = $this->translatePermission($str, 'Drupal6', array(
       'view user account' => 'access user profiles',
       'administer users' => 'administer users',
@@ -84,7 +84,11 @@ class CRM_Core_Permission_Drupal6 extends CRM_Core_Permission_DrupalBase {
       return TRUE;
     }
     if (function_exists('user_access')) {
-      return user_access($str) ? TRUE : FALSE;
+      $account = NULL;
+      if ($userId) {
+        $account = user_load($userId);
+      }
+      return user_access($str, $account);
     }
     return TRUE;
   }
index 7c65629ef26de5f565cf13a1358a24fdd903fb1f..3969874fae185ca621cdbc8638b09da2bb1807e8 100644 (file)
@@ -43,11 +43,11 @@ class CRM_Core_Permission_Drupal8 extends CRM_Core_Permission_DrupalBase {
    * @param string $str
    *   The permission to check.
    *
-   * @param null $contactID
+   * @param int $userId
    *
    * @return bool
    */
-  public function check($str, $contactID = NULL) {
+  public function check($str, $userId = NULL) {
     $str = $this->translatePermission($str, 'Drupal', array(
       'view user account' => 'access user profiles',
     ));
@@ -58,7 +58,8 @@ class CRM_Core_Permission_Drupal8 extends CRM_Core_Permission_DrupalBase {
     if ($str == CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION) {
       return TRUE;
     }
-    return \Drupal::currentUser()->hasPermission($str);
+    $acct = $userId ? \Drupal\user\Entity\User::load($userId) : \Drupal::currentUser();
+    return $acct->hasPermission($str);
   }
 
   /**
index 50f583fb61c34b5b4f56f7da168210a06ff2774e..a0e256b718fbe649b4e7a82c67bdae9ae45f1df7 100644 (file)
@@ -42,12 +42,17 @@ class CRM_Core_Permission_Joomla extends CRM_Core_Permission_Base {
    *
    * @param string $str
    *   The permission to check.
+   * @param int $userId
    *
    * @return bool
    *   true if yes, else false
    */
-  public function check($str) {
+  public function check($str, $userId = NULL) {
     $config = CRM_Core_Config::singleton();
+    // JFactory::getUser does strict type checking, so convert falesy values to NULL
+    if (!$userId) {
+      $userId = NULL;
+    }
 
     $translated = $this->translateJoomlaPermission($str);
     if ($translated === CRM_Core_Permission::ALWAYS_DENY_PERMISSION) {
@@ -61,7 +66,7 @@ class CRM_Core_Permission_Joomla extends CRM_Core_Permission_Base {
     // we've not yet figured out how to bootstrap joomla, so we should
     // not execute hooks if joomla is not loaded
     if (defined('_JEXEC')) {
-      $user = JFactory::getUser();
+      $user = JFactory::getUser($userId);
       $api_key    = CRM_Utils_Request::retrieve('api_key', 'String', $store, FALSE, NULL, 'REQUEST');
 
       // If we are coming from REST we don't have a user but we do have the api_key for a user.
index 57938812b6bf98b2191dbc8e7fe1e78bea3dda79..9ea9ef60e8d48013ddd182b084a7d005818855b0 100644 (file)
@@ -43,11 +43,12 @@ class CRM_Core_Permission_Soap extends CRM_Core_Permission_Base {
    *
    * @param string $str
    *   The permission to check.
+   * @param int $userId
    *
    * @return bool
    *   true if yes, else false
    */
-  public function check($str) {
+  public function check($str, $userId = NULL) {
     return TRUE;
   }
 
index 8dc1a057934c8df49a61e1d4c8697b0151fa1b7d..22b18f76f0feba64fd8e85fcccbad62ac1306c25 100644 (file)
@@ -46,11 +46,12 @@ class CRM_Core_Permission_UnitTests extends CRM_Core_Permission_Base {
    *
    * @param string $str
    *   The permission to check.
+   * @param int $userId
    *
    * @return bool
    *   true if yes, else false
    */
-  public function check($str) {
+  public function check($str, $userId = NULL) {
     if ($str == CRM_Core_Permission::ALWAYS_DENY_PERMISSION) {
       return FALSE;
     }
index bc032d05a276f0b0fdf2ff426de14c61bc6f2588..12ec6438615a0b1f5992af0fe19beabad18d43ac 100644 (file)
@@ -42,11 +42,12 @@ class CRM_Core_Permission_WordPress extends CRM_Core_Permission_Base {
    *
    * @param string $str
    *   The permission to check.
+   * @param int $userId
    *
    * @return bool
    *   true if yes, else false
    */
-  public function check($str) {
+  public function check($str, $userId = NULL) {
     // Generic cms 'administer users' role tranlates to users with the 'edit_users' capability' in WordPress
     $str = $this->translatePermission($str, 'WordPress', array(
       'administer users' => 'edit_users',
@@ -74,16 +75,18 @@ class CRM_Core_Permission_WordPress extends CRM_Core_Permission_Base {
       return TRUE;
     }
 
-    if (current_user_can('super admin') || current_user_can('administrator')) {
+    $user = $userId ? get_userdata($userId) : wp_get_current_user();
+
+    if ($user->has_cap('super admin') || $user->has_cap('administrator')) {
       return TRUE;
     }
 
     // Make string lowercase and convert spaces into underscore
     $str = CRM_Utils_String::munge(strtolower($str));
 
-    if (is_user_logged_in()) {
+    if ($user->exists()) {
       // Check whether the logged in user has the capabilitity
-      if (current_user_can($str)) {
+      if ($user->has_cap($str)) {
         return TRUE;
       }
     }
index c71b57ed24f05c0afb07f9adc9c1993205cde1a3..edaf0d6778ce9bae1658773d6d249c458f1b7a4c 100644 (file)
@@ -39,7 +39,7 @@ interface CRM_Core_PrevNextCache_Interface {
    * @param string $cacheKey
    * @param string $sql
    *   A SQL query. The query *MUST* be a SELECT statement which yields
-   *   the following columns (in order): entity_table, entity_id1, entity_id2, cacheKey, data
+   *   the following columns (in order): cacheKey, entity_id1, data
    * @return bool
    */
   public function fillWithSql($cacheKey, $sql);
@@ -50,9 +50,7 @@ interface CRM_Core_PrevNextCache_Interface {
    * @param string $cacheKey
    * @param array $rows
    *   A list of cache records. Each record should have keys:
-   *    - entity_table
    *    - entity_id1
-   *    - entity_id2
    *    - data
    * @return bool
    */
@@ -89,20 +87,24 @@ interface CRM_Core_PrevNextCache_Interface {
    *
    * @param string $cacheKey
    * @param int $id1
-   * @param int $id2
    *
    * @return array
+   *   List of neighbors.
+   *   [
+   *     'foundEntry' => 1,
+   *     'prev' => ['id1' => 123, 'data'=>'foo'],
+   *     'next' => ['id1' => 456, 'data'=>'foo'],
+   *   ]
    */
-  public function getPositions($cacheKey, $id1, $id2);
+  public function getPositions($cacheKey, $id1);
 
   /**
    * Delete an item from the prevnext cache table based on the entity.
    *
    * @param int $id
    * @param string $cacheKey
-   * @param string $entityTable
    */
-  public function deleteItem($id = NULL, $cacheKey = NULL, $entityTable = 'civicrm_contact');
+  public function deleteItem($id = NULL, $cacheKey = NULL);
 
   /**
    * Get count of matching rows.
index 2f20a63ba96721e126d86dd3a44091f9436de45e..5a5897353332e0ee6b74fe2d7dcd08d152271beb 100644 (file)
@@ -37,13 +37,13 @@ class CRM_Core_PrevNextCache_Sql implements CRM_Core_PrevNextCache_Interface {
    *
    * @param string $sql
    *   A SQL query. The query *MUST* be a SELECT statement which yields
-   *   the following columns (in order): entity_table, entity_id1, entity_id2, cacheKey, data
+   *   the following columns (in order): cacheKey, entity_id1, data
    * @return bool
    * @throws CRM_Core_Exception
    */
   public function fillWithSql($cacheKey, $sql) {
     $insertSQL = "
-INSERT INTO civicrm_prevnext_cache ( entity_table, entity_id1, entity_id2, cacheKey, data )
+INSERT INTO civicrm_prevnext_cache (cacheKey, entity_id1, data)
 ";
     $result = CRM_Core_DAO::executeQuery($insertSQL . $sql, [], FALSE, NULL, FALSE, TRUE, TRUE);
     if (is_a($result, 'DB_Error')) {
@@ -59,9 +59,7 @@ INSERT INTO civicrm_prevnext_cache ( entity_table, entity_id1, entity_id2, cache
 
     $insert = CRM_Utils_SQL_Insert::into('civicrm_prevnext_cache')
       ->columns([
-        'entity_table',
         'entity_id1',
-        'entity_id2',
         'cacheKey',
         'data'
       ]);
@@ -85,38 +83,35 @@ INSERT INTO civicrm_prevnext_cache ( entity_table, entity_id1, entity_id2, cache
    *   To unselect all contact IDs, use NULL.
    */
   public function markSelection($cacheKey, $action, $cIds = NULL) {
-    $entity_table = 'civicrm_contact';
-
     if (!$cacheKey) {
       return;
     }
     $params = array();
 
-    $entity_whereClause = " AND entity_table = '{$entity_table}'";
     if ($cIds && $cacheKey && $action) {
       if (is_array($cIds)) {
         $cIdFilter = "(" . implode(',', $cIds) . ")";
         $whereClause = "
-WHERE cacheKey LIKE %1
+WHERE cacheKey = %1
 AND (entity_id1 IN {$cIdFilter} OR entity_id2 IN {$cIdFilter})
 ";
       }
       else {
         $whereClause = "
-WHERE cacheKey LIKE %1
+WHERE cacheKey = %1
 AND (entity_id1 = %2 OR entity_id2 = %2)
 ";
         $params[2] = array("{$cIds}", 'Integer');
       }
       if ($action == 'select') {
         $whereClause .= "AND is_selected = 0";
-        $sql = "UPDATE civicrm_prevnext_cache SET is_selected = 1 {$whereClause} {$entity_whereClause}";
-        $params[1] = array("{$cacheKey}%", 'String');
+        $sql = "UPDATE civicrm_prevnext_cache SET is_selected = 1 {$whereClause}";
+        $params[1] = array($cacheKey, 'String');
       }
       elseif ($action == 'unselect') {
         $whereClause .= "AND is_selected = 1";
-        $sql = "UPDATE civicrm_prevnext_cache SET is_selected = 0 {$whereClause} {$entity_whereClause}";
-        $params[1] = array("%{$cacheKey}%", 'String');
+        $sql = "UPDATE civicrm_prevnext_cache SET is_selected = 0 {$whereClause}";
+        $params[1] = array($cacheKey, 'String');
       }
       // default action is reseting
     }
@@ -124,10 +119,9 @@ AND (entity_id1 = %2 OR entity_id2 = %2)
       $sql = "
 UPDATE civicrm_prevnext_cache
 SET    is_selected = 0
-WHERE  cacheKey LIKE %1 AND is_selected = 1
-       {$entity_whereClause}
+WHERE  cacheKey = %1 AND is_selected = 1
 ";
-      $params[1] = array("{$cacheKey}%", 'String');
+      $params[1] = array($cacheKey, 'String');
     }
     CRM_Core_DAO::executeQuery($sql, $params);
   }
@@ -145,31 +139,25 @@ WHERE  cacheKey LIKE %1 AND is_selected = 1
    * @return array|NULL
    */
   public function getSelection($cacheKey, $action = 'get') {
-    $entity_table = 'civicrm_contact';
-
     if (!$cacheKey) {
       return NULL;
     }
     $params = array();
 
-    $entity_whereClause = " AND entity_table = '{$entity_table}'";
     if ($cacheKey && ($action == 'get' || $action == 'getall')) {
       $actionGet = ($action == "get") ? " AND is_selected = 1 " : "";
       $sql = "
-SELECT entity_id1, entity_id2 FROM civicrm_prevnext_cache
-WHERE cacheKey LIKE %1
+SELECT entity_id1 FROM civicrm_prevnext_cache
+WHERE cacheKey = %1
       $actionGet
-      $entity_whereClause
 ORDER BY id
 ";
-      $params[1] = array("{$cacheKey}%", 'String');
+      $params[1] = array($cacheKey, 'String');
 
       $contactIds = array($cacheKey => array());
       $cIdDao = CRM_Core_DAO::executeQuery($sql, $params);
       while ($cIdDao->fetch()) {
-        if ($cIdDao->entity_id1 == $cIdDao->entity_id2) {
-          $contactIds[$cacheKey][$cIdDao->entity_id1] = 1;
-        }
+        $contactIds[$cacheKey][$cIdDao->entity_id1] = 1;
       }
       return $contactIds;
     }
@@ -180,15 +168,46 @@ ORDER BY id
    *
    * @param string $cacheKey
    * @param int $id1
-   * @param int $id2
-   *
-   * NOTE: I don't really get why there are two ID columns, but we'll
-   * keep passing them through as a matter of safe-refactoring.
    *
    * @return array
    */
-  public function getPositions($cacheKey, $id1, $id2) {
-    return CRM_Core_BAO_PrevNextCache::getPositions($cacheKey, $id1, $id2);
+  public function getPositions($cacheKey, $id1) {
+    $mergeId = CRM_Core_DAO::singleValueQuery(
+      "SELECT id FROM civicrm_prevnext_cache WHERE cacheKey = %2 AND entity_id1 = %1",
+      [
+        1 => [$id1, 'Integer'],
+        2 => [$cacheKey, 'String'],
+      ]
+    );
+
+    $pos = ['foundEntry' => 0];
+    if ($mergeId) {
+      $pos['foundEntry'] = 1;
+
+      $sql = "SELECT pn.id, pn.entity_id1, pn.entity_id2, pn.data FROM civicrm_prevnext_cache pn ";
+      $wherePrev = " WHERE pn.id < %1 AND pn.cacheKey = %2 ORDER BY ID DESC LIMIT 1";
+      $whereNext = " WHERE pn.id > %1 AND pn.cacheKey = %2 ORDER BY ID ASC LIMIT 1";
+      $p = [
+        1 => [$mergeId, 'Integer'],
+        2 => [$cacheKey, 'String'],
+      ];
+
+      $dao = CRM_Core_DAO::executeQuery($sql . $wherePrev, $p);
+      if ($dao->fetch()) {
+        $pos['prev']['id1'] = $dao->entity_id1;
+        $pos['prev']['mergeId'] = $dao->id;
+        $pos['prev']['data'] = $dao->data;
+      }
+
+      $dao = CRM_Core_DAO::executeQuery($sql . $whereNext, $p);
+      if ($dao->fetch()) {
+        $pos['next']['id1'] = $dao->entity_id1;
+        $pos['next']['mergeId'] = $dao->id;
+        $pos['next']['data'] = $dao->data;
+      }
+    }
+    return $pos;
+
   }
 
   /**
@@ -196,10 +215,21 @@ ORDER BY id
    *
    * @param int $id
    * @param string $cacheKey
-   * @param string $entityTable
    */
-  public function deleteItem($id = NULL, $cacheKey = NULL, $entityTable = 'civicrm_contact') {
-    CRM_Core_BAO_PrevNextCache::deleteItem($id, $cacheKey, $entityTable);
+  public function deleteItem($id = NULL, $cacheKey = NULL) {
+    $sql = "DELETE FROM civicrm_prevnext_cache WHERE (1)";
+    $params = array();
+
+    if (is_numeric($id)) {
+      $sql .= " AND ( entity_id1 = %2 OR entity_id2 = %2 )";
+      $params[2] = array($id, 'Integer');
+    }
+
+    if (isset($cacheKey)) {
+      $sql .= " AND cacheKey = %3";
+      $params[3] = array($cacheKey, 'String');
+    }
+    CRM_Core_DAO::executeQuery($sql, $params);
   }
 
   /**
@@ -209,7 +239,9 @@ ORDER BY id
    * @return int
    */
   public function getCount($cacheKey) {
-    return CRM_Core_BAO_PrevNextCache::getCount($cacheKey, NULL, "entity_table = 'civicrm_contact'");
+    $query = "SELECT COUNT(*) FROM civicrm_prevnext_cache pn WHERE pn.cacheKey = %1";
+    $params = [1 => [$cacheKey, 'String']];
+    return (int) CRM_Core_DAO::singleValueQuery($query, $params, TRUE, FALSE);
   }
 
 }
index 7be010ab6bb151c63538569e20f06813219d62ea..e24e36ff5c9959f7467e304859e816ce8d002d9d 100644 (file)
@@ -725,6 +725,7 @@ class CRM_Core_Resources {
       "bower_components/datatables/media/css/jquery.dataTables.min.css",
       "bower_components/jquery-validation/dist/jquery.validate.min.js",
       "packages/jquery/plugins/jquery.ui.datepicker.validation.min.js",
+      "js/crm.datepicker.js",
       "js/Common.js",
       "js/crm.ajax.js",
       "js/wysiwyg/crm.wysiwyg.js",
index 30ca5ffaf6d4abe8b573ac85396deddd789baa31..0346117f48cb179b0be6e83dad39eaafb8073ba8 100644 (file)
@@ -67,8 +67,8 @@ class CRM_Event_BAO_Event extends CRM_Event_DAO_Event {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Event_DAO_Event', $id, 'is_active', $is_active);
@@ -2064,9 +2064,7 @@ WHERE  ce.loc_block_id = $locBlockId";
    *   the permission that the user has (or null)
    */
   public static function checkPermission($eventId = NULL, $type = CRM_Core_Permission::VIEW) {
-    static $permissions = NULL;
-
-    if (empty($permissions)) {
+    if (!isset(Civi::$statics[__CLASS__]['permissions'])) {
       $params = array(
         'check_permissions' => 1,
         'return' => 'title',
@@ -2085,19 +2083,19 @@ WHERE  ce.loc_block_id = $locBlockId";
       // Search again, but only events created by the user.
       $params['created_id'] = 'user_contact_id';
       $result = civicrm_api3('Event', 'get', $params);
-      $createdEvents = CRM_Utils_Array::collect('title', $result['values']);
+      $createdEvents = array_keys($result['values']);
 
       // Note: for a multisite setup, a user with edit all events, can edit all events
       // including those from other sites
       if (CRM_Core_Permission::check('edit all events')) {
-        $permissions[CRM_Core_Permission::EDIT] = array_keys($allEvents);
+        Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::EDIT] = array_keys($allEvents);
       }
       else {
-        $permissions[CRM_Core_Permission::EDIT] = CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_event', $allEvents, $createdEvents);
+        Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::EDIT] = CRM_ACL_API::group(CRM_Core_Permission::EDIT, NULL, 'civicrm_event', $allEvents, $createdEvents);
       }
 
       if (CRM_Core_Permission::check('edit all events')) {
-        $permissions[CRM_Core_Permission::VIEW] = array_keys($allEvents);
+        Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::VIEW] = array_keys($allEvents);
       }
       else {
         if (CRM_Core_Permission::check('access CiviEvent') &&
@@ -2108,25 +2106,25 @@ WHERE  ce.loc_block_id = $locBlockId";
           // at the same time also allow any hook to override if needed.
           $createdEvents = array_keys($allEvents);
         }
-        $permissions[CRM_Core_Permission::VIEW] = CRM_ACL_API::group(CRM_Core_Permission::VIEW, NULL, 'civicrm_event', $allEvents, $createdEvents);
+        Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::VIEW] = CRM_ACL_API::group(CRM_Core_Permission::VIEW, NULL, 'civicrm_event', $allEvents, $createdEvents);
       }
 
-      $permissions[CRM_Core_Permission::DELETE] = array();
+      Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::DELETE] = array();
       if (CRM_Core_Permission::check('delete in CiviEvent')) {
         // Note: we want to restrict the scope of delete permission to
         // events that are editable/viewable (usecase multisite).
         // We can remove array_intersect once we have ACL support for delete functionality.
-        $permissions[CRM_Core_Permission::DELETE] = array_intersect($permissions[CRM_Core_Permission::EDIT],
-          $permissions[CRM_Core_Permission::VIEW]
+        Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::DELETE] = array_intersect(Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::EDIT],
+          Civi::$statics[__CLASS__]['permissions'][CRM_Core_Permission::VIEW]
         );
       }
     }
 
     if ($eventId) {
-      return in_array($eventId, $permissions[$type]) ? TRUE : FALSE;
+      return in_array($eventId, Civi::$statics[__CLASS__]['permissions'][$type]) ? TRUE : FALSE;
     }
 
-    return $permissions;
+    return Civi::$statics[__CLASS__]['permissions'];
   }
 
   /**
index 53f2720e9ca6f3fb9ed16cb3e5ee283e2fe294b8..b41b3693ccbb59d2cd907e2d27955886cfc6c664 100644 (file)
@@ -125,7 +125,6 @@ class CRM_Event_BAO_ParticipantStatusType extends CRM_Event_DAO_ParticipantStatu
 
     $returnMessages = array();
 
-    $participantRole = CRM_Event_PseudoConstant::participantRole();
     $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
     $expiredStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Negative'");
     $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
@@ -137,8 +136,6 @@ class CRM_Event_BAO_ParticipantStatusType extends CRM_Event_DAO_ParticipantStatu
     $expiredParticipantCount = $waitingConfirmCount = $waitingApprovalCount = 0;
 
     //get all participant who's status in class pending and waiting
-    $query = "SELECT * FROM civicrm_participant WHERE status_id IN {$statusIds} ORDER BY register_date";
-
     $query = "
    SELECT  participant.id,
            participant.contact_id,
index f031f006e0be0d9e491ebec9a541a0fcce2d2874..495522b2a2aa3113c97114aa5a270d306e96771d 100644 (file)
@@ -192,8 +192,8 @@ class CRM_Event_Form_ManageEvent_Repeat extends CRM_Event_Form_ManageEvent {
   }
 
   /**
-   * This function checks if there was any registraion for related event ids,
-   * and returns array of ids with no regsitrations
+   * This function checks if there was any registration for related event ids,
+   * and returns array of ids with no registrations
    *
    * @param string or int or object... $eventID
    *
index 5897aff52bb954058040b74c9a3fca7d9b996686..ec7863ccac2a4982ac34282bd8dda7febc9c161a 100644 (file)
@@ -1692,7 +1692,7 @@ class CRM_Event_Form_Participant extends CRM_Contribute_Form_AbstractEditPayment
               }
             }
             $this->assign('totalTaxAmount', $totalTaxAmount);
-            $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings));
+            $this->assign('taxTerm', $this->getSalesTaxTerm());
             $this->assign('dataArray', $dataArray);
           }
           if (!empty($additionalParticipantDetails)) {
index 9f58bddb3009705349107430a82ccfe8fc8d2204..e7bb4ea2a3ec99b5d9a7d10129bf4ce067194180 100644 (file)
@@ -152,6 +152,12 @@ class CRM_Event_Page_EventInfo extends CRM_Core_Page {
             $displayOpt = CRM_Utils_Array::value('tax_display_settings', $invoiceSettings);
             $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
             foreach ($fieldValues['options'] as $optionId => $optionVal) {
+              if (CRM_Utils_Array::value('visibility_id', $optionVal) != array_search('public', $visibility) &&
+                $adminFieldVisible == FALSE
+              ) {
+                continue;
+              }
+
               $values['feeBlock']['isDisplayAmount'][$fieldCnt] = CRM_Utils_Array::value('is_display_amounts', $fieldValues);
               if ($invoicing && isset($optionVal['tax_amount'])) {
                 $values['feeBlock']['value'][$fieldCnt] = CRM_Price_BAO_PriceField::getTaxLabel($optionVal, 'amount', $displayOpt, $taxTerm);
index f248f51a77b028b53d664a9050e81cd24721a6ca..651fc0f6026b37b89b90859d7ad87ac2f5fa1544 100644 (file)
@@ -41,24 +41,6 @@ class CRM_Export_BAO_Export {
   // CRM-7675
   const EXPORT_ROW_COUNT = 100000;
 
-  /**
-   * Key representing the head of household in the relationship array.
-   *
-   * e.g. 8_a_b.
-   *
-   * @var string
-   */
-  protected static $headOfHouseholdRelationshipKey;
-
-  /**
-   * Key representing the head of household in the relationship array.
-   *
-   * e.g. 8_a_b.
-   *
-   * @var string
-   */
-  protected static $memberOfHouseholdRelationshipKey;
-
   /**
    * Key representing the head of household in the relationship array.
    *
@@ -140,10 +122,8 @@ class CRM_Export_BAO_Export {
 
   /**
    * Get Query Group By Clause
-   * @param int $exportMode
+   * @param \CRM_Export_BAO_ExportProcessor $processor
    *   Export Mode
-   * @param string $queryMode
-   *   Query Mode
    * @param array $returnProperties
    *   Return Properties
    * @param object $query
@@ -152,8 +132,10 @@ class CRM_Export_BAO_Export {
    * @return string $groupBy
    *   Group By Clause
    */
-  public static function getGroupBy($exportMode, $queryMode, $returnProperties, $query) {
+  public static function getGroupBy($processor, $returnProperties, $query) {
     $groupBy = '';
+    $exportMode = $processor->getExportMode();
+    $queryMode = $processor->getQueryMode();
     if (!empty($returnProperties['tags']) || !empty($returnProperties['groups']) ||
       CRM_Utils_Array::value('notes', $returnProperties) ||
       // CRM-9552
@@ -244,7 +226,7 @@ class CRM_Export_BAO_Export {
     $queryOperator = 'AND'
   ) {
 
-    $processor = new CRM_Export_BAO_ExportProcessor($exportMode, $fields, $queryOperator);
+    $processor = new CRM_Export_BAO_ExportProcessor($exportMode, $fields, $queryOperator, $mergeSameHousehold);
     $returnProperties = array();
 
     $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
@@ -252,9 +234,6 @@ class CRM_Export_BAO_Export {
     // without manually testing the export of IM provider still works.
     $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
     self::$relationshipTypes = $processor->getRelationshipTypes();
-    //also merge Head of Household
-    self::$memberOfHouseholdRelationshipKey = CRM_Utils_Array::key('Household Member of', self::$relationshipTypes);
-    self::$headOfHouseholdRelationshipKey = CRM_Utils_Array::key('Head of Household for', self::$relationshipTypes);
 
     $queryMode = $processor->getQueryMode();
 
@@ -373,18 +352,16 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c
 
       foreach ($returnProperties as $key => $value) {
         if (!$processor->isRelationshipTypeKey($key)) {
-          $returnProperties[self::$memberOfHouseholdRelationshipKey][$key] = $value;
-          $returnProperties[self::$headOfHouseholdRelationshipKey][$key] = $value;
+          foreach ($processor->getHouseholdRelationshipTypes() as $householdRelationshipType) {
+            if (!in_array($key, ['location_type', 'im_provider'])) {
+              $returnProperties[$householdRelationshipType][$key] = $value;
+            }
+          }
         }
       }
-
-      unset($returnProperties[self::$memberOfHouseholdRelationshipKey]['location_type']);
-      unset($returnProperties[self::$memberOfHouseholdRelationshipKey]['im_provider']);
-      unset($returnProperties[self::$headOfHouseholdRelationshipKey]['location_type']);
-      unset($returnProperties[self::$headOfHouseholdRelationshipKey]['im_provider']);
     }
 
-    list($relationQuery, $allRelContactArray) = self::buildRelatedContactArray($selectAll, $ids, $exportMode, $componentTable, $returnProperties, $queryMode);
+    list($relationQuery, $allRelContactArray) = self::buildRelatedContactArray($selectAll, $ids, $processor, $componentTable, $returnProperties);
 
     // make sure the groups stuff is included only if specifically specified
     // by the fields param (CRM-1969), else we limit the contacts outputted to only
@@ -429,7 +406,7 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c
 
     $queryString = "$select $from $where $having";
 
-    $groupBy = self::getGroupBy($exportMode, $queryMode, $returnProperties, $query);
+    $groupBy = self::getGroupBy($processor, $returnProperties, $query);
 
     $queryString .= $groupBy;
 
@@ -617,8 +594,9 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c
 
       // merge the records if they have corresponding households
       if ($mergeSameHousehold) {
-        self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, self::$memberOfHouseholdRelationshipKey);
-        self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, self::$headOfHouseholdRelationshipKey);
+        foreach ($processor->getHouseholdRelationshipTypes() as $householdRelationshipType) {
+          self::mergeSameHousehold($exportTempTable, $sqlColumns, $householdRelationshipType);
+        }
       }
 
       // call export hook
@@ -630,7 +608,7 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c
         self::writeCSVFromTable($exportTempTable, $headerRows, $sqlColumns, $exportMode);
       }
       else {
-        // return tableName and sqlColumns in test context
+        // return tableName sqlColumns headerRows in test context
         return array($exportTempTable, $sqlColumns, $headerRows);
       }
 
@@ -1168,18 +1146,15 @@ WHERE  id IN ( $deleteIDString )
    *
    * @param string $exportTempTable
    *   Temporary temp table that stores the records.
-   * @param array $headerRows
-   *   Array of headers for the export file.
    * @param array $sqlColumns
    *   Array of names of the table columns of the temp table.
    * @param string $prefix
    *   Name of the relationship type that is prefixed to the table columns.
    */
-  public static function mergeSameHousehold($exportTempTable, &$headerRows, &$sqlColumns, $prefix) {
+  public static function mergeSameHousehold($exportTempTable, &$sqlColumns, $prefix) {
     $prefixColumn = $prefix . '_';
     $allKeys = array_keys($sqlColumns);
     $replaced = array();
-    $headerRows = array_values($headerRows);
 
     // name map of the non standard fields in header rows & sql columns
     $mappingFields = array(
@@ -1211,9 +1186,6 @@ WHERE  id IN ( $deleteIDString )
     foreach ($replaced as $from => $to) {
       $clause[] = "$from = $to ";
       unset($sqlColumns[$to]);
-      if ($key = CRM_Utils_Array::key($to, $allKeys)) {
-        unset($headerRows[$key]);
-      }
     }
     $query .= implode(",\n", $clause);
     $query .= " WHERE {$replaced['civicrm_primary_id']} != ''";
@@ -1402,18 +1374,19 @@ WHERE  {$whereClause}";
    *   Columns to go in the temp table.
    * @param \CRM_Export_BAO_ExportProcessor $processor
    * @param array|string $value
-   * @param array $phoneTypes
-   * @param array $imProviders
    *
    * @return array
    */
-  public static function setHeaderRows($field, $headerRows, $sqlColumns, $processor, $value, $phoneTypes, $imProviders) {
+  public static function setHeaderRows($field, $headerRows, $sqlColumns, $processor, $value) {
 
     $queryFields = $processor->getQueryFields();
     if (substr($field, -11) == 'campaign_id') {
       // @todo - set this correctly in the xml rather than here.
       $headerRows[] = ts('Campaign ID');
     }
+    elseif ($processor->isMergeSameHousehold() && $field === 'id') {
+      $headerRows[] = ts('Household ID');
+    }
     elseif (isset($queryFields[$field]['title'])) {
       $headerRows[] = $queryFields[$field]['title'];
     }
@@ -1437,7 +1410,10 @@ WHERE  {$whereClause}";
             }
           }
 
-          $headerRows[] = $headerName;
+          if (!$processor->isHouseholdMergeRelationshipTypeKey($field)) {
+            // Do not add to header row if we are only generating for merge reasons.
+            $headerRows[] = $headerName;
+          }
 
           self::sqlColumnDefn($processor, $sqlColumns, $headerName);
         }
@@ -1466,10 +1442,10 @@ WHERE  {$whereClause}";
 
               if (!empty($type[1])) {
                 if (CRM_Utils_Array::value(0, $type) == 'phone') {
-                  $hdr .= "-" . CRM_Utils_Array::value($type[1], $phoneTypes);
+                  $hdr .= "-" . CRM_Core_PseudoConstant::getLabel('CRM_Core_BAO_Phone', 'phone_type_id', $type[1]);
                 }
                 elseif (CRM_Utils_Array::value(0, $type) == 'im') {
-                  $hdr .= "-" . CRM_Utils_Array::value($type[1], $imProviders);
+                  $hdr .= "-" . CRM_Core_PseudoConstant::getLabel('CRM_Core_BAO_IM', 'provider_id', $type[1]);
                 }
               }
               $headerName = $field . '-' . $hdr;
@@ -1525,12 +1501,11 @@ WHERE  {$whereClause}";
     $metadata = $headerRows = $outputColumns = $sqlColumns = array();
     $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
     $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
-
     $queryFields = $processor->getQueryFields();
     foreach ($returnProperties as $key => $value) {
       if ($key != 'location' || !is_array($value)) {
         $outputColumns[$key] = $value;
-        list($headerRows, $sqlColumns) = self::setHeaderRows($key, $headerRows, $sqlColumns, $processor, $value, $phoneTypes, $imProviders);
+        list($headerRows, $sqlColumns) = self::setHeaderRows($key, $headerRows, $sqlColumns, $processor, $value);
       }
       else {
         foreach ($value as $locationType => $locationFields) {
@@ -1555,7 +1530,7 @@ WHERE  {$whereClause}";
               $metadata[$daoFieldName]['pseudoconstant']['var'] = 'imProviders';
             }
             self::sqlColumnDefn($processor, $sqlColumns, $outputFieldName);
-            list($headerRows, $sqlColumns) = self::setHeaderRows($outputFieldName, $headerRows, $sqlColumns, $processor, $value, $phoneTypes, $imProviders);
+            list($headerRows, $sqlColumns) = self::setHeaderRows($outputFieldName, $headerRows, $sqlColumns, $processor, $value);
             if ($actualDBFieldName == 'country' || $actualDBFieldName == 'world_region') {
               $metadata[$daoFieldName] = array('context' => 'country');
             }
@@ -1727,15 +1702,16 @@ WHERE  {$whereClause}";
   /**
    * @param $selectAll
    * @param $ids
-   * @param $exportMode
+   * @param \CRM_Export_BAO_ExportProcessor $processor
    * @param $componentTable
    * @param $returnProperties
-   * @param $queryMode
+   *
    * @return array
    */
-  protected static function buildRelatedContactArray($selectAll, $ids, $exportMode, $componentTable, $returnProperties, $queryMode) {
+  protected static function buildRelatedContactArray($selectAll, $ids, $processor, $componentTable, $returnProperties) {
     $allRelContactArray = $relationQuery = array();
-
+    $queryMode = $processor->getQueryMode();
+    $exportMode = $processor->getExportMode();
     foreach (self::$relationshipTypes as $rel => $dnt) {
       if ($relationReturnProperties = CRM_Utils_Array::value($rel, $returnProperties)) {
         $allRelContactArray[$rel] = array();
index 574941470439751ce8c763c613e1c6c0cf23a44e..b038424a4daabff8b1cfbf25f5cf94e53301463f 100644 (file)
@@ -72,6 +72,13 @@ class CRM_Export_BAO_ExportProcessor {
    */
   protected $requestedFields;
 
+  /**
+   * Is the contact being merged into a single household.
+   *
+   * @var bool
+   */
+  protected $isMergeSameHousehold;
+
   /**
    * Key representing the head of household in the relationship array.
    *
@@ -99,13 +106,15 @@ class CRM_Export_BAO_ExportProcessor {
    * @param int $exportMode
    * @param array|NULL $requestedFields
    * @param string $queryOperator
+   * @param bool $isMergeSameHousehold
    */
-  public function __construct($exportMode, $requestedFields, $queryOperator) {
+  public function __construct($exportMode, $requestedFields, $queryOperator, $isMergeSameHousehold = FALSE) {
     $this->setExportMode($exportMode);
     $this->setQueryMode();
     $this->setQueryOperator($queryOperator);
     $this->setRequestedFields($requestedFields);
     $this->setRelationshipTypes();
+    $this->setIsMergeSameHousehold($isMergeSameHousehold);
   }
 
   /**
@@ -158,6 +167,34 @@ class CRM_Export_BAO_ExportProcessor {
     );
   }
 
+  /**
+   * @return bool
+   */
+  public function isMergeSameHousehold() {
+    return $this->isMergeSameHousehold;
+  }
+
+  /**
+   * @param bool $isMergeSameHousehold
+   */
+  public function setIsMergeSameHousehold($isMergeSameHousehold) {
+    $this->isMergeSameHousehold = $isMergeSameHousehold;
+  }
+
+  /**
+   * Return relationship types for household merge.
+   *
+   * @return mixed
+   */
+  public function getHouseholdRelationshipTypes() {
+    if (!$this->isMergeSameHousehold()) {
+      return [];
+    }
+    return [
+      CRM_Utils_Array::key('Household Member of', $this->getRelationshipTypes()),
+      CRM_Utils_Array::key('Head of Household for', $this->getRelationshipTypes()),
+    ];
+  }
 
   /**
    * @param $fieldName
@@ -167,6 +204,15 @@ class CRM_Export_BAO_ExportProcessor {
     return array_key_exists($fieldName, $this->relationshipTypes);
   }
 
+
+  /**
+   * @param $fieldName
+   * @return bool
+   */
+  public function isHouseholdMergeRelationshipTypeKey($fieldName) {
+    return in_array($fieldName, $this->getHouseholdRelationshipTypes());
+  }
+
   /**
    * @return string
    */
index e171ee9a48bd943685a795e1d81eeffde2a5599a..9e37d4ceaf4db9f34c7ede44bcde362ab9ba4930 100644 (file)
@@ -67,8 +67,8 @@ class CRM_Financial_BAO_FinancialAccount extends CRM_Financial_DAO_FinancialAcco
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return CRM_Core_DAO|null
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Financial_DAO_FinancialAccount', $id, 'is_active', $is_active);
index 3054bb464989e11fb7ce2c35a8ea0af17a533842..e312d2ebc94feeff3312138ed093699420efe7ef 100644 (file)
@@ -150,9 +150,8 @@ class CRM_Financial_BAO_PaymentProcessor extends CRM_Financial_DAO_PaymentProces
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return CRM_Financial_DAO_PaymentProcessor|null
-   *   DAO object on success, null otherwise
-   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Financial_DAO_PaymentProcessor', $id, 'is_active', $is_active);
@@ -273,7 +272,7 @@ class CRM_Financial_BAO_PaymentProcessor extends CRM_Financial_DAO_PaymentProces
    */
   public static function getAllPaymentProcessors($mode = 'all', $reset = FALSE, $isCurrentDomainOnly = TRUE) {
 
-    $cacheKey = 'CRM_Financial_BAO_Payment_Processor_' . $mode . '_' . CRM_Core_Config::domainID();
+    $cacheKey = 'CRM_Financial_BAO_Payment_Processor_' . $mode . '_' . $isCurrentDomainOnly . '_' . CRM_Core_Config::domainID();
     if (!$reset) {
       $processors = CRM_Utils_Cache::singleton()->get($cacheKey);
       if (!empty($processors)) {
@@ -370,10 +369,10 @@ class CRM_Financial_BAO_PaymentProcessor extends CRM_Financial_DAO_PaymentProces
   public static function getPaymentProcessors($capabilities = array(), $ids = FALSE) {
     $testProcessors = in_array('TestMode', $capabilities) ? self::getAllPaymentProcessors('test') : array();
     if (is_array($ids)) {
-      $processors = self::getAllPaymentProcessors('all', TRUE, FALSE);
+      $processors = self::getAllPaymentProcessors('all', FALSE, FALSE);
     }
     else {
-      $processors = self::getAllPaymentProcessors('all', TRUE);
+      $processors = self::getAllPaymentProcessors('all');
     }
 
     if (in_array('TestMode', $capabilities) && is_array($ids)) {
index 6667d8bab7d92f7ade1ab0a013f2c91256ca00fb..70d99b4c555f335b5aa40da3b60d2f09a349fe95 100644 (file)
@@ -73,9 +73,8 @@ class CRM_Financial_BAO_PaymentProcessorType extends CRM_Financial_DAO_PaymentPr
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
-   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Financial_DAO_PaymentProcessorType', $id, 'is_active', $is_active);
diff --git a/CRM/Financial/Form/SalesTaxTrait.php b/CRM/Financial/Form/SalesTaxTrait.php
new file mode 100644 (file)
index 0000000..072126a
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/*
+  +--------------------------------------------------------------------+
+  | CiviCRM version 4.7                                                |
+  +--------------------------------------------------------------------+
+  | Copyright CiviCRM LLC (c) 2004-2018                                |
+  +--------------------------------------------------------------------+
+  | This file is a part of CiviCRM.                                    |
+  |                                                                    |
+  | CiviCRM is free software; you can copy, modify, and distribute it  |
+  | under the terms of the GNU Affero General Public License           |
+  | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+  |                                                                    |
+  | CiviCRM is distributed in the hope that it will be useful, but     |
+  | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+  | See the GNU Affero General Public License for more details.        |
+  |                                                                    |
+  | You should have received a copy of the GNU Affero General Public   |
+  | License and the CiviCRM Licensing Exception along                  |
+  | with this program; if not, contact CiviCRM LLC                     |
+  | at info[AT]civicrm[DOT]org. If you have questions about the        |
+  | 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-2018
+ */
+
+trait CRM_Financial_Form_SalesTaxTrait {
+
+  /**
+   * Assign the sales tax term to the template.
+   */
+  public function assignSalesTaxTermToTemplate() {
+    $this->assign('taxTerm', $this->getSalesTaxTerm());
+  }
+
+  /**
+   * Assign sales tax rates to the template.
+   */
+  public function assignSalesTaxRates() {
+    $this->assign('taxRates', json_encode(CRM_Core_PseudoConstant::getTaxRates()));
+  }
+
+  /**
+   * Return the string to be assigned to the template for sales tax - e.g GST, VAT.
+   *
+   * @return string
+   */
+  public function getSalesTaxTerm() {
+    $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
+    $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
+    if (!$invoicing) {
+      return '';
+    }
+    return CRM_Utils_Array::value('tax_term', $invoiceSettings);
+  }
+
+  /**
+   * Assign information to the template required for sales tax purposes.
+   */
+  public function assignSalesTaxMetadataToTemplate() {
+    $this->assignSalesTaxRates();
+    $this->assignSalesTaxTermToTemplate();
+  }
+
+  /**
+   * Get sales tax rates.
+   *
+   * @return array
+   */
+  public function getTaxRatesForFinancialTypes() {
+    return CRM_Core_PseudoConstant::getTaxRates();
+  }
+
+  /**
+   * @param int $financialTypeID
+   *
+   * @return string
+   */
+  public function getTaxRateForFinancialType($financialTypeID) {
+    return CRM_Utils_Array::value($financialTypeID, $this->getTaxRatesForFinancialTypes());
+  }
+
+}
index 969d4b57e0471e04e922554ab57c36807030100a..6840e3edeee9b0e15f5af408e71c20a9a9f63049 100644 (file)
@@ -67,8 +67,8 @@ class CRM_Mailing_BAO_Component extends CRM_Mailing_DAO_Component {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Mailing_DAO_Component', $id, 'is_active', $is_active);
index 2fa7203cc157b07e4c189b567a8047086638aff3..7c7d4518648272d70d23115f68202e1bd098deeb 100644 (file)
@@ -74,8 +74,8 @@ class CRM_Member_BAO_MembershipStatus extends CRM_Member_DAO_MembershipStatus {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Member_DAO_MembershipStatus', $id, 'is_active', $is_active);
index 796e047a0731b3b474d446b7240f668795a69e39..c308b8ca02a6ec2704ac5a3e539672f89f8d20c7 100644 (file)
@@ -76,8 +76,8 @@ class CRM_Member_BAO_MembershipType extends CRM_Member_DAO_MembershipType {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Member_DAO_MembershipType', $id, 'is_active', $is_active);
@@ -507,6 +507,7 @@ class CRM_Member_BAO_MembershipType extends CRM_Member_DAO_MembershipType {
    *
    * @param int $membershipId
    * @param $changeToday
+   *   If provided, specify an alternative date to use as "today" for renewal
    * @param int $membershipTypeID
    *   If provided, overrides the membership type of the $membershipID membership.
    * @param int $numRenewTerms
index 4c41ab201f61d56b1619bca66fe50aed72309700..2d2a757264135909b5722b58ae41c452a82d441d 100644 (file)
@@ -189,6 +189,7 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment {
    * Build the form object.
    */
   public function buildQuickForm() {
+    $this->assignSalesTaxMetadataToTemplate();
 
     $this->addPaymentProcessorSelect(TRUE, FALSE, TRUE);
     CRM_Core_Payment_Form::buildPaymentForm($this, $this->_paymentProcessor, FALSE, TRUE, $this->getDefaultPaymentInstrumentId());
index b81bc5ec3bb6c1bd5736a8a6999d14fdf7764986..b81a510f1df7d0a1710b4ee6f67cc3d61b98ee70 100644 (file)
@@ -396,14 +396,8 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
    */
   public function buildQuickForm() {
 
-    $this->assign('taxRates', json_encode(CRM_Core_PseudoConstant::getTaxRates()));
-
     $this->assign('currency', CRM_Core_Config::singleton()->defaultCurrencySymbol);
-    $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-    $invoicing = CRM_Utils_Array::value('invoicing', $invoiceSettings);
-    if (isset($invoicing)) {
-      $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings));
-    }
+    $isUpdateToExistingRecurringMembership = $this->isUpdateToExistingRecurringMembership();
     // build price set form.
     $buildPriceSet = FALSE;
     if ($this->_priceSetId || !empty($_POST['price_set_id'])) {
@@ -564,9 +558,8 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
     );
 
     $sel->setOptions(array($selMemTypeOrg, $selOrgMemType));
-    $elements = array();
-    if ($sel) {
-      $elements[] = $sel;
+    if ($isUpdateToExistingRecurringMembership) {
+      $sel->freeze();
     }
 
     $this->applyFilter('__ALL__', 'trim');
@@ -578,8 +571,8 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
     $this->addDate('join_date', ts('Member Since'), FALSE, array('formatType' => 'activityDate'));
     $this->addDate('start_date', ts('Start Date'), FALSE, array('formatType' => 'activityDate'));
     $endDate = $this->addDate('end_date', ts('End Date'), FALSE, array('formatType' => 'activityDate'));
-    if ($endDate) {
-      $elements[] = $endDate;
+    if ($endDate && $isUpdateToExistingRecurringMembership) {
+      $endDate->freeze();
     }
 
     $this->add('text', 'source', ts('Source'),
@@ -601,8 +594,8 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       $statusOverride = $this->addElement('select', 'is_override', ts('Status Override?'),
         CRM_Member_StatusOverrideTypes::getSelectOptions()
       );
-      if ($statusOverride) {
-        $elements[] = $statusOverride;
+      if ($statusOverride && $isUpdateToExistingRecurringMembership) {
+        $statusOverride->freeze();
       }
 
       $this->add('datepicker', 'status_override_end_date', ts('Status Override End Date'), '', FALSE, array('minDate' => time(), 'time' => FALSE));
@@ -669,24 +662,13 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       $this->assign('displayName', $this->_memberDisplayName);
     }
 
-    $isRecur = FALSE;
-    if ($this->_action & CRM_Core_Action::UPDATE) {
-      $recurContributionId = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->_id,
-        'contribution_recur_id'
+    if ($isUpdateToExistingRecurringMembership && CRM_Member_BAO_Membership::isCancelSubscriptionSupported($this->_id)) {
+      $this->assign('cancelAutoRenew',
+        CRM_Utils_System::url('civicrm/contribute/unsubscribe', "reset=1&mid={$this->_id}")
       );
-      if ($recurContributionId && !CRM_Member_BAO_Membership::isSubscriptionCancelled($this->_id)) {
-        $isRecur = TRUE;
-        if (CRM_Member_BAO_Membership::isCancelSubscriptionSupported($this->_id)) {
-          $this->assign('cancelAutoRenew',
-            CRM_Utils_System::url('civicrm/contribute/unsubscribe', "reset=1&mid={$this->_id}")
-          );
-        }
-        foreach ($elements as $elem) {
-          $elem->freeze();
-        }
-      }
     }
-    $this->assign('isRecur', $isRecur);
+
+    $this->assign('isRecur', $isUpdateToExistingRecurringMembership);
 
     $this->addFormRule(array('CRM_Member_Form_Membership', 'formRule'), $this);
     $mailingInfo = Civi::settings()->get('mailing_backend');
@@ -1124,8 +1106,6 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
     $formValues = $this->setPriceSetParameters($formValues);
     $params = $softParams = $ids = array();
 
-    $allMemberStatus = CRM_Member_PseudoConstant::membershipStatus();
-    $allContributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
     $this->processBillingAddress();
 
     if ($this->_id) {
@@ -1196,7 +1176,6 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       $params['tax_amount'] = $formValues['tax_amount'];
     }
     $params['total_amount'] = CRM_Utils_Array::value('amount', $formValues);
-    $submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $formValues);
     if (!empty($lineItem[$this->_priceSetId])) {
       foreach ($lineItem[$this->_priceSetId] as &$li) {
         if (!empty($li['membership_type_id'])) {
@@ -1208,6 +1187,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
         ///CRM-11529 for quick config backoffice transactions
         //when financial_type_id is passed in form, update the
         //lineitems with the financial type selected in form
+        $submittedFinancialType = CRM_Utils_Array::value('financial_type_id', $formValues);
         if ($isQuickConfig && $submittedFinancialType) {
           $li['financial_type_id'] = $submittedFinancialType;
         }
@@ -1269,9 +1249,9 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       }
     }
 
-    // max related memberships - take from form or inherit from membership type
     foreach ($this->_memTypeSelected as $memType) {
       if (array_key_exists('max_related', $formValues)) {
+        // max related memberships - take from form or inherit from membership type
         $membershipTypeValues[$memType]['max_related'] = CRM_Utils_Array::value('max_related', $formValues);
       }
       $membershipTypeValues[$memType]['custom'] = CRM_Core_BAO_CustomField::postProcess($formValues,
@@ -1296,6 +1276,9 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
         $softParams['contact_id'] = $this->_contactID;
       }
     }
+
+    $pendingMembershipStatusId = CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Pending');
+
     if (!empty($formValues['record_contribution'])) {
       $recordContribution = array(
         'total_amount',
@@ -1326,10 +1309,11 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
         }
       }
 
+      $completedContributionStatusId = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
       if (empty($params['is_override']) &&
-        CRM_Utils_Array::value('contribution_status_id', $params) != array_search('Completed', $allContributionStatus)
+        CRM_Utils_Array::value('contribution_status_id', $params) != $completedContributionStatusId
       ) {
-        $params['status_id'] = array_search('Pending', $allMemberStatus);
+        $params['status_id'] = $pendingMembershipStatusId;
         $params['skipStatusCal'] = TRUE;
         $params['is_pay_later'] = 1;
         $this->assign('is_pay_later', 1);
@@ -1448,12 +1432,14 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
         $ids['contribution'] = $contribution->id;
         $params['contribution_recur_id'] = $paymentParams['contributionRecurID'];
       }
+      $paymentStatus = NULL;
 
       if ($params['total_amount'] > 0.0) {
         $payment = $this->_paymentProcessor['object'];
         try {
           $result = $payment->doPayment($paymentParams);
           $formValues = array_merge($formValues, $result);
+          $paymentStatus = CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $formValues['payment_status_id']);
           // Assign amount to template if payment was successful.
           $this->assign('amount', $params['total_amount']);
         }
@@ -1474,8 +1460,8 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
         }
       }
 
-      if ($formValues['payment_status_id'] != array_search('Completed', $allContributionStatus)) {
-        $params['status_id'] = array_search('Pending', $allMemberStatus);
+      if ($paymentStatus !== 'Completed') {
+        $params['status_id'] = $pendingMembershipStatusId;
         $params['skipStatusCal'] = TRUE;
         // unset send-receipt option, since receipt will be sent when ipn is received.
         unset($formValues['send_receipt'], $formValues['send_receipt']);
@@ -1493,7 +1479,7 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
         }
       }
       $now = date('YmdHis');
-      $params['receive_date'] = $now;
+      $params['receive_date'] = date('YmdHis');
       $params['invoice_id'] = $formValues['invoiceID'];
       $params['contribution_source'] = ts('%1 Membership Signup: Credit card or direct debit (by %2)',
         array(1 => $membershipType, 2 => $userName)
@@ -1685,7 +1671,8 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
         }
         if ($taxAmount) {
           $this->assign('totalTaxAmount', $totalTaxAmount);
-          $this->assign('taxTerm', CRM_Utils_Array::value('tax_term', $invoiceSettings));
+          // Not sure why would need this on Submit.... unless it's being used when sending mails in which case this is the wrong place
+          $this->assign('taxTerm', $this->getSalesTaxTerm());
         }
         $this->assign('dataArray', $dataArray);
       }
@@ -1945,4 +1932,19 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
     }
   }
 
+  /**
+   * @return bool
+   */
+  protected function isUpdateToExistingRecurringMembership() {
+    $isRecur = FALSE;
+    if ($this->_action & CRM_Core_Action::UPDATE
+      && CRM_Core_DAO::getFieldValue('CRM_Member_DAO_Membership', $this->_id,
+        'contribution_recur_id')
+      && !CRM_Member_BAO_Membership::isSubscriptionCancelled($this->_id)) {
+
+      $isRecur = TRUE;
+    }
+    return $isRecur;
+  }
+
 }
index 25c90c49699081035d74b470da92e6f3c26e01f6..d5eb08968a686c0ae65cb3bfb70c8abcbdc1b320 100644 (file)
@@ -244,10 +244,7 @@ class CRM_Member_Form_MembershipRenewal extends CRM_Member_Form {
     }
 
     //CRM-16950
-    $taxRates = CRM_Core_PseudoConstant::getTaxRates();
-    $taxRate = CRM_Utils_Array::value($this->allMembershipTypeDetails[$defaults['membership_type_id']]['financial_type_id'], $taxRates);
-
-    $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
+    $taxRate = $this->getTaxRateForFinancialType($this->allMembershipTypeDetails[$defaults['membership_type_id']]['financial_type_id']);
 
     // auto renew options if enabled for the membership
     $options = CRM_Core_SelectValues::memberAutoRenew();
@@ -276,7 +273,8 @@ class CRM_Member_Form_MembershipRenewal extends CRM_Member_Form {
         //CRM-16950
         $taxAmount = NULL;
         $totalAmount = CRM_Utils_Array::value('minimum_fee', $values);
-        if (CRM_Utils_Array::value($values['financial_type_id'], $taxRates)) {
+        // @todo - feels a bug - we use taxRate from the form default rather than from the specified type?!?
+        if ($this->getTaxRateForFinancialType($values['financial_type_id'])) {
           $taxAmount = ($taxRate / 100) * CRM_Utils_Array::value('minimum_fee', $values);
           $totalAmount = $totalAmount + $taxAmount;
         }
@@ -287,7 +285,7 @@ class CRM_Member_Form_MembershipRenewal extends CRM_Member_Form {
           'financial_type_id' => CRM_Utils_Array::value('financial_type_id', $values),
           'total_amount' => CRM_Utils_Money::format($totalAmount, NULL, '%a'),
           'total_amount_numeric' => $totalAmount,
-          'tax_message' => $taxAmount ? ts("Includes %1 amount of %2", array(1 => CRM_Utils_Array::value('tax_term', $invoiceSettings), 2 => CRM_Utils_Money::format($taxAmount))) : $taxAmount,
+          'tax_message' => $taxAmount ? ts("Includes %1 amount of %2", array(1 => $this->getSalesTaxTerm(), 2 => CRM_Utils_Money::format($taxAmount))) : $taxAmount,
         );
 
         if (!empty($values['auto_renew'])) {
index b21a3a21469cc6e41f9883519557d8336fa74413..eaea71fbde4bd7f98f449ba55bc2cabb50798407 100644 (file)
@@ -709,7 +709,9 @@ WHERE pcp.id = %1 AND cc.contribution_status_id =1 AND cc.is_test = 0";
    *   Campaign page id.
    *
    * @param bool $is_active
-   * @return null
+   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setDisable($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_PCP_DAO_PCP', $id, 'is_active', $is_active);
index 0dd12fd66c55bc3038cda89a903e86ad903515fb..4e63f49f59a578e97c1add4b40d3871c6667f547 100644 (file)
@@ -225,8 +225,8 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise.
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Price_DAO_PriceField', $id, 'is_active', $is_active);
index b309facc0816caddf6b97f2fbacafee3ec99cff5..a8c0b1b587ffe87af76bce1e015567d015c31cdb 100644 (file)
@@ -223,9 +223,8 @@ class CRM_Price_BAO_PriceFieldValue extends CRM_Price_DAO_PriceFieldValue {
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
-   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Price_DAO_PriceFieldValue', $id, 'is_active', $is_active);
index 1f8d2fe79bf6acf189714a2e22e9b6c26c5550d4..922653857d8f5264384f966e71c77ad992266b09 100644 (file)
@@ -105,10 +105,8 @@ class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet {
    *   Id of the database record.
    * @param $isActive
    *
-   * @internal param bool $is_active value we want to set the is_active field
-   *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $isActive) {
     return CRM_Core_DAO::setFieldValue('CRM_Price_DAO_PriceSet', $id, 'is_active', $isActive);
@@ -1473,8 +1471,8 @@ GROUP BY     mt.member_of_contact_id ";
    * @param bool $isQuickConfig we want to set the is_quick_config field.
    *   Value we want to set the is_quick_config field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsQuickConfig($id, $isQuickConfig) {
     return CRM_Core_DAO::setFieldValue('CRM_Price_DAO_PriceSet', $id, 'is_quick_config', $isQuickConfig);
index a7dc5733cb44b26fb43adbe2e376f67caaef8480..7cc1f4eda1665daf49afe12d6eac49687b1044f6 100644 (file)
@@ -45,7 +45,6 @@ class CRM_Report_BAO_ReportInstance extends CRM_Report_DAO_ReportInstance {
    * @return CRM_Report_DAO_ReportInstance
    */
   public static function add(&$params) {
-    $instance = new CRM_Report_DAO_ReportInstance();
     if (empty($params)) {
       return NULL;
     }
@@ -109,10 +108,10 @@ class CRM_Report_BAO_ReportInstance extends CRM_Report_DAO_ReportInstance {
     $instance->save();
 
     if ($instanceID) {
-      CRM_Utils_Hook::pre('edit', 'ReportInstance', $instance->id, $instance);
+      CRM_Utils_Hook::post('edit', 'ReportInstance', $instance->id, $instance);
     }
     else {
-      CRM_Utils_Hook::pre('create', 'ReportInstance', $instance->id, $instance);
+      CRM_Utils_Hook::post('create', 'ReportInstance', $instance->id, $instance);
     }
     return $instance;
   }
index f3dbf456e87b073fbf00e46df2d00e96dd9dc172..6bf8ca1a09050a1f9247e9ff4bee870136dde943 100644 (file)
@@ -1393,6 +1393,10 @@ class CRM_Report_Form extends CRM_Core_Form {
     if (!CRM_Core_Permission::check('view report sql')) {
       return;
     }
+    $ignored_output_modes = array('pdf', 'csv', 'print');
+    if (in_array($this->_outputMode, $ignored_output_modes)) {
+      return;
+    }
     $this->tabs['Developer'] = array(
       'title' => ts('Developer'),
       'tpl' => 'Developer',
@@ -1403,7 +1407,7 @@ class CRM_Report_Form extends CRM_Core_Form {
     $this->sqlArray[] = $sql;
     foreach ($this->sqlArray as $sql) {
       foreach (array('LEFT JOIN') as $term) {
-        $sql = str_replace($term, '<br>&nbsp&nbsp' . $term, $sql);
+        $sql = str_replace($term, '<br>  ' . $term, $sql);
       }
       foreach (array('FROM', 'WHERE', 'GROUP BY', 'ORDER BY', 'LIMIT', ';') as $term) {
         $sql = str_replace($term, '<br><br>' . $term, $sql);
@@ -1411,6 +1415,8 @@ class CRM_Report_Form extends CRM_Core_Form {
       $this->sqlFormattedArray[] = $sql;
       $this->assign('sql', implode(';<br><br><br><br>', $this->sqlFormattedArray));
     }
+    $this->assign('sqlModes', $sqlModes = CRM_Utils_SQL::getSqlModes());
+
   }
 
   /**
@@ -2699,39 +2705,7 @@ WHERE cg.extends IN ('" . implode("','", $this->_customGroupExtends) . "') AND
           if (!empty($field['pseudofield'])) {
             continue;
           }
-          $clause = NULL;
-          if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
-            if (CRM_Utils_Array::value('operatorType', $field) ==
-              CRM_Report_Form::OP_MONTH
-            ) {
-              $op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
-              $value = CRM_Utils_Array::value("{$fieldName}_value", $this->_params);
-              if (is_array($value) && !empty($value)) {
-                $clause
-                  = "(month({$field['dbAlias']}) $op (" . implode(', ', $value) .
-                  '))';
-              }
-            }
-            else {
-              $relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
-              $from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
-              $to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
-              $fromTime = CRM_Utils_Array::value("{$fieldName}_from_time", $this->_params);
-              $toTime = CRM_Utils_Array::value("{$fieldName}_to_time", $this->_params);
-              $clause = $this->dateClause($field['dbAlias'], $relative, $from, $to, $field['type'], $fromTime, $toTime);
-            }
-          }
-          else {
-            $op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
-            if ($op) {
-              $clause = $this->whereClause($field,
-                $op,
-                CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
-                CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
-                CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
-              );
-            }
-          }
+          $clause = $this->generateFilterClause($field, $fieldName);
 
           if (!empty($clause)) {
             if (!empty($field['having'])) {
@@ -5406,7 +5380,6 @@ LEFT JOIN civicrm_contact {$field['alias']} ON {$field['alias']}.id = {$this->_a
         'title' => $options['prefix_label'] . ts('Gender'),
         'options' => CRM_Contact_BAO_Contact::buildOptions('gender_id'),
         'operatorType' => CRM_Report_Form::OP_MULTISELECT,
-        'alter_display' => 'alterGenderID',
         'is_fields' => TRUE,
         'is_filters' => TRUE,
       ),
@@ -5795,4 +5768,50 @@ LEFT JOIN civicrm_contact {$field['alias']} ON {$field['alias']}.id = {$this->_a
     }
   }
 
+  /**
+   * Generate clause for the selected filter.
+   *
+   * @param array $field
+   *   Field specification
+   * @param string $fieldName
+   *   Field name.
+   *
+   * @return string
+   *   Relevant where clause.
+   */
+  protected function generateFilterClause($field, $fieldName) {
+    if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
+      if (CRM_Utils_Array::value('operatorType', $field) ==
+        CRM_Report_Form::OP_MONTH
+      ) {
+        $op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
+        $value = CRM_Utils_Array::value("{$fieldName}_value", $this->_params);
+        if (is_array($value) && !empty($value)) {
+          return "(month({$field['dbAlias']}) $op (" . implode(', ', $value) .
+            '))';
+        }
+      }
+      else {
+        $relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
+        $from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
+        $to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
+        $fromTime = CRM_Utils_Array::value("{$fieldName}_from_time", $this->_params);
+        $toTime = CRM_Utils_Array::value("{$fieldName}_to_time", $this->_params);
+        return $this->dateClause($field['dbAlias'], $relative, $from, $to, $field['type'], $fromTime, $toTime);
+      }
+    }
+    else {
+      $op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
+      if ($op) {
+        return $this->whereClause($field,
+          $op,
+          CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
+          CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
+          CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
+        );
+      }
+    }
+    return '';
+  }
+
 }
index aef934e7fa2770eadc95b060fd254a5f9ba39a8c..67466c8cb6aec4761671faabb286b541f7278df6 100644 (file)
@@ -189,22 +189,9 @@ class CRM_Report_Form_Contact_CurrentEmployer extends CRM_Report_Form {
           ),
         ),
       ),
-      'civicrm_group' => array(
-        'dao' => 'CRM_Contact_DAO_Group',
-        'alias' => 'cgroup',
-        'filters' => array(
-          'gid' => array(
-            'name' => 'group_id',
-            'title' => ts('Group'),
-            'type' => CRM_Utils_Type::T_INT,
-            'group' => TRUE,
-            'operatorType' => CRM_Report_Form::OP_MULTISELECT,
-            'options' => CRM_Core_PseudoConstant::staticGroup(),
-          ),
-        ),
-      ),
     );
 
+    $this->_groupFilter = TRUE;
     $this->_tagFilter = TRUE;
     parent::__construct();
   }
index 8b0d9d99733c8f7cfc746476058adf487cdcf0fa..8c5a40c748b02352ade299bec45030d4f303576e 100644 (file)
@@ -747,7 +747,6 @@ UNION ALL
 SELECT civicrm_contact_id, civicrm_contact_sort_name, civicrm_contribution_total_amount, civicrm_contribution_currency
 FROM   civireport_contribution_detail_temp2
 WHERE  civicrm_contribution_contribution_id={$row['civicrm_contribution_contribution_id']}";
-        $this->addToDeveloperTab($query);
         $dao = CRM_Core_DAO::executeQuery($query);
         $string = '';
         $separator = ($this->_outputMode !== 'csv') ? "<br/>" : ' ';
@@ -770,7 +769,6 @@ WHERE  civicrm_contribution_contribution_id={$row['civicrm_contribution_contribu
 SELECT civicrm_contact_id, civicrm_contact_sort_name
 FROM   civireport_contribution_detail_temp1
 WHERE  civicrm_contribution_contribution_id={$row['civicrm_contribution_contribution_id']}";
-        $this->addToDeveloperTab($query);
         $dao = CRM_Core_DAO::executeQuery($query);
         $string = '';
         while ($dao->fetch()) {
index 9430c6fb600b97c64f271ef4f151d65d1239aefe..ba415048658747219199464707a3957ff96db974 100644 (file)
@@ -360,20 +360,6 @@ class CRM_Report_Form_Member_Detail extends CRM_Report_Form {
         $entryFound = TRUE;
       }
 
-      if (array_key_exists('civicrm_address_state_province_id', $row)) {
-        if ($value = $row['civicrm_address_state_province_id']) {
-          $rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
-        }
-        $entryFound = TRUE;
-      }
-
-      if (array_key_exists('civicrm_address_country_id', $row)) {
-        if ($value = $row['civicrm_address_country_id']) {
-          $rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
-        }
-        $entryFound = TRUE;
-      }
-
       if (array_key_exists('civicrm_contact_sort_name', $row) &&
         $rows[$rowNum]['civicrm_contact_sort_name'] &&
         array_key_exists('civicrm_contact_id', $row)
index 6658257a278ba2b1fb99ca4c9977a7c1c34a6981..d0d20efec4d48d9c912501942603d468bd2c23e1 100644 (file)
@@ -181,20 +181,6 @@ class CRM_Report_Form_Pledge_Pbnp extends CRM_Report_Form {
         'fields' => array('email' => NULL),
         'grouping' => 'contact-fields',
       ),
-      'civicrm_group' => array(
-        'dao' => 'CRM_Contact_DAO_Group',
-        'alias' => 'cgroup',
-        'filters' => array(
-          'gid' => array(
-            'name' => 'group_id',
-            'title' => ts('Group'),
-            'type' => CRM_Utils_Type::T_INT,
-            'group' => TRUE,
-            'operatorType' => CRM_Report_Form::OP_MULTISELECT,
-            'options' => CRM_Core_PseudoConstant::staticGroup(),
-          ),
-        ),
-      ),
     );
 
     // If we have a campaign, build out the relevant elements
@@ -211,6 +197,7 @@ class CRM_Report_Form_Pledge_Pbnp extends CRM_Report_Form {
       );
     }
 
+    $this->_groupFilter = TRUE;
     $this->_tagFilter = TRUE;
     $this->_currencyColumn = 'civicrm_pledge_currency';
     parent::__construct();
index 5737fbd5e4711300e6586e44a578fbaf5cb1346e..6b0ed69819312e41fb6f6a70f07657f1dae4e6a7 100644 (file)
@@ -41,12 +41,12 @@ class CRM_Upgrade_Incremental_General {
   /**
    * The recommended PHP version.
    */
-  const RECOMMENDED_PHP_VER = '7.0';
+  const RECOMMENDED_PHP_VER = '7.1';
 
   /**
    * The previous recommended PHP version.
    */
-  const MIN_RECOMMENDED_PHP_VER = '5.6';
+  const MIN_RECOMMENDED_PHP_VER = '7.0';
 
   /**
    * The minimum PHP version required to install Civi.
diff --git a/CRM/Upgrade/Incremental/php/FiveSix.php b/CRM/Upgrade/Incremental/php/FiveSix.php
new file mode 100644 (file)
index 0000000..94f0d4c
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 5                                                  |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2017                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007.                                       |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License along with this program; if not, contact CiviCRM LLC       |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Upgrade logic for FiveSix */
+class CRM_Upgrade_Incremental_php_FiveSix extends CRM_Upgrade_Incremental_Base {
+
+  /**
+   * Compute any messages which should be displayed beforeupgrade.
+   *
+   * Note: This function is called iteratively for each upcoming
+   * revision to the database.
+   *
+   * @param string $preUpgradeMessage
+   * @param string $rev
+   *   a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
+   * @param null $currentVer
+   */
+  public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
+    // Example: Generate a pre-upgrade message.
+    // if ($rev == '5.12.34') {
+    //   $preUpgradeMessage .= '<p>' . ts('A new permission has been added called %1 This Permission is now used to control access to the Manage Tags screen', array(1 => 'manage tags')) . '</p>';
+    // }
+  }
+
+  /**
+   * Compute any messages which should be displayed after upgrade.
+   *
+   * @param string $postUpgradeMessage
+   *   alterable.
+   * @param string $rev
+   *   an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
+   */
+  public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
+    // Example: Generate a post-upgrade message.
+    // if ($rev == '5.12.34') {
+    //   $postUpgradeMessage .= '<br /><br />' . ts("By default, CiviCRM now disables the ability to import directly from SQL. To use this feature, you must explicitly grant permission 'import SQL datasource'.");
+    // }
+  }
+
+  /*
+   * Important! All upgrade functions MUST add a 'runSql' task.
+   * Uncomment and use the following template for a new upgrade version
+   * (change the x in the function name):
+   */
+
+  //  /**
+  //   * Upgrade function.
+  //   *
+  //   * @param string $rev
+  //   */
+  //  public function upgrade_5_0_x($rev) {
+  //    $this->addTask(ts('Upgrade DB to %1: SQL', array(1 => $rev)), 'runSql', $rev);
+  //    $this->addTask('Do the foo change', 'taskFoo', ...);
+  //    // Additional tasks here...
+  //    // Note: do not use ts() in the addTask description because it adds unnecessary strings to transifex.
+  //    // The above is an exception because 'Upgrade DB to %1: SQL' is generic & reusable.
+  //  }
+
+  // public static function taskFoo(CRM_Queue_TaskContext $ctx, ...) {
+  //   return TRUE;
+  // }
+
+}
diff --git a/CRM/Upgrade/Incremental/sql/5.6.alpha1.mysql.tpl b/CRM/Upgrade/Incremental/sql/5.6.alpha1.mysql.tpl
new file mode 100644 (file)
index 0000000..04dc9c8
--- /dev/null
@@ -0,0 +1,4 @@
+{* file to handle db changes in 5.6.alpha1 during upgrade *}
+
+ALTER TABLE civicrm_prevnext_cache
+  CHANGE `entity_id2` `entity_id2` int unsigned NULL   COMMENT 'FK to entity table specified in entity_table column.';
index 0abb97f3a7a94a6ffb92fa35b20844517953da6a..8f7ef8c62a504fdf181856ff9376d6a2890aa6ce 100644 (file)
@@ -172,8 +172,8 @@ class CRM_Upgrade_Snapshot_V4p2_Price_BAO_Field extends CRM_Upgrade_Snapshot_V4p
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Field', $id, 'is_active', $is_active);
index 0bc631b35fdccc69dfecf55c7d1b771e4dfef7c9..10b6c2cd93615541b0ac585f0e4595f89e24dcb2 100644 (file)
@@ -177,9 +177,8 @@ class CRM_Upgrade_Snapshot_V4p2_Price_BAO_FieldValue extends CRM_Upgrade_Snapsho
    * @param bool $is_active
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
-   *
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $is_active) {
     return CRM_Core_DAO::setFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_FieldValue', $id, 'is_active', $is_active);
index 080524203a1c96e2892f63ec2c0d916aa22e2e4a..4b0d898963075d326204d48fcc6cce4dbd627146 100644 (file)
@@ -82,8 +82,8 @@ class CRM_Upgrade_Snapshot_V4p2_Price_BAO_Set extends CRM_Upgrade_Snapshot_V4p2_
    * @param bool $isActive
    *   Value we want to set the is_active field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsActive($id, $isActive) {
     return CRM_Core_DAO::setFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Set', $id, 'is_active', $isActive);
@@ -1134,8 +1134,8 @@ GROUP BY     mt.member_of_contact_id";
    * @param bool $isQuickConfig we want to set the is_quick_config field.
    *   Value we want to set the is_quick_config field.
    *
-   * @return Object
-   *   DAO object on success, null otherwise
+   * @return bool
+   *   true if we found and updated the object, else false
    */
   public static function setIsQuickConfig($id, $isQuickConfig) {
     return CRM_Core_DAO::setFieldValue('CRM_Upgrade_Snapshot_V4p2_Price_DAO_Set', $id, 'is_quick_config', $isQuickConfig);
index a253716e42f30e6b639bcb4157153a31006d8be1..0615165c4c49e213cbdfc8fcc713353e87371196 100644 (file)
@@ -68,7 +68,7 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
     elseif (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER) >= 0) {
       $messages[] = new CRM_Utils_Check_Message(
         __FUNCTION__,
-        ts('This system uses PHP version %1. This meets the minimum requirements for CiviCRM to function but is not recommended. At least PHP version %2 is recommended; the preferrred version is %3.',
+        ts('This system uses PHP version %1. This meets the minimum requirements for CiviCRM to function but is not recommended. At least PHP version %2 is recommended; the preferred version is %3.',
           array(
             1 => $phpVersion,
             2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER,
index 81b322cb5e9aacfc21e233d887ee9d04c02d2ea8..92989a902534cb7c4a605b9482377d6cb7a95cf8 100644 (file)
@@ -1820,13 +1820,15 @@ abstract class CRM_Utils_Hook {
    *   The name of an atomic permission, ie. 'access deleted contacts'
    * @param bool $granted
    *   Whether this permission is currently granted. The hook can change this value.
+   * @param int $contactId
+   *   Contact whose permissions we are checking (if null, assume current user).
    *
    * @return null
    *   The return value is ignored
    */
-  public static function permission_check($permission, &$granted) {
-    return self::singleton()->invoke(array('permission', 'granted'), $permission, $granted,
-      self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject,
+  public static function permission_check($permission, &$granted, $contactId) {
+    return self::singleton()->invoke(array('permission', 'granted', 'contactId'), $permission, $granted, $contactId,
+      self::$_nullObject, self::$_nullObject, self::$_nullObject,
       'civicrm_permission_check'
     );
   }
index 59168cb606a7dc6c890c16118db69f0f5f3fe6f3..455562afd290f765565e8f8a5614d983f8737631 100644 (file)
@@ -95,26 +95,13 @@ class CRM_Utils_Money {
     if (!$currency) {
       $currency = $config->defaultCurrency;
     }
-
-    // money_format() exists only in certain PHP install (CRM-650)
-    // setlocale() affects native gettext (CRM-11054, CRM-9976)
-    if (is_numeric($amount) && function_exists('money_format')) {
-      $lc = setlocale(LC_MONETARY, 0);
-      setlocale(LC_MONETARY, 'en_US.utf8', 'en_US', 'en_US.utf8', 'en_US', 'C');
-      $amount = money_format($valueFormat, $amount);
-      setlocale(LC_MONETARY, $lc);
-    }
-
-    $rep = array(
-      ',' => $config->monetaryThousandSeparator,
-      '.' => $config->monetaryDecimalPoint,
-    );
-
+    $amount = self::formatNumericByFormat($amount, $valueFormat);
     // If it contains tags, means that HTML was passed and the
     // amount is already converted properly,
     // so don't mess with it again.
+    // @todo deprecate handling for the html tags because .... WTF
     if (strpos($amount, '<') === FALSE) {
-      $amount = strtr($amount, $rep);
+      $amount = self::replaceCurrencySeparators($amount);
     }
 
     $replacements = array(
@@ -186,4 +173,105 @@ class CRM_Utils_Money {
     return TRUE;
   }
 
+  /**
+   * Format money for display (just numeric part) according to the current locale.
+   *
+   * This calls the underlying system function but does not handle currency separators.
+   *
+   * It's not totally clear when it changes the $amount value but has historical usage.
+   *
+   * @param $amount
+   *
+   * @return string
+   */
+  protected static function formatLocaleNumeric($amount) {
+    return self::formatNumericByFormat($amount, CRM_Core_Config::singleton()->moneyvalueformat);
+  }
+
+  /**
+   * Format money for display (just numeric part) according to the current locale with rounding.
+   *
+   * At this stage this is conceived as an internal function with the currency wrapper
+   * functions determining the number of places.
+   *
+   * This calls the underlying system function but does not handle currency separators.
+   *
+   * It's not totally clear when it changes the $amount value but has historical usage.
+   *
+   * @param string $amount
+   * @param int $numberOfPlaces
+   *
+   * @return string
+   */
+  protected static function formatLocaleNumericRounded($amount, $numberOfPlaces) {
+    return self::formatLocaleNumeric(round($amount, $numberOfPlaces));
+  }
+
+  /**
+   * Format money for display (just numeric part) according to the current locale with rounding.
+   *
+   * This handles both rounding & replacement of the currency separators for the locale.
+   *
+   * @param string $amount
+   * @param string $currency
+   *
+   * @return string
+   *   Formatted amount.
+   */
+  public static function formatLocaleNumericRoundedByCurrency($amount, $currency) {
+    $amount = self::formatLocaleNumericRounded($amount, self::getCurrencyPrecision($currency));
+    return self::replaceCurrencySeparators($amount);
+  }
+
+  /**
+   * Format money for display (just numeric part) according to the current locale with rounding based on the
+   * default currency for the site.
+   *
+   * @param $amount
+   * @return mixed
+   */
+  public static function formatLocaleNumericRoundedForDefaultCurrency($amount) {
+    return self::formatLocaleNumericRoundedByCurrency($amount, self::getCurrencyPrecision(CRM_Core_Config::singleton()->defaultCurrency));
+  }
+
+  /**
+   * Replace currency separators.
+   *
+   * @param string $amount
+   *
+   * @return string
+   */
+  protected static function replaceCurrencySeparators($amount) {
+    $config = CRM_Core_Config::singleton();
+    $rep = array(
+      ',' => $config->monetaryThousandSeparator,
+      '.' => $config->monetaryDecimalPoint,
+    );
+    return strtr($amount, $rep);
+  }
+
+  /**
+   * Format numeric part of currency by the passed in format.
+   *
+   * This is envisaged as an internal function, with wrapper functions defining valueFormat
+   * into easily understood functions / variables and handling separator conversions and
+   * rounding.
+   *
+   * @param string $amount
+   * @param string $valueFormat
+   *
+   * @return string
+   */
+  protected static function formatNumericByFormat($amount, $valueFormat) {
+    // money_format() exists only in certain PHP install (CRM-650)
+    // setlocale() affects native gettext (CRM-11054, CRM-9976)
+    if (is_numeric($amount) && function_exists('money_format')) {
+      $lc = setlocale(LC_MONETARY, 0);
+      setlocale(LC_MONETARY, 'en_US.utf8', 'en_US', 'en_US.utf8', 'en_US', 'C');
+      $amount = money_format($valueFormat, $amount);
+      setlocale(LC_MONETARY, $lc);
+    }
+    return $amount;
+  }
+
 }
index 4a677da3f6aa1ba9abc61aca9220395bd8de464c..0d6bf7e68f17a4421e512d7dc55aa947acf507fd 100644 (file)
@@ -861,4 +861,13 @@ AND    u.status = 1
     }
   }
 
+  /**
+   * Append Drupal7 js to coreResourcesList.
+   *
+   * @param array $list
+   */
+  public function appendCoreResources(&$list) {
+    $list[] = 'js/crm.drupal7.js';
+  }
+
 }
index 1413f2bd7b9bdcacbb98779cd8d15bd8525b0ff2..b535b0a841bff2481cff3f5fde9f4d7296435dda 100644 (file)
@@ -664,4 +664,13 @@ class CRM_Utils_System_Drupal8 extends CRM_Utils_System_DrupalBase {
     return \Drupal::languageManager()->getCurrentLanguage()->getId();
   }
 
+  /**
+   * Append Drupal8 js to coreResourcesList.
+   *
+   * @param array $list
+   */
+  public function appendCoreResources(&$list) {
+    $list[] = 'js/crm.drupal8.js';
+  }
+
 }
index 6c1eebcd6b5351bf5eebfebdfbae4ecc4240879b..4f81b304ea20ee7a735cfadab4083cdd1be0a09d 100644 (file)
@@ -300,15 +300,6 @@ abstract class CRM_Utils_System_DrupalBase extends CRM_Utils_System_Base {
     _drupal_flush_css_js();
   }
 
-  /**
-   * Append Drupal js to coreResourcesList.
-   *
-   * @param array $list
-   */
-  public function appendCoreResources(&$list) {
-    $list[] = 'js/crm.drupal.js';
-  }
-
   /**
    * @inheritDoc
    */
index 2b8ec1a31a83da2fedcf0bbf7fe758b9985949a7..fafb599b2ff076526292527d3a83c04b9ae0f193 100644 (file)
@@ -529,7 +529,7 @@ class CRM_Utils_System_Joomla extends CRM_Utils_System_Base {
    */
   public function getBasePath() {
     global $civicrm_root;
-    $joomlaPath = explode('/administrator', $civicrm_root);
+    $joomlaPath = explode(DIRECTORY_SEPARATOR . 'administrator', $civicrm_root);
     $joomlaBase = $joomlaPath[0];
     return $joomlaBase;
   }
@@ -589,6 +589,14 @@ class CRM_Utils_System_Joomla extends CRM_Utils_System_Base {
       define('JDEBUG', FALSE);
     }
 
+    // Set timezone for Joomla on Cron
+    $config = JFactory::getConfig();
+    $timezone = $config->get('offset');
+    if ($timezone) {
+      date_default_timezone_set($timezone);
+      CRM_Core_Config::singleton()->userSystem->setMySQLTimeZone();
+    }
+
     // CRM-14281 Joomla wasn't available during bootstrap, so hook_civicrm_config never executes.
     $config = CRM_Core_Config::singleton();
     CRM_Utils_Hook::config($config);
index d00acd75092236e8466f963130f1b1304ee6ff02..8e2ac735ba1b176cb5216da295183ec7733282b9 100644 (file)
@@ -90,7 +90,7 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
       // less randomly.
       \CRM_Utils_Hook::tokenValues($contactArray,
         (array) $contactId,
-        empty($row->context['mailingJob']) ? NULL : $row->context['mailingJob']->id,
+        empty($row->context['mailingJobId']) ? NULL : $row->context['mailingJobId'],
         $messageTokens,
         $row->context['controller']
       );
index 2f51ca951dee70058c560379740406b2b4b04ee8..20a7e0a510cea02ae6f6f215add173c02f2ccc87 100644 (file)
@@ -61,6 +61,7 @@ function _civicrm_api3_payment_processor_create_spec(&$params) {
   $params['payment_processor_type_id']['api.required'] = 1;
   $params['is_default']['api.default'] = 0;
   $params['is_test']['api.default'] = 0;
+  $params['domain_id']['api.default'] = CRM_Core_Config::domainID();
 }
 
 /**
index 337839693525beb7a6acb5f48c826d3037627b1c..b6d678318dbe552f5c8b611bf1f102383040cc03 100644 (file)
@@ -56,7 +56,6 @@ function _civicrm_api3_payment_processor_type_create_spec(&$params) {
   $params['class_name']['api.required'] = 1;
   $params['is_active']['api.default'] = 1;
   $params['is_recur']['api.default'] = FALSE;
-  // FIXME bool support // $params['is_recur']['api.required'] = 1;
   $params['name']['api.required'] = 1;
   $params['title']['api.required'] = 1;
   $params['payment_instrument_id']['api.default'] = 'Credit Card';
index df4b6a8f59f22def31cd409ae40c3ea8a52b7446..62a74d270bb8a6fc0419090c145e2f450d18a0fd 100644 (file)
@@ -313,7 +313,7 @@ function _civicrm_api3_setting_create_spec(&$params) {
  */
 function civicrm_api3_setting_get($params) {
   $domains = _civicrm_api3_setting_getDomainArray($params);
-  $result = $result = CRM_Core_BAO_Setting::getItems($params, $domains, CRM_Utils_Array::value('return', $params, array()));
+  $result = CRM_Core_BAO_Setting::getItems($params, $domains, CRM_Utils_Array::value('return', $params, array()));
   return civicrm_api3_create_success($result, $params, 'Setting', 'get');
 }
 /**
index 1078ccf3d30346eefb791349eebd4dd61199eefb..0988e0cd99530c697b8e7673e32eb7cecfbe860e 100644 (file)
   "require": {
     "dompdf/dompdf" : "0.8.*",
     "electrolinux/phpquery": "^0.9.6",
-    "symfony/config": "^2.6.13 || ~3.0",
-    "symfony/dependency-injection": "^2.6.13 || ~3.0",
-    "symfony/event-dispatcher": "^2.6.13 || ~3.0",
-    "symfony/filesystem": "^2.6.13 || ~3.0",
-    "symfony/process": "^2.6.13 || ~3.0",
+    "symfony/config": "^2.8.44 || ~3.0",
+    "symfony/polyfill-iconv": "~1.0",
+    "symfony/dependency-injection": "^2.8.44 || ~3.0",
+    "symfony/event-dispatcher": "^2.8.44 || ~3.0",
+    "symfony/filesystem": "^2.8.44 || ~3.0",
+    "symfony/process": "^2.8.44 || ~3.0",
     "psr/log": "~1.0.0",
-    "symfony/finder": "^2.6.13 || ~3.0",
+    "symfony/finder": "^2.8.44 || ~3.0",
     "tecnickcom/tcpdf" : "6.2.*",
     "totten/ca-config": "~17.05",
     "zetacomponents/base": "1.7.*",
index 8f3e4d2659e99894ff0300d04addd2785b5eb1e3..7b5f352c9f7c94faaf2c80911a625dfb9ff3e1e1 100644 (file)
@@ -1,10 +1,10 @@
 {
     "_readme": [
         "This file locks the dependencies of your project to a known state",
-        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "233f9c457d9e7d49a6d96c356e1035f1",
+    "content-hash": "38f5450ab72f881008f5cd10bb588b6f",
     "packages": [
         {
             "name": "civicrm/civicrm-cxn-rpc",
             "extra": {
                 "branch-alias": {
                     "dev-develop": "0.7-dev"
+                },
+                "patches_applied": {
+                    "Fix Fatal error: Uncaught Dompdf Exception: No block-level parent found.": "tools/scripts/composer/patches/dompdf_no_block_level_parent_fix.patch"
                 }
             },
             "autoload": {
                 "pear/auth_sasl": "Install optionally via your project's composer.json"
             },
             "type": "library",
+            "extra": {
+                "patches_applied": {
+                    "CRM-8744 Display CiviCRM Specific error message": "tools/scripts/composer/patches/net-smtp-patch.patch",
+                    "Fix PHP7 Compliance": "tools/scripts/composer/patches/net-smtp-php7-patch.patch",
+                    "Fix Pass by reference issues": "tools/scripts/composer/patches/net-smtp-ref-patch.patch",
+                    "Fix TLS support issue in PHP5.6": "tools/scripts/composer/patches/net-smtp-tls-patch.patch"
+                }
+            },
             "autoload": {
                 "psr-0": {
                     "Net": "./"
         },
         {
             "name": "symfony/config",
-            "version": "v2.6.13",
-            "target-dir": "Symfony/Component/Config",
+            "version": "v2.8.44",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/config.git",
-                "reference": "0ca496cbe208fc37c4cf3415ebb3056e0963115b"
+                "reference": "06c0be4cdd8363f3ec8d592c9a4d1b981d5052af"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/config/zipball/0ca496cbe208fc37c4cf3415ebb3056e0963115b",
-                "reference": "0ca496cbe208fc37c4cf3415ebb3056e0963115b",
+                "url": "https://api.github.com/repos/symfony/config/zipball/06c0be4cdd8363f3ec8d592c9a4d1b981d5052af",
+                "reference": "06c0be4cdd8363f3ec8d592c9a4d1b981d5052af",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.3",
-                "symfony/filesystem": "~2.3"
+                "php": ">=5.3.9",
+                "symfony/filesystem": "~2.3|~3.0.0",
+                "symfony/polyfill-ctype": "~1.8"
             },
             "require-dev": {
-                "symfony/phpunit-bridge": "~2.7"
+                "symfony/yaml": "~2.7|~3.0.0"
+            },
+            "suggest": {
+                "symfony/yaml": "To use the yaml reference dumper"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.6-dev"
+                    "dev-master": "2.8-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
+                "psr-4": {
                     "Symfony\\Component\\Config\\": ""
-                }
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
             ],
             "description": "Symfony Config Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-08T05:59:48+00:00"
+            "time": "2018-07-26T11:13:39+00:00"
         },
         {
             "name": "symfony/dependency-injection",
-            "version": "v2.6.13",
-            "target-dir": "Symfony/Component/DependencyInjection",
+            "version": "v2.8.44",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/dependency-injection.git",
-                "reference": "d9fe6837d74aed11e5ee741cd6b6dfe45e0af78e"
+                "reference": "ad2446d39d11c3daaa7f147d957941a187e47357"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d9fe6837d74aed11e5ee741cd6b6dfe45e0af78e",
-                "reference": "d9fe6837d74aed11e5ee741cd6b6dfe45e0af78e",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ad2446d39d11c3daaa7f147d957941a187e47357",
+                "reference": "ad2446d39d11c3daaa7f147d957941a187e47357",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.3"
+                "php": ">=5.3.9"
             },
             "conflict": {
                 "symfony/expression-language": "<2.6"
             },
             "require-dev": {
-                "symfony/config": "~2.2",
-                "symfony/expression-language": "~2.6",
-                "symfony/phpunit-bridge": "~2.7",
-                "symfony/yaml": "~2.1"
+                "symfony/config": "~2.2|~3.0.0",
+                "symfony/expression-language": "~2.6|~3.0.0",
+                "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7"
             },
             "suggest": {
                 "symfony/config": "",
+                "symfony/expression-language": "For using expressions in service container configuration",
                 "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
                 "symfony/yaml": ""
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.6-dev"
+                    "dev-master": "2.8-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
+                "psr-4": {
                     "Symfony\\Component\\DependencyInjection\\": ""
-                }
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
             ],
             "description": "Symfony DependencyInjection Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-22T10:08:40+00:00"
+            "time": "2018-07-26T11:13:39+00:00"
         },
         {
             "name": "symfony/event-dispatcher",
-            "version": "v2.6.13",
-            "target-dir": "Symfony/Component/EventDispatcher",
+            "version": "v2.8.44",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/event-dispatcher.git",
-                "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02"
+                "reference": "84ae343f39947aa084426ed1138bb96bf94d1f12"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/672593bc4b0043a0acf91903bb75a1c82d8f2e02",
-                "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/84ae343f39947aa084426ed1138bb96bf94d1f12",
+                "reference": "84ae343f39947aa084426ed1138bb96bf94d1f12",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.3"
+                "php": ">=5.3.9"
             },
             "require-dev": {
                 "psr/log": "~1.0",
-                "symfony/config": "~2.0,>=2.0.5",
-                "symfony/dependency-injection": "~2.6",
-                "symfony/expression-language": "~2.6",
-                "symfony/phpunit-bridge": "~2.7",
-                "symfony/stopwatch": "~2.3"
+                "symfony/config": "^2.0.5|~3.0.0",
+                "symfony/dependency-injection": "~2.6|~3.0.0",
+                "symfony/expression-language": "~2.6|~3.0.0",
+                "symfony/stopwatch": "~2.3|~3.0.0"
             },
             "suggest": {
                 "symfony/dependency-injection": "",
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.6-dev"
+                    "dev-master": "2.8-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
+                "psr-4": {
                     "Symfony\\Component\\EventDispatcher\\": ""
-                }
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
             ],
             "description": "Symfony EventDispatcher Component",
             "homepage": "https://symfony.com",
-            "time": "2015-05-02T15:18:45+00:00"
+            "time": "2018-07-26T09:03:18+00:00"
         },
         {
             "name": "symfony/filesystem",
-            "version": "v2.6.13",
-            "target-dir": "Symfony/Component/Filesystem",
+            "version": "v2.8.44",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/filesystem.git",
-                "reference": "823c035b1a5c13a4924e324d016eb07e70f94735"
+                "reference": "2d6a4deccdfa2e4e9f113138b93457b2d0886c15"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/filesystem/zipball/823c035b1a5c13a4924e324d016eb07e70f94735",
-                "reference": "823c035b1a5c13a4924e324d016eb07e70f94735",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/2d6a4deccdfa2e4e9f113138b93457b2d0886c15",
+                "reference": "2d6a4deccdfa2e4e9f113138b93457b2d0886c15",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/phpunit-bridge": "~2.7"
+                "php": ">=5.3.9",
+                "symfony/polyfill-ctype": "~1.8"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.6-dev"
+                    "dev-master": "2.8-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
+                "psr-4": {
                     "Symfony\\Component\\Filesystem\\": ""
-                }
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
             ],
             "description": "Symfony Filesystem Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-08T05:59:48+00:00"
+            "time": "2018-07-26T11:13:39+00:00"
         },
         {
             "name": "symfony/finder",
-            "version": "v2.6.13",
-            "target-dir": "Symfony/Component/Finder",
+            "version": "v2.8.44",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/finder.git",
-                "reference": "203a10f928ae30176deeba33512999233181dd28"
+                "reference": "f0de0b51913eb2caab7dfed6413b87e14fca780e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/finder/zipball/203a10f928ae30176deeba33512999233181dd28",
-                "reference": "203a10f928ae30176deeba33512999233181dd28",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/f0de0b51913eb2caab7dfed6413b87e14fca780e",
+                "reference": "f0de0b51913eb2caab7dfed6413b87e14fca780e",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "symfony/phpunit-bridge": "~2.7"
+                "php": ">=5.3.9"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.6-dev"
+                    "dev-master": "2.8-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
+                "psr-4": {
                     "Symfony\\Component\\Finder\\": ""
-                }
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
             ],
             "description": "Symfony Finder Component",
             "homepage": "https://symfony.com",
-            "time": "2015-07-09T16:02:48+00:00"
+            "time": "2018-07-26T11:13:39+00:00"
         },
         {
-            "name": "symfony/process",
-            "version": "v2.6.13",
-            "target-dir": "Symfony/Component/Process",
+            "name": "symfony/polyfill-ctype",
+            "version": "v1.8.0",
             "source": {
                 "type": "git",
-                "url": "https://github.com/symfony/process.git",
-                "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9"
+                "url": "https://github.com/symfony/polyfill-ctype.git",
+                "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/process/zipball/57f1e88bb5dafa449b83f9f265b11d52d517b3e9",
-                "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9",
+                "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/7cc359f1b7b80fc25ed7796be7d96adc9b354bae",
+                "reference": "7cc359f1b7b80fc25ed7796be7d96adc9b354bae",
                 "shasum": ""
             },
             "require": {
                 "php": ">=5.3.3"
             },
-            "require-dev": {
-                "symfony/phpunit-bridge": "~2.7"
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Ctype\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                },
+                {
+                    "name": "Gert de Pagter",
+                    "email": "BackEndTea@gmail.com"
+                }
+            ],
+            "description": "Symfony polyfill for ctype functions",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "ctype",
+                "polyfill",
+                "portable"
+            ],
+            "time": "2018-04-30T19:57:29+00:00"
+        },
+        {
+            "name": "symfony/polyfill-iconv",
+            "version": "v1.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-iconv.git",
+                "reference": "bcc0cd69185b8a5d8b4a5400c489ed3333bf9bb2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/bcc0cd69185b8a5d8b4a5400c489ed3333bf9bb2",
+                "reference": "bcc0cd69185b8a5d8b4a5400c489ed3333bf9bb2",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "suggest": {
+                "ext-iconv": "For best performance"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.6-dev"
+                    "dev-master": "1.9-dev"
                 }
             },
             "autoload": {
-                "psr-0": {
-                    "Symfony\\Component\\Process\\": ""
+                "psr-4": {
+                    "Symfony\\Polyfill\\Iconv\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
                 }
+            ],
+            "description": "Symfony polyfill for the Iconv extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "iconv",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "time": "2018-08-06T14:22:27+00:00"
+        },
+        {
+            "name": "symfony/process",
+            "version": "v2.8.44",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/process.git",
+                "reference": "cc83afdb5ac99147806b3bb65a3ff1227664f596"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/process/zipball/cc83afdb5ac99147806b3bb65a3ff1227664f596",
+                "reference": "cc83afdb5ac99147806b3bb65a3ff1227664f596",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Process\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
             },
             "notification-url": "https://packagist.org/downloads/",
             "license": [
             ],
             "description": "Symfony Process Component",
             "homepage": "https://symfony.com",
-            "time": "2015-06-30T16:10:16+00:00"
+            "time": "2018-07-26T11:13:39+00:00"
         },
         {
             "name": "tecnickcom/tcpdf",
index e005bb004bd2846aeed67e1ebd42edc00a4b47ee..5cf48d3f3cd81cc7c6cb18e4bf52e75f2ce58700 100644 (file)
@@ -63,7 +63,7 @@ html>body .innerbox
 }
 
 #civicrm-menu {
-  position:absolute;
+  position:fixed;
   top:0;
   left:0;
   background:#1B1B1B repeat-x;
index c29270bac9795acb7492d63749b5138bdb9e1187..0a912d1a052de51ba3a09a5d332b903f641eb1bc 100644 (file)
@@ -21,6 +21,10 @@ div#crm-contact-thumbnail {
   border-bottom: 1px solid #FFF;
 }
 
+.crm-summary-block {
+  clear: both;
+}
+
 #crm-container div.crm-inline-edit {
   border: 2px dashed transparent;
   background: none;
@@ -35,7 +39,14 @@ div#crm-contact-thumbnail {
 #crm-container div.crm-inline-edit.form {
   cursor: default;
   border: 2px dashed #6665BF;
-  overflow: auto;
+  box-shadow: rgba(255, 255, 255, 0.3) 0 0 0 99999px;
+  background-color: white;
+  float: left;
+  z-index: 99;
+}
+
+#mainTabContainer:not(.narrowpage) .contactCardRight div.crm-inline-edit.form {
+  float: right;
 }
 
 #crm-container .crm-inline-edit.add-new {
@@ -76,7 +87,8 @@ div#crm-contact-thumbnail {
   white-space: nowrap;
 }
 #crm-container table.crm-inline-edit-form td.crm-label,
-#crm-container div.crm-inline-edit-form .crm-label {
+#crm-container div.crm-inline-edit-form .crm-label,
+#crm-container div.crm-inline-edit-form .messages {
   white-space: normal;
 }
 
index dc64be3d27614c904d646d02675e8ab2f33b1b2e..195f38bec45203c161a2fc9858302c4c09d43fd4 100644 (file)
@@ -295,14 +295,7 @@ br.clear {
 /* Moved from civicrm.css in v3.2 */
 
 ul#civicrm-menu {
-  z-index: 1;
   position:relative;
-  border: none;
-  left:0px;
-  height:0px;
-  padding: 2px 0px 25px 2px !important;
-  padding-bottom:25px !important; /*moz bottom */
-  padding-bottom:2px; /*ie bottom */
 }
 
 div#toolbar-box div.m {
index 6098b242910ceacc705e1bf2320abeb1a7f1edbc..bb73d17e0dc2e8a0f02afaaf6e0ac88a225b842e 100644 (file)
@@ -9,7 +9,7 @@ CRM.$(function($) {
           $.each(result.values, function (id, value) {
             $.each(value, function (fieldname, fieldvalue) {
               $('#' + fieldname).val(fieldvalue).change();
-              $("[name=" + fieldname + "]").val([fieldvalue]);
+              $('[name="' + fieldname + '"]').val([fieldvalue]);
               if ($.isArray(fieldvalue)) {
                 $.each(fieldvalue, function (index, val) {
                   $("#" + fieldname + "_" + val).prop('checked', true);
index 8a5306763778e4b27059c4a0e07e57a9bd870545..985e7d616ccb76c2b00e8e7ece334ce64aa42167 100644 (file)
@@ -646,153 +646,12 @@ if (!CRM.vars) CRM.vars = {};
     return combined;
   }
 
-  function copyAttributes($source, $target, attributes) {
+  CRM.utils.copyAttributes = function ($source, $target, attributes) {
     _.each(attributes, function(name) {
       if ($source.attr(name) !== undefined) {
         $target.attr(name, $source.attr(name));
       }
     });
-  }
-
-  /**
-   * @see http://wiki.civicrm.org/confluence/display/CRMDOC/crmDatepicker
-   */
-  $.fn.crmDatepicker = function(options) {
-    return $(this).each(function() {
-      if ($(this).is('.crm-form-date-wrapper .crm-hidden-date')) {
-        // Already initialized - destroy
-        $(this)
-          .off('.crmDatepicker')
-          .css('display', '')
-          .removeClass('crm-hidden-date')
-          .siblings().remove();
-        $(this).unwrap();
-      }
-      if (options === 'destroy') {
-        return;
-      }
-      var
-        $dataField = $(this).wrap('<span class="crm-form-date-wrapper" />'),
-        settings = _.cloneDeep(options || {}),
-        $dateField = $(),
-        $timeField = $(),
-        $clearLink = $(),
-        hasDatepicker = settings.date !== false && settings.date !== 'yy',
-        type = hasDatepicker ? 'text' : 'number';
-
-      if (settings.allowClear !== undefined ? settings.allowClear : !$dataField.is('.required, [required]')) {
-        $clearLink = $('<a class="crm-hover-button crm-clear-link" title="'+ _.escape(ts('Clear')) +'"><i class="crm-i fa-times"></i></a>')
-          .insertAfter($dataField);
-      }
-      if (settings.time !== false) {
-        $timeField = $('<input>').insertAfter($dataField);
-        copyAttributes($dataField, $timeField, ['class', 'disabled']);
-        $timeField
-          .addClass('crm-form-text crm-form-time')
-          .attr('placeholder', $dataField.attr('time-placeholder') === undefined ? ts('Time') : $dataField.attr('time-placeholder'))
-          .attr('aria-label', $dataField.attr('time-placeholder') === undefined ? ts('Time') : $dataField.attr('time-placeholder'))
-          .change(updateDataField)
-          .timeEntry({
-            spinnerImage: '',
-            show24Hours: settings.time === true || settings.time === undefined ? CRM.config.timeIs24Hr : settings.time == '24'
-          });
-      }
-      if (settings.date !== false) {
-        // Render "number" field for year-only format, calendar popup for all other formats
-        $dateField = $('<input type="' + type + '">').insertAfter($dataField);
-        copyAttributes($dataField, $dateField, ['placeholder', 'style', 'class', 'disabled', 'aria-label']);
-        $dateField.addClass('crm-form-' + type);
-        if (hasDatepicker) {
-          settings.minDate = settings.minDate ? CRM.utils.makeDate(settings.minDate) : null;
-          settings.maxDate = settings.maxDate ? CRM.utils.makeDate(settings.maxDate) : null;
-          settings.dateFormat = typeof settings.date === 'string' ? settings.date : CRM.config.dateInputFormat;
-          settings.changeMonth = _.includes(settings.dateFormat, 'm');
-          settings.changeYear = _.includes(settings.dateFormat, 'y');
-          if (!settings.yearRange && settings.minDate !== null && settings.maxDate !== null) {
-            settings.yearRange = '' + CRM.utils.formatDate(settings.minDate, 'yy') + ':' + CRM.utils.formatDate(settings.maxDate, 'yy');
-          }
-          $dateField.addClass('crm-form-date').datepicker(settings);
-        } else {
-          $dateField.attr('min', settings.minDate ? CRM.utils.formatDate(settings.minDate, 'yy') : '1000');
-          $dateField.attr('max', settings.maxDate ? CRM.utils.formatDate(settings.maxDate, 'yy') : '4000');
-        }
-        $dateField.change(updateDataField);
-      }
-      // Rudimentary validation. TODO: Roll into use of jQUery validate and ui.datepicker.validation
-      function isValidDate() {
-        // FIXME: parseDate doesn't work with incomplete date formats; skip validation if no month, day or year in format
-        var lowerFormat = settings.dateFormat.toLowerCase();
-        if (lowerFormat.indexOf('y') < 0 || lowerFormat.indexOf('m') < 0 || !dateHasDay()) {
-          return true;
-        }
-        try {
-          $.datepicker.parseDate(settings.dateFormat, $dateField.val());
-          return true;
-        } catch (e) {
-          return false;
-        }
-      }
-
-      /**
-       * Does the date format contain the day.
-       *
-       * @returns {boolean}
-       */
-      function dateHasDay() {
-        var lowerFormat = settings.dateFormat.toLowerCase();
-        if (lowerFormat.indexOf('d') < 0) {
-          return false;
-        }
-        return true;
-      }
-      function updateInputFields(e, context) {
-        var val = $dataField.val(),
-          time = null;
-        if (context !== 'userInput' && context !== 'crmClear') {
-          if (hasDatepicker) {
-            $dateField.datepicker('setDate', _.includes(val, '-') ? $.datepicker.parseDate('yy-mm-dd', val) : null);
-          } else if ($dateField.length) {
-            $dateField.val(val.slice(0, 4));
-          }
-          if ($timeField.length) {
-            if (val.length === 8) {
-              time = val;
-            } else if (val.length === 19) {
-              time = val.split(' ')[1];
-            }
-            $timeField.timeEntry('setTime', time);
-          }
-        }
-        $clearLink.css('visibility', val ? 'visible' : 'hidden');
-      }
-      function updateDataField(e, context) {
-        // The crmClear event wipes all the field values anyway, so no need to respond
-        if (context !== 'crmClear') {
-          var val = '';
-          if ($dateField.val()) {
-            if (hasDatepicker && isValidDate() && dateHasDay()) {
-              val = $.datepicker.formatDate('yy-mm-dd', $dateField.datepicker('getDate'));
-              $dateField.removeClass('crm-error');
-            } else if (!hasDatepicker) {
-              val = $dateField.val() + '-01-01';
-            }
-            else if (!dateHasDay()) {
-              // This would be a Year-month date (yyyy-mm)
-              // it could be argued it should not use a datepicker....
-              val = $dateField.val() + '-01';
-            } else {
-              $dateField.addClass('crm-error');
-            }
-          }
-          if ($timeField.val()) {
-            val += (val ? ' ' : '') + $timeField.timeEntry('getTime').toTimeString().substr(0, 8);
-          }
-          $dataField.val(val).trigger('change', ['userInput']);
-        }
-      }
-      $dataField.hide().addClass('crm-hidden-date').on('change.crmDatepicker', updateInputFields);
-      updateInputFields();
-    });
   };
 
   CRM.utils.formatSelect2Result = function (row) {
diff --git a/js/crm.datepicker.js b/js/crm.datepicker.js
new file mode 100644 (file)
index 0000000..cfef977
--- /dev/null
@@ -0,0 +1,144 @@
+(function($, CRM, _) {
+  "use strict";
+
+  /**
+   * @see http://wiki.civicrm.org/confluence/display/CRMDOC/crmDatepicker
+   */
+  $.fn.crmDatepicker = function(options) {
+    return $(this).each(function() {
+      if ($(this).is('.crm-form-date-wrapper .crm-hidden-date')) {
+        // Already initialized - destroy
+        $(this)
+          .off('.crmDatepicker')
+          .css('display', '')
+          .removeClass('crm-hidden-date')
+          .siblings().remove();
+        $(this).unwrap();
+      }
+      if (options === 'destroy') {
+        return;
+      }
+      var
+        $dataField = $(this).wrap('<span class="crm-form-date-wrapper" />'),
+        settings = CRM._.cloneDeep(options || {}),
+        $dateField = $(),
+        $timeField = $(),
+        $clearLink = $(),
+        hasDatepicker = settings.date !== false && settings.date !== 'yy',
+        type = hasDatepicker ? 'text' : 'number';
+
+      if (settings.allowClear !== undefined ? settings.allowClear : !$dataField.is('.required, [required]')) {
+        $clearLink = $('<a class="crm-hover-button crm-clear-link" title="'+ CRM._.escape(ts('Clear')) +'"><i class="crm-i fa-times"></i></a>')
+          .insertAfter($dataField);
+      }
+      if (settings.time !== false) {
+        $timeField = $('<input>').insertAfter($dataField);
+        CRM.utils.copyAttributes($dataField, $timeField, ['class', 'disabled']);
+        $timeField
+          .addClass('crm-form-text crm-form-time')
+          .attr('placeholder', $dataField.attr('time-placeholder') === undefined ? ts('Time') : $dataField.attr('time-placeholder'))
+          .attr('aria-label', $dataField.attr('time-placeholder') === undefined ? ts('Time') : $dataField.attr('time-placeholder'))
+          .change(updateDataField)
+          .timeEntry({
+            spinnerImage: '',
+            show24Hours: settings.time === true || settings.time === undefined ? CRM.config.timeIs24Hr : settings.time == '24'
+          });
+      }
+      if (settings.date !== false) {
+        // Render "number" field for year-only format, calendar popup for all other formats
+        $dateField = $('<input type="' + type + '">').insertAfter($dataField);
+        CRM.utils.copyAttributes($dataField, $dateField, ['placeholder', 'style', 'class', 'disabled', 'aria-label']);
+        $dateField.addClass('crm-form-' + type);
+        if (hasDatepicker) {
+          settings.minDate = settings.minDate ? CRM.utils.makeDate(settings.minDate) : null;
+          settings.maxDate = settings.maxDate ? CRM.utils.makeDate(settings.maxDate) : null;
+          settings.dateFormat = typeof settings.date === 'string' ? settings.date : CRM.config.dateInputFormat;
+          settings.changeMonth = CRM._.includes(settings.dateFormat, 'm');
+          settings.changeYear = CRM._.includes(settings.dateFormat, 'y');
+          if (!settings.yearRange && settings.minDate !== null && settings.maxDate !== null) {
+            settings.yearRange = '' + CRM.utils.formatDate(settings.minDate, 'yy') + ':' + CRM.utils.formatDate(settings.maxDate, 'yy');
+          }
+          $dateField.addClass('crm-form-date').datepicker(settings);
+        } else {
+          $dateField.attr('min', settings.minDate ? CRM.utils.formatDate(settings.minDate, 'yy') : '1000');
+          $dateField.attr('max', settings.maxDate ? CRM.utils.formatDate(settings.maxDate, 'yy') : '4000');
+        }
+        $dateField.change(updateDataField);
+      }
+      // Rudimentary validation. TODO: Roll into use of jQUery validate and ui.datepicker.validation
+      function isValidDate() {
+        // FIXME: parseDate doesn't work with incomplete date formats; skip validation if no month, day or year in format
+        var lowerFormat = settings.dateFormat.toLowerCase();
+        if (lowerFormat.indexOf('y') < 0 || lowerFormat.indexOf('m') < 0 || !dateHasDay()) {
+          return true;
+        }
+        try {
+          $.datepicker.parseDate(settings.dateFormat, $dateField.val());
+          return true;
+        } catch (e) {
+          return false;
+        }
+      }
+
+      /**
+       * Does the date format contain the day.
+       *
+       * @returns {boolean}
+       */
+      function dateHasDay() {
+        var lowerFormat = settings.dateFormat.toLowerCase();
+        if (lowerFormat.indexOf('d') < 0) {
+          return false;
+        }
+        return true;
+      }
+      function updateInputFields(e, context) {
+        var val = $dataField.val(),
+          time = null;
+        if (context !== 'userInput' && context !== 'crmClear') {
+          if (hasDatepicker) {
+            $dateField.datepicker('setDate', CRM._.includes(val, '-') ? $.datepicker.parseDate('yy-mm-dd', val) : null);
+          } else if ($dateField.length) {
+            $dateField.val(val.slice(0, 4));
+          }
+          if ($timeField.length) {
+            if (val.length === 8) {
+              time = val;
+            } else if (val.length === 19) {
+              time = val.split(' ')[1];
+            }
+            $timeField.timeEntry('setTime', time);
+          }
+        }
+        $clearLink.css('visibility', val ? 'visible' : 'hidden');
+      }
+      function updateDataField(e, context) {
+        // The crmClear event wipes all the field values anyway, so no need to respond
+        if (context !== 'crmClear') {
+          var val = '';
+          if ($dateField.val()) {
+            if (hasDatepicker && isValidDate() && dateHasDay()) {
+              val = $.datepicker.formatDate('yy-mm-dd', $dateField.datepicker('getDate'));
+              $dateField.removeClass('crm-error');
+            } else if (!hasDatepicker) {
+              val = $dateField.val() + '-01-01';
+            }
+            else if (!dateHasDay()) {
+              // This would be a Year-month date (yyyy-mm)
+              // it could be argued it should not use a datepicker....
+              val = $dateField.val() + '-01';
+            } else {
+              $dateField.addClass('crm-error');
+            }
+          }
+          if ($timeField.val()) {
+            val += (val ? ' ' : '') + $timeField.timeEntry('getTime').toTimeString().substr(0, 8);
+          }
+          $dataField.val(val).trigger('change', ['userInput']);
+        }
+      }
+      $dataField.hide().addClass('crm-hidden-date').on('change.crmDatepicker', updateInputFields);
+      updateInputFields();
+    });
+  };
+})(jQuery, CRM, CRM._);
similarity index 59%
rename from js/crm.drupal.js
rename to js/crm.drupal7.js
index 7ed33666e29a834c01870d5f18cf10c59f83b13b..4be65e41065e27201a0c8fb9245bb3dec818b5a2 100644 (file)
@@ -10,13 +10,6 @@ CRM.$(function($) {
         // D7 hack, restore toolbar position (CRM-15341)
         $('#toolbar').css('z-index', '');
       }
-    })
-   // d8 Hack to hide title when it should be (CRM-19960)
-   .ready(function() {
-     var pageTitle = $('.page-title');
-     var title = $('.page-title').text();
-     if ('<span id="crm-remove-title" style="display:none">CiviCRM</span>' == title) {
-       pageTitle.hide();
-     }
-   });
+    });
+    $('#civicrm-menu').css({'width': '97%'});
 });
diff --git a/js/crm.drupal8.js b/js/crm.drupal8.js
new file mode 100644 (file)
index 0000000..32c06a6
--- /dev/null
@@ -0,0 +1,17 @@
+// http://civicrm.org/licensing
+CRM.$(function($) {
+   // d8 Hack to hide title when it should be (CRM-19960)
+   var pageTitle = $('.page-title');
+   if ('<span id="crm-remove-title" style="display:none">CiviCRM</span>' == pageTitle.text()) {
+     pageTitle.hide();
+   }
+
+   $('#toolbar-bar').hide();
+
+   $('.crm-hidemenu').click(function(e) {
+     $('#toolbar-bar').slideDown();
+   });
+   $('#crm-notification-container').on('click', '#crm-restore-menu', function() {
+     $('#toolbar-bar').slideUp();
+   });
+});
index d1c9cd3487fd92e2c41ff3800a554f3e608a7bb0..2915dc7814fe5020a03f613abe5ce5eaf923edc5 100644 (file)
@@ -32,6 +32,7 @@ module.exports = function(config) {
       'bower_components/jquery-validation/dist/jquery.validate.min.js',
       'packages/jquery/plugins/jquery.timeentry.js',
       'js/Common.js',
+      'js/crm.datepicker.js',
       'bower_components/angular/angular.js',
       'js/crm.angular.js',
       angularTempFile,
index e9fdf95bb178f048e5c5ede4566199c3fe4bb1b3..0e1bb038263e549064e62165e8370113afad1fe1 100644 (file)
@@ -399,7 +399,7 @@ UNLOCK TABLES;
 
 LOCK TABLES `civicrm_domain` WRITE;
 /*!40000 ALTER TABLE `civicrm_domain` DISABLE KEYS */;
-INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `config_backend`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,NULL,'5.5.beta1',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
+INSERT INTO `civicrm_domain` (`id`, `name`, `description`, `config_backend`, `version`, `contact_id`, `locales`, `locale_custom_strings`) VALUES (1,'Default Domain Name',NULL,NULL,'5.6.alpha1',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
 /*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */;
 UNLOCK TABLES;
 
index f15819318a3ca021d6fb780b8b6ca1b832f48b5b..14dd2bd8d483766e00832fa32c7ec744197ae453 100644 (file)
@@ -60,7 +60,9 @@
           <table class="form-layout-compressed">
             {foreach from=$caseRoles.client item=client}
               <tr class="crm-case-caseview-display_name">
-                <td class="label-left bold" style="padding: 0px; border: none;">{$client.display_name}</td>
+                <td class="label-left bold" style="padding: 0px; border: none;">
+                  <a href="{crmURL p='civicrm/contact/view' q="action=view&reset=1&cid=`$client.contact_id`"}" title="{ts}View contact record{/ts}">{$client.display_name}</a>
+                </td>
               </tr>
               {if $client.phone}
                 <tr class="crm-case-caseview-phone">
index 76d7bb46927f73a275ed8decca64bfb08b842c65..0bfa29b91bd0f4c094f0d458b07144e7e935af1f 100644 (file)
       o.animate({height: '+=50px'}, 200);
       data.snippet = 6;
       data.reset = 1;
-      o.addClass('form');
+      var width = o.width();
       $('.crm-edit-ready').removeClass('crm-edit-ready');
-      o.block();
+      o.block().addClass('form').css('width', '' + width + 'px');
       $.getJSON(CRM.url('civicrm/ajax/inline', data))
         .fail(errorHandler)
         .done(function(response) {
           o.unblock();
           o.css('overflow', 'hidden').wrapInner('<div class="inline-edit-hidden-content" style="display:none" />').append(response.content);
+          // Needed to accurately measure box width
+          $('.crm-container-snippet', o).css('display', 'inline-block');
           // Smooth resizing
-          var newHeight = $('.crm-container-snippet', o).height();
-          var diff = newHeight - parseInt(o.css('height'), 10);
-          if (diff < 0) {
-            diff = 0 - diff;
+          var newHeight = $('.crm-container-snippet', o).height(),
+            speed = newHeight - parseInt(o.css('height'), 10),
+            animation = {height: '' + newHeight + 'px'};
+          // Animation speed is set relative to how much the box needs to grow
+          if (speed < 0) {
+            speed = 0 - speed;
           }
-          o.animate({height: '' + newHeight + 'px'}, diff * 2, function() {
-            o.removeAttr('style');
+          // Horizontal growth
+          var newWidth = $('.crm-container-snippet', o).width();
+          if (newWidth > width) {
+            animation.width = '' + newWidth + 'px';
+            // Slow down animation if we have lots of horizontal growth to do
+            if (newWidth - width > speed) {
+              speed = newWidth - width;
+            }
+          } else {
+            newWidth = width;
+          }
+          $('.crm-container-snippet', o).css('display', '');
+          o.animate(animation, speed, function() {
+            o.css({height: '', width: '', minWidth: '' + newWidth + 'px'});
           });
           $('form', o).validate(CRM.validate.params);
           ajaxFormParams.data = data;
@@ -57,7 +73,7 @@
     $('form', o).ajaxFormUnbind();
 
     if (response.status == 'success' || response.status == 'cancel') {
-      o.trigger('crmFormSuccess', [response]);
+      o.trigger('crmFormSuccess', [response]).removeAttr('style');
       $('.crm-inline-edit-container').addClass('crm-edit-ready');
       var data = o.data('edit-params');
       var dependent = $((o.data('dependent-fields') || []).join(','));
         $('form', container).ajaxFormUnbind();
         $('.inline-edit-hidden-content', container).nextAll().remove();
         $('.inline-edit-hidden-content > *:first-child', container).unwrap();
-        container.removeClass('form');
+        container.removeClass('form').removeAttr('style');
         $('.crm-inline-edit-container').addClass('crm-edit-ready');
         $('a.ui-notify-close', '#crm-notification-container').click();
         return false;
index dd2f3a195d2e047649b44e57e9d8780a4a8adf48..67e814ad53e9aa2b6715f14c03eb765ad0f6b386 100644 (file)
@@ -1,4 +1,9 @@
 <div id="report-tab-set-developer" class="civireport-criteria">
-  <p><b>{ts}Class used{/ts}: {$report_class}</b></p>
+  <p><b>{ts}Class used{/ts}: {$report_class|escape}</b></p>
+  <p>{ts}SQL Modes{/ts}:
+  {foreach from=$sqlModes item=sqlMode}
+    {$sqlMode|escape}
+  {/foreach}
+  </p>
   <pre>{$sql|purify}</pre>
 </div>
index 69151673f3dc4f50076bcd0ee13803e333a786c6..5902068185ebb3523bfcbf100c389bf7178990d9 100644 (file)
 {/strip}{/capture}// <script> Generated {$smarty.now|date_format:'%d %b %Y %H:%M:%S'}
 {literal}
 (function($) {
-  var menuMarkup = {/literal}{$menuMarkup|@json_encode};
-{if $config->userFramework neq 'Joomla'}{literal}
-  $('body').append(menuMarkup);
-
-  $('#civicrm-menu').css({position: "fixed", top: "0px"});
+  var menuMarkup = {/literal}{$menuMarkup|@json_encode}{literal};
 
   //Track Scrolling
-  $(window).scroll(function () {
-    $('div.sticky-header').css({top: $('#civicrm-menu').height() + "px", position: "fixed"});
-  });
-
-  if ($('#edit-shortcuts').length > 0) {
-    $('#civicrm-menu').css({'width': '97%'});
+  if ($('div.sticky-header').length) {
+    $(window).scroll(function () {
+      $('div.sticky-header').css({top: $('#civicrm-menu').height() + "px", position: "fixed"});
+    });
   }
-{/literal}{else}{* Special menu hacks for Joomla *}{literal}
-  // below div is present in older version of joomla 2.5.x
-  var elementExists = $('div#toolbar-box div.m').length;
-  if (elementExists > 0) {
+
+  if ($('div#toolbar-box div.m').length) {
     $('div#toolbar-box div.m').html(menuMarkup);
   }
-  else {
+  else if ($("#crm-nav-menu-container").length) {
     $("#crm-nav-menu-container").html(menuMarkup).css({'padding-bottom': '10px'});
   }
-{/literal}{/if}{literal}
+  else {
+    $('body').append(menuMarkup);
+  }
+
   // CRM-15493 get the current qfKey
   $("input[name=qfKey]", "#quickSearch").val($('#civicrm-navigation-menu').data('qfkey'));
 
index e62c907b243dd0d62691b98edb90a5c7ffb8c63c..9166688b86e7bfd1fa470681245d962eec2ce05d 100644 (file)
@@ -21,12 +21,12 @@ class CRM_Core_ComposerConfigTest extends \PHPUnit_Framework_TestCase {
    */
   public function testHardLocks() {
     $hardLocks = array(
-      'symfony/config' => '/^v2\.6\./',
-      'symfony/dependency-injection' => '/^v2\.6\./',
-      'symfony/event-dispatcher' => '/^v2\.6\./',
-      'symfony/filesystem' => '/^v2\.6\./',
-      'symfony/finder' => '/^v2\.6\./',
-      'symfony/process' => '/^v2\.6\./',
+      'symfony/config' => '/^v2\.8\./',
+      'symfony/dependency-injection' => '/^v2\.8\./',
+      'symfony/event-dispatcher' => '/^v2\.8\./',
+      'symfony/filesystem' => '/^v2\.8\./',
+      'symfony/finder' => '/^v2\.8\./',
+      'symfony/process' => '/^v2\.8\./',
     );
 
     $lockFile = Civi::paths()->getPath('[civicrm.root]/composer.lock');
diff --git a/tests/phpunit/CRM/Event/BAO/EventPermissionsTest.php b/tests/phpunit/CRM/Event/BAO/EventPermissionsTest.php
new file mode 100644 (file)
index 0000000..84828e1
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 5                                                  |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2018                                |
+ +--------------------------------------------------------------------+
+ | This file is a part of CiviCRM.                                    |
+ |                                                                    |
+ | CiviCRM is free software; you can copy, modify, and distribute it  |
+ | under the terms of the GNU Affero General Public License           |
+ | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
+ |                                                                    |
+ | CiviCRM is distributed in the hope that it will be useful, but     |
+ | WITHOUT ANY WARRANTY; without even the implied warranty of         |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
+ | See the GNU Affero General Public License for more details.        |
+ |                                                                    |
+ | You should have received a copy of the GNU Affero General Public   |
+ | License and the CiviCRM Licensing Exception along                  |
+ | with this program; if not, contact CiviCRM LLC                     |
+ | at info[AT]civicrm[DOT]org. If you have questions about the        |
+ | GNU Affero General Public License or the licensing of CiviCRM,     |
+ | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * Class CRM_Event_BAO_EventPermissionsTest
+ * @group headless
+ */
+class CRM_Event_BAO_EventPermissionsTest extends CiviUnitTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    $this->_contactId = $this->createLoggedInUser();
+    $event = $this->eventCreate(array(
+      'created_id' => $this->_contactId,
+    ));
+    $this->_eventId = $event['id'];
+  }
+
+  public function testEditOwnEvent() {
+    CRM_Core_Config::singleton()->userPermissionTemp = ['access civievent', 'access CiviCRM', 'view event info'];
+    unset(\Civi::$statics['CRM_Event_BAO_Event']['permissions']);
+    $permissions = CRM_Event_BAO_Event::checkPermission($this->_eventId, CRM_Core_Permission::EDIT);
+    $this->assertTrue($permissions);
+  }
+
+}
index e6f60a8d8dd288ba9e9a7b0786fc262e4892fc6f..cea24c8dcac36291d3c8d63c22beb59bdf42e629 100644 (file)
@@ -433,7 +433,7 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
       ['Individual', 'city', ''],
       ['Individual', 'state_province', ''],
     ];
-    list($tableName) = CRM_Export_BAO_Export::exportComponents(
+    list($tableName, $sqlColumns, $headerRows) = CRM_Export_BAO_Export::exportComponents(
       FALSE,
       $this->contactIDs,
       [],
@@ -458,6 +458,17 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
       $this->assertEquals($householdID, $dao->civicrm_primary_id);
     }
 
+    $this->assertEquals([
+      0 => 'City',
+      1 => 'State',
+      2 => 'Household ID',
+    ], $headerRows);
+    $this->assertEquals(
+      [
+        'city' => 'city varchar(64)',
+        'state_province' => 'state_province varchar(64)',
+        'civicrm_primary_id' => 'civicrm_primary_id varchar(16)',
+      ], $sqlColumns);
   }
 
   /**
index 14fcde188382d5f6b412979662a29b72c3b722c4..75adbe74a1296ad2397ed7126793d8249129ecdf 100644 (file)
@@ -722,6 +722,7 @@ class CRM_Member_Form_MembershipTest extends CiviUnitTestCase {
    * Test the submit function of the membership form.
    */
   public function testSubmitRecur() {
+    CRM_Core_Session::singleton()->getStatus(TRUE);
     $pendingVal = $this->callAPISuccessGetValue('OptionValue', array(
       'return' => "id",
       'option_group_id' => "contribution_status",
@@ -767,6 +768,14 @@ class CRM_Member_Form_MembershipTest extends CiviUnitTestCase {
       'entity_table' => 'civicrm_membership',
       'contribution_id' => $contribution['id'],
     ), 1);
+    $this->assertEquals([
+      [
+        'text' => 'AnnualFixed membership for Mr. Anthony Anderson II has been added. The new membership End Date is ' . date('F jS, Y', strtotime('last day of this month')) . ' 12:00 AM.',
+        'title' => 'Complete',
+        'type' => 'success',
+        'options' => NULL,
+      ],
+    ], CRM_Core_Session::singleton()->getStatus());
   }
 
   /**
@@ -1281,10 +1290,12 @@ Expires: ',
   }
 
   /**
-   * CRM-21656: Test the submit function of the membership form if Sale Tax is enabled.
-   *  Check that the tax rate isn't reapplied to line item's unit price and total amount
+   * CRM-21656: Test the submit function of the membership form if Sales Tax is enabled.
+   * This test simulates what happens when one hits Edit on a Contribution that has both LineItems and Sales Tax components
+   * Without making any Edits -> check that the LineItem data remain the same
+   * In addition (a data-integrity check) -> check that the LineItem data add up to the data at the Contribution level
    */
-  public function testLineItemAmountOnSaleTax() {
+  public function testLineItemAmountOnSalesTax() {
     $this->enableTaxAndInvoicing();
     $this->relationForFinancialTypeWithFinancialAccount(2);
     $form = $this->getForm();
@@ -1293,6 +1304,8 @@ Expires: ',
     $this->createLoggedInUser();
     $priceSet = $this->callAPISuccess('PriceSet', 'Get', array("extends" => "CiviMember"));
     $form->set('priceSetId', $priceSet['id']);
+    // we are simulating the creation of a Price Set in Administer -> CiviContribute -> Manage Price Sets so set is_quick_config = 0
+    $this->callAPISuccess('PriceSet', 'Create', array("id" => $priceSet['id'], 'is_quick_config' => 0));
     // clean the price options static variable to repopulate the options, in order to fetch tax information
     \Civi::$statics['CRM_Price_BAO_PriceField']['priceOptions'] = NULL;
     CRM_Price_BAO_PriceSet::buildPriceSet($form);
@@ -1336,10 +1349,29 @@ Expires: ',
     ),
     CRM_Core_Action::UPDATE);
 
-    // ensure that the line-item values got unaffected
+    // ensure that the LineItem data remain the same
     $lineItem = $this->callAPISuccessGetSingle('LineItem', array('entity_id' => $membership['id'], 'entity_table' => 'civicrm_membership'));
     $this->assertEquals(1, $lineItem['qty']);
-    $this->assertEquals(5.00, $lineItem['tax_amount']); // ensure that tax amount is not changed
+    $this->assertEquals(50.00, $lineItem['unit_price']);
+    $this->assertEquals(50.00, $lineItem['line_total']);
+    $this->assertEquals(5.00, $lineItem['tax_amount']);
+
+    // ensure that the LineItem data add up to the data at the Contribution level
+    $contribution = $this->callAPISuccessGetSingle('Contribution',
+      array(
+        'contribution_id' => 1,
+        'return' => array('tax_amount', 'total_amount'),
+      )
+    );
+    $this->assertEquals($contribution['total_amount'], $lineItem['line_total'] + $lineItem['tax_amount']);
+    $this->assertEquals($contribution['tax_amount'], $lineItem['tax_amount']);
+
+    $financialItems = $this->callAPISuccess('FinancialItem', 'get', array());
+    $financialItems_sum = 0;
+    foreach ($financialItems['values'] as $financialItem) {
+      $financialItems_sum += $financialItem['amount'];
+    }
+    $this->assertEquals($contribution['total_amount'], $financialItems_sum);
 
     // reset the price options static variable so not leave any dummy data, that might hamper other unit tests
     \Civi::$statics['CRM_Price_BAO_PriceField']['priceOptions'] = NULL;
index 921818cad58c9f5bb95fd77a008f3fe270bea102..d8b8b6635afb9a4e6cfb3654ab5e9494c3e99b78 100644 (file)
@@ -12,8 +12,10 @@ class CRM_Utils_MoneyTest extends CiviUnitTestCase {
 
   /**
    * @dataProvider subtractCurrenciesDataProvider
-   * @param $inputData
-   * @param $expectedResult
+   * @param string $leftOp
+   * @param string $rightOp
+   * @param string $currency
+   * @param float $expectedResult
    */
   public function testSubtractCurrencies($leftOp, $rightOp, $currency, $expectedResult) {
     $this->assertEquals($expectedResult, CRM_Utils_Money::subtractCurrencies($leftOp, $rightOp, $currency));
@@ -44,4 +46,29 @@ class CRM_Utils_MoneyTest extends CiviUnitTestCase {
     );
   }
 
+  /**
+   * Test rounded by currency function.
+   *
+   * In practice this only does rounding to 2 since rounding by any other amount is
+   * only place-holder supported.
+   */
+  public function testFormatLocaleNumericRoundedByCurrency() {
+    $result = CRM_Utils_Money::formatLocaleNumericRoundedByCurrency(8950.3678, 'NZD');
+    $this->assertEquals('8,950.37', $result);
+  }
+
+  /**
+   * Test rounded by currency function.
+   *
+   * This should be formatted according to European standards - . thousand separator
+   * and , for decimal. (The Europeans are wrong but they don't know that. We will forgive them
+   * because ... metric).
+   */
+  public function testFormatLocaleNumericRoundedByCurrencyEuroThousand() {
+    $this->setCurrencySeparators('.');
+    $result = CRM_Utils_Money::formatLocaleNumericRoundedByCurrency(8950.3678, 'NZD');
+    $this->assertEquals('8.950,37', $result);
+    $this->setCurrencySeparators(',');
+  }
+
 }
diff --git a/tests/phpunit/E2E/Core/PrevNextTest.php b/tests/phpunit/E2E/Core/PrevNextTest.php
new file mode 100644 (file)
index 0000000..3ca3c48
--- /dev/null
@@ -0,0 +1,319 @@
+<?php
+
+namespace E2E\Core;
+
+/**
+ * Class PrevNextTest
+ *
+ * Check that the active prev-next service behaves as expected.
+ *
+ * @package E2E\Core
+ * @group e2e
+ */
+class PrevNextTest extends \CiviEndToEndTestCase {
+
+  /**
+   * @var string
+   */
+  protected $cacheKey, $cacheKeyB;
+
+  /**
+   * @var \CRM_Core_PrevNextCache_Interface
+   */
+  protected $prevNext;
+
+  protected function setUp() {
+    parent::setUp();
+    $this->prevNext = \Civi::service('prevnext');
+    $this->cacheKey = 'PrevNextTest_' . \CRM_Utils_String::createRandom(16, \CRM_Utils_String::ALPHANUMERIC);
+    $this->cacheKeyB = 'PrevNextTest_' . \CRM_Utils_String::createRandom(16, \CRM_Utils_String::ALPHANUMERIC);
+    $this->assertTrue(
+      \CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_contact') > 25,
+      'The contact table must have at least 25 records.'
+    );
+  }
+
+  protected function tearDown() {
+    \Civi::service('prevnext')->deleteItem(NULL, $this->cacheKey);
+  }
+
+  public function testFillSql() {
+    $start = 0;
+    $prefillLimit = 25;
+    $sort = NULL;
+
+    $query = new \CRM_Contact_BAO_Query(array(), NULL, NULL, FALSE, FALSE, 1, FALSE, TRUE, FALSE, NULL, 'AND');
+    $sql = $query->searchQuery($start, $prefillLimit, $sort, FALSE, $query->_includeContactIds,
+      FALSE, TRUE, TRUE);
+    $selectSQL = "SELECT DISTINCT '$this->cacheKey', contact_a.id, contact_a.sort_name";
+    $sql = str_replace(array("SELECT contact_a.id as contact_id", "SELECT contact_a.id as id"), $selectSQL, $sql);
+
+    $this->assertTrue(
+      $this->prevNext->fillWithSql($this->cacheKey, $sql),
+      "fillWithSql should return TRUE on success"
+    );
+
+    $this->assertEquals(25, $this->prevNext->getCount($this->cacheKey));
+    $this->assertEquals(0, $this->prevNext->getCount('not-a-key-' . $this->cacheKey));
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    $this->assertCount($prefillLimit, $all);
+    $this->assertCount($prefillLimit, array_unique(array_keys($all)));
+    $this->assertEquals([1], array_unique(array_values($all)));
+
+    $this->assertSelections([]);
+  }
+
+  public function testFillArray() {
+    $rowSetA = [
+      ['entity_id1' => 100, 'data' => 'Alice'],
+      ['entity_id1' => 400, 'data' => 'Bob'],
+      ['entity_id1' => 200, 'data' => 'Carol'],
+    ];
+    $rowSetB = [
+      ['entity_id1' => 300, 'data' => 'Dave'],
+    ];
+
+    $this->assertTrue(
+      $this->prevNext->fillWithArray($this->cacheKey, $rowSetA),
+      "fillWithArray should return TRUE on success"
+    );
+    $this->assertTrue(
+      $this->prevNext->fillWithArray($this->cacheKey, $rowSetB),
+      "fillWithArray should return TRUE on success"
+    );
+
+    $this->assertEquals(4, $this->prevNext->getCount($this->cacheKey));
+    $this->assertEquals(0, $this->prevNext->getCount('not-a-key-' . $this->cacheKey));
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    $this->assertEquals([100, 400, 200, 300], array_keys($all));
+    $this->assertEquals([1], array_unique(array_values($all)));
+
+    $this->assertSelections([]);
+  }
+
+  public function getFillFunctions() {
+    return [
+      ['testFillSql'],
+      ['testFillArray'],
+    ];
+  }
+
+  /**
+   * Select and unselect one item.
+   *
+   * @dataProvider getFillFunctions
+   */
+  public function testMarkSelection_1($fillFunction) {
+    call_user_func([$this, $fillFunction]);
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    list ($id1, $id2) = array_keys($all);
+    $this->prevNext->markSelection($this->cacheKey, 'select', $id1);
+
+    $this->assertSelections([$id1]);
+
+    $this->prevNext->markSelection($this->cacheKey, 'unselect', $id1);
+    $this->assertSelections([]);
+  }
+
+  /**
+   * Select and unselect two items.
+   *
+   * @dataProvider getFillFunctions
+   */
+  public function testMarkSelection_2($fillFunction) {
+    call_user_func([$this, $fillFunction]);
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    list ($id1, $id2, $id3) = array_keys($all);
+
+    $this->prevNext->markSelection($this->cacheKey, 'select', [$id1, $id3]);
+    $this->assertSelections([$id1, $id3]);
+
+    $this->prevNext->markSelection($this->cacheKey, 'unselect', $id1);
+    $this->assertSelections([$id3]);
+
+    $this->prevNext->markSelection($this->cacheKey, 'select', $id2);
+    $this->assertSelections([$id2, $id3]);
+
+    $this->prevNext->markSelection($this->cacheKey, 'unselect');
+    $this->assertSelections([]);
+  }
+
+  /**
+   * Check the neighbors of the first item.
+   *
+   * @dataProvider getFillFunctions
+   */
+  public function testGetPosition_first($fillFunction) {
+    call_user_func([$this, $fillFunction]);
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    list ($id1, $id2, $id3) = array_keys($all);
+
+    $pos = $this->prevNext->getPositions($this->cacheKey, $id1);
+
+    $this->assertTrue((bool) $pos['foundEntry']);
+
+    $this->assertEquals($id2, $pos['next']['id1']);
+    $this->assertTrue(!empty($pos['next']['data']));
+
+    $this->assertTrue(!isset($pos['prev']));
+  }
+
+  /**
+   * Check the neighbors of a middle item.
+   *
+   * @dataProvider getFillFunctions
+   */
+  public function testGetPosition_middle($fillFunction) {
+    call_user_func([$this, $fillFunction]);
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    list ($id1, $id2, $id3) = array_keys($all);
+
+    $pos = $this->prevNext->getPositions($this->cacheKey, $id2);
+    $this->assertTrue((bool) $pos['foundEntry']);
+
+    $this->assertEquals($id3, $pos['next']['id1']);
+    $this->assertTrue(!empty($pos['next']['data']));
+
+    $this->assertEquals($id1, $pos['prev']['id1']);
+    $this->assertTrue(!empty($pos['prev']['data']));
+  }
+
+  /**
+   * Check the neighbors of the last item.
+   *
+   * @dataProvider getFillFunctions
+   */
+  public function testGetPosition_last($fillFunction) {
+    call_user_func([$this, $fillFunction]);
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    list ($idLast, $idPrev) = array_reverse(array_keys($all));
+
+    $pos = $this->prevNext->getPositions($this->cacheKey, $idLast);
+    $this->assertTrue((bool) $pos['foundEntry']);
+
+    $this->assertTrue(!isset($pos['next']));
+
+    $this->assertEquals($idPrev, $pos['prev']['id1']);
+    $this->assertTrue(!empty($pos['prev']['data']));
+  }
+
+  /**
+   * Check the neighbors of the last item.
+   *
+   * @dataProvider getFillFunctions
+   */
+  public function testGetPosition_invalid($fillFunction) {
+    call_user_func([$this, $fillFunction]);
+
+    $pos = $this->prevNext->getPositions($this->cacheKey, 99999999);
+    $this->assertFalse((bool) $pos['foundEntry']);
+    $this->assertTrue(!isset($pos['next']));
+    $this->assertTrue(!isset($pos['prev']));
+  }
+
+  public function testDeleteByCacheKey() {
+    // Add background data
+    $this->prevNext->fillWithArray($this->cacheKeyB, [
+      ['entity_id1' => 100, 'data' => 'Alice'],
+      ['entity_id1' => 150, 'data' => 'Dave'],
+    ]);
+    $this->prevNext->markSelection($this->cacheKeyB, 'select', 100);
+    $this->assertSelections([100], 'get', $this->cacheKeyB);
+    $this->assertSelections([100, 150], 'getall', $this->cacheKeyB);
+
+    // Add some data that we're actually working with.
+    $this->testFillArray();
+
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    $this->assertEquals([100, 400, 200, 300], array_keys($all));
+
+    list ($id1, $id2, $id3) = array_keys($all);
+    $this->prevNext->markSelection($this->cacheKey, 'select', [$id1, $id3]);
+    $this->assertSelections([$id1, $id3]);
+
+    $this->prevNext->deleteItem(NULL, $this->cacheKey);
+    $all = $this->prevNext->getSelection($this->cacheKey, 'getall')[$this->cacheKey];
+    $this->assertEquals([], array_keys($all));
+    $this->assertSelections([]);
+
+    // Ensure background data was untouched.
+    $this->assertSelections([100], 'get', $this->cacheKeyB);
+    $this->assertSelections([100, 150], 'getall', $this->cacheKeyB);
+  }
+
+  public function testDeleteByEntityId() {
+    // Fill two caches
+    $this->prevNext->fillWithArray($this->cacheKey, [
+      ['entity_id1' => 100, 'data' => 'Alice'],
+      ['entity_id1' => 150, 'data' => 'Dave'],
+    ]);
+    $this->prevNext->markSelection($this->cacheKey, 'select', 100);
+    $this->assertSelections([100], 'get', $this->cacheKey);
+    $this->assertSelections([100, 150], 'getall', $this->cacheKey);
+
+    $this->prevNext->fillWithArray($this->cacheKeyB, [
+      ['entity_id1' => 100, 'data' => 'Alice'],
+      ['entity_id1' => 400, 'data' => 'Bob'],
+    ]);
+    $this->prevNext->markSelection($this->cacheKeyB, 'select', [100, 400]);
+    $this->assertSelections([100, 400], 'get', $this->cacheKeyB);
+    $this->assertSelections([100, 400], 'getall', $this->cacheKeyB);
+
+    // Delete
+    $this->prevNext->deleteItem(100);
+    $this->assertSelections([], 'get', $this->cacheKey);
+    $this->assertSelections([150], 'getall', $this->cacheKey);
+    $this->assertSelections([400], 'get', $this->cacheKeyB);
+    $this->assertSelections([400], 'getall', $this->cacheKeyB);
+  }
+
+  public function testDeleteAll() {
+    // Fill two caches
+    $this->prevNext->fillWithArray($this->cacheKey, [
+      ['entity_id1' => 100, 'data' => 'Alice'],
+      ['entity_id1' => 150, 'data' => 'Dave'],
+    ]);
+    $this->prevNext->markSelection($this->cacheKey, 'select', 100);
+    $this->assertSelections([100], 'get', $this->cacheKey);
+    $this->assertSelections([100, 150], 'getall', $this->cacheKey);
+
+    $this->prevNext->fillWithArray($this->cacheKeyB, [
+      ['entity_id1' => 100, 'data' => 'Alice'],
+      ['entity_id1' => 400, 'data' => 'Bob'],
+    ]);
+    $this->prevNext->markSelection($this->cacheKeyB, 'select', [100, 400]);
+    $this->assertSelections([100, 400], 'get', $this->cacheKeyB);
+    $this->assertSelections([100, 400], 'getall', $this->cacheKeyB);
+
+    // Delete
+    $this->prevNext->deleteItem(NULL, NULL);
+    $this->assertSelections([], 'get', $this->cacheKey);
+    $this->assertSelections([], 'getall', $this->cacheKey);
+    $this->assertSelections([], 'get', $this->cacheKeyB);
+    $this->assertSelections([], 'getall', $this->cacheKeyB);
+  }
+
+
+  /**
+   * Assert that the current cacheKey has a list of selected contact IDs.
+   *
+   * @param array $ids
+   *   Contact IDs that should be selected.
+   */
+  protected function assertSelections($ids, $action = 'get', $cacheKey = NULL) {
+    if ($cacheKey === NULL) {
+      $cacheKey = $this->cacheKey;
+    }
+    $selected = $this->prevNext->getSelection($cacheKey, $action)[$cacheKey];
+    $this->assertEquals($ids, array_keys($selected));
+    $this->assertCount(count($ids), $selected);
+  }
+
+}
index ac469d7cdcecd119d0fefc5785de1a0291926f4f..b86b1efd01fc523989ea2c55bb98970515048466 100644 (file)
     <type>int unsigned</type>
     <default>NULL</default>
     <add>2.2</add>
+    <pseudoconstant>
+      <optionGroupName>visibility</optionGroupName>
+    </pseudoconstant>
   </field>
   <field>
     <name>icon</name>
index 5fda09bd84eb7e62c5ad7b2d314277c8687983db..caee9ef7fa58d3338db66a49353c1f274711042c 100644 (file)
@@ -37,7 +37,7 @@
     <name>entity_id2</name>
     <title>Prev Next Entity ID 2</title>
     <type>int unsigned</type>
-    <required>true</required>
+    <required>false</required>
     <comment>FK to entity table specified in entity_table column.</comment>
     <add>3.4</add>
   </field>
index 69459e2ea64312286832cc185721356318218504..b348d6acac62503b568c6eb65b5ed4d2920f6328 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="iso-8859-1" ?>
 <version>
-  <version_no>5.5.beta1</version_no>
+  <version_no>5.6.alpha1</version_no>
 </version>