Merge pull request #12801 from civicrm/5.5
authorEileen McNaughton <eileen@mcnaughty.com>
Tue, 11 Sep 2018 21:03:52 +0000 (09:03 +1200)
committerGitHub <noreply@github.com>
Tue, 11 Sep 2018 21:03:52 +0000 (09:03 +1200)
5.5

157 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/Admin/Form/Setting.php
CRM/Admin/Form/SettingTrait.php [new file with mode: 0644]
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/Case/Page/AJAX.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.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/CustomField.php
CRM/Core/DAO/OptionValue.php
CRM/Core/DAO/PrevNextCache.php
CRM/Core/DAO/UFField.php
CRM/Core/Form.php
CRM/Core/I18n/SchemaStructure_5_4_alpha1.php [new file with mode: 0644]
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/PaymentEdit.php
CRM/Financial/Form/SalesTaxTrait.php [new file with mode: 0644]
CRM/Friend/Form.php
CRM/Logging/Schema.php
CRM/Mailing/BAO/Component.php
CRM/Mailing/BAO/Mailing.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/Contact/Detail.php
CRM/Report/Form/Contact/Relationship.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/PDF/Label.php
CRM/Utils/Recent.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
ang/crmMailing/BlockPreview.js
ang/crmMailing/services.js
api/v3/Case.php
api/v3/Mailing.php
api/v3/PaymentProcessor.php
api/v3/PaymentProcessorType.php
api/v3/Setting.php
composer.json
composer.lock
css/civicrm.css
css/civicrmNavigation.css
css/contactSummary.css
css/joomla.css
js/AlternateContactSelector.js
js/Common.js
js/crm.ajax.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/Admin/Page/Reminders.tpl
templates/CRM/Case/Form/CaseView.tpl
templates/CRM/Contact/Page/Inline/Address.tpl
templates/CRM/Contact/Page/View/Summary.js
templates/CRM/Contribute/Form/AdditionalInfo/AdditionalDetail.tpl
templates/CRM/Contribute/Form/Contribution.tpl
templates/CRM/Member/Form/Membership.tpl
templates/CRM/Member/Form/MembershipType.tpl
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/Mailing/BAO/MailingTest.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/CustomField.xml
xml/schema/Core/OptionValue.xml
xml/schema/Core/PrevNextCache.xml
xml/schema/Core/UFField.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 695f6f097df4bcf63c494d270d9bafe460934f46..09c0b03842295585430788d12b4d72eed2d71d3f 100644 (file)
  */
 class CRM_Admin_Form_Setting extends CRM_Core_Form {
 
+  use CRM_Admin_Form_SettingTrait;
+
   protected $_settings = array();
 
+  protected $includesReadOnlyFields;
+
   /**
    * Set default values for the form.
    *
@@ -93,80 +97,11 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form {
       )
     );
 
-    $descriptions = array();
-    $settingMetaData = $this->getSettingsMetaData();
-    foreach ($settingMetaData as $setting => $props) {
-      if (isset($props['quick_form_type'])) {
-        if (isset($props['pseudoconstant'])) {
-          $options = civicrm_api3('Setting', 'getoptions', array(
-            'field' => $setting,
-          ));
-        }
-        else {
-          $options = NULL;
-        }
-        //Load input as readonly whose values are overridden in civicrm.settings.php.
-        if (Civi::settings()->getMandatory($setting)) {
-          $props['html_attributes']['readonly'] = TRUE;
-          $setStatus = TRUE;
-        }
-
-        $add = 'add' . $props['quick_form_type'];
-        if ($add == 'addElement') {
-          $this->$add(
-            $props['html_type'],
-            $setting,
-            ts($props['title']),
-            ($options !== NULL) ? $options['values'] : CRM_Utils_Array::value('html_attributes', $props, array()),
-            ($options !== NULL) ? CRM_Utils_Array::value('html_attributes', $props, array()) : NULL
-          );
-        }
-        elseif ($add == 'addSelect') {
-          $this->addElement('select', $setting, ts($props['title']), $options['values'], CRM_Utils_Array::value('html_attributes', $props));
-        }
-        elseif ($add == 'addCheckBox') {
-          $this->addCheckBox($setting, ts($props['title']), $options['values'], NULL, CRM_Utils_Array::value('html_attributes', $props), NULL, NULL, array('&nbsp;&nbsp;'));
-        }
-        elseif ($add == 'addChainSelect') {
-          $this->addChainSelect($setting, array(
-            'label' => ts($props['title']),
-          ));
-        }
-        elseif ($add == 'addMonthDay') {
-          $this->add('date', $setting, ts($props['title']), CRM_Core_SelectValues::date(NULL, 'M d'));
-        }
-        else {
-          $this->$add($setting, ts($props['title']));
-        }
-        // Migrate to using an array as easier in smart...
-        $descriptions[$setting] = ts($props['description']);
-        $this->assign("{$setting}_description", ts($props['description']));
-        if ($setting == 'max_attachments') {
-          //temp hack @todo fix to get from metadata
-          $this->addRule('max_attachments', ts('Value should be a positive number'), 'positiveInteger');
-        }
-        if ($setting == 'maxFileSize') {
-          //temp hack
-          $this->addRule('maxFileSize', ts('Value should be a positive number'), 'positiveInteger');
-        }
+    $this->addFieldsDefinedInSettingsMetadata();
 
-      }
-    }
-    if (!empty($setStatus)) {
+    if ($this->includesReadOnlyFields) {
       CRM_Core_Session::setStatus(ts("Some fields are loaded as 'readonly' as they have been set (overridden) in civicrm.settings.php."), '', 'info', array('expires' => 0));
     }
-    // setting_description should be deprecated - see Mail.tpl for metadata based tpl.
-    $this->assign('setting_descriptions', $descriptions);
-    $this->assign('settings_fields', $settingMetaData);
-  }
-
-  /**
-   * Get default entity.
-   *
-   * @return string
-   */
-  public function getDefaultEntity() {
-    return 'Setting';
   }
 
   /**
@@ -185,6 +120,7 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form {
    * @todo Document what I do.
    *
    * @param array $params
+   * @throws \CRM_Core_Exception
    */
   public function commonProcess(&$params) {
 
@@ -216,20 +152,19 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form {
         unset($params[$name]);
       }
     }
-    $settings = array_intersect_key($params, $this->_settings);
-    $result = civicrm_api('setting', 'create', $settings + array('version' => 3));
-    foreach ($settings as $setting => $settingGroup) {
-      //@todo array_diff this
-      unset($params[$setting]);
+    try {
+      $settings = $this->getSettingsToSetByMetadata($params);
+      civicrm_api3('setting', 'create', $settings);
     }
-    if (!empty($result['error_message'])) {
-      CRM_Core_Session::setStatus($result['error_message'], ts('Save Failed'), 'error');
+    catch (CiviCRM_API3_Exception $e) {
+      CRM_Core_Session::setStatus($e->getMessage(), ts('Save Failed'), 'error');
     }
 
-    //CRM_Core_BAO_ConfigSetting::create($params);
+    $this->filterParamsSetByMetadata($params);
+
     $params = CRM_Core_BAO_ConfigSetting::filterSkipVars($params);
     if (!empty($params)) {
-      CRM_Core_Error::fatal('Unrecognized setting. This may be a config field which has not been properly migrated to a setting. (' . implode(', ', array_keys($params)) . ')');
+      throw new CRM_Core_Exception('Unrecognized setting. This may be a config field which has not been properly migrated to a setting. (' . implode(', ', array_keys($params)) . ')');
     }
 
     CRM_Core_Config::clearDBCache();
@@ -299,17 +234,4 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form {
     ) + $autoSearchFields;
   }
 
-  /**
-   * Get the metadata relating to the settings on the form, ordered by the keys in $this->_settings.
-   *
-   * @return array
-   */
-  protected function getSettingsMetaData() {
-    $allSettingMetaData = civicrm_api3('setting', 'getfields', array());
-    $settingMetaData = array_intersect_key($allSettingMetaData['values'], $this->_settings);
-    // This array_merge re-orders to the key order of $this->_settings.
-    $settingMetaData = array_merge($this->_settings, $settingMetaData);
-    return $settingMetaData;
-  }
-
 }
diff --git a/CRM/Admin/Form/SettingTrait.php b/CRM/Admin/Form/SettingTrait.php
new file mode 100644 (file)
index 0000000..734eccc
--- /dev/null
@@ -0,0 +1,158 @@
+<?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        |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC (c) 2004-2018
+ */
+
+/**
+ * This trait allows us to consolidate Preferences & Settings forms.
+ *
+ * It is intended mostly as part of a refactoring process to get rid of having 2.
+ */
+trait CRM_Admin_Form_SettingTrait {
+
+  /**
+   * @var array
+   */
+  protected $settingsMetadata;
+
+  /**
+   * Get default entity.
+   *
+   * @return string
+   */
+  public function getDefaultEntity() {
+    return 'Setting';
+  }
+
+  /**
+   * Get the metadata relating to the settings on the form, ordered by the keys in $this->_settings.
+   *
+   * @return array
+   */
+  protected function getSettingsMetaData() {
+    if (empty($this->settingsMetadata)) {
+      $allSettingMetaData = civicrm_api3('setting', 'getfields', []);
+      $this->settingsMetadata = array_intersect_key($allSettingMetaData['values'], $this->_settings);
+      // This array_merge re-orders to the key order of $this->_settings.
+      $this->settingsMetadata = array_merge($this->_settings, $this->settingsMetadata);
+    }
+    return $this->settingsMetadata;
+  }
+
+  /**
+   * Get the settings which can be stored based on metadata.
+   *
+   * @param array $params
+   * @return array
+   */
+  protected function getSettingsToSetByMetadata($params) {
+    return array_intersect_key($params, $this->_settings);
+  }
+
+  /**
+   * @param $params
+   */
+  protected function filterParamsSetByMetadata(&$params) {
+    foreach ($this->getSettingsToSetByMetadata($params) as $setting => $settingGroup) {
+      //@todo array_diff this
+      unset($params[$setting]);
+    }
+  }
+
+  /**
+   * Add fields in the metadata to the template.
+   */
+  protected function addFieldsDefinedInSettingsMetadata() {
+    $settingMetaData = $this->getSettingsMetaData();
+    $descriptions = [];
+    foreach ($settingMetaData as $setting => $props) {
+      if (isset($props['quick_form_type'])) {
+        if (isset($props['pseudoconstant'])) {
+          $options = civicrm_api3('Setting', 'getoptions', [
+            'field' => $setting,
+          ]);
+        }
+        else {
+          $options = NULL;
+        }
+        //Load input as readonly whose values are overridden in civicrm.settings.php.
+        if (Civi::settings()->getMandatory($setting)) {
+          $props['html_attributes']['readonly'] = TRUE;
+          $this->includesReadOnlyFields = TRUE;
+        }
+
+        $add = 'add' . $props['quick_form_type'];
+        if ($add == 'addElement') {
+          $this->$add(
+            $props['html_type'],
+            $setting,
+            ts($props['title']),
+            ($options !== NULL) ? $options['values'] : CRM_Utils_Array::value('html_attributes', $props, []),
+            ($options !== NULL) ? CRM_Utils_Array::value('html_attributes', $props, []) : NULL
+          );
+        }
+        elseif ($add == 'addSelect') {
+          $this->addElement('select', $setting, ts($props['title']), $options['values'], CRM_Utils_Array::value('html_attributes', $props));
+        }
+        elseif ($add == 'addCheckBox') {
+          $this->addCheckBox($setting, ts($props['title']), $options['values'], NULL, CRM_Utils_Array::value('html_attributes', $props), NULL, NULL, ['&nbsp;&nbsp;']);
+        }
+        elseif ($add == 'addChainSelect') {
+          $this->addChainSelect($setting, [
+            'label' => ts($props['title']),
+          ]);
+        }
+        elseif ($add == 'addMonthDay') {
+          $this->add('date', $setting, ts($props['title']), CRM_Core_SelectValues::date(NULL, 'M d'));
+        }
+        else {
+          $this->$add($setting, ts($props['title']));
+        }
+        // Migrate to using an array as easier in smart...
+        $descriptions[$setting] = ts($props['description']);
+        $this->assign("{$setting}_description", ts($props['description']));
+        if ($setting == 'max_attachments') {
+          //temp hack @todo fix to get from metadata
+          $this->addRule('max_attachments', ts('Value should be a positive number'), 'positiveInteger');
+        }
+        if ($setting == 'maxFileSize') {
+          //temp hack
+          $this->addRule('maxFileSize', ts('Value should be a positive number'), 'positiveInteger');
+        }
+
+      }
+    }
+    // setting_description should be deprecated - see Mail.tpl for metadata based tpl.
+    $this->assign('setting_descriptions', $descriptions);
+    $this->assign('settings_fields', $settingMetaData);
+  }
+
+}
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..0e4260c3ef8e74fd60e88b9f6949266dee921efb 100644 (file)
@@ -676,7 +676,8 @@ LEFT JOIN civicrm_option_group aog ON aog.name='activity_type'
     $mask = CRM_Core_Action::mask($permissions);
 
     $caseTypes = CRM_Case_PseudoConstant::caseType('name');
-    foreach ($result->fetchAll() as $key => $case) {
+    foreach ($result->fetchAll() as $case) {
+      $key = $case['case_id'];
       $casesList[$key] = array();
       $casesList[$key]['DT_RowId'] = $case['case_id'];
       $casesList[$key]['DT_RowAttr'] = array('data-entity' => 'case', 'data-id' => $case['case_id']);
@@ -909,15 +910,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 +1087,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 +1108,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 +1199,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 +1212,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 bc09f142f0a41f3dca0522b710a7df30985586bb..9301abd0eed93567c00bfe8c17161effa5ff20ab 100644 (file)
@@ -207,7 +207,7 @@ class CRM_Case_Page_AJAX {
       'recordsTotal' => $cases['total'],
     );
     unset($cases['total']);
-    $casesDT['data'] = $cases;
+    $casesDT['data'] = array_values($cases);
 
     CRM_Utils_JSON::output($casesDT);
   }
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..2b0b209fd208cc961e482e806649e8d6b680f8ed 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,
@@ -4205,6 +4208,12 @@ civicrm_relationship.start_date > {$today}
       }
       $sql = "
         CREATE TEMPORARY TABLE {$relationshipTempTable}
+          (
+            `contact_id` int(10) unsigned NOT NULL DEFAULT '0',
+            `contact_id_alt` int(10) unsigned NOT NULL DEFAULT '0',
+            KEY `contact_id` (`contact_id`),
+            KEY `contact_id_alt` (`contact_id_alt`)
+          )
           (SELECT contact_id_b as contact_id, contact_id_a as contact_id_alt, civicrm_relationship.id
             FROM civicrm_relationship
             INNER JOIN  civicrm_contact c ON civicrm_relationship.contact_id_a = c.id
@@ -5965,8 +5974,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 77a15ced8221c800f8a36872a8c640a68d026ae7..3090952dc55180df88f15f148dadfc445470d3cb 100644 (file)
@@ -378,7 +378,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       }
     }
 
-    $amountFields = array('non_deductible_amount', 'fee_amount', 'net_amount');
+    $amountFields = array('non_deductible_amount', 'fee_amount');
     foreach ($amountFields as $amt) {
       if (isset($defaults[$amt])) {
         $defaults[$amt] = CRM_Utils_Money::format($defaults[$amt], NULL, '%a');
@@ -535,7 +535,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
       'invoice_id',
       'non_deductible_amount',
       'fee_amount',
-      'net_amount',
     );
     foreach ($additionalDetailFields as $key) {
       if (!empty($defaults[$key])) {
@@ -883,13 +882,6 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
 
     $softErrors = CRM_Contribute_Form_SoftCredit::formRule($fields, $errors, $self);
 
-    if (!empty($fields['total_amount']) && (!empty($fields['net_amount']) || !empty($fields['fee_amount']))) {
-      $sum = CRM_Utils_Rule::cleanMoney($fields['net_amount']) + CRM_Utils_Rule::cleanMoney($fields['fee_amount']);
-      if (CRM_Utils_Rule::cleanMoney($fields['total_amount']) != $sum) {
-        $errors['total_amount'] = ts('The sum of fee amount and net amount must be equal to total amount');
-      }
-    }
-
     //CRM-16285 - Function to handle validation errors on form, for recurring contribution field.
     CRM_Contribute_BAO_ContributionRecur::validateRecurContribution($fields, $files, $self, $errors);
 
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 fea2e7e4c7df6d3ed5dd65c7b2d4b45f872e2fc8..cda6a54a25d979e465b208c56da29c19cd27e10b 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/CustomField.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:7f096c92af68ef9564675e3d708fbbe1)
+ * (GenCodeChecksum:73d7ccebba6055cae4fa0c9d797025c4)
  */
 
 /**
@@ -256,6 +256,7 @@ class CRM_Core_DAO_CustomField extends CRM_Core_DAO {
     if (!isset(Civi::$statics[__CLASS__]['links'])) {
       Civi::$statics[__CLASS__]['links'] = static ::createReferenceColumns(__CLASS__);
       Civi::$statics[__CLASS__]['links'][] = new CRM_Core_Reference_Basic(self::getTableName(), 'custom_group_id', 'civicrm_custom_group', 'id');
+      Civi::$statics[__CLASS__]['links'][] = new CRM_Core_Reference_Basic(self::getTableName(), 'option_group_id', 'civicrm_option_group', 'id');
       CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'links_callback', Civi::$statics[__CLASS__]['links']);
     }
     return Civi::$statics[__CLASS__]['links'];
@@ -598,6 +599,7 @@ class CRM_Core_DAO_CustomField extends CRM_Core_DAO {
           'entity' => 'CustomField',
           'bao' => 'CRM_Core_BAO_CustomField',
           'localizable' => 0,
+          'FKClassName' => 'CRM_Core_DAO_OptionGroup',
           'pseudoconstant' => [
             'table' => 'civicrm_option_group',
             'keyColumn' => 'id',
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 b560e442ed366c1f5a8e9d53b71d1d9a25a44130..f0945794cce5aeefd6b75491828b22e62af3c1b0 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Core/UFField.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:4777c5b97760d4bd4b7138468d18ded5)
+ * (GenCodeChecksum:20b17223454fb0b4a8e2801193ff253c)
  */
 
 /**
@@ -363,6 +363,10 @@ class CRM_Core_DAO_UFField extends CRM_Core_DAO {
           'entity' => 'UFField',
           'bao' => 'CRM_Core_BAO_UFField',
           'localizable' => 0,
+          'pseudoconstant' => [
+            'optionGroupName' => 'phone_type',
+            'optionEditPath' => 'civicrm/admin/options/phone_type',
+          ]
         ],
         'website_type_id' => [
           'name' => 'website_type_id',
@@ -373,6 +377,10 @@ class CRM_Core_DAO_UFField extends CRM_Core_DAO {
           'entity' => 'UFField',
           'bao' => 'CRM_Core_BAO_UFField',
           'localizable' => 0,
+          'pseudoconstant' => [
+            'optionGroupName' => 'website_type',
+            'optionEditPath' => 'civicrm/admin/options/website_type',
+          ]
         ],
         'label' => [
           'name' => 'label',
index 70e560494a7a23b1cf1d056d20073c3c42f9c2d5..613bcf227deeb3854f3d1edf4f214b2eec23a4fe 100644 (file)
@@ -2069,7 +2069,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
       $validUser = CRM_Contact_BAO_Contact_Utils::validChecksum($tempID, $userChecksum);
       if ($validUser) {
         CRM_Core_Resources::singleton()->addVars('coreForm', array('contact_id' => (int) $tempID));
-        CRM_Core_Resources::singleton()->addVars('coreForm', array('checksum' => (int) $tempID));
+        CRM_Core_Resources::singleton()->addVars('coreForm', array('checksum' => $userChecksum));
         return $tempID;
       }
     }
diff --git a/CRM/Core/I18n/SchemaStructure_5_4_alpha1.php b/CRM/Core/I18n/SchemaStructure_5_4_alpha1.php
new file mode 100644 (file)
index 0000000..5c88141
--- /dev/null
@@ -0,0 +1,714 @@
+<?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        |
++--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC (c) 2004-2018
+ *
+ * Generated from schema_structure.tpl
+ * DO NOT EDIT.  Generated by CRM_Core_CodeGen
+ */
+class CRM_Core_I18n_SchemaStructure_5_4_alpha1 {
+
+  /**
+   * Get translatable columns.
+   *
+   * @return array
+   *   A table-indexed array of translatable columns.
+   */
+  public static function columns() {
+    static $result = NULL;
+    if (!$result) {
+      $result = [
+        'civicrm_location_type' => [
+          'display_name' => "varchar(64)",
+        ],
+        'civicrm_option_group' => [
+          'title' => "varchar(255)",
+          'description' => "varchar(255)",
+        ],
+        'civicrm_relationship_type' => [
+          'label_a_b' => "varchar(64)",
+          'label_b_a' => "varchar(64)",
+          'description' => "varchar(255)",
+        ],
+        'civicrm_contact_type' => [
+          'label' => "varchar(64)",
+          'description' => "text",
+        ],
+        'civicrm_batch' => [
+          'title' => "varchar(255)",
+          'description' => "text",
+        ],
+        'civicrm_premiums' => [
+          'premiums_intro_title' => "varchar(255)",
+          'premiums_intro_text' => "text",
+          'premiums_nothankyou_label' => "varchar(255)",
+        ],
+        'civicrm_membership_status' => [
+          'label' => "varchar(128)",
+        ],
+        'civicrm_survey' => [
+          'title' => "varchar(255)",
+          'instructions' => "text",
+          'thankyou_title' => "varchar(255)",
+          'thankyou_text' => "text",
+        ],
+        'civicrm_participant_status_type' => [
+          'label' => "varchar(255)",
+        ],
+        'civicrm_case_type' => [
+          'title' => "varchar(64)",
+          'description' => "varchar(255)",
+        ],
+        'civicrm_tell_friend' => [
+          'title' => "varchar(255)",
+          'intro' => "text",
+          'suggested_message' => "text",
+          'thankyou_title' => "varchar(255)",
+          'thankyou_text' => "text",
+        ],
+        'civicrm_custom_group' => [
+          'title' => "varchar(64)",
+          'help_pre' => "text",
+          'help_post' => "text",
+        ],
+        'civicrm_custom_field' => [
+          'label' => "varchar(255)",
+          'help_pre' => "text",
+          'help_post' => "text",
+        ],
+        'civicrm_option_value' => [
+          'label' => "varchar(512)",
+          'description' => "text",
+        ],
+        'civicrm_group' => [
+          'title' => "varchar(64)",
+        ],
+        'civicrm_contribution_page' => [
+          'title' => "varchar(255)",
+          'intro_text' => "text",
+          'pay_later_text' => "text",
+          'pay_later_receipt' => "text",
+          'initial_amount_label' => "varchar(255)",
+          'initial_amount_help_text' => "text",
+          'thankyou_title' => "varchar(255)",
+          'thankyou_text' => "text",
+          'thankyou_footer' => "text",
+          'receipt_from_name' => "varchar(255)",
+          'receipt_text' => "text",
+          'footer_text' => "text",
+        ],
+        'civicrm_product' => [
+          'name' => "varchar(255)",
+          'description' => "text",
+          'options' => "text",
+        ],
+        'civicrm_membership_type' => [
+          'name' => "varchar(128)",
+          'description' => "varchar(255)",
+        ],
+        'civicrm_membership_block' => [
+          'new_title' => "varchar(255)",
+          'new_text' => "text",
+          'renewal_title' => "varchar(255)",
+          'renewal_text' => "text",
+        ],
+        'civicrm_price_set' => [
+          'title' => "varchar(255)",
+          'help_pre' => "text",
+          'help_post' => "text",
+        ],
+        'civicrm_dashboard' => [
+          'label' => "varchar(255)",
+        ],
+        'civicrm_uf_group' => [
+          'title' => "varchar(64)",
+          'frontend_title' => "varchar(64)",
+          'help_pre' => "text",
+          'help_post' => "text",
+          'cancel_button_text' => "varchar(64)",
+          'submit_button_text' => "varchar(64)",
+        ],
+        'civicrm_uf_field' => [
+          'help_post' => "text",
+          'help_pre' => "text",
+          'label' => "varchar(255)",
+        ],
+        'civicrm_price_field' => [
+          'label' => "varchar(255)",
+          'help_pre' => "text",
+          'help_post' => "text",
+        ],
+        'civicrm_price_field_value' => [
+          'label' => "varchar(255)",
+          'description' => "text",
+          'help_pre' => "text",
+          'help_post' => "text",
+        ],
+        'civicrm_pcp_block' => [
+          'link_text' => "varchar(255)",
+        ],
+        'civicrm_event' => [
+          'title' => "varchar(255)",
+          'summary' => "text",
+          'description' => "text",
+          'registration_link_text' => "varchar(255)",
+          'event_full_text' => "text",
+          'fee_label' => "varchar(255)",
+          'intro_text' => "text",
+          'footer_text' => "text",
+          'confirm_title' => "varchar(255)",
+          'confirm_text' => "text",
+          'confirm_footer_text' => "text",
+          'confirm_email_text' => "text",
+          'confirm_from_name' => "varchar(255)",
+          'thankyou_title' => "varchar(255)",
+          'thankyou_text' => "text",
+          'thankyou_footer_text' => "text",
+          'pay_later_text' => "text",
+          'pay_later_receipt' => "text",
+          'initial_amount_label' => "varchar(255)",
+          'initial_amount_help_text' => "text",
+          'waitlist_text' => "text",
+          'approval_req_text' => "text",
+          'template_title' => "varchar(255)",
+        ],
+      ];
+    }
+    return $result;
+  }
+
+  /**
+   * Get a table indexed array of the indices for translatable fields.
+   *
+   * @return array
+   *   Indices for translatable fields.
+   */
+  public static function indices() {
+    static $result = NULL;
+    if (!$result) {
+      $result = [
+        'civicrm_custom_group' => [
+          'UI_title_extends' => [
+            'name' => 'UI_title_extends',
+            'field' => [
+              'title',
+              'extends',
+            ],
+            'unique' => 1,
+          ],
+        ],
+        'civicrm_custom_field' => [
+          'UI_label_custom_group_id' => [
+            'name' => 'UI_label_custom_group_id',
+            'field' => [
+              'label',
+              'custom_group_id',
+            ],
+            'unique' => 1,
+          ],
+        ],
+        'civicrm_group' => [
+          'UI_title' => [
+            'name' => 'UI_title',
+            'field' => [
+              'title',
+            ],
+            'unique' => 1,
+          ],
+        ],
+      ];
+    }
+    return $result;
+  }
+
+  /**
+   * Get tables with translatable fields.
+   *
+   * @return array
+   *   Array of names of tables with fields that can be translated.
+   */
+  public static function tables() {
+    static $result = NULL;
+    if (!$result) {
+      $result = array_keys(self::columns());
+    }
+    return $result;
+  }
+
+  /**
+   * Get a list of widgets for editing translatable fields.
+   *
+   * @return array
+   *   Array of the widgets for editing translatable fields.
+   */
+  public static function widgets() {
+    static $result = NULL;
+    if (!$result) {
+      $result = [
+        'civicrm_location_type' => [
+          'display_name' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_option_group' => [
+          'title' => [
+            'type' => "Text",
+          ],
+          'description' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_relationship_type' => [
+          'label_a_b' => [
+            'type' => "Text",
+          ],
+          'label_b_a' => [
+            'type' => "Text",
+          ],
+          'description' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_contact_type' => [
+          'label' => [
+            'type' => "Text",
+          ],
+          'description' => [
+            'type' => "TextArea",
+            'rows' => "2",
+            'cols' => "60",
+          ],
+        ],
+        'civicrm_batch' => [
+          'title' => [
+            'type' => "Text",
+          ],
+          'description' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+        ],
+        'civicrm_premiums' => [
+          'premiums_intro_title' => [
+            'type' => "Text",
+          ],
+          'premiums_intro_text' => [
+            'type' => "Text",
+          ],
+          'premiums_nothankyou_label' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_membership_status' => [
+          'label' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_survey' => [
+          'title' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'instructions' => [
+            'type' => "TextArea",
+            'rows' => "20",
+            'cols' => "80",
+          ],
+          'thankyou_title' => [
+            'type' => "Text",
+          ],
+          'thankyou_text' => [
+            'type' => "TextArea",
+            'rows' => "8",
+            'cols' => "60",
+          ],
+        ],
+        'civicrm_participant_status_type' => [
+          'label' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_case_type' => [
+          'title' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'description' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_tell_friend' => [
+          'title' => [
+            'type' => "Text",
+          ],
+          'intro' => [
+            'type' => "Text",
+          ],
+          'suggested_message' => [
+            'type' => "Text",
+          ],
+          'thankyou_title' => [
+            'type' => "Text",
+          ],
+          'thankyou_text' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_custom_group' => [
+          'title' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'help_pre' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+          'help_post' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+        ],
+        'civicrm_custom_field' => [
+          'label' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'help_pre' => [
+            'type' => "Text",
+          ],
+          'help_post' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_option_value' => [
+          'label' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'description' => [
+            'type' => "TextArea",
+            'rows' => "8",
+            'cols' => "60",
+          ],
+        ],
+        'civicrm_group' => [
+          'title' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_contribution_page' => [
+          'title' => [
+            'type' => "Text",
+          ],
+          'intro_text' => [
+            'type' => "RichTextEditor",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'pay_later_text' => [
+            'type' => "Text",
+          ],
+          'pay_later_receipt' => [
+            'type' => "Text",
+          ],
+          'initial_amount_label' => [
+            'type' => "Text",
+          ],
+          'initial_amount_help_text' => [
+            'type' => "Text",
+          ],
+          'thankyou_title' => [
+            'type' => "Text",
+          ],
+          'thankyou_text' => [
+            'type' => "RichTextEditor",
+            'rows' => "8",
+            'cols' => "60",
+          ],
+          'thankyou_footer' => [
+            'type' => "RichTextEditor",
+            'rows' => "8",
+            'cols' => "60",
+          ],
+          'receipt_from_name' => [
+            'type' => "Text",
+          ],
+          'receipt_text' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'footer_text' => [
+            'type' => "RichTextEditor",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+        ],
+        'civicrm_product' => [
+          'name' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'description' => [
+            'type' => "Text",
+          ],
+          'options' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_membership_type' => [
+          'name' => [
+            'type' => "Text",
+            'label' => "Name",
+          ],
+          'description' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+            'label' => "Description",
+          ],
+        ],
+        'civicrm_membership_block' => [
+          'new_title' => [
+            'type' => "Text",
+          ],
+          'new_text' => [
+            'type' => "Text",
+          ],
+          'renewal_title' => [
+            'type' => "Text",
+          ],
+          'renewal_text' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_price_set' => [
+          'title' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'help_pre' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+          'help_post' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+        ],
+        'civicrm_dashboard' => [
+          'label' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_uf_group' => [
+          'title' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'frontend_title' => [
+            'type' => "Text",
+          ],
+          'help_pre' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+          'help_post' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+          'cancel_button_text' => [
+            'type' => "Text",
+          ],
+          'submit_button_text' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_uf_field' => [
+          'help_post' => [
+            'type' => "Text",
+          ],
+          'help_pre' => [
+            'type' => "Text",
+          ],
+          'label' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+        ],
+        'civicrm_price_field' => [
+          'label' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'help_pre' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+          'help_post' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "80",
+          ],
+        ],
+        'civicrm_price_field_value' => [
+          'label' => [
+            'type' => "Text",
+          ],
+          'description' => [
+            'type' => "TextArea",
+            'rows' => "2",
+            'cols' => "60",
+          ],
+          'help_pre' => [
+            'type' => "TextArea",
+            'rows' => "2",
+            'cols' => "60",
+          ],
+          'help_post' => [
+            'type' => "TextArea",
+            'rows' => "2",
+            'cols' => "60",
+          ],
+        ],
+        'civicrm_pcp_block' => [
+          'link_text' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_event' => [
+          'title' => [
+            'type' => "Text",
+          ],
+          'summary' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "60",
+          ],
+          'description' => [
+            'type' => "TextArea",
+            'rows' => "8",
+            'cols' => "60",
+          ],
+          'registration_link_text' => [
+            'type' => "Text",
+          ],
+          'event_full_text' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "60",
+          ],
+          'fee_label' => [
+            'type' => "Text",
+          ],
+          'intro_text' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'footer_text' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'confirm_title' => [
+            'type' => "Text",
+          ],
+          'confirm_text' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'confirm_footer_text' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'confirm_email_text' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "50",
+          ],
+          'confirm_from_name' => [
+            'type' => "Text",
+          ],
+          'thankyou_title' => [
+            'type' => "Text",
+          ],
+          'thankyou_text' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'thankyou_footer_text' => [
+            'type' => "TextArea",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'pay_later_text' => [
+            'type' => "Text",
+          ],
+          'pay_later_receipt' => [
+            'type' => "Text",
+          ],
+          'initial_amount_label' => [
+            'type' => "Text",
+          ],
+          'initial_amount_help_text' => [
+            'type' => "Text",
+          ],
+          'waitlist_text' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "60",
+          ],
+          'approval_req_text' => [
+            'type' => "TextArea",
+            'rows' => "4",
+            'cols' => "60",
+          ],
+          'template_title' => [
+            'type' => "Text",
+          ],
+        ],
+      ];
+    }
+    return $result;
+  }
+
+}
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..2e6c5e0bd70e2f9cfa7833320cd7131dd54ea7e9 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);
@@ -1826,7 +1826,10 @@ WHERE  id = $cfID
         $title = $groupTitles = array();
         foreach ($additionalIDs as $pId => $cId) {
           //get the params submitted by participant.
-          $participantParams = CRM_Utils_Array::value($pId, $values['params'], array());
+          $participantParams = NULL;
+          if (isset($values['params'])) {
+            $participantParams = CRM_Utils_Array::value($pId, $values['params'], array());
+          }
 
           list($profilePre, $groupTitles) = self::buildCustomDisplay($preProfileID,
             'additionalCustomPre',
@@ -2064,9 +2067,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 +2086,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 +2109,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);
index 3f53f37e8446e9656c3aad68f2c95a92f64d2567..32d5aebc9015ddf8b83ba8fbb1e994ff0f52b556 100644 (file)
@@ -81,7 +81,13 @@ class CRM_Financial_Form_PaymentEdit extends CRM_Core_Form {
    * @return array
    */
   public function setDefaultValues() {
-    return $this->_values;
+    $defaults = $this->_values;
+    // Format money fields - localize for display
+    $moneyFields = ['total_amount', 'fee_amount', 'net_amount'];
+    foreach ($moneyFields as $field) {
+      $defaults[$field] = CRM_Utils_Money::formatLocaleNumericRoundedForDefaultCurrency($this->_values[$field]);
+    }
+    return $defaults;
   }
 
   /**
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 9b2a9c9f765540efcb5a4c9a63e36c8eb216eadc..459384ca45346caca661dbe292c34e5c1cdc1255 100644 (file)
@@ -95,6 +95,7 @@ class CRM_Friend_Form extends CRM_Core_Form {
       if ($pcomponent == 'event') {
         $this->_entityTable = 'civicrm_event';
         $isShare = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $this->_entityId, 'is_share');
+        $this->_title = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $this->_entityId, 'title');
       }
       else {
         $isShare = CRM_Utils_Array::value('is_share', $values);
index a24906ef91b1e79ca374af2d5c63847170126e52..c11b32e136bb9560586207bb1a271f4129b80869 100644 (file)
@@ -331,7 +331,7 @@ AND    (TABLE_NAME LIKE 'log_civicrm_%' $nonStandardTableNameString )
         $updateLogConn = TRUE;
       }
       if (!empty($alterSql)) {
-        CRM_Core_DAO::executeQuery("ALTER TABLE {$this->db}.{$logTable} " . implode(', ', $alterSql));
+        CRM_Core_DAO::executeQuery("ALTER TABLE {$this->db}.{$logTable} " . implode(', ', $alterSql), [], TRUE, NULL, FALSE, FALSE);
       }
     }
     if ($updateLogConn) {
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 212284f00ee82f09cc36837396c9a07b98d16c7b..dd4ef5bc013ed71cd92dfe30153d805129e1b3f5 100644 (file)
@@ -282,8 +282,10 @@ class CRM_Mailing_BAO_Mailing extends CRM_Mailing_DAO_Mailing {
     // Get recipients selected in prior mailings
     if (!empty($priorMailingIDs['Include'])) {
       CRM_Utils_SQL_Select::from('civicrm_mailing_recipients')
-        ->select("contact_id, $entityColumn")
+        ->select("DISTINCT civicrm_mailing_recipients.contact_id, $entityColumn")
+        ->join('temp', " LEFT JOIN $excludeTempTablename temp ON civicrm_mailing_recipients.contact_id = temp.contact_id ")
         ->where('mailing_id IN (#mailings)')
+        ->where('temp.contact_id IS NULL')
         ->param('#mailings', $priorMailingIDs['Include'])
         ->insertIgnoreInto($includedTempTablename, array('contact_id', $entityColumn))
         ->execute();
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..913654e2b8140fd9c2d189a0bd9553e6eb241299 100644 (file)
@@ -91,6 +91,29 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment {
     return 'Membership';
   }
 
+  /**
+   * @var array
+   */
+  protected $statusMessage = [];
+
+  /**
+   * Add to the status message.
+   *
+   * @param $message
+   */
+  protected function addStatusMessage($message) {
+    $this->statusMessage[] = $message;
+  }
+
+  /**
+   * Get the status message.
+   *
+   * @return string
+   */
+  protected function getStatusMessage() {
+    return implode(' ', $this->statusMessage);
+  }
+
   /**
    * Values submitted to the form, processed along the way.
    *
@@ -189,6 +212,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..19766da30a5e129cc718d4574a47d0d8c22db726 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);
       }
@@ -1838,11 +1825,10 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
    *
    * @param CRM_Member_BAO_Membership $membership
    * @param string $endDate
-   * @param bool $receiptSend
    *
    * @return string
    */
-  protected function getStatusMessageForUpdate($membership, $endDate, $receiptSend) {
+  protected function getStatusMessageForUpdate($membership, $endDate) {
     // End date can be modified by hooks, so if end date is set then use it.
     $endDate = ($membership->end_date) ? $membership->end_date : $endDate;
 
@@ -1851,10 +1837,6 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       $endDate = CRM_Utils_Date::customFormat($endDate);
       $statusMsg .= ' ' . ts('The membership End Date is %1.', array(1 => $endDate));
     }
-
-    if ($receiptSend) {
-      $statusMsg .= ' ' . ts('A confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail));
-    }
     return $statusMsg;
   }
 
@@ -1862,17 +1844,15 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
    * Get status message for create action.
    *
    * @param string $endDate
-   * @param bool $receiptSend
    * @param array $membershipTypes
    * @param array $createdMemberships
    * @param bool $isRecur
    * @param array $calcDates
-   * @param bool $mailSent
    *
    * @return array|string
    */
-  protected function getStatusMessageForCreate($endDate, $receiptSend, $membershipTypes, $createdMemberships,
-                                               $isRecur, $calcDates, $mailSent) {
+  protected function getStatusMessageForCreate($endDate, $membershipTypes, $createdMemberships,
+                                               $isRecur, $calcDates) {
     // FIX ME: fix status messages
 
     $statusMsg = array();
@@ -1896,9 +1876,6 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
       }
     }
     $statusMsg = implode('<br/>', $statusMsg);
-    if ($receiptSend && !empty($mailSent)) {
-      $statusMsg .= ' ' . ts('A membership confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail));
-    }
     return $statusMsg;
   }
 
@@ -1910,19 +1887,21 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
    * @param $createdMemberships
    * @param $isRecur
    * @param $calcDates
-   * @param $mailSend
+   * @param $mailSent
    */
-  protected function setStatusMessage($membership, $endDate, $receiptSend, $membershipTypes, $createdMemberships, $isRecur, $calcDates, $mailSend) {
-    $statusMsg = '';
+  protected function setStatusMessage($membership, $endDate, $receiptSend, $membershipTypes, $createdMemberships, $isRecur, $calcDates, $mailSent) {
     if (($this->_action & CRM_Core_Action::UPDATE)) {
-      $statusMsg = $this->getStatusMessageForUpdate($membership, $endDate, $receiptSend);
+      $this->addStatusMessage($this->getStatusMessageForUpdate($membership, $endDate));
     }
     elseif (($this->_action & CRM_Core_Action::ADD)) {
-      $statusMsg = $this->getStatusMessageForCreate($endDate, $receiptSend, $membershipTypes, $createdMemberships,
-        $isRecur, $calcDates, $mailSend);
+      $this->addStatusMessage($this->getStatusMessageForCreate($endDate, $membershipTypes, $createdMemberships,
+        $isRecur, $calcDates));
+    }
+    if ($receiptSend && $mailSent) {
+      $this->addStatusMessage(ts('A membership confirmation and receipt has been sent to %1.', array(1 => $this->_contributorEmail)));
     }
 
-    CRM_Core_Session::setStatus($statusMsg, ts('Complete'), 'success');
+    CRM_Core_Session::setStatus($this->getStatusMessage(), ts('Complete'), 'success');
     //CRM-15187
     // display message when membership type is changed
     if (($this->_action & CRM_Core_Action::UPDATE) && $this->_id && !in_array($this->_memType, $this->_memTypeSelected)) {
@@ -1945,4 +1924,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 722c35f32364f3895c42aa49cbe297b994db1552..76861112042e4181ed98c55f7e6162dfdc6a9c11 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'])) {
@@ -4937,7 +4911,7 @@ LEFT JOIN civicrm_contact {$field['alias']} ON {$field['alias']}.id = {$this->_a
    * @param array $field
    * @param string $table
    */
-  private function setEntityRefDefaults(&$field, $table) {
+  public function setEntityRefDefaults(&$field, $table) {
     $field['attributes'] = $field['attributes'] ? $field['attributes'] : array();
     $field['attributes'] += array(
       'entity' => CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getClassForTable($table)),
@@ -5794,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..8c86c2b9a027389d97ca6df35de1280a0e151025 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();
   }
@@ -373,7 +360,7 @@ FROM civicrm_contact {$this->_aliases['civicrm_contact']}
 
       // Handle ID to label conversion for contact fields
       $entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'contact/currentEmployer', 'View Contact Detail') ? TRUE : $entryFound;
-
+      $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, NULL, NULL) ? TRUE : $entryFound;
       // display birthday in the configured custom format
       if (array_key_exists('civicrm_contact_birth_date', $row)) {
         $birthDate = $row['civicrm_contact_birth_date'];
@@ -396,21 +383,6 @@ FROM civicrm_contact {$this->_aliases['civicrm_contact']}
         $entryFound = TRUE;
       }
 
-      // handle country
-      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_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;
-      }
-
       // skip looking further in rows, if first row itself doesn't
       // have the column we need
       if (!$entryFound) {
index 238bffa09b8cc7af6039c23b45d7335ce0571d81..7658ca71ff24cc150ee64be0d6074465be820a99 100644 (file)
@@ -840,12 +840,7 @@ class CRM_Report_Form_Contact_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;
-      }
+      $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, NULL, NULL) ? TRUE : $entryFound;
 
       // skip looking further in rows, if first row itself doesn't
       // have the column we need
index 0e34078cdfb1f19f716de7d9cc01fef65e05ea8f..7b975912065859dedeb2aff4c96fbd3b54528c7c 100644 (file)
@@ -720,23 +720,7 @@ class CRM_Report_Form_Contact_Relationship extends CRM_Report_Form {
         $entryFound = TRUE;
       }
 
-      // Handle country
-      // @todo use alterDisplayAddressFields function
-      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;
-      }
-
-      // Handle state/province
-      // @todo use alterDisplayAddressFields function
-      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;
-      }
+      $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, NULL, NULL) ? TRUE : $entryFound;
 
       // Handle contact name A
       // @todo refactor into separate function
index 2369127d1aedaa8c5b40105a5ff382ee04e573f3..46411ad870679b4a98db46298b3a7e8afd5976a2 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..0c44427fe6c03eb1676d53164bd6e433fdf53c4b 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,
@@ -125,13 +125,21 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
    */
   public function checkPhpEcrypt() {
     $messages = array();
+    $mailingBackend = Civi::settings()->get('mailing_backend');
+    if (!is_array($mailingBackend)
+      || !isset($mailingBackend['outBound_option'])
+      || $mailingBackend['outBound_option'] != CRM_Mailing_Config::OUTBOUND_OPTION_SMTP
+      || !CRM_Utils_Array::value('smtpAuth', $mailingBackend)
+    ) {
+      return $messages;
+    }
+
     $test_pass = 'iAmARandomString';
     $encrypted_test_pass = CRM_Utils_Crypt::encrypt($test_pass);
     if ($encrypted_test_pass == base64_encode($test_pass)) {
       $messages[] = new CRM_Utils_Check_Message(
         __FUNCTION__,
-        ts('Your PHP does not include the recommended encryption functions. Some passwords will not be stored encrypted, and if you have recently upgraded from a PHP that does include these functions, your encrypted passwords will not be decrypted correctly. If you are using PHP 7.0 or earlier, you probably want to include the "%1" extension.',
-          array('1' => 'mcrypt')
+        ts('Your PHP does not include the mcrypt encryption functions. Your SMTP password will not be stored encrypted, and if you have recently upgraded from a PHP that stored it with encryption, it will not be decrypted correctly.'
         ),
         ts('PHP Missing Extension "mcrypt"'),
         \Psr\Log\LogLevel::WARNING,
@@ -560,26 +568,24 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
     }
     elseif (!is_writable($basedir)) {
       $messages[] = new CRM_Utils_Check_Message(
-        __FUNCTION__,
+        __FUNCTION__ . 'Writable',
         ts('Your extensions directory (%1) is read-only. If you would like to perform downloads or upgrades, then change the file permissions.',
           array(1 => $basedir)),
         ts('Read-Only Extensions'),
         \Psr\Log\LogLevel::WARNING,
         'fa-plug'
       );
-      return $messages;
     }
 
     if (empty($extensionSystem->getDefaultContainer()->baseUrl)) {
       $messages[] = new CRM_Utils_Check_Message(
-        __FUNCTION__,
+        __FUNCTION__ . 'URL',
         ts('The extensions URL is not properly set. Please go to the <a href="%1">URL setting page</a> and correct it.',
           array(1 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1'))),
         ts('Extensions url missing'),
         \Psr\Log\LogLevel::ERROR,
         'fa-plug'
       );
-      return $messages;
     }
 
     if (!$extensionSystem->getBrowser()->isEnabled()) {
@@ -680,7 +686,7 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
 
     if ($errors) {
       $messages[] = new CRM_Utils_Check_Message(
-        __FUNCTION__,
+        __FUNCTION__ . 'Error',
         '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>',
         ts('Extension Error'),
         \Psr\Log\LogLevel::ERROR,
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 0f6a613feb8c35815e0a63bea435fecc864a806b..97d765de033bfa8409a8ad7ab732d734644742e0 100644 (file)
@@ -184,8 +184,10 @@ class CRM_Utils_PDF_Label extends TCPDF {
    * @param string $text
    */
   public function generateLabel($text) {
+    // paddingLeft is used for both left & right padding so needs to be
+    // subtracted twice from width to get the width that is available for text
     $args = array(
-      'w' => $this->width,
+      'w' => $this->width - 2 * $this->paddingLeft,
       'h' => 0,
       'txt' => $text,
       'border' => 0,
index f3baf09271927f078747cb57930c96411460b359..0fadf5de6fe87c18930ab5d7d1a6223e6ee59bed 100644 (file)
@@ -116,7 +116,7 @@ class CRM_Utils_Recent {
 
     // make sure item is not already present in list
     for ($i = 0; $i < count(self::$_recent); $i++) {
-      if (self::$_recent[$i]['type'] === $type && self::$_recent[$i]['id'] === $id) {
+      if (self::$_recent[$i]['type'] === $type && self::$_recent[$i]['id'] == $id) {
         // delete item from array
         array_splice(self::$_recent, $i, 1);
         break;
@@ -174,6 +174,7 @@ class CRM_Utils_Recent {
       }
     }
 
+    CRM_Utils_Hook::recent(self::$_recent);
     $session = CRM_Core_Session::singleton();
     $session->set(self::STORE_NAME, self::$_recent);
   }
@@ -200,15 +201,17 @@ class CRM_Utils_Recent {
       self::$_recent[] = $tempRecent[$i];
     }
 
+    CRM_Utils_Hook::recent(self::$_recent);
     $session = CRM_Core_Session::singleton();
     $session->set(self::STORE_NAME, self::$_recent);
   }
 
   /**
    * Check if a provider is allowed to add stuff.
-   * If correspondig setting is empty, all are allowed
+   * If corresponding setting is empty, all are allowed
    *
    * @param string $providerName
+   * @return bool
    */
   public static function isProviderEnabled($providerName) {
 
@@ -230,6 +233,8 @@ class CRM_Utils_Recent {
 
   /**
    * Gets the list of available providers to civi's recent items stack
+   *
+   * @return array
    */
   public static function getProviders() {
     $providers = array(
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 c2b692462e53dc8388eca0cac11e66ce74833e20..5e582dc0566a0d5cb06576db3bf397c66cbf1a4f 100644 (file)
@@ -21,6 +21,7 @@
           });
         };
         scope.doSend = function doSend(recipient) {
+          recipient = JSON.parse(JSON.stringify(recipient).replace(/\,\s/g, ','));
           scope.$eval(attr.onSend, {
             preview: {recipient: recipient}
           });
index e50a0a0f7a7a5dca40039ea4be5026775f8b97cf..45c206373230e3a0002834b5ec657f8b7a4d0ed2 100644 (file)
       // @param mailing Object (per APIv3)
       // @return Promise an object with "subject", "body_text", "body_html"
       preview: function preview(mailing) {
+        return this.getPreviewContent(qApi, mailing);
+      },
+
+      // @param backend
+      // @param mailing Object (per APIv3)
+      // @return preview content
+      getPreviewContent: function getPreviewContent(backend, mailing) {
         if (CRM.crmMailing.workflowEnabled && !CRM.checkPerm('create mailings') && !CRM.checkPerm('access CiviMail')) {
-          return qApi('Mailing', 'preview', {id: mailing.id}).then(function(result) {
+          return backend('Mailing', 'preview', {id: mailing.id}).then(function(result) {
             return result.values;
           });
         }
         else {
-          // Protect against races in saving and previewing by chaining create+preview.
-          var params = angular.extend({}, mailing, mailing.recipients, {
-            id: mailing.id,
-            'api.Mailing.preview': {
-              id: '$value.id'
-            }
-          });
-          delete params.scheduled_date;
-          delete params.recipients; // the content was merged in
-          params._skip_evil_bao_auto_recipients_ = 1; // skip recipient rebuild on mail preview
-          return qApi('Mailing', 'create', params).then(function(result) {
-            mailing.modified_date = result.values[result.id].modified_date;
+          var params = angular.extend({}, mailing);
+          delete params.id;
+          return backend('Mailing', 'preview', params).then(function(result) {
             // changes rolled back, so we don't care about updating mailing
-            return result.values[result.id]['api.Mailing.preview'].values;
+            return result.values;
           });
         }
       },
         };
         var result = null;
         var p = crmMailingMgr
-          .preview(mailing)
+          .getPreviewContent(CRM.api3, mailing)
           .then(function (content) {
             var options = CRM.utils.adjustDialogDefaults({
               autoOpen: false,
index 7aa2bdf88f3bb90b1e70d89f2c5ab2e1123fc463..87d13b534762493e2cc4ace373aec7a98c87af20 100644 (file)
@@ -202,7 +202,7 @@ function _civicrm_api3_case_get_spec(&$params) {
   );
   $params['tag_id'] = array(
     'title' => 'Tags',
-    'description' => 'Find activities with specified tags.',
+    'description' => 'Find cases with specified tags.',
     'type' => 1,
     'FKClassName' => 'CRM_Core_DAO_Tag',
     'FKApiName' => 'Tag',
index 39df78ef10262030f8e2f8ced7b353e1dea23bf2..b36910159176f161ff590119472b86b8bdf906a4 100644 (file)
@@ -547,21 +547,22 @@ function civicrm_api3_mailing_event_open($params) {
  * @throws \API_Exception
  */
 function civicrm_api3_mailing_preview($params) {
-  civicrm_api3_verify_mandatory($params,
-    'CRM_Mailing_DAO_Mailing',
-    array('id'),
-    FALSE
-  );
-
   $fromEmail = NULL;
   if (!empty($params['from_email'])) {
     $fromEmail = $params['from_email'];
   }
 
-  $session = CRM_Core_Session::singleton();
   $mailing = new CRM_Mailing_BAO_Mailing();
-  $mailing->id = $params['id'];
-  $mailing->find(TRUE);
+  $mailingID = CRM_Utils_Array::value('id', $params);
+  if ($mailingID) {
+    $mailing->id = $mailingID;
+    $mailing->find(TRUE);
+  }
+  else {
+    $mailing->copyValues($params);
+  }
+
+  $session = CRM_Core_Session::singleton();
 
   CRM_Mailing_BAO_Mailing::tokenReplace($mailing);
 
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 a89e60458bc8eaaa5fa9c89f714df2eaeebbd787..a4d85b07b68cf332fd9cb51fb548eea1e09fc428 100644 (file)
@@ -384,6 +384,10 @@ input.crm-form-entityref {
   text-align: right;
 }
 
+.crm-container .crm-section .label label{
+  white-space: normal;
+}
+
 .crm-container .label-left .label {
   text-align: left;
 }
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..4cb7aaa69b367877b1a8854dbcc898a186b9f0ca 100644 (file)
@@ -35,7 +35,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 {
@@ -52,12 +59,12 @@ div#crm-contact-thumbnail {
   border-bottom-left-radius: 1em;
 }
 
-#crm-container .crm-inline-edit.add-new .crm-edit-help {
+#crm-container .crm-address-block+.crm-address-block .add-new .crm-edit-help {
   display: block;
   background-color: #EBEBEB;
 }
 
-#crm-container .crm-edit-ready .crm-inline-edit:hover .crm-edit-help {
+#crm-container .crm-edit-ready .crm-summary-block .crm-inline-edit:hover .crm-edit-help {
   display: block;
   background-color: #DFE1FF;
 }
@@ -66,6 +73,10 @@ div#crm-contact-thumbnail {
   display: none !important;
 }
 
+#crm-container .crm-address-block+.crm-address-block .add-new .crm-summary-row {
+  display: none;
+}
+
 #crm-container span.crm-custom-greeting {
   font-size: 9px;
 }
@@ -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) {
index e1742da8fd9873c3bd318435de350b867686df80..5a1155c8462bd2a24a1e90d91eefc77628be87db 100644 (file)
         return false;
       }
       // Compare arguments
-      $.each(newUrl.split('?')[1].split('&'), function(k, v) {
+      $.each((newUrl.split('?')[1] || '').split('&'), function(k, v) {
         var arg = v.split('=');
         args[arg[0]] = arg[1];
       });
-      $.each(oldUrl.split('?')[1].split('&'), function(k, v) {
+      $.each((oldUrl.split('?')[1] || '').split('&'), function(k, v) {
         var arg = v.split('=');
         if (args[arg[0]] !== undefined && arg[1] !== args[arg[0]]) {
           same = false;
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 e533bf45ce30fd8d68c03ac76126b585e4f0d73a..4ee45c6a5bfd77dbc7f15899a749e22e90471da6 100644 (file)
@@ -32,7 +32,7 @@
   <table id="scheduleReminders" class="display">
     <thead>
     <tr id="options" class="columnheader">
-      <th class="sortable">{ts}Title{/ts}</th>
+      <th id="sortable">{ts}Title{/ts}</th>
       <th >{ts}Reminder For{/ts}</th>
       <th >{ts}When{/ts}</th>
       <th >{ts}While{/ts}</th>
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 10439c08e043c3d847cb07a8fe48436e220fa51e..f847a9f41bd70ac81fd3c1a87ae3956974cca3dd 100644 (file)
         <span class="crm-i fa-pencil"></span> {if $add}{ts}Edit address{/ts}{else}{ts}Add address{/ts}{/if}
       </div>
     {/if}
-    {if $add }
+    {if !$add}
+      <div class="crm-summary-row">
+        <div class="crm-label">{ts}Address{/ts}</div>
+        <div class="crm-content"></div>
+      </div>
+    {else}
       <div class="crm-summary-row {if $add.is_primary eq 1} primary{/if}">
         <div class="crm-label">
           {ts 1=$add.location_type}%1 Address{/ts}
index 76d7bb46927f73a275ed8decca64bfb08b842c65..95c2abe55801689d173cf086104881466b71dbc5 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;
             CRM.api3('address', 'delete', {id: $block.data('edit-params').aid}, true)
               .done(function(data) {
                 $('.crm-inline-edit-container').addClass('crm-edit-ready');
-                $block.remove();
+                $block.closest('.crm-address-block').remove();
                 reloadBlock('.crm-inline-edit.address:not(.add-new)');
               });
             });
index cb1e683a1af896072618ce500d9cd608b1b72439..190e1b4fd836ac457fc01430fcc5cc95d04f4fa7 100644 (file)
@@ -33,8 +33,6 @@
             <span class="description">{ts}Non-deductible portion of this contribution.{/ts}</span></td></tr>
         <tr class="crm-contribution-form-block-fee_amount"><td class="label">{$form.fee_amount.label}</td><td{$valueStyle}>{$form.fee_amount.html|crmMoney:$currency:'XXX':'YYY'}<br />
             <span class="description">{ts}Processing fee for this transaction (if applicable).{/ts}</span></td></tr>
-
-        <tr class="crm-contribution-form-block-net_amount"><td class="label">{$form.net_amount.label}</td><td{$valueStyle}>{$form.net_amount.html|crmMoney:$currency:'':1}<br />
             <span class="description">{ts}Net value of the contribution (Total Amount minus Fee).{/ts}</span></td></tr>
         <tr class="crm-contribution-form-block-invoice_id"><td class="label">{$form.invoice_id.label}</td><td{$valueStyle}>{$form.invoice_id.html}<br />
             <span class="description">{ts}Unique internal reference ID for this contribution.{/ts}</span></td></tr>
index 44f813d4be0b56bc635fa5f40674d63be6b9c551..b38df538290c546626fadc7d1c05fad0db648e42 100644 (file)
@@ -44,7 +44,7 @@
     {/if}
   </div>
   {/if}
-  
+
   <div class="crm-block crm-form-block crm-contribution-form-block">
 
   {if !$email and $action neq 8 and $context neq 'standalone'}
@@ -52,7 +52,7 @@
     <div class="icon inform-icon"></div>&nbsp;{ts}You will not be able to send an automatic email receipt for this contribution because there is no email address recorded for this contact. If you want a receipt to be sent when this contribution is recorded, click Cancel and then click Edit from the Summary tab to add an email address before recording the contribution.{/ts}
   </div>
   {/if}
-  
+
   {if $action eq 8}
   <div class="messages status no-popup">
     <div class="icon inform-icon"></div>
@@ -590,15 +590,6 @@ function showStartDate( ) {
 var thousandMarker = "{/literal}{$config->monetaryThousandSeparator}{literal}";
 var separator = "{/literal}{$config->monetaryDecimalPoint}{literal}";
 
-cj('#fee_amount').change( function() {
-  var totalAmount = cj('#total_amount').val().replace(thousandMarker,'').replace(separator,'.');
-  var feeAmount = cj('#fee_amount').val().replace(thousandMarker,'').replace(separator,'.');
-  var netAmount = totalAmount - feeAmount;
-  if (totalAmount) {
-    cj('#net_amount').val(CRM.formatMoney(netAmount, true));
-  }
-});
-
 cj("#financial_type_id").on("change",function(){
     cj('#total_amount').trigger("change");
 })
index cdda8dd679693da987994c812ea695fdf7c8b1af..ab0efc27720d7805becaa97f1c0571dd416a5044 100644 (file)
         var fname = '#priceset';
         if ( !priceSetId ) {
         cj('#membership_type_id_1').val(0);
-        CRM.buildCustomData(customDataType, 'null' );
+        CRM.buildCustomData(customDataType, null );
 
         // hide price set fields.
         cj( fname ).hide( );
 
       subTypeNames = currentMembershipType.join(',');
       if ( subTypeNames.length < 1 ) {
-        subTypeNames = 'null';
+        subTypeNames = null;
       }
 
       CRM.buildCustomData( customDataType, subTypeNames );
index 2fee1d365533c295c56128ae527c100f610f39a4..3f9a87461669823c891da18feb92118e8273bcc4 100644 (file)
       </div>
     </fieldset>
 
+    {include file="CRM/common/customDataBlock.tpl"}
+
     <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
   {/if}
     <div class="spacer"></div>
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 5e999c45e8bce377d29206a14833340f0d9fa1d3..4d3d77d2b9ee16f8bfc17208b2ebe7daacc56aa4 100644 (file)
@@ -130,6 +130,59 @@ class CRM_Mailing_BAO_MailingTest extends CiviUnitTestCase {
     $this->contactDelete($this->allowedContactId);
   }
 
+  /**
+   * Test mailing receipients when using previous mailing as include and contact is in exclude as well
+   */
+  public function testMailingIncludePreviousMailingExcludeGroup() {
+    $groupName = 'Test static group ' . substr(sha1(rand()), 0, 7);
+    $groupName2 = 'Test static group 2' . substr(sha1(rand()), 0, 7);
+    $groupID = $this->groupCreate([
+      'name' => $groupName,
+      'title' => $groupName,
+      'is_active' => 1,
+    ]);
+    $groupID2 = $this->groupCreate([
+      'name' => $groupName2,
+      'title' => $groupName2,
+      'is_active' => 1,
+    ]);
+    $contactID = $this->individualCreate(array(), 0);
+    $contactID2 = $this->individualCreate(array(), 2);
+    $this->callAPISuccess('GroupContact', 'Create', array(
+      'group_id' => $groupID,
+      'contact_id' => $contactID,
+    ));
+    $this->callAPISuccess('GroupContact', 'Create', array(
+      'group_id' => $groupID,
+      'contact_id' => $contactID2,
+    ));
+    $this->callAPISuccess('GroupContact', 'Create', array(
+      'group_id' => $groupID2,
+      'contact_id' => $contactID2,
+    ));
+    // Create dummy mailing
+    $mailingID = $this->callAPISuccess('Mailing', 'create', array())['id'];
+    $this->createMailingGroup($mailingID, $groupID);
+    $expectedContactIDs = [$contactID, $contactID2];
+    $this->assertRecipientsCorrect($mailingID, $expectedContactIDs);
+    $mailingID2 = $this->callAPISuccess('Mailing', 'create', array())['id'];
+    $this->createMailingGroup($mailingID2, $groupID2, 'Exclude');
+    $this->callAPISuccess('MailingGroup', 'create', array(
+      'mailing_id' => $mailingID2,
+      'group_type' => 'Include',
+      'entity_table' => CRM_Mailing_BAO_Mailing::getTableName(),
+      'entity_id' => $mailingID,
+    ));
+    $expectedContactIDs = [$contactID];
+    $this->assertRecipientsCorrect($mailingID2, $expectedContactIDs);
+    $this->callAPISuccess('mailing', 'delete', ['id' => $mailingID2]);
+    $this->callAPISuccess('mailing', 'delete', ['id' => $mailingID]);
+    $this->callAPISuccess('group', 'delete', ['id' => $groupID]);
+    $this->callAPISuccess('group', 'delete', ['id' => $groupID2]);
+    $this->callAPISuccess('contact', 'delete', ['id' => $contactID, 'skip_undelete' => TRUE]);
+    $this->callAPISuccess('contact', 'delete', ['id' => $contactID2, 'skip_undelete' => TRUE]);
+  }
+
   /**
    * Test verify that a disabled mailing group doesn't prvent access to the mailing generated with the group.
    */
index 14fcde188382d5f6b412979662a29b72c3b722c4..7641ab34f1efd64bc08e8f33d879190aa84cb832 100644 (file)
@@ -464,6 +464,7 @@ class CRM_Member_Form_MembershipTest extends CiviUnitTestCase {
    * @dataProvider getThousandSeparators
    */
   public function testSubmit($thousandSeparator) {
+    CRM_Core_Session::singleton()->getStatus(TRUE);
     $this->setCurrencySeparators($thousandSeparator);
     $form = $this->getForm();
     $form->preProcess();
@@ -472,7 +473,7 @@ class CRM_Member_Form_MembershipTest extends CiviUnitTestCase {
     $this->createLoggedInUser();
     $params = array(
       'cid' => $this->_individualId,
-      'join_date' => date('m/d/Y', time()),
+      'join_date' => date('2/d/Y', time()),
       'start_date' => '',
       'end_date' => '',
       // This format reflects the 23 being the organisation & the 25 being the type.
@@ -545,6 +546,14 @@ class CRM_Member_Form_MembershipTest extends CiviUnitTestCase {
       'Receipt text',
     ));
     $this->mut->stop();
+    $this->assertEquals([
+      [
+        'text' => 'AnnualFixed membership for Mr. Anthony Anderson II has been added. The new membership End Date is December 31st, ' . date('Y') . '. A membership confirmation and receipt has been sent to anthony_anderson@civicrm.org.',
+        'title' => 'Complete',
+        'type' => 'success',
+        'options' => NULL,
+      ],
+    ], CRM_Core_Session::singleton()->getStatus());
   }
 
   /**
@@ -722,6 +731,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 +777,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 +1299,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 +1313,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 +1358,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 8d81309544f2910a1852834c8306f29b09143c72..919ec7588276e05e5e2bd0e1c8291fd64cfef893 100644 (file)
       <labelColumn>title</labelColumn>
     </pseudoconstant>
   </field>
+  <foreignKey>
+    <name>option_group_id</name>
+    <table>civicrm_option_group</table>
+    <key>id</key>
+    <add>5.6</add>
+    <onDelete>SET NULL</onDelete>
+  </foreignKey>
   <field>
     <name>filter</name>
     <type>varchar</type>
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 55eb156e605c45957e22118054a1a0574e036976..fd0322b49af398c1912a61825901ca489d7b15d2 100644 (file)
     <type>int unsigned</type>
     <comment>Phone Type Id, if required</comment>
     <add>2.2</add>
+    <pseudoconstant>
+      <optionGroupName>phone_type</optionGroupName>
+    </pseudoconstant>
   </field>
   <field>
     <name>website_type_id</name>
     <type>int unsigned</type>
     <comment>Website Type Id, if required</comment>
     <add>4.5</add>
+    <pseudoconstant>
+      <optionGroupName>website_type</optionGroupName>
+    </pseudoconstant>
   </field>
   <field>
     <name>label</name>
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>