Merge pull request #15421 from artfulrobot/queue-safety
authorMatthew Wire <mjw@mjwconsult.co.uk>
Sun, 13 Oct 2019 15:04:22 +0000 (16:04 +0100)
committerGitHub <noreply@github.com>
Sun, 13 Oct 2019 15:04:22 +0000 (16:04 +0100)
Fix bug in SQL queue that can cause tasks to be run twice in a multiprocess environment

105 files changed:
CRM/Admin/Form/Setting/Miscellaneous.php
CRM/Admin/Form/SettingTrait.php
CRM/Contact/BAO/Group.php
CRM/Contact/BAO/Query.php
CRM/Contact/BAO/SavedSearch.php
CRM/Contact/Form/Edit/Address.php
CRM/Contact/Form/Task/PDFLetterCommon.php
CRM/Contribute/BAO/Contribution.php
CRM/Contribute/BAO/ContributionRecur.php
CRM/Contribute/DAO/Contribution.php
CRM/Contribute/DAO/ContributionPage.php
CRM/Contribute/Form/AbstractEditPayment.php
CRM/Contribute/Form/AdditionalPayment.php
CRM/Contribute/Form/Contribution/Confirm.php
CRM/Contribute/Form/Contribution/Main.php
CRM/Contribute/Form/ContributionBase.php
CRM/Contribute/Form/ContributionCharts.php
CRM/Contribute/Form/ContributionPage/Settings.php
CRM/Contribute/Form/Search.php
CRM/Core/BAO/Dashboard.php
CRM/Core/BAO/File.php
CRM/Core/BAO/FinancialTrxn.php
CRM/Core/Config/MagicMerge.php
CRM/Core/Form.php
CRM/Core/Form/Search.php
CRM/Core/I18n.php
CRM/Core/I18n/SchemaStructure.php
CRM/Core/I18n/SchemaStructure_5_20_alpha1.php [new file with mode: 0644]
CRM/Core/Invoke.php
CRM/Event/Cart/Form/Checkout/Payment.php
CRM/Event/Form/ManageEvent/Location.php
CRM/Event/Form/Participant.php
CRM/Event/Form/Registration.php
CRM/Event/Form/Registration/Confirm.php
CRM/Event/Form/Registration/Register.php
CRM/Export/BAO/Export.php
CRM/Export/BAO/ExportProcessor.php
CRM/Financial/BAO/FinancialAccount.php
CRM/Financial/DAO/FinancialTrxn.php
CRM/Financial/Form/FinancialAccount.php
CRM/Financial/Form/FinancialTypeAccount.php
CRM/Import/Parser.php
CRM/Member/BAO/Membership.php
CRM/Pledge/Form/Pledge.php
CRM/Report/Form/Contribute/Lybunt.php
CRM/Report/Form/Contribute/Summary.php
CRM/Report/Form/Contribute/Sybunt.php
CRM/Report/Form/Event/IncomeCountSummary.php
CRM/Report/Form/Event/Summary.php
CRM/Report/Form/Mailing/Bounce.php
CRM/Report/Form/Mailing/Clicks.php
CRM/Report/Form/Mailing/Opened.php
CRM/Report/Form/Mailing/Summary.php
CRM/Report/Form/Member/Summary.php
CRM/Report/Form/Membership/Summary.php
CRM/Upgrade/Incremental/php/FiveTwenty.php [new file with mode: 0644]
CRM/Upgrade/Incremental/sql/5.19.beta1.mysql.tpl [new file with mode: 0644]
CRM/Upgrade/Incremental/sql/5.20.alpha1.mysql.tpl [new file with mode: 0644]
CRM/Utils/Chart.php [new file with mode: 0644]
CRM/Utils/Check/Component.php
CRM/Utils/DeprecatedUtils.php
CRM/Utils/Hook.php
CRM/Utils/OpenFlashChart.php [deleted file]
Civi/Api4/Service/Spec/Provider/GetActionDefaultsProvider.php
ang/crmCaseType.js
api/v3/LocBlock.php
api/v3/PaymentProcessor.php
api/v3/System/setting-whitelist.txt
api/v3/examples/Contribution/ContributionCreateWithHonoreeContact.ex.php
api/v3/examples/Contribution/ContributionCreateWithNote.ex.php
api/v3/examples/Contribution/ContributionCreateWithSoftCredit.ex.php
api/v3/examples/Contribution/ContributionCreateWithSoftCreditDefaults.ex.php
api/v3/examples/Contribution/Create.ex.php
api/v3/examples/Contribution/CreateWithNestedLineItems.ex.php
contributor-key.yml
css/civicrm.css
release-notes.md
release-notes/5.18.2.md [new file with mode: 0644]
settings/Core.setting.php
sql/GenerateData.php
sql/GenerateReportData.php
sql/civicrm_generated.mysql
templates/CRM/Admin/Page/ConfigTaskList.tpl
templates/CRM/Contact/Page/DashBoardDashlet.tpl
templates/CRM/Contribute/Form/ContributionCharts.tpl
templates/CRM/Contribute/Form/ContributionPage/Settings.tpl
templates/CRM/Pledge/Form/Pledge.tpl
templates/CRM/Report/Form/Layout/Graph.tpl
templates/CRM/common/CMSPrint.tpl
templates/CRM/common/chart.tpl [new file with mode: 0644]
templates/CRM/common/joomla.tpl
templates/CRM/common/openFlashChart.tpl [deleted file]
tests/karma/unit/crmCaseTypeSpec.js
tests/phpunit/CRM/Contribute/BAO/ContributionRecurTest.php
tests/phpunit/CRM/Contribute/Import/Parser/ContributionTest.php
tests/phpunit/CRM/Core/BAO/FinancialTrxnTest.php
tests/phpunit/CRM/Core/BAO/LocationTest.php
tests/phpunit/CRM/Export/BAO/ExportTest.php
tests/phpunit/CRM/Utils/Mail/EmailProcessorInboundTest.php [new file with mode: 0644]
tests/phpunit/CRM/Utils/Mail/data/inbound/test_message_many_attachments.eml [new file with mode: 0644]
tests/phpunit/api/v4/Action/EventTest.php [new file with mode: 0644]
xml/schema/Contribute/Contribution.xml
xml/schema/Contribute/ContributionPage.xml
xml/schema/Financial/FinancialTrxn.xml
xml/version.xml

index 8b92a4b411f5e23960565f56cadf68c2275e9252..d1277923a82f94fea7c7f63d06231062f61f9f20 100644 (file)
@@ -38,6 +38,7 @@ class CRM_Admin_Form_Setting_Miscellaneous extends CRM_Admin_Form_Setting {
 
   protected $_settings = [
     'max_attachments' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
+    'max_attachments_backend' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'contact_undelete' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'empoweredBy' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
     'logging' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
@@ -73,6 +74,7 @@ class CRM_Admin_Form_Setting_Miscellaneous extends CRM_Admin_Form_Setting {
     $this->assign('pure_config_settings', [
       'empoweredBy',
       'max_attachments',
+      'max_attachments_backend',
       'maxFileSize',
       'secondDegRelPermissions',
       'recentItemsMaxCount',
index 1642b79ddffd35d2b43ee41c0ecfeeeef7b0cd59..ec6e15cfa71d162f39980d4209252a694a36d042 100644 (file)
@@ -250,6 +250,10 @@ trait CRM_Admin_Form_SettingTrait {
           //temp hack @todo fix to get from metadata
           $this->addRule('max_attachments', ts('Value should be a positive number'), 'positiveInteger');
         }
+        if ($setting == 'max_attachments_backend') {
+          //temp hack @todo fix to get from metadata
+          $this->addRule('max_attachments_backend', ts('Value should be a positive number'), 'positiveInteger');
+        }
         if ($setting == 'maxFileSize') {
           //temp hack
           $this->addRule('maxFileSize', ts('Value should be a positive number'), 'positiveInteger');
index 552db8f9d111e2ee9cb822c5d3b7bb6ca8b74695..074fcf2623ad79daa697e1d86931ef2d320e1cbf 100644 (file)
@@ -421,7 +421,6 @@ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group {
       $group->name = substr($group->name, 0, -4) . "_{$group->id}";
     }
 
-    $group->buildClause();
     $group->save();
 
     // add custom field values
@@ -501,25 +500,6 @@ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group {
     return $group;
   }
 
-  /**
-   * Given a saved search compute the clause and the tables
-   * and store it for future use
-   */
-  public function buildClause() {
-    $params = [['group', 'IN', [$this->id], 0, 0]];
-
-    if (!empty($params)) {
-      $tables = $whereTables = [];
-      $this->where_clause = CRM_Contact_BAO_Query::getWhereClause($params, NULL, $tables, $whereTables);
-      if (!empty($tables)) {
-        $this->select_tables = serialize($tables);
-      }
-      if (!empty($whereTables)) {
-        $this->where_tables = serialize($whereTables);
-      }
-    }
-  }
-
   /**
    * Defines a new smart group.
    *
index 9d5e64a38a51f8abc6ded53b8399ec8d61e7d0cd..56acef4c367048474d7af5ea890932b8c0d3040e 100644 (file)
@@ -6419,6 +6419,10 @@ AND   displayRelType.is_active = 1
         if (!empty($pseudoConstantMetadata['optionGroupName'])
           || $this->isPseudoFieldAnFK($fieldSpec)
         ) {
+          // dev/core#1305 @todo this is not the right thing to do but for now avoid fatal error
+          if (empty($fieldSpec['bao'])) {
+            continue;
+          }
           $sortedOptions = $fieldSpec['bao']::buildOptions($fieldSpec['name'], NULL, [
             'orderColumn' => CRM_Utils_Array::value('labelColumn', $pseudoConstantMetadata, 'label'),
           ]);
index 749a716a4938d7b3cfc6ba298d49ffd311afe2b8..396cb3826ae57ab23da2c0e5fff825b5d8a5e30c 100644 (file)
@@ -324,43 +324,6 @@ LEFT JOIN civicrm_email ON (contact_a.id = civicrm_email.contact_id AND civicrm_
     }
   }
 
-  /**
-   * Given a saved search compute the clause and the tables and store it for future use.
-   */
-  public function buildClause() {
-    $fv = unserialize($this->form_values);
-
-    if ($this->mapping_id) {
-      $params = CRM_Core_BAO_Mapping::formattedFields($fv);
-    }
-    else {
-      $params = CRM_Contact_BAO_Query::convertFormValues($fv);
-    }
-
-    if (!empty($params)) {
-      $tables = $whereTables = [];
-      $this->where_clause = CRM_Contact_BAO_Query::getWhereClause($params, NULL, $tables, $whereTables);
-      if (!empty($tables)) {
-        $this->select_tables = serialize($tables);
-      }
-      if (!empty($whereTables)) {
-        $this->where_tables = serialize($whereTables);
-      }
-    }
-  }
-
-  /**
-   * Save the search.
-   *
-   * @param bool $hook
-   */
-  public function save($hook = TRUE) {
-    // first build the computed fields
-    $this->buildClause();
-
-    parent::save($hook);
-  }
-
   /**
    * Given an id, get the name of the saved search.
    *
index 8cc795e56a58641032734354de33b0050c5e6504..21dbd8cf68d3d78fd8adc0987d1c8a1dfebf89c0 100644 (file)
@@ -46,6 +46,8 @@ class CRM_Contact_Form_Edit_Address {
    *   False, if we want to skip the address sharing features.
    * @param bool $inlineEdit
    *   True when edit used in inline edit.
+   *
+   * @throws \CiviCRM_API3_Exception
    */
   public static function buildQuickForm(&$form, $addressBlockCount = NULL, $sharing = TRUE, $inlineEdit = FALSE) {
     // passing this via the session is AWFUL. we need to fix this
@@ -130,13 +132,13 @@ class CRM_Contact_Form_Edit_Address {
           continue;
         }
       }
-      if ($name == 'address_name') {
+      if ($name === 'address_name') {
         $name = 'name';
       }
 
       $params = ['entity' => 'address'];
 
-      if ($name == 'postal_code_suffix') {
+      if ($name === 'postal_code_suffix') {
         $params['label'] = ts('Suffix');
       }
 
@@ -366,12 +368,12 @@ class CRM_Contact_Form_Edit_Address {
       $requireOmission = NULL;
       foreach ($groupTree as $csId => $csVal) {
         // only process Address entity fields
-        if ($csVal['extends'] != 'Address') {
+        if ($csVal['extends'] !== 'Address') {
           continue;
         }
 
         foreach ($csVal['fields'] as $cdId => $cdVal) {
-          if ($cdVal['is_required']) {
+          if (!empty($cdVal['is_required'])) {
             $elementName = $cdVal['element_name'];
             if (in_array($elementName, $form->_required)) {
               // store the omitted rule for a element, to be used later on
@@ -391,6 +393,9 @@ class CRM_Contact_Form_Edit_Address {
    * @param CRM_Core_Form $form
    * @param int $entityId
    * @param int $blockId
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   protected static function addCustomDataToForm(&$form, $entityId, $blockId) {
     $groupTree = CRM_Core_BAO_CustomGroup::getTree('Address', NULL, $entityId);
@@ -417,7 +422,7 @@ class CRM_Contact_Form_Edit_Address {
           continue;
         }
 
-        // inorder to set correct defaults for checkbox custom data, we need to converted flat key to array
+        // in order to set correct defaults for checkbox custom data, we need to converted flat key to array
         // this works for all types custom data
         $keyValues = explode('[', str_replace(']', '', $key));
         $addressDefaults[$keyValues[0]][$keyValues[1]][$keyValues[2]] = $val;
index c5b8439801d013d5d009addb698eb4c68b84190e..a0424e1d6cf7d82729dc6a03b1c0add185d32d57 100644 (file)
@@ -180,7 +180,7 @@ class CRM_Contact_Form_Task_PDFLetterCommon extends CRM_Core_Form_Task_PDFLetter
     }
 
     $tee = NULL;
-    if ($isLiveMode && Civi::settings()->get('recordGeneratedLetters') === 'combined-attached') {
+    if (self::isLiveMode($form) && Civi::settings()->get('recordGeneratedLetters') === 'combined-attached') {
       if (count($activityIds) !== 1) {
         throw new CRM_Core_Exception("When recordGeneratedLetters=combined-attached, there should only be one activity.");
       }
index 58efcf8f3af3e954e8264b5ba74754f7a03d8b0d..7259c633a016a279443fbdac99076c35875a882e 100644 (file)
@@ -155,7 +155,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
       if (($params['contribution_status_id'] == array_search('Refunded', $contributionStatus)
         || $params['contribution_status_id'] == array_search('Cancelled', $contributionStatus))
       ) {
-        if (empty($params['creditnote_id']) || $params['creditnote_id'] == "null") {
+        if (empty($params['creditnote_id'])) {
           $params['creditnote_id'] = self::createCreditNoteId();
         }
       }
@@ -1100,14 +1100,14 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
    * functions.
    *
    * @param array $params
-   * @param string $context
-   * @param array $previousContributionStatus
-   * @param string $currentContributionStatus
    *
    * @return bool[]
    *   Return indicates whether the updateFinancialAccounts function should continue & whether this is a refund.
    */
-  private static function updateFinancialAccountsOnContributionStatusChange(&$params, $context, $previousContributionStatus, $currentContributionStatus) {
+  private static function updateFinancialAccountsOnContributionStatusChange(&$params) {
+    $previousContributionStatus = CRM_Contribute_PseudoConstant::contributionStatus($params['prevContribution']->contribution_status_id, 'name');
+    $currentContributionStatus = CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $params['contribution']->contribution_status_id);
+
     $isARefund = FALSE;
     if ((($previousContributionStatus == 'Partially paid' && $currentContributionStatus == 'Completed')
         || ($previousContributionStatus == 'Pending refund' && $currentContributionStatus == 'Completed')
@@ -1118,90 +1118,89 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
     ) {
       return [FALSE, $isARefund];
     }
-    if ($context == 'changedStatus') {
-      if ($previousContributionStatus == 'Completed'
-        && (self::isContributionStatusNegative($params['contribution']->contribution_status_id))
-      ) {
-        $isARefund = TRUE;
+
+    if ($previousContributionStatus == 'Completed'
+      && (self::isContributionStatusNegative($params['contribution']->contribution_status_id))
+    ) {
+      $isARefund = TRUE;
+      // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
+      $params['trxnParams']['total_amount'] = -$params['total_amount'];
+      if (empty($params['contribution']->creditnote_id)) {
+        $creditNoteId = self::createCreditNoteId();
+        CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $params['contribution']->id, 'creditnote_id', $creditNoteId);
+      }
+    }
+    elseif (($previousContributionStatus == 'Pending'
+        && $params['prevContribution']->is_pay_later) || $previousContributionStatus == 'In Progress'
+    ) {
+      $financialTypeID = CRM_Utils_Array::value('financial_type_id', $params) ? $params['financial_type_id'] : $params['prevContribution']->financial_type_id;
+      $arAccountId = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($financialTypeID, 'Accounts Receivable Account is');
+
+      if ($currentContributionStatus == 'Cancelled') {
         // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
+        $params['trxnParams']['to_financial_account_id'] = $arAccountId;
         $params['trxnParams']['total_amount'] = -$params['total_amount'];
-        if (empty($params['contribution']->creditnote_id) || $params['contribution']->creditnote_id == "null") {
+        if (empty($params['contribution']->creditnote_id)) {
           $creditNoteId = self::createCreditNoteId();
           CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $params['contribution']->id, 'creditnote_id', $creditNoteId);
         }
       }
-      elseif (($previousContributionStatus == 'Pending'
-          && $params['prevContribution']->is_pay_later) || $previousContributionStatus == 'In Progress'
-      ) {
-        $financialTypeID = CRM_Utils_Array::value('financial_type_id', $params) ? $params['financial_type_id'] : $params['prevContribution']->financial_type_id;
-        $arAccountId = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount($financialTypeID, 'Accounts Receivable Account is');
-
-        if ($currentContributionStatus == 'Cancelled') {
-          // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
-          $params['trxnParams']['to_financial_account_id'] = $arAccountId;
-          $params['trxnParams']['total_amount'] = -$params['total_amount'];
-          if (is_null($params['contribution']->creditnote_id) || $params['contribution']->creditnote_id == "null") {
-            $creditNoteId = self::createCreditNoteId();
-            CRM_Core_DAO::setFieldValue('CRM_Contribute_DAO_Contribution', $params['contribution']->id, 'creditnote_id', $creditNoteId);
-          }
-        }
-        else {
-          // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
-          $params['trxnParams']['from_financial_account_id'] = $arAccountId;
-        }
+      else {
+        // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
+        $params['trxnParams']['from_financial_account_id'] = $arAccountId;
       }
+    }
 
-      if (($previousContributionStatus == 'Pending'
-          || $previousContributionStatus == 'In Progress')
-        && ($currentContributionStatus == 'Completed')
-      ) {
-        if (empty($params['line_item'])) {
-          //CRM-15296
-          //@todo - check with Joe regarding this situation - payment processors create pending transactions with no line items
-          // when creating recurring membership payment - there are 2 lines to comment out in contributonPageTest if fixed
-          // & this can be removed
-          return [FALSE, $isARefund];
-        }
-        // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
-        // This is an update so original currency if none passed in.
-        $params['trxnParams']['currency'] = CRM_Utils_Array::value('currency', $params, $params['prevContribution']->currency);
+    if (($previousContributionStatus == 'Pending'
+        || $previousContributionStatus == 'In Progress')
+      && ($currentContributionStatus == 'Completed')
+    ) {
+      if (empty($params['line_item'])) {
+        //CRM-15296
+        //@todo - check with Joe regarding this situation - payment processors create pending transactions with no line items
+        // when creating recurring membership payment - there are 2 lines to comment out in contributonPageTest if fixed
+        // & this can be removed
+        return [FALSE, $isARefund];
+      }
+      // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
+      // This is an update so original currency if none passed in.
+      $params['trxnParams']['currency'] = CRM_Utils_Array::value('currency', $params, $params['prevContribution']->currency);
 
-        self::recordAlwaysAccountsReceivable($params['trxnParams'], $params);
-        $trxn = CRM_Core_BAO_FinancialTrxn::create($params['trxnParams']);
-        // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
-        $params['entity_id'] = self::$_trxnIDs[] = $trxn->id;
-        $query = "UPDATE civicrm_financial_item SET status_id = %1 WHERE entity_id = %2 and entity_table = 'civicrm_line_item'";
-        $sql = "SELECT id, amount FROM civicrm_financial_item WHERE entity_id = %1 and entity_table = 'civicrm_line_item'";
+      self::recordAlwaysAccountsReceivable($params['trxnParams'], $params);
+      $trxn = CRM_Core_BAO_FinancialTrxn::create($params['trxnParams']);
+      // @todo we should stop passing $params by reference - splitting this out would be a step towards that.
+      $params['entity_id'] = self::$_trxnIDs[] = $trxn->id;
+      $query = "UPDATE civicrm_financial_item SET status_id = %1 WHERE entity_id = %2 and entity_table = 'civicrm_line_item'";
+      $sql = "SELECT id, amount FROM civicrm_financial_item WHERE entity_id = %1 and entity_table = 'civicrm_line_item'";
 
-        $entityParams = [
-          'entity_table' => 'civicrm_financial_item',
-        ];
-        foreach ($params['line_item'] as $fieldId => $fields) {
-          foreach ($fields as $fieldValueId => $lineItemDetails) {
-            $fparams = [
-              1 => [
-                CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_FinancialItem', 'status_id', 'Paid'),
-                'Integer',
-              ],
-              2 => [$lineItemDetails['id'], 'Integer'],
-            ];
-            CRM_Core_DAO::executeQuery($query, $fparams);
-            $fparams = [
-              1 => [$lineItemDetails['id'], 'Integer'],
-            ];
-            $financialItem = CRM_Core_DAO::executeQuery($sql, $fparams);
-            while ($financialItem->fetch()) {
-              $entityParams['entity_id'] = $financialItem->id;
-              $entityParams['amount'] = $financialItem->amount;
-              foreach (self::$_trxnIDs as $tID) {
-                $entityParams['financial_trxn_id'] = $tID;
-                CRM_Financial_BAO_FinancialItem::createEntityTrxn($entityParams);
-              }
+      $entityParams = [
+        'entity_table' => 'civicrm_financial_item',
+      ];
+      foreach ($params['line_item'] as $fieldId => $fields) {
+        foreach ($fields as $fieldValueId => $lineItemDetails) {
+          $fparams = [
+            1 => [
+              CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_FinancialItem', 'status_id', 'Paid'),
+              'Integer',
+            ],
+            2 => [$lineItemDetails['id'], 'Integer'],
+          ];
+          CRM_Core_DAO::executeQuery($query, $fparams);
+          $fparams = [
+            1 => [$lineItemDetails['id'], 'Integer'],
+          ];
+          $financialItem = CRM_Core_DAO::executeQuery($sql, $fparams);
+          while ($financialItem->fetch()) {
+            $entityParams['entity_id'] = $financialItem->id;
+            $entityParams['amount'] = $financialItem->amount;
+            foreach (self::$_trxnIDs as $tID) {
+              $entityParams['financial_trxn_id'] = $tID;
+              CRM_Financial_BAO_FinancialItem::createEntityTrxn($entityParams);
             }
           }
         }
-        return [FALSE, $isARefund];
       }
+      return [FALSE, $isARefund];
     }
     return [TRUE, $isARefund];
   }
@@ -3717,11 +3716,9 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
     $trxnID = NULL;
     $inputParams = $params;
     $isARefund = FALSE;
-    $currentContributionStatus = CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $params['contribution']->contribution_status_id);
-    $previousContributionStatus = CRM_Contribute_PseudoConstant::contributionStatus($params['prevContribution']->contribution_status_id, 'name');
 
     if ($context == 'changedStatus') {
-      list($continue, $isARefund) = self::updateFinancialAccountsOnContributionStatusChange($params, $context, $previousContributionStatus, $currentContributionStatus);
+      list($continue, $isARefund) = self::updateFinancialAccountsOnContributionStatusChange($params);
       // @todo - it may be that this is always false & the parent function is just a confusing wrapper for the child fn.
       if (!$continue) {
         return;
@@ -3773,8 +3770,6 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
         $params['line_item'][$fieldId][$fieldValueId]['financial_item_id'] = $financialItem->id;
 
         if (($lineItemDetails['tax_amount'] && $lineItemDetails['tax_amount'] !== 'null') || ($context == 'changeFinancialType')) {
-          $invoiceSettings = Civi::settings()->get('contribution_invoice_settings');
-          $taxTerm = CRM_Utils_Array::value('tax_term', $invoiceSettings);
           $taxAmount = (float) $lineItemDetails['tax_amount'];
           if ($context == 'changeFinancialType' && $lineItemDetails['tax_amount'] === 'null') {
             // reverse the Sale Tax amount if there is no tax rate associated with new Financial Type
@@ -3785,12 +3780,9 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
           }
           if ($taxAmount != 0) {
             $itemParams['amount'] = self::getMultiplier($params['contribution']->contribution_status_id, $context) * $taxAmount;
-            $itemParams['description'] = $taxTerm;
+            $itemParams['description'] = CRM_Invoicing_Utils::getTaxTerm();
             if ($lineItemDetails['financial_type_id']) {
-              $itemParams['financial_account_id'] = CRM_Contribute_PseudoConstant::getRelationalFinancialAccount(
-                $lineItemDetails['financial_type_id'],
-                'Sales Tax Account is'
-              );
+              $itemParams['financial_account_id'] = CRM_Financial_BAO_FinancialAccount::getSalesTaxFinancialAccount($lineItemDetails['financial_type_id']);
             }
             CRM_Financial_BAO_FinancialItem::create($itemParams, NULL, $trxnIds);
           }
index dc0b467ff884fef56e53829cf2ade1dca542a88d..7f80887281a1fc7c6f98c613da1af6941a068cc7 100644 (file)
@@ -428,14 +428,31 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
    * @throws \CiviCRM_API3_Exception
    */
   public static function getTemplateContribution($id, $overrides = []) {
-    $templateContribution = civicrm_api3('Contribution', 'get', [
-      'contribution_recur_id' => $id,
-      'options' => ['limit' => 1, 'sort' => ['id DESC']],
-      'sequential' => 1,
-      'contribution_test' => '',
+    // use api3 because api4 doesn't handle ContributionRecur yet...
+    $is_test = civicrm_api3('ContributionRecur', 'getvalue', [
+      'return' => "is_test",
+      'id' => $id,
     ]);
-    if ($templateContribution['count']) {
-      $result = array_merge($templateContribution['values'][0], $overrides);
+    // First look for new-style template contribution with is_template=1
+    $templateContributions = \Civi\Api4\Contribution::get()
+      ->addWhere('contribution_recur_id', '=', $id)
+      ->addWhere('is_template', '=', 1)
+      ->addWhere('is_test', '=', $is_test)
+      ->addOrderBy('id', 'DESC')
+      ->setLimit(1)
+      ->execute();
+    if (!$templateContributions->count()) {
+      // Fall back to old style template contributions
+      $templateContributions = \Civi\Api4\Contribution::get()
+        ->addWhere('contribution_recur_id', '=', $id)
+        ->addWhere('is_test', '=', $is_test)
+        ->addOrderBy('id', 'DESC')
+        ->setLimit(1)
+        ->execute();
+    }
+    if ($templateContributions->count()) {
+      $templateContribution = $templateContributions->first();
+      $result = array_merge($templateContribution, $overrides);
       $result['line_item'] = CRM_Contribute_BAO_ContributionRecur::calculateRecurLineItems($id, $result['total_amount'], $result['financial_type_id']);
       return $result;
     }
index a30e2042ea9741a8e48e74c956cc600df3682ec6..018f1e0c1f463579a84d134592125d7ff1f6ee69 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Contribute/Contribution.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:b4e84298d9ba23d3b2fae0768fc5cb58)
+ * (GenCodeChecksum:a9f83aa612e82ee87ace74e75fe23466)
  */
 
 /**
@@ -226,6 +226,13 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO {
    */
   public $revenue_recognition_date;
 
+  /**
+   * Shows this is a template for recurring contributions.
+   *
+   * @var bool
+   */
+  public $is_template;
+
   /**
    * Class constructor.
    */
@@ -839,6 +846,23 @@ class CRM_Contribute_DAO_Contribution extends CRM_Core_DAO {
             'formatType' => 'activityDateTime',
           ],
         ],
+        'is_template' => [
+          'name' => 'is_template',
+          'type' => CRM_Utils_Type::T_BOOLEAN,
+          'title' => ts('Is a Template Contribution'),
+          'description' => ts('Shows this is a template for recurring contributions.'),
+          'import' => TRUE,
+          'where' => 'civicrm_contribution.is_template',
+          'export' => TRUE,
+          'default' => '0',
+          'table_name' => 'civicrm_contribution',
+          'entity' => 'Contribution',
+          'bao' => 'CRM_Contribute_BAO_Contribution',
+          'localizable' => 0,
+          'html' => [
+            'type' => 'CheckBox',
+          ],
+        ],
       ];
       CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
     }
index 4ba652bdae28b59368ba985f0bbf12f8215a2ff1..69a3cefef865f8cc684bad2ad6eac628060c08fd 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Contribute/ContributionPage.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:70763e4804af1e4e3ddbac7b60cbd242)
+ * (GenCodeChecksum:35e26556fcbed13acc434279f2ebaee5)
  */
 
 /**
@@ -343,6 +343,13 @@ class CRM_Contribute_DAO_ContributionPage extends CRM_Core_DAO {
    */
   public $is_billing_required;
 
+  /**
+   * Contribution Page Public title
+   *
+   * @var string
+   */
+  public $frontend_title;
+
   /**
    * Class constructor.
    */
@@ -993,6 +1000,23 @@ class CRM_Contribute_DAO_ContributionPage extends CRM_Core_DAO {
           'bao' => 'CRM_Contribute_BAO_ContributionPage',
           'localizable' => 0,
         ],
+        'contribution_page_frontend_title' => [
+          'name' => 'frontend_title',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => ts('Public Title'),
+          'description' => ts('Contribution Page Public title'),
+          'maxlength' => 255,
+          'size' => CRM_Utils_Type::HUGE,
+          'where' => 'civicrm_contribution_page.frontend_title',
+          'default' => 'NULL',
+          'table_name' => 'civicrm_contribution_page',
+          'entity' => 'ContributionPage',
+          'bao' => 'CRM_Contribute_BAO_ContributionPage',
+          'localizable' => 1,
+          'html' => [
+            'type' => 'Text',
+          ],
+        ],
       ];
       CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
     }
index aafbf0a4231c13d36ebdc66f6674a0e257b204af..bc37b6f8a9be49b9fe43ab4a63b2f1dffabc803e 100644 (file)
@@ -578,9 +578,7 @@ WHERE  contribution_id = {$id}
         $this->_params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($this->_params);
       }
       $this->assign('credit_card_exp_date', CRM_Utils_Date::mysqlToIso(CRM_Utils_Date::format($this->_params['credit_card_exp_date'])));
-      $this->assign('credit_card_number',
-        CRM_Utils_System::mungeCreditCard($this->_params['credit_card_number'])
-      );
+      $this->assign('credit_card_number', CRM_Utils_System::mungeCreditCard($this->_params['credit_card_number']));
       $this->assign('credit_card_type', CRM_Utils_Array::value('credit_card_type', $this->_params));
     }
     $this->_params['ip_address'] = CRM_Utils_System::ipAddress();
index fdb7c478f3a9c81eb86813aa1df0568dee07aaf0..e6aceaa3dd7a362dad8309a4c97d19aa2343c9fe 100644 (file)
@@ -108,18 +108,18 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
       $this->_fromEmails['from_email_id'] = CRM_Core_BAO_Email::getFromEmail();
     }
 
-    $paymentInfo = CRM_Core_BAO_FinancialTrxn::getPartialPaymentWithType($this->_id, $entityType);
     $paymentDetails = CRM_Contribute_BAO_Contribution::getPaymentInfo($this->_id, $this->_component, FALSE, TRUE);
+    $paymentAmt = CRM_Contribute_BAO_Contribution::getContributionBalance($this->_id);
 
     $this->_amtPaid = $paymentDetails['paid'];
     $this->_amtTotal = $paymentDetails['total'];
 
-    if (!empty($paymentInfo['refund_due'])) {
-      $paymentAmt = $this->_refund = $paymentInfo['refund_due'];
+    if ($paymentAmt < 0) {
+      $this->_refund = $paymentAmt;
       $this->_paymentType = 'refund';
     }
-    elseif (!empty($paymentInfo['amount_owed'])) {
-      $paymentAmt = $this->_owed = $paymentInfo['amount_owed'];
+    elseif ($paymentAmt > 0) {
+      $this->_owed = $paymentAmt;
       $this->_paymentType = 'owed';
     }
     else {
@@ -520,18 +520,18 @@ class CRM_Contribute_Form_AdditionalPayment extends CRM_Contribute_Form_Abstract
     if (!empty($params['contribution_id'])) {
       $this->_contributionId = $params['contribution_id'];
 
-      $paymentInfo = CRM_Core_BAO_FinancialTrxn::getPartialPaymentWithType($this->_contributionId, $entityType);
       $paymentDetails = CRM_Contribute_BAO_Contribution::getPaymentInfo($this->_contributionId, $entityType, FALSE, TRUE);
 
+      $paymentAmount = CRM_Contribute_BAO_Contribution::getContributionBalance($this->_contributionId);
       $this->_amtPaid = $paymentDetails['paid'];
       $this->_amtTotal = $paymentDetails['total'];
 
-      if (!empty($paymentInfo['refund_due'])) {
-        $this->_refund = $paymentInfo['refund_due'];
+      if ($paymentAmount < 0) {
+        $this->_refund = $paymentAmount;
         $this->_paymentType = 'refund';
       }
-      elseif (!empty($paymentInfo['amount_owed'])) {
-        $this->_owed = $paymentInfo['amount_owed'];
+      elseif ($paymentAmount > 0) {
+        $this->_owed = $paymentAmount;
         $this->_paymentType = 'owed';
       }
     }
index d4654c012344cb4a0e48e16cfef5052b97dc7fd8..a977f45dde3db6fb75b2e5aab908941b808d262a 100644 (file)
@@ -1537,8 +1537,9 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
         if (!empty($form->_params['membership_source'])) {
           $membershipSource = $form->_params['membership_source'];
         }
-        elseif (isset($form->_values['title']) && !empty($form->_values['title'])) {
-          $membershipSource = ts('Online Contribution:') . ' ' . $form->_values['title'];
+        elseif ((isset($form->_values['title']) && !empty($form->_values['title'])) || (isset($form->_values['frontend_title']) && !empty($form->_values['frontend_title']))) {
+          $title = !empty($form->_values['frontend_title']) ? $form->_values['frontend_title'] : $form->_values['title'];
+          $membershipSource = ts('Online Contribution:') . ' ' . $title;
         }
         $isPayLater = NULL;
         if (isset($form->_params)) {
@@ -2056,7 +2057,8 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
       }
     }
     // add a description field at the very beginning
-    $this->_params['description'] = ts('Online Contribution') . ': ' . (($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']);
+    $title = !empty($this->_values['frontend_title']) ? $this->_values['frontend_title'] : $this->_values['title'];
+    $this->_params['description'] = ts('Online Contribution') . ': ' . (!empty($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $title);
 
     $this->_params['accountingCode'] = CRM_Utils_Array::value('accountingCode', $this->_values);
 
index 6b8d915b8d5d8875cc5f67b17153126c9bd42ba8..1a23147d47bd8ed3cd14515cf53f556fef76f573 100644 (file)
@@ -1217,7 +1217,8 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $invoiceID = md5(uniqid(rand(), TRUE));
     $this->set('invoiceID', $invoiceID);
     $params['invoiceID'] = $invoiceID;
-    $params['description'] = ts('Online Contribution') . ': ' . ((!empty($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $this->_values['title']));
+    $title = !empty($this->_values['frontend_title']) ? $this->_values['frontend_title'] : $this->_values['title'];
+    $params['description'] = ts('Online Contribution') . ': ' . ((!empty($this->_pcpInfo['title']) ? $this->_pcpInfo['title'] : $title));
     $params['button'] = $this->controller->getButtonName();
     // required only if is_monetary and valid positive amount
     // @todo it seems impossible for $memFee to be greater than 0 & $params['amount'] not to
index 0399436fd8c180c25b2d8696ea11e73022f649f4..21cc18e75a1cc2cba6f4df2f939c3756677c011b 100644 (file)
@@ -286,9 +286,6 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
 
     // we do not want to display recently viewed items, so turn off
     $this->assign('displayRecent', FALSE);
-    // Contribution page values are cleared from session, so can't use normal Printer Friendly view.
-    // Use Browser Print instead.
-    $this->assign('browserPrint', TRUE);
 
     // action
     $this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 'add');
@@ -471,7 +468,9 @@ class CRM_Contribute_Form_ContributionBase extends CRM_Core_Form {
       CRM_Utils_Array::value('cancelSubscriptionUrl', $this->_values)
     );
 
-    $this->setTitle(($this->_pcpId ? $this->_pcpInfo['title'] : $this->_values['title']));
+    $title = !empty($this->_values['frontend_title']) ? $this->_values['frontend_title'] : $this->_values['title'];
+
+    $this->setTitle(($this->_pcpId ? $this->_pcpInfo['title'] : $title));
     $this->_defaults = [];
 
     $this->_amount = $this->get('amount');
index ac5866da5bd00bd10a6453274356642e48dfa157..158db37c79d4a4dfa8e2b2aed42b6f972998afeb 100644 (file)
@@ -173,11 +173,11 @@ class CRM_Contribute_Form_ContributionCharts extends CRM_Core_Form {
         $monthlyChart = TRUE;
       }
 
-      $values['divName'] = "open_flash_chart_{$chartKey}";
+      $values['divName'] = "chart_{$chartKey}";
       $funName = ($chartType == 'bvg') ? 'barChart' : 'pieChart';
 
       // build the chart objects.
-      $values['object'] = CRM_Utils_OpenFlashChart::$funName($values);
+      $values['object'] = CRM_Utils_Chart::$funName($values);
 
       //build the urls.
       $urlCnt = 0;
@@ -230,8 +230,8 @@ class CRM_Contribute_Form_ContributionCharts extends CRM_Core_Form {
     // finally assign this chart data to template.
     $this->assign('hasYearlyChart', $yearlyChart);
     $this->assign('hasByMonthChart', $monthlyChart);
-    $this->assign('hasOpenFlashChart', empty($chartData) ? FALSE : TRUE);
-    $this->assign('openFlashChartData', json_encode($chartData));
+    $this->assign('hasChart', empty($chartData) ? FALSE : TRUE);
+    $this->assign('chartData', json_encode($chartData ?? []));
   }
 
 }
index 0e7ae3ae58f8258ad42115e39a3d69bf959b0ec5..55fe85b695d107c40d8f98a060ac10d56bdd45be 100644 (file)
@@ -135,6 +135,7 @@ class CRM_Contribute_Form_ContributionPage_Settings extends CRM_Contribute_Form_
 
     // name
     $this->add('text', 'title', ts('Title'), $attributes['title'], TRUE);
+    $this->addField('contribution_page_frontend_title', ['entity' => 'ContributionPage']);
 
     //CRM-7362 --add campaigns.
     CRM_Campaign_BAO_Campaign::addCampaign($this, CRM_Utils_Array::value('campaign_id', $this->_values));
index 6fdb263afb1a390e9cd1203e4439d16a2a3c0a81..6923169fe6b902cc1ba28a44347e1ea7cdcdd59d 100644 (file)
@@ -99,12 +99,7 @@ class CRM_Contribute_Form_Search extends CRM_Core_Form_Search {
     }
 
     if ($this->_force) {
-      // Search field metadata is normally added in buildForm but we are bypassing that in this flow
-      // (I've always found the flow kinda confusing & perhaps that is the problem but this mitigates)
-      $this->addSearchFieldMetadata(['Contribution' => CRM_Contribute_BAO_Query::getSearchFieldMetadata()]);
-      $this->addSearchFieldMetadata(['ContributionRecur' => CRM_Contribute_BAO_ContributionRecur::getContributionRecurSearchFieldMetadata()]);
-      $this->postProcess();
-      $this->set('force', 0);
+      $this->handleForcedSearch();
     }
 
     $sortID = NULL;
@@ -475,4 +470,14 @@ class CRM_Contribute_Form_Search extends CRM_Core_Form_Search {
     return ts('Find Contributions');
   }
 
+  /**
+   * Set the metadata for the form.
+   *
+   * @throws \CiviCRM_API3_Exception
+   */
+  protected function setSearchMetadata() {
+    $this->addSearchFieldMetadata(['Contribution' => CRM_Contribute_BAO_Query::getSearchFieldMetadata()]);
+    $this->addSearchFieldMetadata(['ContributionRecur' => CRM_Contribute_BAO_ContributionRecur::getContributionRecurSearchFieldMetadata()]);
+  }
+
 }
index 2c89838c40ba87704ecba71db6d9e47488704c43..a94154d178f63da4bea9d3aca6b3d5b4df798900 100644 (file)
@@ -357,13 +357,39 @@ class CRM_Core_BAO_Dashboard extends CRM_Core_DAO_Dashboard {
       }
     }
 
-    // Disable inactive widgets
-    $dashletClause = $dashletIDs ? "dashboard_id NOT IN  (" . implode(',', $dashletIDs) . ")" : '(1)';
+    // Find dashlets in this domain.
+    $domainDashlets = civicrm_api3('Dashboard', 'get', [
+      'return' => array('id'),
+      'domain_id' => CRM_Core_Config::domainID(),
+      'options' => ['limit' => 0],
+    ]);
+
+    // Get the array of IDs.
+    $domainDashletIDs = [];
+    if ($domainDashlets['is_error'] == 0) {
+      $domainDashletIDs = CRM_Utils_Array::collect('id', $domainDashlets['values']);
+    }
+
+    // Restrict query to Dashlets in this domain.
+    $domainDashletClause = !empty($domainDashletIDs) ? "dashboard_id IN (" . implode(',', $domainDashletIDs) . ")" : '(1)';
+
+    // Target only those Dashlets which are inactive.
+    $dashletClause = $dashletIDs ? "dashboard_id NOT IN (" . implode(',', $dashletIDs) . ")" : '(1)';
+
+    // Build params.
+    $params = [
+      1 => [$contactID, 'Integer'],
+    ];
+
+    // Build query.
     $updateQuery = "UPDATE civicrm_dashboard_contact
                     SET is_active = 0
-                    WHERE $dashletClause AND contact_id = {$contactID}";
+                    WHERE $domainDashletClause
+                    AND $dashletClause
+                    AND contact_id = %1";
 
-    CRM_Core_DAO::executeQuery($updateQuery);
+    // Disable inactive widgets.
+    CRM_Core_DAO::executeQuery($updateQuery, $params);
   }
 
   /**
index a0a28476edc2777c95dcf5b4accb80d980df820f..7bf3ae3918b36f22f85035220b9a5d5cd8c03608 100644 (file)
@@ -40,6 +40,13 @@ class CRM_Core_BAO_File extends CRM_Core_DAO_File {
 
   public static $_signableFields = ['entityTable', 'entityID', 'fileID'];
 
+  /**
+   * If there is no setting configured on the admin screens, maximum number
+   * of attachments to try to process when given a list of attachments to
+   * process.
+   */
+  const DEFAULT_MAX_ATTACHMENTS_BACKEND = 100;
+
   /**
    * Takes an associative array and creates a File object.
    *
@@ -596,24 +603,37 @@ AND       CEF.entity_id    = %2";
    * @param int $entityID
    */
   public static function processAttachment(&$params, $entityTable, $entityID) {
-    $numAttachments = Civi::settings()->get('max_attachments');
+    $numAttachments = Civi::settings()->get('max_attachments_backend') ?? self::DEFAULT_MAX_ATTACHMENTS_BACKEND;
 
     for ($i = 1; $i <= $numAttachments; $i++) {
-      if (
-        isset($params["attachFile_$i"]) &&
-        is_array($params["attachFile_$i"])
-      ) {
-        self::filePostProcess(
-          $params["attachFile_$i"]['location'],
-          NULL,
-          $entityTable,
-          $entityID,
-          NULL,
-          TRUE,
-          $params["attachFile_$i"],
-          "attachFile_$i",
-          $params["attachFile_$i"]['type']
-        );
+      if (isset($params["attachFile_$i"])) {
+        /**
+         * Moved the second condition into its own if block to avoid changing
+         * how it works if there happens to be an entry that is not an array,
+         * since we now might exit loop early via newly added break below.
+         */
+        if (is_array($params["attachFile_$i"])) {
+          self::filePostProcess(
+            $params["attachFile_$i"]['location'],
+            NULL,
+            $entityTable,
+            $entityID,
+            NULL,
+            TRUE,
+            $params["attachFile_$i"],
+            "attachFile_$i",
+            $params["attachFile_$i"]['type']
+          );
+        }
+      }
+      else {
+        /**
+         * No point looping 100 times if there aren't any more.
+         * This assumes the array is continuous and doesn't skip array keys,
+         * but (a) where would it be doing that, and (b) it would have caused
+         * problems before anyway if there were skipped keys.
+         */
+        break;
       }
     }
   }
index b02538e4294d08ae3b409854e590bac877feb6d2..995fb6403ab8d9cb33d3674151aba10a80fd7b0c 100644 (file)
@@ -454,6 +454,7 @@ WHERE ceft.entity_id = %1";
    * @return array
    */
   public static function getPartialPaymentWithType($entityId, $entityName = 'participant', $lineItemTotal = NULL) {
+    CRM_Core_Error::deprecatedFunctionWarning('CRM_Contribute_BAO_Contribution::getContributionBalance');
     $value = NULL;
     if (empty($entityName)) {
       return $value;
index 30188ce3bfc878e310754d5ea7c9735443d7147b..4fedbc69af6ce859784a43b37eecd8e8491b97ec 100644 (file)
@@ -168,6 +168,7 @@ class CRM_Core_Config_MagicMerge {
       'maxFileSize' => ['setting'],
       // renamed.
       'maxAttachments' => ['setting', 'max_attachments'],
+      'maxAttachmentsBackend' => ['setting', 'max_attachments_backend'],
       'monetaryDecimalPoint' => ['setting'],
       'monetaryThousandSeparator' => ['setting'],
       'moneyformat' => ['setting'],
index db02ed542a955b0a7a3ce41737c30442df77a0de..5f61bbd2965fdac15f6943921ac1d6081fd05ca4 100644 (file)
@@ -862,8 +862,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
       $params = array_merge($params, $addressParams);
     }
 
-    // @fixme it would be really nice to have a comment here so I had a clue why we are setting $fields[$name] = 1
-    // Also how does relate to similar code in CRM_Contact_BAO_Contact::addBillingNameFieldsIfOtherwiseNotSet()
+    // How does this relate to similar code in CRM_Contact_BAO_Contact::addBillingNameFieldsIfOtherwiseNotSet()?
     $nameFields = ['first_name', 'middle_name', 'last_name'];
     foreach ($nameFields as $name) {
       if (array_key_exists("billing_$name", $params)) {
@@ -871,6 +870,16 @@ class CRM_Core_Form extends HTML_QuickForm_Page {
         $params['preserveDBName'] = TRUE;
       }
     }
+
+    // For legacy reasons we set these creditcard expiry fields if present
+    if (isset($params['credit_card_exp_date'])) {
+      $params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($params);
+      $params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($params);
+    }
+
+    // Assign IP address parameter
+    $params['ip_address'] = CRM_Utils_System::ipAddress();
+
     return $params;
   }
 
index fed155bbff75a8273d115a755ebe90ccdf455f18..50499e9a5127a17d20531fc68402ecf55528e254 100644 (file)
@@ -491,4 +491,25 @@ class CRM_Core_Form_Search extends CRM_Core_Form {
     return (array) $this->get('formValues');
   }
 
+  /**
+   * Set the metadata for the form.
+   *
+   * @throws \CiviCRM_API3_Exception
+   */
+  protected function setSearchMetadata() {}
+
+  /**
+   * Handle force=1 in the url.
+   *
+   * Search field metadata is normally added in buildForm but we are bypassing that in this flow
+   * (I've always found the flow kinda confusing & perhaps that is the problem but this mitigates)
+   *
+   * @throws \CiviCRM_API3_Exception
+   */
+  protected function handleForcedSearch() {
+    $this->setSearchMetadata();
+    $this->postProcess();
+    $this->set('force', 0);
+  }
+
 }
index f6ef3f4de173f3b85387121838c4fdbe2ebf67ae..02557bbb7b698701edcb57454cfa247ea0c240e1 100644 (file)
@@ -326,6 +326,7 @@ class CRM_Core_I18n {
    *   The params of the translation (if any).
    *   - domain: string|array a list of translation domains to search (in order)
    *   - context: string
+   *   - skip_translation: flag (do only escape/replacement, skip the actual translation)
    *
    * @return string
    *   the translated string
@@ -378,24 +379,26 @@ class CRM_Core_I18n {
     $raw = !empty($params['raw']);
     unset($params['raw']);
 
-    if (!empty($domain)) {
-      // It might be prettier to cast to an array, but this is high-traffic stuff.
-      if (is_array($domain)) {
-        foreach ($domain as $d) {
-          $candidate = $this->crm_translate_raw($text, $d, $count, $plural, $context);
-          if ($candidate != $text) {
-            $text = $candidate;
-            break;
+    if (!isset($params['skip_translation'])) {
+      if (!empty($domain)) {
+        // It might be prettier to cast to an array, but this is high-traffic stuff.
+        if (is_array($domain)) {
+          foreach ($domain as $d) {
+            $candidate = $this->crm_translate_raw($text, $d, $count, $plural, $context);
+            if ($candidate != $text) {
+              $text = $candidate;
+              break;
+            }
           }
         }
+        else {
+          $text = $this->crm_translate_raw($text, $domain, $count, $plural, $context);
+        }
       }
       else {
-        $text = $this->crm_translate_raw($text, $domain, $count, $plural, $context);
+        $text = $this->crm_translate_raw($text, NULL, $count, $plural, $context);
       }
     }
-    else {
-      $text = $this->crm_translate_raw($text, NULL, $count, $plural, $context);
-    }
 
     // replace the numbered %1, %2, etc. params if present
     if (count($params) && !$raw) {
@@ -768,7 +771,7 @@ class CRM_Core_I18n {
  *   the translated string
  */
 function ts($text, $params = []) {
-  static $areSettingsAvailable = FALSE;
+  static $bootstrapReady = FALSE;
   static $lastLocale = NULL;
   static $i18n = NULL;
   static $function = NULL;
@@ -778,14 +781,19 @@ function ts($text, $params = []) {
   }
 
   // When the settings become available, lookup customTranslateFunction.
-  if (!$areSettingsAvailable) {
-    $areSettingsAvailable = (bool) \Civi\Core\Container::getBootService('settings_manager');
-    if ($areSettingsAvailable) {
+  if (!$bootstrapReady) {
+    $bootstrapReady = (bool) \Civi\Core\Container::isContainerBooted();
+    if ($bootstrapReady) {
+      // just got ready: determine whether there is a working custom translation function
       $config = CRM_Core_Config::singleton();
       if (isset($config->customTranslateFunction) and function_exists($config->customTranslateFunction)) {
         $function = $config->customTranslateFunction;
       }
     }
+    else {
+      // don't _translate_ anything until bootstrap has progressed enough
+      $params['skip_translation'] = 1;
+    }
   }
 
   $activeLocale = CRM_Core_I18n::getLocale();
index 899d84423106df2dbaf00257263ce7ab3eb4c7ea..a093cbbff57f9d23d2ebde27161b62db3d760fb2 100644 (file)
@@ -123,6 +123,7 @@ class CRM_Core_I18n_SchemaStructure {
           'receipt_from_name' => "varchar(255) COMMENT 'FROM email name used for receipts generated by contributions to this contribution page.'",
           'receipt_text' => "text COMMENT 'text to include above standard receipt info on receipt email. emails are text-only, so do not allow html for now'",
           'footer_text' => "text COMMENT 'Text and html allowed. Displayed at the bottom of the first page of the contribution wizard.'",
+          'frontend_title' => "varchar(255) DEFAULT NULL COMMENT 'Contribution Page Public title'",
         ],
         'civicrm_product' => [
           'name' => "varchar(255) NOT NULL COMMENT 'Required product/premium name'",
@@ -476,6 +477,9 @@ class CRM_Core_I18n_SchemaStructure {
             'rows' => "6",
             'cols' => "50",
           ],
+          'frontend_title' => [
+            'type' => "Text",
+          ],
         ],
         'civicrm_product' => [
           'name' => [
diff --git a/CRM/Core/I18n/SchemaStructure_5_20_alpha1.php b/CRM/Core/I18n/SchemaStructure_5_20_alpha1.php
new file mode 100644 (file)
index 0000000..d7bf2af
--- /dev/null
@@ -0,0 +1,726 @@
+<?php
+/*
++--------------------------------------------------------------------+
+| CiviCRM version 5                                                  |
++--------------------------------------------------------------------+
+| Copyright CiviCRM LLC (c) 2004-2019                                |
++--------------------------------------------------------------------+
+| 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-2019
+ *
+ * Generated from schema_structure.tpl
+ * DO NOT EDIT.  Generated by CRM_Core_CodeGen
+ */
+class CRM_Core_I18n_SchemaStructure_5_20_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) COMMENT 'Location Type Display Name.'",
+        ],
+        'civicrm_option_group' => [
+          'title' => "varchar(255) COMMENT 'Option Group title.'",
+          'description' => "varchar(255) COMMENT 'Option group description.'",
+        ],
+        'civicrm_relationship_type' => [
+          'label_a_b' => "varchar(64) COMMENT 'label for relationship of contact_a to contact_b.'",
+          'label_b_a' => "varchar(64) COMMENT 'Optional label for relationship of contact_b to contact_a.'",
+          'description' => "varchar(255) COMMENT 'Optional verbose description of the relationship type.'",
+        ],
+        'civicrm_contact_type' => [
+          'label' => "varchar(64) COMMENT 'localized Name of Contact Type.'",
+          'description' => "text COMMENT 'localized Optional verbose description of the type.'",
+        ],
+        'civicrm_batch' => [
+          'title' => "varchar(255) COMMENT 'Friendly Name.'",
+          'description' => "text COMMENT 'Description of this batch set.'",
+        ],
+        'civicrm_premiums' => [
+          'premiums_intro_title' => "varchar(255) COMMENT 'Title for Premiums section.'",
+          'premiums_intro_text' => "text COMMENT 'Displayed in <div> at top of Premiums section of page. Text and HTML allowed.'",
+          'premiums_nothankyou_label' => "varchar(255) COMMENT 'Label displayed for No Thank-you option in premiums block (e.g. No thank you)'",
+        ],
+        'civicrm_membership_status' => [
+          'label' => "varchar(128) COMMENT 'Label for Membership Status'",
+        ],
+        'civicrm_survey' => [
+          'title' => "varchar(255) NOT NULL COMMENT 'Title of the Survey.'",
+          'instructions' => "text COMMENT 'Script instructions for volunteers to use for the survey.'",
+          'thankyou_title' => "varchar(255) COMMENT 'Title for Thank-you page (header title tag, and display at the top of the page).'",
+          'thankyou_text' => "text COMMENT 'text and html allowed. displayed above result on success page'",
+        ],
+        'civicrm_participant_status_type' => [
+          'label' => "varchar(255) COMMENT 'localized label for display of this status type'",
+        ],
+        'civicrm_case_type' => [
+          'title' => "varchar(64) NOT NULL COMMENT 'Natural language name for Case Type'",
+          'description' => "varchar(255) COMMENT 'Description of the Case Type'",
+        ],
+        'civicrm_tell_friend' => [
+          'title' => "varchar(255)",
+          'intro' => "text COMMENT 'Introductory message to contributor or participant displayed on the Tell a Friend form.'",
+          'suggested_message' => "text COMMENT 'Suggested message to friends, provided as default on the Tell A Friend form.'",
+          'thankyou_title' => "varchar(255) COMMENT 'Text for Tell a Friend thank you page header and HTML title.'",
+          'thankyou_text' => "text COMMENT 'Thank you message displayed on success page.'",
+        ],
+        'civicrm_custom_group' => [
+          'title' => "varchar(64) NOT NULL COMMENT 'Friendly Name.'",
+          'help_pre' => "text COMMENT 'Description and/or help text to display before fields in form.'",
+          'help_post' => "text COMMENT 'Description and/or help text to display after fields in form.'",
+        ],
+        'civicrm_custom_field' => [
+          'label' => "varchar(255) NOT NULL COMMENT 'Text for form field label (also friendly name for administering this custom property).'",
+          'help_pre' => "text COMMENT 'Description and/or help text to display before this field.'",
+          'help_post' => "text COMMENT 'Description and/or help text to display after this field.'",
+        ],
+        'civicrm_option_value' => [
+          'label' => "varchar(512) NOT NULL COMMENT 'Option string as displayed to users - e.g. the label in an HTML OPTION tag.'",
+          'description' => "text COMMENT 'Optional description.'",
+        ],
+        'civicrm_group' => [
+          'title' => "varchar(64) COMMENT 'Name of Group.'",
+        ],
+        'civicrm_contribution_page' => [
+          'title' => "varchar(255) COMMENT 'Contribution Page title. For top of page display'",
+          'intro_text' => "text COMMENT 'Text and html allowed. Displayed below title.'",
+          'pay_later_text' => "text COMMENT 'The text displayed to the user in the main form'",
+          'pay_later_receipt' => "text COMMENT 'The receipt sent to the user instead of the normal receipt text'",
+          'initial_amount_label' => "varchar(255) COMMENT 'Initial amount label for partial payment'",
+          'initial_amount_help_text' => "text COMMENT 'Initial amount help text for partial payment'",
+          'thankyou_title' => "varchar(255) COMMENT 'Title for Thank-you page (header title tag, and display at the top of the page).'",
+          'thankyou_text' => "text COMMENT 'text and html allowed. displayed above result on success page'",
+          'thankyou_footer' => "text COMMENT 'Text and html allowed. displayed at the bottom of the success page. Common usage is to include link(s) to other pages such as tell-a-friend, etc.'",
+          'receipt_from_name' => "varchar(255) COMMENT 'FROM email name used for receipts generated by contributions to this contribution page.'",
+          'receipt_text' => "text COMMENT 'text to include above standard receipt info on receipt email. emails are text-only, so do not allow html for now'",
+          'footer_text' => "text COMMENT 'Text and html allowed. Displayed at the bottom of the first page of the contribution wizard.'",
+          'frontend_title' => "varchar(255) COMMENT 'Contribution Page Public title'",
+        ],
+        'civicrm_product' => [
+          'name' => "varchar(255) NOT NULL COMMENT 'Required product/premium name'",
+          'description' => "text COMMENT 'Optional description of the product/premium.'",
+          'options' => "text COMMENT 'Store comma-delimited list of color, size, etc. options for the product.'",
+        ],
+        'civicrm_payment_processor' => [
+          'title' => "varchar(127) COMMENT 'Payment Processor Descriptive Name.'",
+        ],
+        'civicrm_membership_type' => [
+          'name' => "varchar(128) COMMENT 'Name of Membership Type'",
+          'description' => "varchar(255) COMMENT 'Description of Membership Type'",
+        ],
+        'civicrm_membership_block' => [
+          'new_title' => "varchar(255) COMMENT 'Title to display at top of block'",
+          'new_text' => "text COMMENT 'Text to display below title'",
+          'renewal_title' => "varchar(255) COMMENT 'Title for renewal'",
+          'renewal_text' => "text COMMENT 'Text to display for member renewal'",
+        ],
+        'civicrm_price_set' => [
+          'title' => "varchar(255) NOT NULL COMMENT 'Displayed title for the Price Set.'",
+          'help_pre' => "text COMMENT 'Description and/or help text to display before fields in form.'",
+          'help_post' => "text COMMENT 'Description and/or help text to display after fields in form.'",
+        ],
+        'civicrm_dashboard' => [
+          'label' => "varchar(255) COMMENT 'dashlet title'",
+        ],
+        'civicrm_uf_group' => [
+          'title' => "varchar(64) NOT NULL COMMENT 'Form title.'",
+          'frontend_title' => "varchar(64) COMMENT 'Profile Form Public title'",
+          'help_pre' => "text COMMENT 'Description and/or help text to display before fields in form.'",
+          'help_post' => "text COMMENT 'Description and/or help text to display after fields in form.'",
+          'cancel_button_text' => "varchar(64) DEFAULT NULL COMMENT 'Custom Text to display on the Cancel button when used in create or edit mode'",
+          'submit_button_text' => "varchar(64) DEFAULT NULL COMMENT 'Custom Text to display on the submit button on profile edit/create screens'",
+        ],
+        'civicrm_uf_field' => [
+          'help_post' => "text COMMENT 'Description and/or help text to display after this field.'",
+          'help_pre' => "text COMMENT 'Description and/or help text to display before this field.'",
+          'label' => "varchar(255) NOT NULL COMMENT 'To save label for fields.'",
+        ],
+        'civicrm_price_field' => [
+          'label' => "varchar(255) NOT NULL COMMENT 'Text for form field label (also friendly name for administering this field).'",
+          'help_pre' => "text COMMENT 'Description and/or help text to display before this field.'",
+          'help_post' => "text COMMENT 'Description and/or help text to display after this field.'",
+        ],
+        'civicrm_price_field_value' => [
+          'label' => "varchar(255) COMMENT 'Price field option label'",
+          'description' => "text DEFAULT NULL COMMENT 'Price field option description.'",
+          'help_pre' => "text DEFAULT NULL COMMENT 'Price field option pre help text.'",
+          'help_post' => "text DEFAULT NULL COMMENT 'Price field option post field help.'",
+        ],
+        'civicrm_pcp_block' => [
+          'link_text' => "varchar(255) DEFAULT NULL COMMENT 'Link text for PCP.'",
+        ],
+        'civicrm_event' => [
+          'title' => "varchar(255) COMMENT 'Event Title (e.g. Fall Fundraiser Dinner)'",
+          'summary' => "text COMMENT 'Brief summary of event. Text and html allowed. Displayed on Event Registration form and can be used on other CMS pages which need an event summary.'",
+          'description' => "text COMMENT 'Full description of event. Text and html allowed. Displayed on built-in Event Information screens.'",
+          'registration_link_text' => "varchar(255) COMMENT 'Text for link to Event Registration form which is displayed on Event Information screen when is_online_registration is true.'",
+          'event_full_text' => "text COMMENT 'Message to display on Event Information page and INSTEAD OF Event Registration form if maximum participants are signed up. Can include email address/info about getting on a waiting list, etc. Text and html allowed.'",
+          'fee_label' => "varchar(255)",
+          'intro_text' => "text COMMENT 'Introductory message for Event Registration page. Text and html allowed. Displayed at the top of Event Registration form.'",
+          'footer_text' => "text COMMENT 'Footer message for Event Registration page. Text and html allowed. Displayed at the bottom of Event Registration form.'",
+          'confirm_title' => "varchar(255) DEFAULT NULL COMMENT 'Title for Confirmation page.'",
+          'confirm_text' => "text COMMENT 'Introductory message for Event Registration page. Text and html allowed. Displayed at the top of Event Registration form.'",
+          'confirm_footer_text' => "text COMMENT 'Footer message for Event Registration page. Text and html allowed. Displayed at the bottom of Event Registration form.'",
+          'confirm_email_text' => "text COMMENT 'text to include above standard event info on confirmation email. emails are text-only, so do not allow html for now'",
+          'confirm_from_name' => "varchar(255) COMMENT 'FROM email name used for confirmation emails.'",
+          'thankyou_title' => "varchar(255) DEFAULT NULL COMMENT 'Title for ThankYou page.'",
+          'thankyou_text' => "text COMMENT 'ThankYou Text.'",
+          'thankyou_footer_text' => "text COMMENT 'Footer message.'",
+          'pay_later_text' => "text COMMENT 'The text displayed to the user in the main form'",
+          'pay_later_receipt' => "text COMMENT 'The receipt sent to the user instead of the normal receipt text'",
+          'initial_amount_label' => "varchar(255) COMMENT 'Initial amount label for partial payment'",
+          'initial_amount_help_text' => "text COMMENT 'Initial amount help text for partial payment'",
+          'waitlist_text' => "text COMMENT 'Text to display when the event is full, but participants can signup for a waitlist.'",
+          'approval_req_text' => "text COMMENT 'Text to display when the approval is required to complete registration for an event.'",
+          'template_title' => "varchar(255) COMMENT 'Event Template Title'",
+        ],
+      ];
+    }
+    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",
+          ],
+          'frontend_title' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_product' => [
+          'name' => [
+            'type' => "Text",
+            'required' => "true",
+          ],
+          'description' => [
+            'type' => "Text",
+          ],
+          'options' => [
+            'type' => "Text",
+          ],
+        ],
+        'civicrm_payment_processor' => [
+          'title' => [
+            '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' => "RichTextEditor",
+            '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' => "RichTextEditor",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'footer_text' => [
+            'type' => "RichTextEditor",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'confirm_title' => [
+            'type' => "Text",
+          ],
+          'confirm_text' => [
+            'type' => "RichTextEditor",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'confirm_footer_text' => [
+            'type' => "RichTextEditor",
+            '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' => "RichTextEditor",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'thankyou_footer_text' => [
+            'type' => "RichTextEditor",
+            'rows' => "6",
+            'cols' => "50",
+          ],
+          'pay_later_text' => [
+            'type' => "RichTextEditor",
+          ],
+          '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 9f9a8b776b56d23b77fa2bc666be70836dccf9a8..bc9dad29b12b874bd87a6769a9a9d51ae158a634 100644 (file)
@@ -193,12 +193,6 @@ class CRM_Core_Invoke {
     $template->assign('formTpl', 'default');
 
     if ($item) {
-      // CRM-7656 - make sure we send a clean sanitized path to create printer friendly url
-      $printerFriendly = CRM_Utils_System::makeURL(
-          'snippet', FALSE, FALSE,
-          CRM_Utils_Array::value('path', $item)
-        ) . '2';
-      $template->assign('printerFriendly', $printerFriendly);
 
       if (!array_key_exists('page_callback', $item)) {
         CRM_Core_Error::debug('Bad item', $item);
index ece09d61d1eabb66abccaac915b109f6ba226189..5c6ec96fff1d42becab46981f6ffc911b98f9292 100644 (file)
@@ -597,21 +597,12 @@ class CRM_Event_Cart_Form_Checkout_Payment extends CRM_Event_Cart_Form_Cart {
    * @throws Exception
    */
   public function make_payment(&$params) {
-    $config = CRM_Core_Config::singleton();
-    if (isset($params["billing_state_province_id-{$this->_bltID}"]) && $params["billing_state_province_id-{$this->_bltID}"]) {
-      $params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params["billing_state_province_id-{$this->_bltID}"]);
-    }
-
-    if (isset($params["billing_country_id-{$this->_bltID}"]) && $params["billing_country_id-{$this->_bltID}"]) {
-      $params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($params["billing_country_id-{$this->_bltID}"]);
-    }
-    $params['ip_address'] = CRM_Utils_System::ipAddress();
-    $params['currencyID'] = $config->defaultCurrency;
+    $params = $this->prepareParamsForPaymentProcessor($params);
+    $params['currencyID'] = CRM_Core_Config::singleton()->defaultCurrency;
 
     $payment = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
     CRM_Core_Payment_Form::mapParams($this->_bltID, $params, $params, TRUE);
-    $params['month'] = $params['credit_card_exp_date']['M'];
-    $params['year'] = $params['credit_card_exp_date']['Y'];
+
     try {
       $result = $payment->doPayment($params);
     }
index 7e2c8a8889dc968e6707625c4c9c560e743dc646..3573106ad52182c6e12c7ae28678d3253a22b874 100644 (file)
@@ -262,8 +262,7 @@ class CRM_Event_Form_ManageEvent_Location extends CRM_Event_Form_ManageEvent {
     }
 
     // create/update event location
-    $location = CRM_Core_BAO_Location::create($params, TRUE, 'event');
-    $params['loc_block_id'] = $location['id'];
+    $params['loc_block_id'] = CRM_Core_BAO_Location::create($params, TRUE, 'event')['id'];
 
     // finally update event params
     $params['id'] = $this->_id;
index bc1d548deea171e0e0a5f9c7b0ac884f372c29b7..dbb46acb7941f49c735cdb47390713cb22b8f57a 100644 (file)
@@ -1228,9 +1228,7 @@ class CRM_Event_Form_Participant extends CRM_Contribute_Form_AbstractEditPayment
 
     if ($this->_mode) {
       // add all the additional payment params we need
-      $this->_params["state_province-{$this->_bltID}"] = $this->_params["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($this->_params["billing_state_province_id-{$this->_bltID}"]);
-      $this->_params["country-{$this->_bltID}"] = $this->_params["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($this->_params["billing_country_id-{$this->_bltID}"]);
-
+      $this->_params = $this->prepareParamsForPaymentProcessor($this->_params);
       $this->_params['amount'] = $params['fee_amount'];
       $this->_params['amount_level'] = $params['amount_level'];
       $this->_params['currencyID'] = $config->defaultCurrency;
@@ -1483,8 +1481,6 @@ class CRM_Event_Form_Participant extends CRM_Contribute_Form_AbstractEditPayment
             $ppDAO->save();
           }
         }
-        // next create the transaction record
-        $transaction = new CRM_Core_Transaction();
 
         // CRM-11124
         if ($this->_params['discount_id']) {
@@ -1495,7 +1491,6 @@ class CRM_Event_Form_Participant extends CRM_Contribute_Form_AbstractEditPayment
             CRM_Price_BAO_PriceSet::parseFirstPriceSetValueIDFromParams($this->_params)
           );
         }
-        $transaction->commit();
       }
     }
 
index 2ac411173084408c1538eda1749c9c219b116bc4..c313e911d93164b5a577c4e22ec6e728b6220e85 100644 (file)
@@ -394,9 +394,6 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
 
     // we do not want to display recently viewed items on Registration pages
     $this->assign('displayRecent', FALSE);
-    // Registration page values are cleared from session, so can't use normal Printer Friendly view.
-    // Use Browser Print instead.
-    $this->assign('browserPrint', TRUE);
 
     $isShowLocation = CRM_Utils_Array::value('is_show_location', $this->_values['event']);
     $this->assign('isShowLocation', $isShowLocation);
@@ -697,12 +694,10 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
    * Handle process after the confirmation of payment by User.
    *
    * @param int $contactID
-   * @param null $contribution
-   * @param null $payment
+   * @param \CRM_Contribute_BAO_Contribution $contribution
    */
-  public function confirmPostProcess($contactID = NULL, $contribution = NULL, $payment = NULL) {
+  public function confirmPostProcess($contactID = NULL, $contribution = NULL) {
     // add/update contact information
-    $fields = array();
     unset($this->_params['note']);
 
     //to avoid conflict overwrite $this->_params
@@ -1598,7 +1593,7 @@ class CRM_Event_Form_Registration extends CRM_Core_Form {
         }
 
         $this->set('value', $value);
-        $this->confirmPostProcess($contactID, NULL, NULL);
+        $this->confirmPostProcess($contactID, NULL);
 
         //lets get additional participant id to cancel.
         if ($this->_allowConfirmation && is_array($cancelledIds)) {
index 18e9ca607c533fb2f38e473123fc21d9f6126106..65d6560c50e05f4548798e2ec336869141814d02 100644 (file)
@@ -90,21 +90,9 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
     if (!$this->preProcessExpress()) {
       //process only primary participant params.
       $registerParams = $this->_params[0];
-      if (isset($registerParams["billing_state_province_id-{$this->_bltID}"])
-        && $registerParams["billing_state_province_id-{$this->_bltID}"]
-      ) {
-        $registerParams["billing_state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($registerParams["billing_state_province_id-{$this->_bltID}"]);
-      }
+      $registerParams = $this->prepareParamsForPaymentProcessor($registerParams);
 
-      if (isset($registerParams["billing_country_id-{$this->_bltID}"]) && $registerParams["billing_country_id-{$this->_bltID}"]) {
-        $registerParams["billing_country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($registerParams["billing_country_id-{$this->_bltID}"]);
-      }
-      if (isset($registerParams['credit_card_exp_date'])) {
-        $registerParams['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($registerParams);
-        $registerParams['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($registerParams);
-      }
       if ($this->_values['event']['is_monetary']) {
-        $registerParams['ip_address'] = CRM_Utils_System::ipAddress();
         $registerParams['currencyID'] = $this->_params[0]['currencyID'];
       }
       //assign back primary participant params.
@@ -472,7 +460,6 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
     $payment = $registerByID = $primaryCurrencyID = $contribution = NULL;
     $paymentObjError = ts('The system did not record payment details for this payment and so could not process the transaction. Please report this error to the site administrator.');
 
-    $this->participantIDS = [];
     $fields = [];
     foreach ($params as $key => $value) {
       CRM_Event_Form_Registration_Confirm::fixLocationFields($value, $fields, $this);
@@ -674,7 +661,7 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
       }
       $this->assign('register_date', $registerDate);
 
-      $this->confirmPostProcess($contactID, $contribution, $payment);
+      $this->confirmPostProcess($contactID, $contribution);
     }
 
     //handle if no additional participant.
@@ -1196,13 +1183,13 @@ class CRM_Event_Form_Registration_Confirm extends CRM_Event_Form_Registration {
     }
 
     //get email primary first if exist
-    $subscribtionEmail = ['email' => CRM_Utils_Array::value('email-Primary', $params)];
-    if (!$subscribtionEmail['email']) {
-      $subscribtionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
+    $subscriptionEmail = ['email' => CRM_Utils_Array::value('email-Primary', $params)];
+    if (!$subscriptionEmail['email']) {
+      $subscriptionEmail['email'] = CRM_Utils_Array::value("email-{$form->_bltID}", $params);
     }
     // subscribing contact to groups
-    if (!empty($subscribeGroupIds) && $subscribtionEmail['email']) {
-      CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscribtionEmail, $contactID);
+    if (!empty($subscribeGroupIds) && $subscriptionEmail['email']) {
+      CRM_Mailing_Event_BAO_Subscribe::commonSubscribe($subscribeGroupIds, $subscriptionEmail, $contactID);
     }
 
     return $contactID;
index 77297e325afd4d2eaba861e8438882e8eb3c5877..bb69047bc3aeec7a77bbe9f709792c6034645661 100644 (file)
@@ -1105,23 +1105,9 @@ class CRM_Event_Form_Registration_Register extends CRM_Event_Form_Registration {
       $this->set('contributeMode', 'direct');
 
       // This code is duplicated multiple places and should be consolidated.
-      if (isset($params["state_province_id-{$this->_bltID}"]) &&
-        $params["state_province_id-{$this->_bltID}"]
-      ) {
-        $params["state_province-{$this->_bltID}"] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params["state_province_id-{$this->_bltID}"]);
-      }
+      $params = $this->prepareParamsForPaymentProcessor($params);
 
-      if (isset($params["country_id-{$this->_bltID}"]) &&
-        $params["country_id-{$this->_bltID}"]
-      ) {
-        $params["country-{$this->_bltID}"] = CRM_Core_PseudoConstant::countryIsoCode($params["country_id-{$this->_bltID}"]);
-      }
-      if (isset($params['credit_card_exp_date'])) {
-        $params['year'] = CRM_Core_Payment_Form::getCreditCardExpirationYear($params);
-        $params['month'] = CRM_Core_Payment_Form::getCreditCardExpirationMonth($params);
-      }
       if ($this->_values['event']['is_monetary']) {
-        $params['ip_address'] = CRM_Utils_System::ipAddress();
         $params['currencyID'] = $config->defaultCurrency;
         $params['invoiceID'] = $invoiceID;
       }
index a95df716d8f73142bfe454d3668ead18e346a5e0..1541cb9e8eca698f46805ad3cf27aad6134fb435 100644 (file)
@@ -128,6 +128,9 @@ INSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_c
 
     if ($processor->isMergeSameAddress()) {
       foreach (array_keys($processor->getAdditionalFieldsForSameAddressMerge()) as $field) {
+        if ($field === 'id') {
+          $field = 'civicrm_primary_id';
+        }
         $processor->setColumnAsCalculationOnly($field);
       }
     }
index 7d311aa7df9c74f0a182347ddfc1091085fb18df..9a5d5f92c8d03f19853ec7abc37645b29a4d2aa3 100644 (file)
@@ -803,7 +803,7 @@ class CRM_Export_BAO_ExportProcessor {
             $addressWhere .= " OR civicrm_address.supplemental_address_1 <> ''";
           }
         }
-        $whereClauses['address'] = $addressWhere;
+        $whereClauses['address'] = '(' . $addressWhere . ')';
       }
     }
 
@@ -2376,6 +2376,7 @@ WHERE  id IN ( $deleteIDString )
 
     $query = "SELECT * FROM $exportTempTable";
 
+    $this->instantiateTempTable($headerRows);
     while (1) {
       $limitQuery = $query . "
 LIMIT $offset, $limit
@@ -2395,16 +2396,38 @@ LIMIT $offset, $limit
         }
         $componentDetails[] = $row;
       }
-      CRM_Core_Report_Excel::writeCSVFile($this->getExportFileName(),
-        $headerRows,
-        $componentDetails,
-        NULL,
-        $writeHeader
-      );
-
-      $writeHeader = FALSE;
+      $this->writeRows($headerRows, $componentDetails);
+
       $offset += $limit;
     }
   }
 
+  /**
+   * Set up the temp table.
+   *
+   * @param array $headerRows
+   */
+  protected function instantiateTempTable(array $headerRows) {
+    CRM_Utils_System::download(CRM_Utils_String::munge($this->getExportFileName()),
+      'text/x-csv',
+      CRM_Core_DAO::$_nullObject,
+      'csv',
+      FALSE
+    );
+    CRM_Core_Report_Excel::makeCSVTable($headerRows, [], NULL, TRUE, TRUE);
+  }
+
+  /**
+   * @param array $headerRows
+   * @param array $componentDetails
+   */
+  protected function writeRows(array $headerRows, array $componentDetails) {
+    CRM_Core_Report_Excel::writeCSVFile($this->getExportFileName(),
+      $headerRows,
+      $componentDetails,
+      NULL,
+      FALSE
+    );
+  }
+
 }
index 85afbee9deb7d18cf632e1919a4f7796d4f29158..af012f8c9836162c2968761648234c67f809a02e 100644 (file)
@@ -270,6 +270,19 @@ WHERE cft.id = %1
     return Civi::$statics[__CLASS__]['entity_financial_account'][$financialTypeID][$relationTypeId];
   }
 
+  /**
+   * Get the sales tax financial account id for the financial type id.
+   *
+   * This is a helper wrapper to make the function name more readable.
+   *
+   * @param int $financialAccountID
+   *
+   * @return int
+   */
+  public static function getSalesTaxFinancialAccount($financialAccountID) {
+    return self::getFinancialAccountForFinancialTypeByRelationship($financialAccountID, 'Sales Tax Account is');
+  }
+
   /**
    * Get Financial Account type relations.
    *
index c740bff55fbf4ed12f72db083eefd0cd573d7c9d..837ddd678225b6adf4d81360748a3fe7453d6e42 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Generated from xml/schema/CRM/Financial/FinancialTrxn.xml
  * DO NOT EDIT.  Generated by CRM_Core_CodeGen
- * (GenCodeChecksum:ea6e4e27680634c1c2e4def15d91e02c)
+ * (GenCodeChecksum:30dff7f6f16ef7cd997187a202a59173)
  */
 
 /**
@@ -145,6 +145,13 @@ class CRM_Financial_DAO_FinancialTrxn extends CRM_Core_DAO {
    */
   public $pan_truncation;
 
+  /**
+   * Payment Processor external order reference
+   *
+   * @var string
+   */
+  public $order_reference;
+
   /**
    * Class constructor.
    */
@@ -460,6 +467,22 @@ class CRM_Financial_DAO_FinancialTrxn extends CRM_Core_DAO {
             'type' => 'Text',
           ],
         ],
+        'financial_trxn_order_reference' => [
+          'name' => 'order_reference',
+          'type' => CRM_Utils_Type::T_STRING,
+          'title' => ts('Order Reference'),
+          'description' => ts('Payment Processor external order reference'),
+          'maxlength' => 255,
+          'size' => 25,
+          'where' => 'civicrm_financial_trxn.order_reference',
+          'table_name' => 'civicrm_financial_trxn',
+          'entity' => 'FinancialTrxn',
+          'bao' => 'CRM_Financial_DAO_FinancialTrxn',
+          'localizable' => 0,
+          'html' => [
+            'type' => 'Text',
+          ],
+        ],
       ];
       CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
     }
index 724059888435b786647d486bd64771415267e97a..098e9dcb4cc05beaaba9c2526dfa0af42ca89b88 100644 (file)
@@ -154,6 +154,7 @@ class CRM_Financial_Form_FinancialAccount extends CRM_Contribute_Form {
     }
     if ($self->_action & CRM_Core_Action::UPDATE) {
       if (!(isset($values['is_tax']))) {
+        // @todo replace with call to CRM_Financial_BAO_FinancialAccount getSalesTaxFinancialAccount
         $relationshipId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Sales Tax Account is' "));
         $params = [
           'financial_account_id' => $self->_id,
index 3ac1bd169660a77a5bc4bdd9517774386ce2c467..b6834aac46e9e25e09aa5094713d05d06386ad01 100644 (file)
@@ -244,6 +244,7 @@ class CRM_Financial_Form_FinancialTypeAccount extends CRM_Contribute_Form {
       ];
       $defaults = [];
       if ($self->_action == CRM_Core_Action::ADD) {
+        // @todo replace with call to CRM_Financial_BAO_FinancialAccount getSalesTaxFinancialAccount
         $relationshipId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Sales Tax Account is' "));
         $isTax = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_FinancialAccount', $values['financial_account_id'], 'is_tax');
         if ($values['account_relationship'] == $relationshipId) {
index 3c71a3ca33a1d485a6673d65be1d09759a3d10fe..3766625e71da5bfd4102a925f6daa47072c95d29 100644 (file)
@@ -550,7 +550,9 @@ abstract class CRM_Import_Parser {
   /**
    * Parse a field which could be represented by a label or name value rather than the DB value.
    *
-   * We will try to match name first but if not available then see if we have a label that can be converted to a name.
+   * We will try to match name first or (per https://lab.civicrm.org/dev/core/issues/1285 if we have an id.
+   *
+   * but if not available then see if we have a label that can be converted to a name.
    *
    * @param string|int|null $submittedValue
    * @param array $fieldSpec
@@ -559,15 +561,24 @@ abstract class CRM_Import_Parser {
    * @return mixed
    */
   protected function parsePseudoConstantField($submittedValue, $fieldSpec) {
+    // dev/core#1289 Somehow we have wound up here but the BAO has not been specified in the fieldspec so we need to check this but future us problem, for now lets just return the submittedValue
+    if (!isset($fieldSpec['bao'])) {
+      return $submittedValue;
+    }
     /* @var \CRM_Core_DAO $bao */
     $bao = $fieldSpec['bao'];
     // For historical reasons use validate as context - ie disabled name matches ARE permitted.
     $nameOptions = $bao::buildOptions($fieldSpec['name'], 'validate');
-    if (!isset($nameOptions[$submittedValue])) {
-      $labelOptions = array_flip($bao::buildOptions($fieldSpec['name'], 'match'));
-      if (isset($labelOptions[$submittedValue])) {
-        return array_search($labelOptions[$submittedValue], $nameOptions, TRUE);
-      }
+    if (isset($nameOptions[$submittedValue])) {
+      return $submittedValue;
+    }
+    if (in_array($submittedValue, $nameOptions)) {
+      return array_search($submittedValue, $nameOptions, TRUE);
+    }
+
+    $labelOptions = array_flip($bao::buildOptions($fieldSpec['name'], 'match'));
+    if (isset($labelOptions[$submittedValue])) {
+      return array_search($labelOptions[$submittedValue], $nameOptions, TRUE);
     }
     return '';
   }
index 54ea9d029781cf01ec629f2806aba31aee423c2f..db9c7f3995c0421b563e1fc4732dd98997fe4907 100644 (file)
@@ -360,12 +360,22 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership {
     }
     $params['skipLineItem'] = TRUE;
 
-    //record contribution for this membership
+    // Record contribution for this membership and create a MembershipPayment
     if (!empty($params['contribution_status_id']) && empty($params['relate_contribution_id'])) {
       $memInfo = array_merge($params, ['membership_id' => $membership->id]);
       $params['contribution'] = self::recordMembershipContribution($memInfo);
     }
 
+    // Add/update MembershipPayment record for this membership if it is a related contribution
+    if (!empty($params['relate_contribution_id'])) {
+      $membershipPaymentParams = [
+        'membership_id' => $membership->id,
+        'membership_type_id' => $membership->membership_type_id,
+        'contribution_id' => $params['relate_contribution_id'],
+      ];
+      civicrm_api3('MembershipPayment', 'create', $membershipPaymentParams);
+    }
+
     if (!empty($params['lineItems'])) {
       $params['line_item'] = $params['lineItems'];
     }
@@ -402,16 +412,6 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership {
       );
     }
 
-    //insert payment record for this membership
-    if (!empty($params['relate_contribution_id'])) {
-      $membershipPaymentParams = [
-        'membership_id' => $membership->id,
-        'membership_type_id' => $membership->membership_type_id,
-        'contribution_id' => $params['relate_contribution_id'],
-      ];
-      civicrm_api3('MembershipPayment', 'create', $membershipPaymentParams);
-    }
-
     $transaction->commit();
 
     self::createRelatedMemberships($params, $membership);
@@ -2438,14 +2438,17 @@ WHERE      civicrm_membership.is_test = 0
 
   /**
    * Record contribution record associated with membership.
+   * This will update an existing contribution if $params['contribution_id'] is passed in.
+   * This will create a MembershipPayment to link the contribution and membership
    *
    * @param array $params
    *   Array of submitted params.
    * @param array $ids
    *   (@return CRM_Contribute_BAO_Contribution
    *
-   * @throws \CiviCRM_API3_Exception
+   * @return CRM_Contribute_BAO_Contribution
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   public static function recordMembershipContribution(&$params, $ids = []) {
     if (!empty($ids)) {
index e7478f8b1310de74db35e4ceccccb1eca04fb1dd..3e80eb7615da505ff7ff5a7ccaa28d868a4d1852 100644 (file)
@@ -96,7 +96,6 @@ class CRM_Pledge_Form_Pledge extends CRM_Core_Form {
       list($this->userDisplayName,
         $this->userEmail
         ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID);
-      $this->assign('displayName', $this->userDisplayName);
     }
 
     $this->setPageTitle(ts('Pledge'));
@@ -153,6 +152,9 @@ class CRM_Pledge_Form_Pledge extends CRM_Core_Form {
       $this->assign('installments', $defaults['installments']);
     }
     else {
+      if ($this->_contactID) {
+        $defaults['contact_id'] = $this->_contactID;
+      }
       // default values.
       $defaults['create_date'] = date('Y-m-d');
       $defaults['start_date'] = date('Y-m-d');
@@ -211,11 +213,9 @@ class CRM_Pledge_Form_Pledge extends CRM_Core_Form {
       return;
     }
 
-    if ($this->_context == 'standalone') {
-      $this->addEntityRef('contact_id', ts('Contact'), [
-        'create' => TRUE,
-        'api' => ['extra' => ['email']],
-      ], TRUE);
+    $contactField = $this->addEntityRef('contact_id', ts('Contact'), ['create' => TRUE, 'api' => ['extra' => ['email']]], TRUE);
+    if ($this->_context != 'standalone') {
+      $contactField->freeze();
     }
 
     $showAdditionalInfo = FALSE;
@@ -545,12 +545,6 @@ class CRM_Pledge_Form_Pledge extends CRM_Core_Form {
       // send Acknowledgment mail.
       CRM_Pledge_BAO_Pledge::sendAcknowledgment($this, $params);
 
-      if (!isset($this->userEmail)) {
-        list($this->userDisplayName,
-          $this->userEmail
-          ) = CRM_Contact_BAO_Contact_Location::getEmailDetails($this->_contactID);
-      }
-
       $statusMsg .= ' ' . ts("An acknowledgment email has been sent to %1.<br />", [1 => $this->userEmail]);
 
       // build the payment urls.
index 9c6704058a645244a0ec98b060dc6b96ddabe1f2..15526bd03071c620cfaa5b7f0fcd958fbdf5fa01 100644 (file)
@@ -660,7 +660,7 @@ class CRM_Report_Form_Contribute_Lybunt extends CRM_Report_Form {
     ];
     if ($this->_params['charts']) {
       // build chart.
-      CRM_Utils_OpenFlashChart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
+      CRM_Utils_Chart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
       $this->assign('chartType', $this->_params['charts']);
     }
   }
index bffb359186fc21a24a837b82c2afc00d7027d2ae..2239525f91290958e864a563e6055c50e98e2032 100644 (file)
@@ -849,7 +849,7 @@ ROUND(AVG({$this->_aliases['civicrm_contribution_soft']}.amount), 2) as civicrm_
         $config = CRM_Core_Config::Singleton();
         $graphRows['xname'] = $this->_interval;
         $graphRows['yname'] = ts('Amount (%1)', array(1 => $config->defaultCurrency));
-        CRM_Utils_OpenFlashChart::chart($graphRows, $this->_params['charts'], $this->_interval);
+        CRM_Utils_Chart::chart($graphRows, $this->_params['charts'], $this->_interval);
         $this->assign('chartType', $this->_params['charts']);
       }
     }
index 56c3d45e31cb65f9bb6034151a12c6bee5f08eed..98ac7baefc27127dc917e69eef105b4f1c4ba3ff 100644 (file)
@@ -544,7 +544,7 @@ class CRM_Report_Form_Contribute_Sybunt extends CRM_Report_Form {
     ];
     if ($this->_params['charts']) {
       // build the chart.
-      CRM_Utils_OpenFlashChart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
+      CRM_Utils_Chart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
       $this->assign('chartType', $this->_params['charts']);
     }
   }
index 25c5c533b2bbfea7a83f5674fee6e4dc59a3c1e0..40373be36cc6329bde5f4492fbf56e61c9f86ef7 100644 (file)
@@ -399,7 +399,7 @@ class CRM_Report_Form_Event_IncomeCountSummary extends CRM_Report_Form {
           $chartInfo['xLabelAngle'] = 20;
 
           // build the chart.
-          CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
+          CRM_Utils_Chart::buildChart($chartInfo, $this->_params['charts']);
         }
       }
     }
index bfbc8e5a9187fef7be3efd6db31c6e042c0b32f4..b046a7b779eb4daa34a96a9037f7d530da759545 100644 (file)
@@ -368,7 +368,7 @@ class CRM_Report_Form_Event_Summary extends CRM_Report_Form {
           $chartInfo['xLabelAngle'] = 20;
 
           // build the chart.
-          CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
+          CRM_Utils_Chart::buildChart($chartInfo, $this->_params['charts']);
           $this->assign('chartType', $this->_params['charts']);
         }
       }
index 9cb491a484ae968b36bb2735c4af0ad3615ab586..9130fb95c746ab94388191171c4fa5ad43e525d4 100644 (file)
@@ -429,7 +429,7 @@ class CRM_Report_Form_Mailing_Bounce extends CRM_Report_Form {
     }
 
     // build the chart.
-    CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
+    CRM_Utils_Chart::buildChart($chartInfo, $this->_params['charts']);
     $this->assign('chartType', $this->_params['charts']);
   }
 
index b2239e02b2e52c6743a8588a5f167b9b88c149a9..032e47d150637b331f60651dcc3fa3f02e2a7a93 100644 (file)
@@ -349,7 +349,7 @@ class CRM_Report_Form_Mailing_Clicks extends CRM_Report_Form {
     }
 
     // build the chart.
-    CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
+    CRM_Utils_Chart::buildChart($chartInfo, $this->_params['charts']);
     $this->assign('chartType', $this->_params['charts']);
   }
 
index f040552ca47925724a0cde6558c01a390520b4bd..1c2893f2a881c3efcd8cfbb8a53fbfa05b985261 100644 (file)
@@ -340,7 +340,7 @@ class CRM_Report_Form_Mailing_Opened extends CRM_Report_Form {
     }
 
     // build the chart.
-    CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
+    CRM_Utils_Chart::buildChart($chartInfo, $this->_params['charts']);
     $this->assign('chartType', $this->_params['charts']);
   }
 
index 549eaf7cda531b6ee697b72ef3cce76c20005a45..a43467175c402c14fe1e6a4063c8f38bcbff041e 100644 (file)
@@ -42,7 +42,7 @@ class CRM_Report_Form_Mailing_Summary extends CRM_Report_Form {
 
   protected $_charts = [
     '' => 'Tabular',
-    'bar_3dChart' => 'Bar Chart',
+    'barchart' => 'Bar Chart',
   ];
 
   /**
@@ -625,7 +625,7 @@ class CRM_Report_Form_Mailing_Summary extends CRM_Report_Form {
     $chartInfo['xSize'] = ((count($rows) * 125) + (count($rows) * count($criteria) * 40));
 
     // build the chart.
-    CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
+    CRM_Utils_Chart::buildChart($chartInfo, $this->_params['charts']);
     $this->assign('chartType', $this->_params['charts']);
   }
 
index 78084e4ab7163974f67af2b37fd51c7482bccda3..620189b553ea07aacd313b7107e72a30bbb1f852 100644 (file)
@@ -524,10 +524,10 @@ GROUP BY    {$this->_aliases['civicrm_contribution']}.currency
           'xname' => ts('Member Since / Member Type'),
           'yname' => ts('Fees'),
         ];
-        CRM_Utils_OpenFlashChart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
+        CRM_Utils_Chart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
       }
       else {
-        CRM_Utils_OpenFlashChart::chart($graphRows, $this->_params['charts'], $this->_interval);
+        CRM_Utils_Chart::chart($graphRows, $this->_params['charts'], $this->_interval);
       }
     }
     $this->assign('chartType', $this->_params['charts']);
index 9ab478c0846ae746ae44c57f12c4aaaa89370705..de12e54c119f66c2cac64a923fdcddaab3e28957 100644 (file)
@@ -342,7 +342,7 @@ LEFT  JOIN civicrm_contribution  {$this->_aliases['civicrm_contribution']}
       }
 
       // build chart.
-      CRM_Utils_OpenFlashChart::chart($graphRows, $this->_params['charts'], $this->_interval);
+      CRM_Utils_Chart::chart($graphRows, $this->_params['charts'], $this->_interval);
     }
     parent::endPostProcess();
   }
diff --git a/CRM/Upgrade/Incremental/php/FiveTwenty.php b/CRM/Upgrade/Incremental/php/FiveTwenty.php
new file mode 100644 (file)
index 0000000..9485ff8
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 5                                                  |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2019                                |
+ +--------------------------------------------------------------------+
+ | 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 FiveTwenty */
+class CRM_Upgrade_Incremental_php_FiveTwenty 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, "%1", has been added. This permission is now used to control access to the Manage Tags screen.', array(1 => ts('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):
+   */
+
+  // public static function taskFoo(CRM_Queue_TaskContext $ctx, ...) {
+  //   return TRUE;
+  // }
+
+  /**
+   * Upgrade function.
+   *
+   * @param string $rev
+   */
+  public function upgrade_5_20_alpha1($rev) {
+    $this->addTask('Add frontend title column to contribution page table', 'addColumn', 'civicrm_contribution_page',
+      'frontend_title', "varchar(255) DEFAULT NULL COMMENT 'Contribution Page Public title'", TRUE, '5.20.alpha1');
+    $this->addTask('Add is_template field to civicrm_contribution', 'addColumn', 'civicrm_contribution', 'is_template',
+      "tinyint(4) DEFAULT '0' COMMENT 'Shows this is a template for recurring contributions.'", FALSE, '5.20.alpha1');
+    $this->addTask('Add order_reference field to civicrm_financial_trxn', 'addColumn', 'civicrm_financial_trxn', 'order_reference',
+      "varchar(255) COMMENT 'Payment Processor external order reference'", FALSE, '5.20.alpha1');
+    $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
+  }
+
+}
diff --git a/CRM/Upgrade/Incremental/sql/5.19.beta1.mysql.tpl b/CRM/Upgrade/Incremental/sql/5.19.beta1.mysql.tpl
new file mode 100644 (file)
index 0000000..e565ce5
--- /dev/null
@@ -0,0 +1 @@
+{* file to handle db changes in 5.19.beta1 during upgrade *}
diff --git a/CRM/Upgrade/Incremental/sql/5.20.alpha1.mysql.tpl b/CRM/Upgrade/Incremental/sql/5.20.alpha1.mysql.tpl
new file mode 100644 (file)
index 0000000..34686ec
--- /dev/null
@@ -0,0 +1 @@
+{* file to handle db changes in 5.20.alpha1 during upgrade *}
diff --git a/CRM/Utils/Chart.php b/CRM/Utils/Chart.php
new file mode 100644 (file)
index 0000000..6562773
--- /dev/null
@@ -0,0 +1,331 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 5                                                  |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2019                                |
+ +--------------------------------------------------------------------+
+ | 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-2019
+ */
+
+/**
+ * Build various graphs using the dc chart library.
+ */
+class CRM_Utils_Chart {
+
+  /**
+   * Colours.
+   * @var array
+   */
+  private static $_colours = [
+    "#C3CC38",
+    "#C8B935",
+    "#CEA632",
+    "#D3932F",
+    "#D9802C",
+    "#FA6900",
+    "#DC9B57",
+    "#F78F01",
+    "#5AB56E",
+    "#6F8069",
+    "#C92200",
+    "#EB6C5C",
+  ];
+
+  /**
+   * Build The Bar Gharph.
+   *
+   * @param array $params
+   *   Assoc array of name/value pairs.
+   *
+   * @return object
+   *   $chart   object of open flash chart.
+   */
+  public static function barChart($params) {
+    $output = static::commonParamsManipulation($params);
+    if (empty($output)) {
+      return NULL;
+    }
+    $output['type'] = 'barchart';
+    // Default title
+    $output += ['title' => ts('Bar Chart')];
+
+    // ? Not sure what reports use this, but it's not implemented.
+    // call user define function to handle on click event.
+    // if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
+    //  $bars[$barCount]->set_on_click($onClickFunName);
+    // }
+
+    //// get the currency to set in tooltip.
+    //$tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
+
+    return $output;
+  }
+
+  /**
+   * Build a pie chart.
+   *
+   * @param array $params
+   *   Assoc array of name/value pairs.
+   *
+   * @return array
+   */
+  public static function pieChart($params) {
+    $output = static::commonParamsManipulation($params);
+    if (empty($output)) {
+      return NULL;
+    }
+    $output['type'] = 'piechart';
+    $output += ['title' => ts('Pie Chart')];
+
+    // ? Not sure what reports use this, but it's not implemented.
+    // call user define function to handle on click event.
+    // if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
+    //  $bars[$barCount]->set_on_click($onClickFunName);
+    // }
+
+    //// get the currency to set in tooltip.
+    //$tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
+
+    return $output;
+  }
+
+  /**
+   * Common data manipulation for charts.
+   *
+   * @param array $params
+   *   Assoc array of name/value pairs.
+   *
+   * @return array
+   */
+  public static function commonParamsManipulation($params) {
+    if (empty($params)) {
+      return NULL;
+    }
+    $output = [];
+    if (empty($params['multiValues'])) {
+      $params['multiValues'] = [$params['values']];
+    }
+
+    $output['values'] = [];
+    foreach ($params['multiValues'] as $i => $dataSet) {
+      $output['values'][$i] = [];
+      foreach ($dataSet as $k => $v) {
+        $output['values'][$i][] = ['label' => $k, 'value' => (double) $v];
+      }
+    }
+    if (!$output['values']) {
+      return NULL;
+    }
+
+    // Ensure there's a legend (title)
+    if (!empty($params['legend'])) {
+      $output['title'] = $params['legend'];
+    }
+
+    $output['symbol'] = CRM_Core_BAO_Country::defaultCurrencySymbol();
+
+    // ? Not sure what reports use this, but it's not implemented.
+    // call user define function to handle on click event.
+    // if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
+    //  $bars[$barCount]->set_on_click($onClickFunName);
+    // }
+
+    //// get the currency to set in tooltip.
+    //$tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
+
+    return $output;
+  }
+
+  /**
+   * @param $rows
+   * @param $chart
+   * @param $interval
+   *
+   * @return array
+   */
+  public static function chart($rows, $chart, $interval) {
+    $lcInterval = strtolower($interval);
+    $label = ucfirst($lcInterval);
+    $chartData = $dateKeys = [];
+    $intervalLabels = [
+      'year' => ts('Yearly'),
+      'fiscalyear' => ts('Yearly (Fiscal)'),
+      'month' => ts('Monthly'),
+      'quarter' => ts('Quarterly'),
+      'week' => ts('Weekly'),
+      'yearweek' => ts('Weekly'),
+    ];
+
+    switch ($lcInterval) {
+      case 'month':
+      case 'quarter':
+      case 'week':
+      case 'yearweek':
+        foreach ($rows['receive_date'] as $key => $val) {
+          list($year, $month) = explode('-', $val);
+          $dateKeys[] = substr($rows[$interval][$key], 0, 3) . ' of ' . $year;
+        }
+        $legend = $intervalLabels[$lcInterval];
+        break;
+
+      default:
+        foreach ($rows['receive_date'] as $key => $val) {
+          list($year, $month) = explode('-', $val);
+          $dateKeys[] = $year;
+        }
+        $legend = ts("%1", [1 => $label]);
+        if (!empty($intervalLabels[$lcInterval])) {
+          $legend = $intervalLabels[$lcInterval];
+        }
+        break;
+    }
+
+    if (!empty($dateKeys)) {
+      $graph = [];
+      if (!array_key_exists('multiValue', $rows)) {
+        $rows['multiValue'] = [$rows['value']];
+      }
+      foreach ($rows['multiValue'] as $key => $val) {
+        $graph[$key] = array_combine($dateKeys, $rows['multiValue'][$key]);
+      }
+      $chartData = [
+        'legend' => "$legend " . CRM_Utils_Array::value('legend', $rows, ts('Contribution')) . ' ' . ts('Summary'),
+        'values' => $graph[0],
+        'multiValues' => $graph,
+        'barKeys' => CRM_Utils_Array::value('barKeys', $rows, []),
+      ];
+    }
+
+    // rotate the x labels.
+    $chartData['xLabelAngle'] = CRM_Utils_Array::value('xLabelAngle', $rows, 0);
+    if (!empty($rows['tip'])) {
+      $chartData['tip'] = $rows['tip'];
+    }
+
+    // legend
+    $chartData['xname'] = CRM_Utils_Array::value('xname', $rows);
+    $chartData['yname'] = CRM_Utils_Array::value('yname', $rows);
+
+    // carry some chart params if pass.
+    foreach ([
+      'xSize',
+      'ySize',
+      'divName',
+    ] as $f) {
+      if (!empty($rows[$f])) {
+        $chartData[$f] = $rows[$f];
+      }
+    }
+
+    return self::buildChart($chartData, $chart);
+  }
+
+  /**
+   * @param $rows
+   * @param $chart
+   * @param $interval
+   * @param $chartInfo
+   *
+   * @return array
+   */
+  public static function reportChart($rows, $chart, $interval, &$chartInfo) {
+    foreach ($interval as $key => $val) {
+      $graph[$val] = $rows['value'][$key];
+    }
+
+    $chartData = [
+      'values' => $graph,
+      'legend' => $chartInfo['legend'],
+      'xname' => $chartInfo['xname'],
+      'yname' => $chartInfo['yname'],
+    ];
+
+    // rotate the x labels.
+    $chartData['xLabelAngle'] = CRM_Utils_Array::value('xLabelAngle', $chartInfo, 20);
+    if (!empty($chartInfo['tip'])) {
+      $chartData['tip'] = $chartInfo['tip'];
+    }
+
+    // carry some chart params if pass.
+    foreach ([
+      'xSize',
+      'ySize',
+      'divName',
+    ] as $f) {
+      if (!empty($rows[$f])) {
+        $chartData[$f] = $rows[$f];
+      }
+    }
+
+    return self::buildChart($chartData, $chart);
+  }
+
+  /**
+   * @param array $params
+   * @param $chart
+   *
+   * @return array
+   */
+  public static function buildChart(&$params, $chart) {
+    $theChart = [];
+    if ($chart && is_array($params) && !empty($params)) {
+      // build the chart objects.
+      $chartObj = CRM_Utils_Chart::$chart($params);
+
+      if ($chartObj) {
+        // calculate chart size.
+        $xSize = CRM_Utils_Array::value('xSize', $params, 400);
+        $ySize = CRM_Utils_Array::value('ySize', $params, 300);
+        if ($chart == 'barChart') {
+          $ySize = CRM_Utils_Array::value('ySize', $params, 250);
+          $xSize = 60 * count($params['values']);
+          // hack to show tooltip.
+          if ($xSize < 200) {
+            $xSize = (count($params['values']) > 1) ? 100 * count($params['values']) : 170;
+          }
+          elseif ($xSize > 600 && count($params['values']) > 1) {
+            $xSize = (count($params['values']) + 400 / count($params['values'])) * count($params['values']);
+          }
+        }
+
+        // generate unique id for this chart instance
+        $uniqueId = md5(uniqid(rand(), TRUE));
+
+        $theChart["chart_{$uniqueId}"]['size'] = ['xSize' => $xSize, 'ySize' => $ySize];
+        $theChart["chart_{$uniqueId}"]['object'] = $chartObj;
+
+        // assign chart data to template
+        $template = CRM_Core_Smarty::singleton();
+        $template->assign('uniqueId', $uniqueId);
+        $template->assign("chartData", json_encode($theChart ?? []));
+      }
+    }
+
+    return $theChart;
+  }
+
+}
index 0c07a9395334cf6462860964931825574655d7c7..3772b4b3836b38488c87715929e6e91e94510a6f 100644 (file)
@@ -104,11 +104,19 @@ abstract class CRM_Utils_Check_Component {
    * @throws \Civi\API\Exception\UnauthorizedException
    */
   public function isDisabled($method) {
-
-    $checks = $this->getChecksConfig();
-    if (!empty($checks[$method])) {
-      return (bool) empty($checks[$method]['is_active']);
+    try {
+      $checks = $this->getChecksConfig();
+      if (!empty($checks[$method])) {
+        return (bool) empty($checks[$method]['is_active']);
+      }
     }
+    catch (PEAR_Exception $e) {
+      // if we're hitting this, DB migration to 5.19 probably hasn't run yet, so
+      // is_active doesn't exist. Ignore this error so the status check (which
+      // might warn about missing migrations!) still renders.
+      // TODO: remove at some point after 5.19
+    }
+
     return FALSE;
   }
 
index 3ed6d8f86235bb08c643aa066dedccf50c6022cb..ed07a6b2aa61e717ac5062ac9045f5db1e34366f 100644 (file)
@@ -879,10 +879,15 @@ function _civicrm_api3_deprecated_activity_buildmailparams($result, $activityTyp
   $params['activity_date_time'] = $result['date'];
   $params['details'] = $result['body'];
 
-  for ($i = 1; $i <= 5; $i++) {
+  $numAttachments = Civi::settings()->get('max_attachments_backend') ?? CRM_Core_BAO_File::DEFAULT_MAX_ATTACHMENTS_BACKEND;
+  for ($i = 1; $i <= $numAttachments; $i++) {
     if (isset($result["attachFile_$i"])) {
       $params["attachFile_$i"] = $result["attachFile_$i"];
     }
+    else {
+      // No point looping 100 times if there's only one attachment
+      break;
+    }
   }
 
   return $params;
index 76887f2bc3cba8bb4ab9908f63b7c4cf6c739db6..3993c4349ae8b1da642b6be076f1bd695ae4002c 100644 (file)
@@ -188,6 +188,11 @@ abstract class CRM_Utils_Hook {
       return $event->getReturnValues();
     }
     else {
+      // We need to ensure tht we will still run known bootstrap related hooks even if the container is not booted.
+      $prebootContainerHooks = array_merge($upgradeFriendlyHooks, ['civicrm_entityTypes', 'civicrm_config']);
+      if (!\Civi\Core\Container::isContainerBooted() && !in_array($fnSuffix, $prebootContainerHooks)) {
+        return;
+      }
       $count = is_array($names) ? count($names) : $names;
       return $this->invokeViaUF($count, $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $fnSuffix);
     }
diff --git a/CRM/Utils/OpenFlashChart.php b/CRM/Utils/OpenFlashChart.php
deleted file mode 100644 (file)
index 178f093..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-<?php
-/*
- +--------------------------------------------------------------------+
- | CiviCRM version 5                                                  |
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2019                                |
- +--------------------------------------------------------------------+
- | 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-2019
- */
-
-require_once 'packages/OpenFlashChart/php-ofc-library/open-flash-chart.php';
-
-/**
- * Build various graphs using Open Flash Chart library.
- */
-class CRM_Utils_OpenFlashChart {
-
-  /**
-   * Colours.
-   * @var array
-   */
-  private static $_colours = [
-    "#C3CC38",
-    "#C8B935",
-    "#CEA632",
-    "#D3932F",
-    "#D9802C",
-    "#FA6900",
-    "#DC9B57",
-    "#F78F01",
-    "#5AB56E",
-    "#6F8069",
-    "#C92200",
-    "#EB6C5C",
-  ];
-
-  /**
-   * Build The Bar Gharph.
-   *
-   * @param array $params
-   *   Assoc array of name/value pairs.
-   *
-   * @return object
-   *   $chart   object of open flash chart.
-   */
-  public static function &barChart(&$params) {
-    $chart = NULL;
-    if (empty($params)) {
-      return $chart;
-    }
-    if (empty($params['multiValues'])) {
-      $params['multiValues'] = [$params['values']];
-    }
-
-    $values = CRM_Utils_Array::value('multiValues', $params);
-    if (!is_array($values) || empty($values)) {
-      return $chart;
-    }
-
-    // get the required data.
-    $chartTitle = !empty($params['legend']) ? $params['legend'] : ts('Bar Chart');
-
-    $xValues = $yValues = [];
-    $xValues = array_keys($values[0]);
-    $yValues = array_values($values[0]);
-
-    // set y axis parameters.
-    $yMin = 0;
-
-    // calculate max scale for graph.
-    $yMax = ceil(max($yValues));
-    if ($mod = $yMax % (str_pad(5, strlen($yMax) - 1, 0))) {
-      $yMax += str_pad(5, strlen($yMax) - 1, 0) - $mod;
-    }
-    $ySteps = $yMax / 5;
-
-    $bars = [];
-    $symbol = CRM_Core_BAO_Country::defaultCurrencySymbol();
-    foreach ($values as $barCount => $barVal) {
-      $bars[$barCount] = new bar_glass();
-
-      $yValues = array_values($barVal);
-      foreach ($yValues as &$yVal) {
-        // type casting is required for chart to render values correctly
-        $yVal = (double) $yVal;
-      }
-      $bars[$barCount]->set_values($yValues);
-      if ($barCount > 0) {
-        // FIXME: for bars > 2, we'll need to come out with other colors
-        $bars[$barCount]->colour('#BF3B69');
-      }
-
-      if ($barKey = CRM_Utils_Array::value($barCount, CRM_Utils_Array::value('barKeys', $params))) {
-        $bars[$barCount]->key($barKey, 12);
-      }
-
-      // call user define function to handle on click event.
-      if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
-        $bars[$barCount]->set_on_click($onClickFunName);
-      }
-
-      // get the currency to set in tooltip.
-      $tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
-      $bars[$barCount]->set_tooltip($tooltip);
-    }
-
-    // create x axis label obj.
-    $xLabels = new x_axis_labels();
-    // set_labels function requires xValues array of string or x_axis_label
-    // so type casting array values to string values
-    array_walk($xValues, function (&$value, $index) {
-      $value = (string) $value;
-    });
-    $xLabels->set_labels($xValues);
-
-    // set angle for labels.
-    if ($xLabelAngle = CRM_Utils_Array::value('xLabelAngle', $params)) {
-      $xLabels->rotate($xLabelAngle);
-    }
-
-    // create x axis obj.
-    $xAxis = new x_axis();
-    $xAxis->set_labels($xLabels);
-
-    // create y axis and set range.
-    $yAxis = new y_axis();
-    $yAxis->set_range($yMin, $yMax, $ySteps);
-
-    // create chart title obj.
-    $title = new title($chartTitle);
-
-    // create chart.
-    $chart = new open_flash_chart();
-
-    // add x axis w/ labels to chart.
-    $chart->set_x_axis($xAxis);
-
-    // add y axis values to chart.
-    $chart->add_y_axis($yAxis);
-
-    // set title to chart.
-    $chart->set_title($title);
-
-    // add bar element to chart.
-    foreach ($bars as $bar) {
-      $chart->add_element($bar);
-    }
-
-    // add x axis legend.
-    if ($xName = CRM_Utils_Array::value('xname', $params)) {
-      $xLegend = new x_legend($xName);
-      $xLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
-      $chart->set_x_legend($xLegend);
-    }
-
-    // add y axis legend.
-    if ($yName = CRM_Utils_Array::value('yname', $params)) {
-      $yLegend = new y_legend($yName);
-      $yLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
-      $chart->set_y_legend($yLegend);
-    }
-
-    return $chart;
-  }
-
-  /**
-   * Build The Pie Gharph.
-   *
-   * @param array $params
-   *   Assoc array of name/value pairs.
-   *
-   * @return object
-   *   $chart   object of open flash chart.
-   */
-  public static function &pieChart(&$params) {
-    $chart = NULL;
-    if (empty($params)) {
-      return $chart;
-    }
-    $allValues = CRM_Utils_Array::value('values', $params);
-    if (!is_array($allValues) || empty($allValues)) {
-      return $chart;
-    }
-
-    // get the required data.
-    $values = [];
-    foreach ($allValues as $label => $value) {
-      $values[] = new pie_value((double) $value, $label);
-    }
-    $graphTitle = !empty($params['legend']) ? $params['legend'] : ts('Pie Chart');
-
-    // get the currency.
-    $symbol = CRM_Core_BAO_Country::defaultCurrencySymbol();
-
-    $pie = new pie();
-    $pie->radius(100);
-
-    // call user define function to handle on click event.
-    if ($onClickFunName = CRM_Utils_Array::value('on_click_fun_name', $params)) {
-      $pie->on_click($onClickFunName);
-    }
-
-    $pie->set_start_angle(35);
-    $pie->add_animation(new pie_fade());
-    $pie->add_animation(new pie_bounce(2));
-
-    // set the tooltip.
-    $tooltip = CRM_Utils_Array::value('tip', $params, "Amount is $symbol #val# of $symbol #total# <br>#percent#");
-    $pie->set_tooltip($tooltip);
-
-    // set colours.
-    $pie->set_colours(self::$_colours);
-
-    $pie->set_values($values);
-
-    // create chart.
-    $chart = new open_flash_chart();
-
-    // create chart title obj.
-    $title = new title($graphTitle);
-    $chart->set_title($title);
-
-    $chart->add_element($pie);
-    $chart->x_axis = NULL;
-
-    return $chart;
-  }
-
-  /**
-   * Build The 3-D Bar Gharph.
-   *
-   * @param array $params
-   *   Assoc array of name/value pairs.
-   *
-   * @return object
-   *   $chart   object of open flash chart.
-   */
-  public static function &bar_3dChart(&$params) {
-    $chart = NULL;
-    if (empty($params)) {
-      return $chart;
-    }
-
-    // $params['values'] should contains the values for each
-    // criteria defined in $params['criteria']
-    $values = CRM_Utils_Array::value('values', $params);
-    $criteria = CRM_Utils_Array::value('criteria', $params);
-    if (!is_array($values) || empty($values) || !is_array($criteria) || empty($criteria)) {
-      return $chart;
-    }
-
-    // get the required data.
-    $xReferences = $xValueLabels = $xValues = $yValues = [];
-
-    foreach ($values as $xVal => $yVal) {
-      if (!is_array($yVal) || empty($yVal)) {
-        continue;
-      }
-
-      $xValueLabels[] = (string) $xVal;
-      foreach ($criteria as $criteria) {
-        $xReferences[$criteria][$xVal] = (double) CRM_Utils_Array::value($criteria, $yVal, 0);
-        $yValues[] = (double) CRM_Utils_Array::value($criteria, $yVal, 0);
-      }
-    }
-
-    if (empty($xReferences)) {
-
-      return $chart;
-
-    }
-
-    // get the currency.
-    $symbol = CRM_Core_BAO_Country::defaultCurrencySymbol();
-
-    // set the tooltip.
-    $tooltip = CRM_Utils_Array::value('tip', $params, "$symbol #val#");
-
-    $count = 0;
-    foreach ($xReferences as $criteria => $values) {
-      $toolTipVal = $tooltip;
-      // for separate tooltip for each criteria
-      if (is_array($tooltip)) {
-        $toolTipVal = CRM_Utils_Array::value($criteria, $tooltip, "$symbol #val#");
-      }
-
-      // create bar_3d object
-      $xValues[$count] = new bar_3d();
-      // set colour pattel
-      $xValues[$count]->set_colour(self::$_colours[$count]);
-      // define colur pattel with bar criteria
-      $xValues[$count]->key((string) $criteria, 12);
-      // define bar chart values
-      $xValues[$count]->set_values(array_values($values));
-
-      // set tooltip
-      $xValues[$count]->set_tooltip($toolTipVal);
-      $count++;
-    }
-
-    $chartTitle = !empty($params['legend']) ? $params['legend'] : ts('Bar Chart');
-
-    // set y axis parameters.
-    $yMin = 0;
-
-    // calculate max scale for graph.
-    $yMax = ceil(max($yValues));
-    if ($mod = $yMax % (str_pad(5, strlen($yMax) - 1, 0))) {
-      $yMax += str_pad(5, strlen($yMax) - 1, 0) - $mod;
-    }
-
-    // if max value of y-axis <= 0, then set default values
-    if ($yMax <= 0) {
-      $ySteps = 1;
-      $yMax = 5;
-    }
-    else {
-      $ySteps = $yMax / 5;
-    }
-
-    // create x axis label obj.
-    $xLabels = new x_axis_labels();
-    $xLabels->set_labels($xValueLabels);
-
-    // set angle for labels.
-    if ($xLabelAngle = CRM_Utils_Array::value('xLabelAngle', $params)) {
-      $xLabels->rotate($xLabelAngle);
-    }
-
-    // create x axis obj.
-    $xAxis = new x_axis();
-    $xAxis->set_labels($xLabels);
-
-    // create y axis and set range.
-    $yAxis = new y_axis();
-    $yAxis->set_range($yMin, $yMax, $ySteps);
-
-    // create chart title obj.
-    $title = new title($chartTitle);
-
-    // create chart.
-    $chart = new open_flash_chart();
-
-    // add x axis w/ labels to chart.
-    $chart->set_x_axis($xAxis);
-
-    // add y axis values to chart.
-    $chart->add_y_axis($yAxis);
-
-    // set title to chart.
-    $chart->set_title($title);
-
-    foreach ($xValues as $bar) {
-      // add bar element to chart.
-      $chart->add_element($bar);
-    }
-
-    // add x axis legend.
-    if ($xName = CRM_Utils_Array::value('xname', $params)) {
-      $xLegend = new x_legend($xName);
-      $xLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
-      $chart->set_x_legend($xLegend);
-    }
-
-    // add y axis legend.
-    if ($yName = CRM_Utils_Array::value('yname', $params)) {
-      $yLegend = new y_legend($yName);
-      $yLegend->set_style("{font-size: 13px; color:#000000; font-family: Verdana; text-align: center;}");
-      $chart->set_y_legend($yLegend);
-    }
-
-    return $chart;
-  }
-
-  /**
-   * @param $rows
-   * @param $chart
-   * @param $interval
-   *
-   * @return array
-   */
-  public static function chart($rows, $chart, $interval) {
-    $lcInterval = strtolower($interval);
-    $label = ucfirst($lcInterval);
-    $chartData = $dateKeys = [];
-    $intervalLabels = [
-      'year' => ts('Yearly'),
-      'fiscalyear' => ts('Yearly (Fiscal)'),
-      'month' => ts('Monthly'),
-      'quarter' => ts('Quarterly'),
-      'week' => ts('Weekly'),
-      'yearweek' => ts('Weekly'),
-    ];
-
-    switch ($lcInterval) {
-      case 'month':
-      case 'quarter':
-      case 'week':
-      case 'yearweek':
-        foreach ($rows['receive_date'] as $key => $val) {
-          list($year, $month) = explode('-', $val);
-          $dateKeys[] = substr($rows[$interval][$key], 0, 3) . ' of ' . $year;
-        }
-        $legend = $intervalLabels[$lcInterval];
-        break;
-
-      default:
-        foreach ($rows['receive_date'] as $key => $val) {
-          list($year, $month) = explode('-', $val);
-          $dateKeys[] = $year;
-        }
-        $legend = ts("%1", [1 => $label]);
-        if (!empty($intervalLabels[$lcInterval])) {
-          $legend = $intervalLabels[$lcInterval];
-        }
-        break;
-    }
-
-    if (!empty($dateKeys)) {
-      $graph = [];
-      if (!array_key_exists('multiValue', $rows)) {
-        $rows['multiValue'] = [$rows['value']];
-      }
-      foreach ($rows['multiValue'] as $key => $val) {
-        $graph[$key] = array_combine($dateKeys, $rows['multiValue'][$key]);
-      }
-      $chartData = [
-        'legend' => "$legend " . CRM_Utils_Array::value('legend', $rows, ts('Contribution')) . ' ' . ts('Summary'),
-        'values' => $graph[0],
-        'multiValues' => $graph,
-        'barKeys' => CRM_Utils_Array::value('barKeys', $rows, []),
-      ];
-    }
-
-    // rotate the x labels.
-    $chartData['xLabelAngle'] = CRM_Utils_Array::value('xLabelAngle', $rows, 0);
-    if (!empty($rows['tip'])) {
-      $chartData['tip'] = $rows['tip'];
-    }
-
-    // legend
-    $chartData['xname'] = CRM_Utils_Array::value('xname', $rows);
-    $chartData['yname'] = CRM_Utils_Array::value('yname', $rows);
-
-    // carry some chart params if pass.
-    foreach ([
-      'xSize',
-      'ySize',
-      'divName',
-    ] as $f) {
-      if (!empty($rows[$f])) {
-        $chartData[$f] = $rows[$f];
-      }
-    }
-
-    return self::buildChart($chartData, $chart);
-  }
-
-  /**
-   * @param $rows
-   * @param $chart
-   * @param $interval
-   * @param $chartInfo
-   *
-   * @return array
-   */
-  public static function reportChart($rows, $chart, $interval, &$chartInfo) {
-    foreach ($interval as $key => $val) {
-      $graph[$val] = $rows['value'][$key];
-    }
-
-    $chartData = [
-      'values' => $graph,
-      'legend' => $chartInfo['legend'],
-      'xname' => $chartInfo['xname'],
-      'yname' => $chartInfo['yname'],
-    ];
-
-    // rotate the x labels.
-    $chartData['xLabelAngle'] = CRM_Utils_Array::value('xLabelAngle', $chartInfo, 20);
-    if (!empty($chartInfo['tip'])) {
-      $chartData['tip'] = $chartInfo['tip'];
-    }
-
-    // carry some chart params if pass.
-    foreach ([
-      'xSize',
-      'ySize',
-      'divName',
-    ] as $f) {
-      if (!empty($rows[$f])) {
-        $chartData[$f] = $rows[$f];
-      }
-    }
-
-    return self::buildChart($chartData, $chart);
-  }
-
-  /**
-   * @param array $params
-   * @param $chart
-   *
-   * @return array
-   */
-  public static function buildChart(&$params, $chart) {
-    $openFlashChart = [];
-    if ($chart && is_array($params) && !empty($params)) {
-      // build the chart objects.
-      $chartObj = CRM_Utils_OpenFlashChart::$chart($params);
-
-      $openFlashChart = [];
-      if ($chartObj) {
-        // calculate chart size.
-        $xSize = CRM_Utils_Array::value('xSize', $params, 400);
-        $ySize = CRM_Utils_Array::value('ySize', $params, 300);
-        if ($chart == 'barChart') {
-          $ySize = CRM_Utils_Array::value('ySize', $params, 250);
-          $xSize = 60 * count($params['values']);
-          // hack to show tooltip.
-          if ($xSize < 200) {
-            $xSize = (count($params['values']) > 1) ? 100 * count($params['values']) : 170;
-          }
-          elseif ($xSize > 600 && count($params['values']) > 1) {
-            $xSize = (count($params['values']) + 400 / count($params['values'])) * count($params['values']);
-          }
-        }
-
-        // generate unique id for this chart instance
-        $uniqueId = md5(uniqid(rand(), TRUE));
-
-        $openFlashChart["chart_{$uniqueId}"]['size'] = ['xSize' => $xSize, 'ySize' => $ySize];
-        $openFlashChart["chart_{$uniqueId}"]['object'] = $chartObj;
-
-        // assign chart data to template
-        $template = CRM_Core_Smarty::singleton();
-        $template->assign('uniqueId', $uniqueId);
-        $template->assign("openFlashChartData", json_encode($openFlashChart));
-      }
-    }
-
-    return $openFlashChart;
-  }
-
-}
index f532e356096c449e885aae33c7b19e911e8c73d9..58c59e47f622bfe069f9e05ab7254534301039a9 100644 (file)
@@ -56,6 +56,11 @@ class GetActionDefaultsProvider implements Generic\SpecProviderInterface {
     if ($isTestField) {
       $isTestField->setDefaultValue('0');
     }
+
+    $isTemplateField = $spec->getFieldByName('is_template');
+    if ($isTemplateField) {
+      $isTemplateField->setDefaultValue('0');
+    }
   }
 
   /**
index daee538ae4c1ef90b7d893b7628bdc8da8ab2bd7..af7958e344366745f4bf1d7f30f35f423b0d4a90 100644 (file)
     $scope.addRoleOnTheFly = function(roles, newType) {
       roles.push({name: newType.label_b_a, displaylabel: newType.label_a_b});
       // Assume that the case role should be A-B but add both directions as options.
-      $scope.relationshipTypeOptions.push({id: newType.label_a_b, text: newType.label_a_b});
+      $scope.relationshipTypeOptions.push({id: newType.label_a_b, text: newType.label_b_a});
       if (newType.label_a_b != newType.label_b_a) {
-        $scope.relationshipTypeOptions.push({id: newType.label_b_a, text: newType.label_b_a});
+        $scope.relationshipTypeOptions.push({id: newType.label_b_a, text: newType.label_a_b});
       }
     };
 
index 0e7ef7c6429de7bedd48ab57a25b872dc31a125d..7572e0fc00172101f7843e1425bab37e86afc7eb 100644 (file)
@@ -41,6 +41,7 @@
  *   API result array.
  *
  * @throws \API_Exception
+ * @throws \CiviCRM_API3_Exception
  */
 function civicrm_api3_loc_block_create($params) {
   $entities = [];
index 0c8b7c13166265dab6dac8f6cadceae849ba119c..5cd0195f0949ca012c5efcfaec49ad5a92996639 100644 (file)
@@ -155,7 +155,7 @@ function _civicrm_api3_payment_processor_pay_spec(&$params) {
   ];
   $params['amount'] = [
     'api.required' => TRUE,
-    'title' => ts('Amount to refund'),
+    'title' => ts('Amount to pay'),
     'type' => CRM_Utils_Type::T_MONEY,
   ];
 }
index 5f4b74bd9bfe8014c3162ca12e8a51a91dc21c98..a3674146350a41aebea2a1b9f174dc0f7a2f3e52 100644 (file)
@@ -32,6 +32,7 @@ mailerJobSize
 mailerJobsMax
 maxFileSize
 max_attachments
+max_attachments_backend
 replyTo
 secondDegRelPermissions
 securityAlert
index e775abbb76edda865a38580d7a539adb53345f57..a1e4172a0add88e9ae1173cdcfc4982d85f62e48 100644 (file)
@@ -9,7 +9,7 @@
  */
 function contribution_create_example() {
   $params = [
-    'contact_id' => 31,
+    'contact_id' => 32,
     'receive_date' => '20120511',
     'total_amount' => '100',
     'financial_type_id' => 1,
@@ -18,7 +18,7 @@ function contribution_create_example() {
     'net_amount' => '95',
     'source' => 'SSF',
     'contribution_status_id' => 1,
-    'honor_contact_id' => 32,
+    'honor_contact_id' => 33,
   ];
 
   try{
@@ -56,7 +56,7 @@ function contribution_create_expectedresult() {
     'values' => [
       '1' => [
         'id' => '1',
-        'contact_id' => '31',
+        'contact_id' => '32',
         'financial_type_id' => '1',
         'contribution_page_id' => '',
         'payment_instrument_id' => '4',
@@ -85,6 +85,7 @@ function contribution_create_expectedresult() {
         'creditnote_id' => '',
         'tax_amount' => '',
         'revenue_recognition_date' => '',
+        'is_template' => '',
         'contribution_type_id' => '1',
       ],
     ],
index 1c22dd7f1f7409a3e51a3b2dfd574fd5e12a9718..16bf6b2e4dcce9b23a970e0b487169e48f93b771 100644 (file)
@@ -9,7 +9,7 @@
  */
 function contribution_create_example() {
   $params = [
-    'contact_id' => 25,
+    'contact_id' => 26,
     'receive_date' => '2012-01-01',
     'total_amount' => '100',
     'financial_type_id' => 1,
@@ -59,7 +59,7 @@ function contribution_create_expectedresult() {
     'values' => [
       '1' => [
         'id' => '1',
-        'contact_id' => '25',
+        'contact_id' => '26',
         'financial_type_id' => '1',
         'contribution_page_id' => '',
         'payment_instrument_id' => '1',
@@ -88,6 +88,7 @@ function contribution_create_expectedresult() {
         'creditnote_id' => '',
         'tax_amount' => '',
         'revenue_recognition_date' => '',
+        'is_template' => '',
         'contribution_type_id' => '1',
       ],
     ],
index e4d36539ba9ad5b1442f1c2df3fb6d4b10985384..d830ef95e0cddec7a811ba8cdebee0c6ed27c132 100644 (file)
@@ -9,7 +9,7 @@
  */
 function contribution_create_example() {
   $params = [
-    'contact_id' => 27,
+    'contact_id' => 28,
     'receive_date' => '20120511',
     'total_amount' => '100',
     'financial_type_id' => 1,
@@ -20,7 +20,7 @@ function contribution_create_example() {
     'contribution_status_id' => 1,
     'soft_credit' => [
       '1' => [
-        'contact_id' => 28,
+        'contact_id' => 29,
         'amount' => 50,
         'soft_credit_type_id' => 3,
       ],
@@ -62,7 +62,7 @@ function contribution_create_expectedresult() {
     'values' => [
       '1' => [
         'id' => '1',
-        'contact_id' => '27',
+        'contact_id' => '28',
         'financial_type_id' => '1',
         'contribution_page_id' => '',
         'payment_instrument_id' => '4',
@@ -91,6 +91,7 @@ function contribution_create_expectedresult() {
         'creditnote_id' => '',
         'tax_amount' => '',
         'revenue_recognition_date' => '',
+        'is_template' => '',
         'contribution_type_id' => '1',
       ],
     ],
index 2c6729fb0a90e80739f285933a3daa0f6dd7b211..915a68c5bcdede4501e431f6688eef4d235f4661 100644 (file)
@@ -9,7 +9,7 @@
  */
 function contribution_create_example() {
   $params = [
-    'contact_id' => 29,
+    'contact_id' => 30,
     'receive_date' => '20120511',
     'total_amount' => '100',
     'financial_type_id' => 1,
@@ -18,7 +18,7 @@ function contribution_create_example() {
     'net_amount' => '95',
     'source' => 'SSF',
     'contribution_status_id' => 1,
-    'soft_credit_to' => 30,
+    'soft_credit_to' => 31,
   ];
 
   try{
@@ -56,7 +56,7 @@ function contribution_create_expectedresult() {
     'values' => [
       '1' => [
         'id' => '1',
-        'contact_id' => '29',
+        'contact_id' => '30',
         'financial_type_id' => '1',
         'contribution_page_id' => '',
         'payment_instrument_id' => '4',
@@ -85,6 +85,7 @@ function contribution_create_expectedresult() {
         'creditnote_id' => '',
         'tax_amount' => '',
         'revenue_recognition_date' => '',
+        'is_template' => '',
         'contribution_type_id' => '1',
       ],
     ],
index 7540683df7fc2d51c2f5afa1760fb1ed614911e1..1d47cb3a30d3b14b16a431a638df01aecd81e461 100644 (file)
@@ -83,6 +83,7 @@ function contribution_create_expectedresult() {
         'creditnote_id' => '',
         'tax_amount' => '',
         'revenue_recognition_date' => '',
+        'is_template' => '',
         'contribution_type_id' => '1',
       ],
     ],
index 3c27c405c59f2120a26ccc1a500e6918b4303ed0..36e23c41c7b4d437ac53b6c4b304a6a4409ae704 100644 (file)
@@ -9,7 +9,7 @@
  */
 function contribution_create_example() {
   $params = [
-    'contact_id' => 12,
+    'contact_id' => 13,
     'receive_date' => '20120511',
     'total_amount' => '100',
     'financial_type_id' => 1,
@@ -73,7 +73,7 @@ function contribution_create_expectedresult() {
     'values' => [
       '1' => [
         'id' => '1',
-        'contact_id' => '12',
+        'contact_id' => '13',
         'financial_type_id' => '1',
         'contribution_page_id' => '',
         'payment_instrument_id' => '1',
@@ -102,6 +102,7 @@ function contribution_create_expectedresult() {
         'creditnote_id' => '',
         'tax_amount' => 0,
         'revenue_recognition_date' => '',
+        'is_template' => '',
         'contribution_type_id' => '1',
         'api.line_item.create' => [
           '0' => [
index c0c8223f508a9c606e6ffdd23fa9a0887637b2a4..f6b6e5690894034bd7ba97dad83ce8c36ab5a29c 100644 (file)
 
 - github      : wmortada
   name        : William Mortada
-  organization: Community IT Academy
+  organization: a-n The Artists Information Company
   jira        : wmortada
 
 - name        : Philipp Michael
index 932661cfc60dc849bb38853382c266858c3c4342..83214556d55ec4eaaba7d2db0554bd7701e3fabb 100644 (file)
@@ -1812,16 +1812,6 @@ input.crm-form-entityref {
 
 /* Set/alter ICONS */
 
-#crm-container div#printer-friendly {
-  float: right;
-  position: relative;
-  margin: -2em 0.5em 0 0;
-}
-/* For Joomla, margin 0 works correctly */
-#crm-container table#crm-content div#printer-friendly {
-  margin: 0;
-}
-
 #crm-container .order-icon {
   height: 15px;
   width: 10px;
@@ -3659,9 +3649,11 @@ span.crm-status-icon {
 .crm-container.crm-public .select2-results {
   font-size: 14px;
 }
+.crm-container.crm-public .select2-container * {
+  box-sizing: content-box;
+}
 .crm-container.crm-public .select2-container .select2-choice {
   padding: 5px 5px 5px 8px;
-  height: 35px;
 }
 .crm-container.crm-public .select2-container-multi .select2-choices {
   padding: 4px;
index 2d4a28470b2ba16e0f5f05d88332eebb42035e86..af0935c78820ef893955b1911c08893dc967787b 100644 (file)
@@ -15,6 +15,16 @@ Other resources for identifying changes are:
     * https://github.com/civicrm/civicrm-joomla
     * https://github.com/civicrm/civicrm-wordpress
 
+## CiviCRM 5.18.2
+
+Released October 9, 2019
+
+- **[Synopsis](release-notes/5.18.2.md#synopsis)**
+- **[Bugs resolved](release-notes/5.18.2.md#bugs)**
+- **[Credits](release-notes/5.18.2.md#credits)**
+- **[Feedback](release-notes/5.18.2.md#feedback)**
+
+
 ## CiviCRM 5.18.1
 
 Released October 5, 2019
diff --git a/release-notes/5.18.2.md b/release-notes/5.18.2.md
new file mode 100644 (file)
index 0000000..5ae23b8
--- /dev/null
@@ -0,0 +1,43 @@
+# CiviCRM 5.18.2
+
+Released October 9, 2019
+
+- **[Synopsis](#synopsis)**
+- **[Bugs resolved](#bugs)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="synopsis"></a>Synopsis
+
+| *Does this version...?*                                         |         |
+|:--------------------------------------------------------------- |:-------:|
+| Fix security vulnerabilities?                                   |   no    |
+| Change the database schema?                                     |   no    |
+| Alter the API?                                                  |   no    |
+| Require attention to configuration options?                     |   no    |
+| Fix problems installing or upgrading to a previous version?     |   no    |
+| Introduce features?                                             |   no    |
+| **Fix bugs?**                                                   | **yes** |
+
+## <a name="bugs"></a>Bugs resolved
+
+* **_PDFLetter_: Fix a warning on the "Print/Merge Document" screen ([dev/core#1281](https://lab.civicrm.org/dev/core/issues/1281): [#15420](https://github.com/civicrm/civicrm-core/pull/15420))**
+* **_Export_: Wrong export list when selecting contact and also when using option "Exclude contacts with "do not mail" (et al)" ([dev/core#1293](https://lab.civicrm.org/dev/core/issues/1293): [#15439](https://github.com/civicrm/civicrm-core/pull/15439))**
+* **_Export_: Ensure that an export file is always generated - even if dataset is empty" ([dev/core#1293](https://lab.civicrm.org/dev/core/issues/1293): [#15440](https://github.com/civicrm/civicrm-core/pull/15440))**
+* **_Import_: Fix value-matching when using certain numerical identifiers ([dev/core#1285](https://lab.civicrm.org/dev/core/issues/1285): [#15453](https://github.com/civicrm/civicrm-core/pull/15453))**
+* **_Import_: "Contribution" import with custom fields may fail due to an underfined index ([dev/core#1269](https://lab.civicrm.org/dev/core/issues/1269): [#15447](https://github.com/civicrm/civicrm-core/pull/15447))**
+* **_Profiles_: Fix sorting by custom fields when using profile search results ([dev/core#1305](https://lab.civicrm.org/dev/core/issues/1305): [#15454](https://github.com/civicrm/civicrm-core/pull/15454))**
+
+
+## <a name="credits"></a>Credits
+
+This release was developed by the following authors and reviewers:
+
+Wikimedia Foundation - Eileen McNaughton; skherraz; tapash;
+Dave D; Australian Greens - Seamus Lee
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Tim Otten and Andrew Hunt.  If you'd like to
+provide feedback on them, please login to https://chat.civicrm.org/civicrm and
+contact `@agh1`.
index 68d82a2367aebaf3d5bf0ad766f9341a7b99ff0a..033d69c18aacf8ba5ec8b7cdbf4cecc9207e4451 100644 (file)
@@ -387,7 +387,27 @@ return [
     'title' => ts('Maximum Attachments'),
     'is_domain' => 1,
     'is_contact' => 0,
-    'description' => ts('Maximum number of files (documents, images, etc.) which can be attached to emails or activities.'),
+    'description' => ts('Maximum number of files (documents, images, etc.) which can be attached to emails or activities. This setting applies to UI forms and limits the number of fields available on the form.'),
+    'help_text' => NULL,
+  ],
+  'max_attachments_backend' => [
+    'group_name' => 'CiviCRM Preferences',
+    'group' => 'core',
+    'name' => 'max_attachments_backend',
+    'legacy_key' => 'maxAttachmentsBackend',
+    'type' => 'Integer',
+    'quick_form_type' => 'Element',
+    'html_type' => 'text',
+    'html_attributes' => [
+      'size' => 2,
+      'maxlength' => 8,
+    ],
+    'default' => CRM_Core_BAO_File::DEFAULT_MAX_ATTACHMENTS_BACKEND,
+    'add' => '5.20',
+    'title' => ts('Maximum Attachments For Backend Processes'),
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'description' => ts('Maximum number of files (documents, images, etc.) which can be processed during backend processing such as automated inbound email processing. This should be a big number higher than the other Maximum Attachments setting above. This setting here merely provides an upper limit to prevent attacks that might overload the server.'),
     'help_text' => NULL,
   ],
   'maxFileSize' => [
index ebd098bdd4981006d14e16a090851c41d0f9738c..f3b7274bc19bb7311a753fb218ae346baacc049f 100644 (file)
@@ -1119,8 +1119,6 @@ class CRM_GCD {
       $group->visibility = 'Public Pages';
       $group->is_active = 1;
       $group->save();
-      $group->buildClause();
-      $group->save();
     }
 
     // 60 are for newsletter
index e3b1dfd33261e299610207bac6ef83d7d8361bbf..0eeacf25e0f85b701fb3808e6a565138c94bbc1b 100644 (file)
@@ -1087,8 +1087,6 @@ class CRM_GCD {
       $group->visibility = 'Public Pages';
       $group->is_active  = 1;
       $group->save();
-      $group->buildClause();
-      $group->save();
     }
 
     // 60 are for newsletter
index 394c05b8b1273560c2a633d3146b9e7ca77c5129..8c573952a35cadf8ca127ae2d4d5e65a0c8a9f84 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.19.alpha1',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.20.alpha1',1,NULL,'a:1:{s:5:\"en_US\";a:0:{}}');
 /*!40000 ALTER TABLE `civicrm_domain` ENABLE KEYS */;
 UNLOCK TABLES;
 
index 144a29dfbce476100a29a97fccd3ef6fba05c663..ae975c47a95a45ef2577a16c59f76def7da3f33d 100644 (file)
     <tr class="columnheader">
         <td colspan="2">{ts}Sending Emails (includes contribution receipts and event confirmations){/ts}</td>
     </tr>
-    <tr class="even">
-        <td class="tasklist nowrap"><a href="{crmURL p="civicrm/admin/setting/smtp" q="reset=1&civicrmDestination=`$destination`"}" title="{$linkTitle|escape}">{ts}Outbound Email{/ts}</a></td>
-        <td>{ts}Settings for outbound email - either SMTP server, port and authentication or Sendmail path and argument.{/ts}</td>
-    </tr>
     <tr class="even">
         <td class="tasklist nowrap"><a href="{crmURL p="civicrm/admin/options/from_email_address" q="reset=1&civicrmDestination=`$destination`"}" title="{$linkTitle|escape}">{ts}From Email Addresses{/ts}</a></td>
         <td>{ts}Define general email address(es) that can be used as the FROM address when sending email to contacts from within CiviCRM (e.g. info@example.org){/ts}</td>
     </tr>
+    <tr class="even">
+        <td class="tasklist nowrap"><a href="{crmURL p="civicrm/admin/setting/smtp" q="reset=1&civicrmDestination=`$destination`"}" title="{$linkTitle|escape}">{ts}Outbound Email{/ts}</a></td>
+        <td>{ts}Settings for outbound email - either SMTP server, port and authentication or Sendmail path and argument.{/ts}</td>
+    </tr>
 
     <tr class="columnheader">
         <td colspan="2">{ts}Online Contributions / Online Membership Signup / Online Event Registration{/ts}</td>
index 607abd348e9050d74e7c9a785a8d2cf700c68985..61d8adccf98ae0fb1facb18c05c79a8739cc537c 100644 (file)
@@ -24,7 +24,7 @@
  +--------------------------------------------------------------------+
 *}
 {include file="CRM/common/dashboard.tpl"}
-{include file="CRM/common/openFlashChart.tpl"}
+{include file="CRM/common/chart.tpl"}
 {* Alerts for critical configuration settings. *}
 {$communityMessages}
 <div class="crm-submit-buttons crm-dashboard-controls">
index 4db862fc7dd1c39e580d4da3089e4896b08cb743..0faf575cd321f4ca40fdc8eb2cde1e5e55daf2ff 100644 (file)
 {* Display monthly and yearly contributions using Google charts (Bar and Pie) *}
 {if $hasContributions}
 <div id="chartData">
-<table class="chart">
-  <tr class="crm-contribution-form-block-open_flash_chart">
-     <td>
+<table >
+  <tr class="crm-contribution-form-block-chart">
+     <td width="50%">
          {if $hasByMonthChart}
              {* display monthly chart *}
-             <div id="open_flash_chart_by_month"></div>
+             <div id="chart_by_month"></div>
          {else}
        {ts}There were no contributions during the selected year.{/ts}
          {/if}
      </td>
-     <td>
+     <td width="50%">
           {* display yearly chart *}
-         <div id="open_flash_chart_by_year"></div>
+         <div id="chart_by_year"></div>
      </td>
   </tr>
 </table>
  </div>
 {/if}
 
-{if $hasOpenFlashChart}
-{include file="CRM/common/openFlashChart.tpl" contriChart=true}
+{if $hasChart}
+{include file="CRM/common/chart.tpl" contriChart=true}
 
 {literal}
 <script type="text/javascript">
 
   CRM.$(function($) {
-    var chartData = {/literal}{$openFlashChartData}{literal};
-    $.each(chartData, function(chartID, chartValues) {
-      createSWFObject(chartID, chartValues.divName, chartValues.size.xSize, chartValues.size.ySize, 'loadData');
-    });
-  });
+    var allData = {/literal}{$chartData}{literal};
 
-  function loadData( chartID ) {
-     var allData = {/literal}{$openFlashChartData}{literal};
-     return JSON.stringify(allData[chartID].object);
-  }
+    $.each( allData, function( chartID, chartValues ) {
+        var divName = "chart_" + chartID;
+        createChart( chartID, divName, 300, 300, allData[chartID].object );
+        });
 
-  function byMonthOnClick( barIndex ) {
-     var allData = {/literal}{$openFlashChartData}{literal};
-     var url     = eval( "allData.by_month.on_click_urls.url_" + barIndex );
-     if ( url ) window.location.href = url;
-  }
+    function byMonthOnClick( barIndex ) {
+       var url = allData.by_month.on_click_urls['url_' + barIndex];
+       if ( url ) window.location.href = url;
+    }
 
-  function byYearOnClick( barIndex ) {
-     var allData = {/literal}{$openFlashChartData}{literal};
-     var url     = eval( "allData.by_year.on_click_urls.url_" + barIndex );
-     if ( url ) window.location.href = url;
-  }
+    function byYearOnClick( barIndex ) {
+       var url = allData.by_year.on_click_urls['url_' + barIndex];
+       if ( url ) window.location.href = url;
+    }
 
- </script>
+  });
+</script>
 {/literal}
 {/if}
index 3b8a79fda7dea283567f1f912f19899f6d5ab208..007f33036bb90a1f8165dea6061aade14715b37d 100644 (file)
@@ -38,6 +38,9 @@
     <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="top"}</div>
   <table class="form-layout-compressed">
   <tr class="crm-contribution-contributionpage-settings-form-block-title"><td class="label">{$form.title.label} {if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_contribution_page' field='title' id=$contributionPageID}{/if}</td><td>{$form.title.html}<br/>
+            <span class="description">{ts}This title will be displayed at the top of the page unless the frontend title field is filled out.<br />Please use only alphanumeric, spaces, hyphens and dashes for Title.{/ts}</td>
+  </tr>
+  <tr class="crm-contribution-contributionpage-settings-form-block-frontend-title"><td class="label">{$form.contribution_page_frontend_title.label} {if $action == 2}{include file='CRM/Core/I18n/Dialog.tpl' table='civicrm_contribution_page' field='frontend_title' id=$contributionPageID}{/if}</td><td>{$form.contribution_page_frontend_title.html}<br/>
             <span class="description">{ts}This title will be displayed at the top of the page.<br />Please use only alphanumeric, spaces, hyphens and dashes for Title.{/ts}</td>
   </tr>
   <tr class="crm-contribution-contributionpage-settings-form-block-financial_type_id"><td class="label">{$form.financial_type_id.label}</td><td>{$form.financial_type_id.html}<br />
index 461f8a8122c0ec842c430be1be1aa127e3007b7a..7c006e99e57e9decdc0b69b93ed8f3f39d942b1b 100644 (file)
     </div>
    {else}
       <table class="form-layout-compressed">
-        {if $context eq 'standalone'}
           <tr class="crm-pledge-form-contact-id">
             <td class="label">{$form.contact_id.label}</td>
             <td>{$form.contact_id.html}</td>
           </tr>
-        {else}
-          <tr class="crm-pledge-form-block-displayName">
-            <td class="font-size12pt right"><strong>{ts}Pledge by{/ts}</strong></td>
-            <td class="font-size12pt"><strong>{$displayName}</strong></td>
-          </tr>
-        {/if}
           <tr class="crm-pledge-form-block-amount">
             <td class="label">{$form.amount.label}</td>
             <td>
index b6c4bd37fe97576b66ca5ff2ab0a61028cfa91ad..f49ee1037580bcb1d23aaf2d4fe3608d8467556f 100644 (file)
  | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
  +--------------------------------------------------------------------+
 *}
-{assign var=uploadURL value=$config->imageUploadURL|replace:'/persist/contribute/':'/persist/'|cat:'openFlashChart/'}
+{assign var=uploadURL value=$config->imageUploadURL|replace:'/persist/contribute/':'/persist/'}
 {* Display weekly,Quarterly,monthly and yearly contributions using pChart (Bar and Pie) *}
 {if $chartEnabled and $chartSupported}
-<div class='crm-flashchart'>
-<table class="chart">
-        <tr>
-            <td>
-                {if $outputMode eq 'print' OR $outputMode eq 'pdf'}
-                    <img src="{$uploadURL|cat:$chartId}.png" />
-                {else}
-              <div id="open_flash_chart_{$uniqueId}"></div>
-                {/if}
-            </td>
-        </tr>
-</table>
-</div>
-
-{if !$printOnly} {* NO print section starts *}
-{if !$section}
-        {include file="CRM/common/openFlashChart.tpl" divId="open_flash_chart_$uniqueId"}
+  <div class='crm-chart'>
+    {if $outputMode eq 'print' OR $outputMode eq 'pdf'}
+      <img src="{$uploadURL|cat:$chartId}.png" />
+    {else}
+      <div id="chart_{$uniqueId}"></div>
+    {/if}
+  </div>
 {/if}
 
-{literal}
-<script type="text/javascript">
-   CRM.$(function($) {
-     buildChart( );
-
-     $("input[id$='submit_print'],input[id$='submit_pdf']").bind('click', function(e){
-       // image creator php file path and append image name
-       var url = CRM.url('civicrm/report/chart', 'name=' + '{/literal}{$chartId}{literal}' + '.png');
+{if !$printOnly} {* NO print section starts *}
+  {if !$section}
+    {include file="CRM/common/chart.tpl" divId="chart_$uniqueId"}
+  {/if}
+  {if $chartData}
+    {literal}
+    <script type="text/javascript">
+       CRM.$(function($) {
+         // Build all charts.
+         var allData = {/literal}{$chartData}{literal};
 
-       //fetch object and 'POST' image
-       swfobject.getObjectById("open_flash_chart_{/literal}{$uniqueId}{literal}").post_image(url, true, false);
-     });
+         $.each( allData, function( chartID, chartValues ) {
+           var divName = {/literal}"chart_{$uniqueId}"{literal};
+           createChart( chartID, divName, chartValues.size.xSize, chartValues.size.ySize, allData[chartID].object );
+         });
 
-     function buildChart( ) {
-       var chartData = {/literal}{$openFlashChartData}{literal};
-       $.each( chartData, function( chartID, chartValues ) {
-         var divName = {/literal}"open_flash_chart_{$uniqueId}"{literal};
-         var loadDataFunction  = {/literal}"loadData{$uniqueId}"{literal};
+         $("input[id$='submit_print'],input[id$='submit_pdf']").bind('click', function(e){
+           // image creator php file path and append image name
+           var url = CRM.url('civicrm/report/chart', 'name=' + '{/literal}{$chartId}{literal}' + '.png');
 
-         createSWFObject( chartID, divName, chartValues.size.xSize, chartValues.size.ySize, loadDataFunction );
+           //fetch object and 'POST' image
+           swfobject.getObjectById("chart_{/literal}{$uniqueId}{literal}").post_image(url, true, false);
+         });
        });
-     }
-   });
 
-  function loadData{/literal}{$uniqueId}{literal}( chartID ) {
-      var allData = {/literal}{$openFlashChartData}{literal};
-      return JSON.stringify(allData[chartID].object);
-  }
-</script>
-{/literal}
-{/if}
+    </script>
+    {/literal}
+  {/if}
 {/if}
index f091432f4734c437c5ed7ce4834766ddf4db508c..75df8102bfa074763fdb8c5fee48ce79e5cbbd73 100644 (file)
   </div>
 {/if}
 
-{if isset($browserPrint) and $browserPrint}
-{* Javascript window.print link. Used for public pages where we can't do printer-friendly view. *}
-<div id="printer-friendly">
-<a href="#" onclick="window.print(); return false;" title="{ts}Print this page.{/ts}">
-  <i class="crm-i fa-print"></i>
-</a>
-</div>
-{else}
-{* Printer friendly link/icon. *}
-<div id="printer-friendly">
-<a href="{$printerFriendly}" target='_blank' title="{ts}Printer-friendly view of this page.{/ts}">
-  <i class="crm-i fa-print"></i>
-</a>
-</div>
-{/if}
-
 {if $pageTitle}
   <div class="crm-title">
     <h1 class="title">{if $isDeleted}<del>{/if}{$pageTitle}{if $isDeleted}</del>{/if}</h1>
diff --git a/templates/CRM/common/chart.tpl b/templates/CRM/common/chart.tpl
new file mode 100644 (file)
index 0000000..1400408
--- /dev/null
@@ -0,0 +1,167 @@
+{*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 5                                                  |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2019                                |
+ +--------------------------------------------------------------------+
+ | 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        |
+ +--------------------------------------------------------------------+
+*}
+<script src="{$config->resourceBase}/bower_components/d3/d3.min.js"></script>
+<script src="{$config->resourceBase}/bower_components/crossfilter2/crossfilter.min.js"></script>
+<script src="{$config->resourceBase}/bower_components/dc-2.1.x/dc.min.js"></script>
+<style src="{$config->resourceBase}/bower_components/dc-2.1.x/dc.min.css"></style>
+{literal}
+<style>
+  .dc-chart path.domain {
+    fill: none;
+    stroke: black;
+  }
+</style>
+<script type="text/javascript">
+function createChart( chartID, divName, xSize, ySize, data ) {
+
+  var div = document.getElementById(divName);
+  if (!div) {
+    console.log("no element found for chart id ", divName);
+    return;
+  }
+
+  // Figure out suitable size based on container size.
+  // In some cases the containing element has no size. We should insist on a minimum size.
+  var w = Math.max(Math.min(div.clientWidth - 32, 800), 316);
+  var h = Math.min(400, parseInt(w / 2));
+
+  var chartNode = document.createElement('div');
+  var heading = document.createElement('h2');
+  heading.textContent = data.title;
+  heading.style.marginBottom = '1rem';
+  heading.style.textAlign = 'center';
+  div.style.width = w + 'px';
+  div.style.marginLeft = 'auto';
+  div.style.marginRight = 'auto';
+
+  var links = document.createElement('div');
+  links.style.textAlign = 'center';
+  links.style.marginBottom = '1rem';
+  var linkSVG = document.createElement('a');
+  linkSVG.href = '#';
+  linkSVG.textContent = 'Download chart (SVG)';
+  linkSVG.addEventListener('click', e => {
+    e.preventDefault();
+    e.stopPropagation();
+    // Create an image.
+    var svg = div.querySelector('svg');
+    var xml = new XMLSerializer().serializeToString(svg);
+    var image64 =  'data:image/svg+xml;base64,' + btoa(xml);
+
+    downloadImageUrl('image/svg+xml', image64, data.title.replace(/[^a-zA-Z0-9-]+/g, '') + '.svg');
+  });
+  function downloadImageUrl(mime, url, filename) {
+    var downloadLink = document.createElement('a');
+    downloadLink.download = filename;
+    downloadLink.href = url;
+    downloadLink.downloadurl = [mime, downloadLink.download, url].join(':');
+    document.body.append(downloadLink);
+    downloadLink.click();
+    document.body.removeChild(downloadLink);
+  }
+  var linkPNG = document.createElement('a');
+  linkPNG.href = '#';
+  linkPNG.textContent = 'Download chart (PNG)';
+  linkPNG.addEventListener('click', e => {
+    e.preventDefault();
+    e.stopPropagation();
+    // Create an image.
+
+    var canvas = document.createElement('canvas');
+    canvas.width = w;
+    canvas.height = h;
+    div.appendChild(canvas);
+
+    var svg = div.querySelector('svg');
+    var xml = new XMLSerializer().serializeToString(svg);
+    var svg64 = btoa(xml);
+    var b64Start = 'data:image/svg+xml;base64,';
+    var image64 = b64Start + svg64;
+
+    var img = document.createElement('img');
+    img.onload = function() {
+      canvas.getContext('2d').drawImage(img, 0, 0);
+      // canvas.style.display = 'block';
+      var imgURL = canvas.toDataURL('image/png');
+      downloadImageUrl('image/png', imgURL, data.title.replace(/[^a-zA-Z0-9-]+/g, '') + '.png');
+      div.removeChild(canvas);
+    };
+    img.src = image64;
+  });
+
+  links.appendChild(linkSVG);
+  links.appendChild(document.createTextNode(' | '));
+  links.appendChild(linkPNG);
+
+  var crossfilterData, ndx, dataDimension, dataGroup, chart;
+  ndx = crossfilter(data.values[0]);
+  dataDimension = ndx.dimension(d => d.label);
+  dataGroup = dataDimension.group().reduceSum(d => d.value);
+  var ordinals = data.values[0].map(d => d.label);
+
+  if (data.type === 'barchart') {
+    chart = dc.barChart(chartNode)
+      .width(w)
+      .height(h)
+      .dimension(dataDimension)
+      .group(dataGroup)
+      .gap(4) // px
+      .x(d3.scale.ordinal(ordinals).domain(ordinals))
+      .xUnits(dc.units.ordinal)
+      .margins({top: 10, right: 30, bottom: 30, left: 90})
+      .elasticY(true)
+      .renderLabel(false)
+      .renderHorizontalGridLines(true)
+      .title(item=> item.key + ': ' + item.value)
+      //.turnOnControls(true)
+      .renderTitle(true);
+  }
+  else if (data.type === 'piechart') {
+    chart = dc.pieChart(chartNode)
+      .width(w)
+      .height(h)
+      .radius(parseInt(h / 2) - 5) // define pie radius
+      .innerRadius(parseInt(h / 4) - 5) // optional
+      .externalRadiusPadding(5)
+      .legend(dc.legend().legendText(d => d.name).y(5))
+      .dimension(dataDimension)
+      .group(dataGroup)
+      .renderLabel(false)
+      .title(item=> item.key + ': ' + item.value)
+      .turnOnControls(true)
+      .renderTitle(true);
+  }
+  // Delay rendering so that animation looks good.
+  window.setTimeout(() => {
+    div.appendChild(heading);
+    div.appendChild(chartNode);
+    div.appendChild(links);
+
+    dc.renderAll();
+  }, 1500);
+}
+</script>
+{/literal}
index 71f11c2b84c0717f73676476754773a8caea24f3..7902146d48e99229887df16aee941b964c67ef4f 100644 (file)
     </div>
     {/if}
 
-{if $browserPrint}
-{* Javascript window.print link. Used for public pages where we can't do printer-friendly view. *}
-<div id="printer-friendly"><a href="#" onclick="window.print(); return false;" title="{ts}Print this page.{/ts}"><i class="crm-i fa-print"></i></a></div>
-{else}
-{* Printer friendly link/icon. *}
-<div id="printer-friendly"><a href="{$printerFriendly}" target='_blank' title="{ts}Printer-friendly view of this page.{/ts}"><i class="crm-i fa-print"></i></a></div>
-{/if}
-
 {if $pageTitle}
   <div class="crm-title">
     <h1 class="title">{if $isDeleted}<del>{/if}{$pageTitle}{if $isDeleted}</del>{/if}</h1>
diff --git a/templates/CRM/common/openFlashChart.tpl b/templates/CRM/common/openFlashChart.tpl
deleted file mode 100644 (file)
index 0995cd1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-{*
- +--------------------------------------------------------------------+
- | CiviCRM version 5                                                  |
- +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2019                                |
- +--------------------------------------------------------------------+
- | 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        |
- +--------------------------------------------------------------------+
-*}
-<script type="text/javascript" src="{$config->resourceBase}packages/OpenFlashChart/js/json/openflashchart.packed.js"></script>
-<script type="text/javascript" src="{$config->resourceBase}packages/OpenFlashChart/js/swfobject.js"></script>
-{literal}
-<script type="text/javascript">
-    function createSWFObject( chartID, divName, xSize, ySize, loadDataFunction ) {
-       var flashFilePath = {/literal}"{$config->resourceBase}packages/OpenFlashChart/open-flash-chart.swf"{literal};
-
-       //create object.
-       swfobject.embedSWF( flashFilePath, divName,
-                         xSize, ySize, "9.0.0",
-                         "expressInstall.swf",
-                         {"get-data":loadDataFunction, "id":chartID},
-                         null,
-                         {"wmode": 'transparent'}
-                        );
-    }
-  OFC = {};
-  OFC.jquery = {
-           name: "jQuery",
-             image: function(src) { return "<img src='data:image/png;base64," + $('#'+src)[0].get_img_binary() + "' />"},
-             popup: function(src) {
-             var img_win = window.open('', 'Save Chart as Image');
-             // HTML, HEAD, and BODY tags in JS literals obfuscated to avoid being parsed as DOM elements.
-             var html = 'html', head = 'head', body = 'body';
-           img_win.document.write('<' + html + '><' + head + '><title>Save Chart as Image<\/title><\/' + head + '><' + body + '>' + OFC.jquery.image(src) + ' <\/' + body + '><\/' + html + '>');
-           img_win.document.close();
-                       }
-                 }
-
-function save_image( divName ) {
-      var divId = {/literal}"{$contriChart}"{literal} ? 'open_flash_chart_'+divName : {/literal}"{$divId}"{literal};
-          if( !divId ) {
-               divId = 'open_flash_'+divName;
-        }
-      OFC.jquery.popup( divId );
-}
-
-</script>
-{/literal}
index 3b21d3e4c165feaaa91cc1c1ed4b2846bc47e863..258488ed768ee5020eb25756de99de47416b354f 100644 (file)
@@ -547,6 +547,114 @@ describe('crmCaseType', function() {
         );
       });
     });
+
+    describe('when adding a role on-the-fly', function() {
+      beforeEach(inject(function ($controller) {
+        ctrl = $controller('CaseTypeCtrl', {$scope: scope, apiCalls: apiCalls});
+      }));
+
+      it('updates the case roles for unidirectional', function() {
+        // first simulate the ajax popup to create a new relationship type
+        var newType = {
+          "id": "33",
+          "name_a_b": "Some New Type is",
+          "label_a_b": "Some New Type is",
+          "name_b_a": "Some New Type for",
+          "label_b_a": "Some New Type for",
+          "description": "Some New Type",
+          "contact_type_a": "Individual",
+          "contact_type_b": "Individual",
+          "is_reserved": "0",
+          "is_active": "1"
+        };
+        apiCalls.relTypes.values.push(newType);
+
+        // now let the real code do what it does with the new type
+        scope.addRoleOnTheFly(scope.caseType.definition.caseRoles, newType);
+
+        expect(scope.caseType.definition.caseRoles).toEqual(
+          [
+            {
+              name: 'Homeless Services Coordinator',
+              creator: '1',
+              manager: '1',
+              displaylabel: 'Homeless Services Coordinator is'
+            },
+            {
+              name: 'Some New Type for',
+              displaylabel: 'Some New Type is'
+            }
+          ]
+        );
+
+        expect(scope.relationshipTypeOptions.slice(-2)).toEqual(
+          [
+            {
+              id: 'Some New Type is',
+              text: 'Some New Type for'
+            },
+            {
+              id: 'Some New Type for',
+              text: 'Some New Type is'
+            }
+          ]
+        );
+      });
+
+      it('updates the case roles for bidirectional', function() {
+        // first simulate the ajax popup to create a new relationship type
+        var newType = {
+          "id": "34",
+          "name_a_b": "Friend of",
+          "label_a_b": "Friend of",
+          "name_b_a": "Friend of",
+          "label_b_a": "Friend of",
+          "description": "Friend",
+          "contact_type_a": "Individual",
+          "contact_type_b": "Individual",
+          "is_reserved": "0",
+          "is_active": "1"
+        };
+        apiCalls.relTypes.values.push(newType);
+
+        // now let the real code do what it does with the new type
+        scope.addRoleOnTheFly(scope.caseType.definition.caseRoles, newType);
+
+        expect(scope.caseType.definition.caseRoles).toEqual(
+          [
+            {
+              name: 'Homeless Services Coordinator',
+              creator: '1',
+              manager: '1',
+              displaylabel: 'Homeless Services Coordinator is'
+            },
+            {
+              name: 'Friend of',
+              displaylabel: 'Friend of'
+            }
+          ]
+        );
+
+        expect(scope.relationshipTypeOptions.slice(-1)).toEqual(
+          [
+            {
+              id: 'Friend of',
+              text: 'Friend of'
+            }
+          ]
+        );
+
+        // Check that it did NOT add two entries for this bidirectional type
+        expect(scope.relationshipTypeOptions.slice(-2,-1)).not.toEqual(
+          [
+            {
+              id: 'Friend of',
+              text: 'Friend of'
+            }
+          ]
+        );
+      });
+    });
   });
 
   describe('crmAddName', function () {
index 0b120f16f43bb59a76a414886b7a1ea357bf473f..bd8370cbceb1bee2e15e56189c0be0fe7e7bdb84 100644 (file)
@@ -94,7 +94,7 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase {
   }
 
   /**
-   * Test checking if contribution recurr object can allow for changes to financial types.
+   * Test checking if contribution recur object can allow for changes to financial types.
    *
    */
   public function testSupportFinancialTypeChange() {
@@ -130,4 +130,108 @@ class CRM_Contribute_BAO_ContributionRecurTest extends CiviUnitTestCase {
     $this->assertEquals('XAU', $dao->currency, 'Edit clobbered recur currency');
   }
 
+  /**
+   * Check test contributions aren't picked up as template for non-test recurs
+   *
+   */
+  public function testGetTemplateContributionMatchTest1() {
+    $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
+    // Create a first contrib
+    $firstContrib = $this->callAPISuccess('Contribution', 'create', [
+      'contribution_recur_id' => $contributionRecur['id'],
+      'total_amount' => '3.00',
+      'financial_type_id' => 1,
+      'payment_instrument_id' => 1,
+      'currency' => 'USD',
+      'contact_id' => $this->individualCreate(),
+      'contribution_status_id' => 1,
+      'receive_date' => 'yesterday',
+    ]);
+    // Create a test contrib - should not be picked up as template for non-test recur
+    $this->callAPISuccess('Contribution', 'create', [
+      'contribution_recur_id' => $contributionRecur['id'],
+      'total_amount' => '3.00',
+      'financial_type_id' => 1,
+      'payment_instrument_id' => 1,
+      'currency' => 'USD',
+      'contact_id' => $this->individualCreate(),
+      'contribution_status_id' => 1,
+      'receive_date' => 'yesterday',
+      'is_test' => 1,
+    ]);
+    $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']);
+    $this->assertEquals($firstContrib['id'], $fetchedTemplate['id']);
+  }
+
+  /**
+   * Check non-test contributions aren't picked up as template for test recurs
+   *
+   */
+  public function testGetTemplateContributionMatchTest() {
+    $params = $this->_params;
+    $params['is_test'] = 1;
+    $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $params);
+    // Create a first test contrib
+    $firstContrib = $this->callAPISuccess('Contribution', 'create', [
+      'contribution_recur_id' => $contributionRecur['id'],
+      'total_amount' => '3.00',
+      'financial_type_id' => 1,
+      'payment_instrument_id' => 1,
+      'currency' => 'USD',
+      'contact_id' => $this->individualCreate(),
+      'contribution_status_id' => 1,
+      'receive_date' => 'yesterday',
+      'is_test' => 1,
+    ]);
+    // Create a non-test contrib - should not be picked up as template for non-test recur
+    // This shouldn't occur - a live contrib against a test recur, but that's not the point...
+    $this->callAPISuccess('Contribution', 'create', [
+      'contribution_recur_id' => $contributionRecur['id'],
+      'total_amount' => '3.00',
+      'financial_type_id' => 1,
+      'payment_instrument_id' => 1,
+      'currency' => 'USD',
+      'contact_id' => $this->individualCreate(),
+      'contribution_status_id' => 1,
+      'receive_date' => 'yesterday',
+      'is_test' => 0,
+    ]);
+    $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']);
+    $this->assertEquals($firstContrib['id'], $fetchedTemplate['id']);
+  }
+
+  /**
+   * Test that is_template contribution is used where available
+   *
+   */
+  public function testGetTemplateContributionNewTemplate() {
+    $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', $this->_params);
+    // Create the template
+    $templateContrib = $this->callAPISuccess('Contribution', 'create', [
+      'contribution_recur_id' => $contributionRecur['id'],
+      'total_amount' => '3.00',
+      'financial_type_id' => 1,
+      'payment_instrument_id' => 1,
+      'currency' => 'USD',
+      'contact_id' => $this->individualCreate(),
+      'contribution_status_id' => 1,
+      'receive_date' => 'yesterday',
+      'is_template' => 1,
+    ]);
+    // Create another normal contrib
+    $this->callAPISuccess('Contribution', 'create', [
+      'contribution_recur_id' => $contributionRecur['id'],
+      'total_amount' => '3.00',
+      'financial_type_id' => 1,
+      'payment_instrument_id' => 1,
+      'currency' => 'USD',
+      'contact_id' => $this->individualCreate(),
+      'contribution_status_id' => 1,
+      'receive_date' => 'yesterday',
+    ]);
+    $fetchedTemplate = CRM_Contribute_BAO_ContributionRecur::getTemplateContribution($contributionRecur['id']);
+    // Fetched template should be the is_template, not the latest contrib
+    $this->assertEquals($fetchedTemplate['id'], $templateContrib['id']);
+  }
+
 }
index 0128b02c0de030e12d7feafdb46b11ff7bc5bd22..7213e1100dc69454e8a24a4f7efc5e536dc17ed4 100644 (file)
@@ -148,6 +148,12 @@ class CRM_Contribute_Import_Parser_ContributionTest extends CiviUnitTestCase {
     $values['contribution_status_id'] = 'just say no';
     $this->runImport($values, CRM_Import_Parser::DUPLICATE_UPDATE, CRM_Import_Parser::ERROR);
     $this->callAPISuccessGetCount('Contribution', ['contact_id' => $contactID], 2);
+
+    // Per https://lab.civicrm.org/dev/core/issues/1285 it's a bit arguable but Ok we can support id...
+    $values['contribution_status_id'] = 3;
+    $this->runImport($values, CRM_Import_Parser::DUPLICATE_UPDATE, NULL);
+    $this->callAPISuccessGetCount('Contribution', ['contact_id' => $contactID, 'contribution_status_id' => 3], 1);
+
   }
 
   /**
index ee66811b23b46f0410841d96bc2458b2c9b25a3e..b8fc1773f7657bc0043069c71b3afd2549c54a88 100644 (file)
@@ -247,9 +247,9 @@ class CRM_Core_BAO_FinancialTrxnTest extends CiviUnitTestCase {
   }
 
   /**
-   * Test getPartialPaymentWithType function.
+   * Test testGetContributionBalance function.
    */
-  public function testGetPartialPaymentWithType() {
+  public function testGetContributionBalance() {
     //create the contribution that isn't paid yet
     $contactId = $this->individualCreate();
     $params = [
@@ -270,7 +270,7 @@ class CRM_Core_BAO_FinancialTrxnTest extends CiviUnitTestCase {
     ];
     $this->callAPISuccess('Payment', 'create', $params);
     //amount owed should be one cent
-    $amountOwed = CRM_Core_BAO_FinancialTrxn::getPartialPaymentWithType($contribution['id'], 'contribution')['amount_owed'];
+    $amountOwed = CRM_Contribute_BAO_Contribution::getContributionBalance($contribution['id']);
     $this->assertTrue(0.01 == $amountOwed, 'Amount does not match');
   }
 
index 7df8d0ec80ededa03ef451d664e60a0195c36021..8c780007592124162fee98b1d420ef5f01124714 100644 (file)
@@ -148,9 +148,7 @@ class CRM_Core_BAO_LocationTest extends CiviUnitTestCase {
 
     $params['contact_id'] = $contactId;
 
-    $location = CRM_Core_BAO_Location::create($params);
-
-    $locBlockId = CRM_Utils_Array::value('id', $location);
+    $locBlockId = CRM_Core_BAO_Location::create($params);
 
     //Now check DB for contact
     $searchParams = [
@@ -201,8 +199,6 @@ class CRM_Core_BAO_LocationTest extends CiviUnitTestCase {
     $compareParams = ['phone' => '9833910234'];
     $this->assertDBCompareValues('CRM_Core_DAO_Phone', $searchParams, $compareParams);
 
-    //delete the location block
-    CRM_Core_BAO_Location::deleteLocBlock($locBlockId);
     $this->contactDelete($contactId);
   }
 
@@ -267,8 +263,7 @@ class CRM_Core_BAO_LocationTest extends CiviUnitTestCase {
     //create location block.
     //with various element of location block
     //like address, phone, email, im.
-    $location = CRM_Core_BAO_Location::create($params, NULL, TRUE);
-    $locBlockId = CRM_Utils_Array::value('id', $location);
+    $locBlockId = CRM_Core_BAO_Location::create($params, NULL, TRUE)['id'];
 
     //update event record with location block id
     $eventParams = [
@@ -356,100 +351,6 @@ class CRM_Core_BAO_LocationTest extends CiviUnitTestCase {
     $this->contactDelete($this->_contactId);
   }
 
-  /**
-   * DeleteLocBlock() method
-   * delete the location block
-   * created with various elements.
-   */
-  public function testDeleteLocBlock() {
-    $this->_contactId = $this->individualCreate();
-    //create test event record.
-    $event = $this->eventCreate();
-    $params['location'][1] = [
-      'location_type_id' => 1,
-      'is_primary' => 1,
-      'address' => [
-        'street_address' => 'Saint Helier St',
-        'supplemental_address_1' => 'Hallmark Ct',
-        'supplemental_address_2' => 'Jersey Village',
-        'supplemental_address_3' => 'My Town',
-        'city' => 'Newark',
-        'postal_code' => '01903',
-        'country_id' => 1228,
-        'state_province_id' => 1029,
-        'geo_code_1' => '18.219023',
-        'geo_code_2' => '-105.00973',
-      ],
-      'email' => [
-        '1' => ['email' => 'john.smith@example.org'],
-      ],
-      'phone' => [
-        '1' => [
-          'phone_type_id' => 1,
-          'phone' => '303443689',
-        ],
-        '2' => [
-          'phone_type_id' => 2,
-          'phone' => '9833910234',
-        ],
-      ],
-      'im' => [
-        '1' => [
-          'name' => 'jane.doe',
-          'provider_id' => 1,
-        ],
-      ],
-    ];
-    $params['entity_id'] = $event['id'];
-    $params['entity_table'] = 'civicrm_event';
-
-    //create location block.
-    //with various elements
-    //like address, phone, email, im.
-    $location = CRM_Core_BAO_Location::create($params, NULL, TRUE);
-    $locBlockId = CRM_Utils_Array::value('id', $location);
-    //update event record with location block id
-    $eventParams = [
-      'id' => $event['id'],
-      'loc_block_id' => $locBlockId,
-    ];
-    CRM_Event_BAO_Event::add($eventParams);
-
-    //delete the location block
-    CRM_Core_BAO_Location::deleteLocBlock($locBlockId);
-
-    //Now check DB for location elements.
-    //Now check DB for Address
-    $this->assertDBNull('CRM_Core_DAO_Address', 'Saint Helier St', 'id', 'street_address',
-      'Database check, Address deleted successfully.'
-    );
-    //Now check DB for Email
-    $this->assertDBNull('CRM_Core_DAO_Email', 'john.smith@example.org', 'id', 'email',
-      'Database check, Email deleted successfully.'
-    );
-    //Now check DB for Phone
-    $this->assertDBNull('CRM_Core_DAO_Phone', '303443689', 'id', 'phone',
-      'Database check, Phone deleted successfully.'
-    );
-    //Now check DB for Mobile
-    $this->assertDBNull('CRM_Core_DAO_Phone', '9833910234', 'id', 'phone',
-      'Database check, Mobile deleted successfully.'
-    );
-    //Now check DB for IM
-    $this->assertDBNull('CRM_Core_DAO_IM', 'jane.doe', 'id', 'name',
-      'Database check, IM deleted successfully.'
-    );
-
-    //cleanup DB by deleting the record.
-    $this->eventDelete($event['id']);
-    $this->contactDelete($this->_contactId);
-
-    //Now check DB for Event
-    $this->assertDBNull('CRM_Event_DAO_Event', $event['id'], 'id', 'id',
-      'Database check, Event deleted successfully.'
-    );
-  }
-
   /**
    * GetValues() method
    * get the values of various location elements
index 537ed560bb6d7b836c0c6cfc8f8c3b5a7cb0e518..3f2ffdb4a09d35cfd689c5bc548176277fe5daa5 100644 (file)
@@ -1044,6 +1044,17 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
     $this->assertEquals(CRM_Contact_BAO_Contact::getMasterDisplayName($this->masterAddressID), $row['Home-Master Address Belongs To']);
   }
 
+  /**
+   * Test merging same address when specifying fields.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \League\Csv\Exception
+   */
+  public function testMergeSameAddressSpecifyFields() {
+    $this->setUpContactSameAddressExportData();
+    $this->doExportTest(['mergeSameAddress' => TRUE, 'fields' => [['contact_type' => 'Individual', 'name' => 'master_id', 'location_type_id' => 1]]]);
+  }
+
   /**
    * Test the merge same address option.
    *
@@ -1178,6 +1189,31 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
     $this->assertCount(2, $this->csv);
   }
 
+  /**
+   * Test exporting when no rows are retrieved.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \League\Csv\Exception
+   */
+  public function testExportNoRows() {
+    $contactA = $this->callAPISuccess('contact', 'create', [
+      'first_name' => 'John',
+      'last_name' => 'Doe',
+      'contact_type' => 'Individual',
+    ]);
+    $this->doExportTest([
+      'selectAll' => TRUE,
+      'ids' => [$contactA['id']],
+      'exportParams' => [
+        'postal_mailing_export' => [
+          'postal_mailing_export' => TRUE,
+        ],
+        'mergeSameAddress' => TRUE,
+      ],
+    ]);
+    $this->assertEquals('Contact ID', $this->csv->getHeader()[0]);
+  }
+
   /**
    * Test that deceased and do not mail contacts are removed from contacts before
    *
@@ -1202,6 +1238,21 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
       'contact_type' => 'Individual',
     ], $reason));
 
+    // Create another contact not included in the exporrt set.
+    $this->callAPISuccess('contact', 'create', array_merge([
+      'first_name' => 'Janet',
+      'last_name' => 'Doe',
+      'contact_type' => 'Individual',
+      'api.address.create' => ['supplemental_address_1' => 'An address'],
+    ], $reason));
+
+    // Create another contact not included in the exporrt set.
+    $this->callAPISuccess('contact', 'create', array_merge([
+      'first_name' => 'Janice',
+      'last_name' => 'Doe',
+      'contact_type' => 'Individual',
+    ], $reason));
+
     //create address for contact A
     $this->callAPISuccess('address', 'create', [
       'contact_id' => $contactA['id'],
diff --git a/tests/phpunit/CRM/Utils/Mail/EmailProcessorInboundTest.php b/tests/phpunit/CRM/Utils/Mail/EmailProcessorInboundTest.php
new file mode 100644 (file)
index 0000000..c461e05
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * Class CRM_Utils_Mail_EmailProcessorInboundTest
+ * @group headless
+ */
+class CRM_Utils_Mail_EmailProcessorInboundTest extends CiviUnitTestCase {
+
+  /**
+   * MailSettings record id.
+   *
+   * @var int
+   */
+  protected $mailSettingsId;
+
+  public function setUp() {
+    parent::setUp();
+    CRM_Utils_File::cleanDir(__DIR__ . '/data/mail');
+    mkdir(__DIR__ . '/data/mail');
+    // Note this is configured for Inbound Email Processing (not bounces)
+    // but otherwise is the same as bounces.
+    $this->mailSettingsId = $this->callAPISuccess('MailSettings', 'create', [
+      'name' => 'local',
+      'protocol' => 'Localdir',
+      'source' => __DIR__ . '/data/mail',
+      'domain' => 'example.com',
+      // a little weird - is_default=0 means for inbound email processing
+      'is_default' => '0',
+      'domain_id' => 1,
+    ])['id'];
+  }
+
+  public function tearDown() {
+    CRM_Utils_File::cleanDir(__DIR__ . '/data/mail');
+    $this->callAPISuccess('MailSettings', 'delete', [
+      'id' => $this->mailSettingsId,
+    ]);
+    parent::tearDown();
+  }
+
+  /**
+   * Fetch activities with many attachments
+   *
+   * In particular the default limit for the UI is 3, which is how this came up
+   * because it was also being used as a limit for backend processes. So we
+   * test 4, which is bigger than 3 (unless running on a 2-bit CPU).
+   */
+  public function testFetchActivitiesWithManyAttachments() {
+    $mail = 'test_message_many_attachments.eml';
+
+    // paranoid check that settings are the standard defaults
+    $currentUIMax = Civi::settings()->get('max_attachments');
+    $currentBackendMax = Civi::settings()->get('max_attachments_backend');
+    if ($currentUIMax > 3) {
+      Civi::settings()->set('max_attachments', 3);
+    }
+    if ($currentBackendMax < CRM_Core_BAO_File::DEFAULT_MAX_ATTACHMENTS_BACKEND) {
+      Civi::settings()->set('max_attachments_backend', CRM_Core_BAO_File::DEFAULT_MAX_ATTACHMENTS_BACKEND);
+    }
+
+    // create some contacts
+    $senderContactId = $this->individualCreate([], 1);
+    $senderContact = $this->callAPISuccess('Contact', 'getsingle', [
+      'id' => $senderContactId,
+    ]);
+    $recipientContactId = $this->individualCreate([], 2);
+    $recipientContact = $this->callAPISuccess('Contact', 'getsingle', [
+      'id' => $recipientContactId,
+    ]);
+
+    $templateFillData = [
+      'the_date' => date('r'),
+      'from_name' => $senderContact['display_name'],
+      'from_email' => $senderContact['email'],
+      'to_email' => $recipientContact['email'],
+    ];
+
+    // Retrieve the template and insert our data like current dates
+    $file_contents = file_get_contents(__DIR__ . '/data/inbound/' . $mail);
+    foreach ($templateFillData as $field => $value) {
+      $file_contents = str_replace("%%{$field}%%", $value, $file_contents);
+    }
+    // put it in the mail dir
+    file_put_contents(__DIR__ . '/data/mail/' . $mail, $file_contents);
+
+    // run the job
+    $this->callAPISuccess('job', 'fetch_activities', []);
+
+    // check that file was removed from mail dir
+    $this->assertFalse(file_exists(__DIR__ . '/data/mail/' . $mail));
+
+    // get the filed activity, by sender contact id
+    $activities = $this->callAPISuccess('Activity', 'get', [
+      'source_contact_id' => $senderContact['id'],
+    ]);
+    $this->assertEquals(1, $activities['count']);
+
+    // check subject
+    $activity = $activities['values'][$activities['id']];
+    $this->assertEquals('Testing 4 attachments', $activity['subject']);
+
+    // Check target is our recipient
+    $targets = $this->callAPISuccess('ActivityContact', 'get', [
+      'activity_id' => $activity['id'],
+      'record_type_id' => 'Activity Targets',
+    ]);
+    $this->assertEquals($recipientContact['id'], $targets['values'][$targets['id']]['contact_id']);
+
+    // Check we have 4 attachments
+    $attachments = $this->callAPISuccess('Attachment', 'get', [
+      'entity_id' => $activity['id'],
+      'entity_table' => 'civicrm_activity',
+    ]);
+    $this->assertEquals(4, $attachments['count']);
+
+    // reset in case it was different from defaults
+    Civi::settings()->set('max_attachments', $currentUIMax);
+    Civi::settings()->set('max_attachments_backend', $currentBackendMax);
+  }
+
+}
diff --git a/tests/phpunit/CRM/Utils/Mail/data/inbound/test_message_many_attachments.eml b/tests/phpunit/CRM/Utils/Mail/data/inbound/test_message_many_attachments.eml
new file mode 100644 (file)
index 0000000..6ee592f
--- /dev/null
@@ -0,0 +1,123 @@
+MIME-Version: 1.0\r
+Date: %%the_date%%\r
+Message-ID: <CAL+tpUmRn2J7zcjUAv4WXMTJZcEV67V2_Ktu77Ha_MGmth0CmQ@mail.gmail.com>\r
+Subject: Testing 4 attachments\r
+From: %%from_name%% <%%from_email%%>\r
+To: %%to_email%%\r
+Content-Type: multipart/mixed; boundary="000000000000a2ad5f059325db35"\r
+\r
+--000000000000a2ad5f059325db35\r
+Content-Type: multipart/alternative; boundary="000000000000a2ad5a059325db33"\r
+\r
+--000000000000a2ad5a059325db33\r
+Content-Type: text/plain; charset="UTF-8"\r
+\r
+test\r
+\r
+--000000000000a2ad5a059325db33\r
+Content-Type: text/html; charset="UTF-8"\r
+\r
+<div dir="ltr">test<br></div>\r
+\r
+--000000000000a2ad5a059325db33--\r
+--000000000000a2ad5f059325db35\r
+Content-Type: image/gif; name="c.gif"\r
+Content-Disposition: attachment; filename="c.gif"\r
+Content-Transfer-Encoding: base64\r
+X-Attachment-Id: f_k0v4qdju2\r
+Content-ID: <f_k0v4qdju2>\r
+\r
+R0lGODlhPwA+APcAAAAAAAAAMwAAZgAAmQAAzAAA/wArAAArMwArZgArmQArzAAr/wBVAABVMwBV\r
+ZgBVmQBVzABV/wCAAACAMwCAZgCAmQCAzACA/wCqAACqMwCqZgCqmQCqzACq/wDVAADVMwDVZgDV\r
+mQDVzADV/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMrADMrMzMrZjMrmTMr\r
+zDMr/zNVADNVMzNVZjNVmTNVzDNV/zOAADOAMzOAZjOAmTOAzDOA/zOqADOqMzOqZjOqmTOqzDOq\r
+/zPVADPVMzPVZjPVmTPVzDPV/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2Yr\r
+AGYrM2YrZmYrmWYrzGYr/2ZVAGZVM2ZVZmZVmWZVzGZV/2aAAGaAM2aAZmaAmWaAzGaA/2aqAGaq\r
+M2aqZmaqmWaqzGaq/2bVAGbVM2bVZmbVmWbVzGbV/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kA\r
+ZpkAmZkAzJkA/5krAJkrM5krZpkrmZkrzJkr/5lVAJlVM5lVZplVmZlVzJlV/5mAAJmAM5mAZpmA\r
+mZmAzJmA/5mqAJmqM5mqZpmqmZmqzJmq/5nVAJnVM5nVZpnVmZnVzJnV/5n/AJn/M5n/Zpn/mZn/\r
+zJn//8wAAMwAM8wAZswAmcwAzMwA/8wrAMwrM8wrZswrmcwrzMwr/8xVAMxVM8xVZsxVmcxVzMxV\r
+/8yAAMyAM8yAZsyAmcyAzMyA/8yqAMyqM8yqZsyqmcyqzMyq/8zVAMzVM8zVZszVmczVzMzV/8z/\r
+AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8rAP8rM/8rZv8rmf8rzP8r//9VAP9V\r
+M/9VZv9Vmf9VzP9V//+AAP+AM/+AZv+Amf+AzP+A//+qAP+qM/+qZv+qmf+qzP+q///VAP/VM//V\r
+Zv/Vmf/VzP/V////AP//M///Zv//mf//zP///wAAAAAAAAAAAAAAACH5BAEAAPwALAAAAAA/AD4A\r
+AAjCAPcJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX\r
+IgHInAnT4MybOGvi3JmzJc+fNFcCHQpAJdCCP1HyVLjU5E6GT0tGhdpzZNWGV0NmXTgVZFesN62G\r
+jbi1Y1muY7WmfXh2Y9uEbzPGPTgXY92BXz/eFbjXYl6Ef/XODSz4bVOnh/EmRkx08cnGhKVClqmT\r
+aE2CSS9r3sy5s+fPoEOLHk26tOnTqFPXDAgAOw==\r
+--000000000000a2ad5f059325db35\r
+Content-Type: image/gif; name="b.gif"\r
+Content-Disposition: attachment; filename="b.gif"\r
+Content-Transfer-Encoding: base64\r
+X-Attachment-Id: f_k0v4qdjj1\r
+Content-ID: <f_k0v4qdjj1>\r
+\r
+R0lGODlhPwA+APcAAAAAAAAAMwAAZgAAmQAAzAAA/wArAAArMwArZgArmQArzAAr/wBVAABVMwBV\r
+ZgBVmQBVzABV/wCAAACAMwCAZgCAmQCAzACA/wCqAACqMwCqZgCqmQCqzACq/wDVAADVMwDVZgDV\r
+mQDVzADV/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMrADMrMzMrZjMrmTMr\r
+zDMr/zNVADNVMzNVZjNVmTNVzDNV/zOAADOAMzOAZjOAmTOAzDOA/zOqADOqMzOqZjOqmTOqzDOq\r
+/zPVADPVMzPVZjPVmTPVzDPV/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2Yr\r
+AGYrM2YrZmYrmWYrzGYr/2ZVAGZVM2ZVZmZVmWZVzGZV/2aAAGaAM2aAZmaAmWaAzGaA/2aqAGaq\r
+M2aqZmaqmWaqzGaq/2bVAGbVM2bVZmbVmWbVzGbV/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kA\r
+ZpkAmZkAzJkA/5krAJkrM5krZpkrmZkrzJkr/5lVAJlVM5lVZplVmZlVzJlV/5mAAJmAM5mAZpmA\r
+mZmAzJmA/5mqAJmqM5mqZpmqmZmqzJmq/5nVAJnVM5nVZpnVmZnVzJnV/5n/AJn/M5n/Zpn/mZn/\r
+zJn//8wAAMwAM8wAZswAmcwAzMwA/8wrAMwrM8wrZswrmcwrzMwr/8xVAMxVM8xVZsxVmcxVzMxV\r
+/8yAAMyAM8yAZsyAmcyAzMyA/8yqAMyqM8yqZsyqmcyqzMyq/8zVAMzVM8zVZszVmczVzMzV/8z/\r
+AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8rAP8rM/8rZv8rmf8rzP8r//9VAP9V\r
+M/9VZv9Vmf9VzP9V//+AAP+AM/+AZv+Amf+AzP+A//+qAP+qM/+qZv+qmf+qzP+q///VAP/VM//V\r
+Zv/Vmf/VzP/V////AP//M///Zv//mf//zP///wAAAAAAAAAAAAAAACH5BAEAAPwALAAAAAA/AD4A\r
+AAjCAPcJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX\r
+IgHInAnT4MybOGvi3JmzJc+fNFcCHQpAJdCCP1HyVLjU5E6GT0tGhdpzZNWGV0NmXTgVZFesN62G\r
+jbi1Y1muY7WmfXh2Y9uEbzPGPTgXY92BXz/eFbjXYl6Ef/XODSz4bVOnh/EmRkx08cnGhKVClqmT\r
+aE2CSS9r3sy5s+fPoEOLHk26tOnTqFPXDAgAOw==\r
+--000000000000a2ad5f059325db35\r
+Content-Type: image/gif; name="d.gif"\r
+Content-Disposition: attachment; filename="d.gif"\r
+Content-Transfer-Encoding: base64\r
+X-Attachment-Id: f_k0v4qdk73\r
+Content-ID: <f_k0v4qdk73>\r
+\r
+R0lGODlhPwA+APcAAAAAAAAAMwAAZgAAmQAAzAAA/wArAAArMwArZgArmQArzAAr/wBVAABVMwBV\r
+ZgBVmQBVzABV/wCAAACAMwCAZgCAmQCAzACA/wCqAACqMwCqZgCqmQCqzACq/wDVAADVMwDVZgDV\r
+mQDVzADV/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMrADMrMzMrZjMrmTMr\r
+zDMr/zNVADNVMzNVZjNVmTNVzDNV/zOAADOAMzOAZjOAmTOAzDOA/zOqADOqMzOqZjOqmTOqzDOq\r
+/zPVADPVMzPVZjPVmTPVzDPV/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2Yr\r
+AGYrM2YrZmYrmWYrzGYr/2ZVAGZVM2ZVZmZVmWZVzGZV/2aAAGaAM2aAZmaAmWaAzGaA/2aqAGaq\r
+M2aqZmaqmWaqzGaq/2bVAGbVM2bVZmbVmWbVzGbV/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kA\r
+ZpkAmZkAzJkA/5krAJkrM5krZpkrmZkrzJkr/5lVAJlVM5lVZplVmZlVzJlV/5mAAJmAM5mAZpmA\r
+mZmAzJmA/5mqAJmqM5mqZpmqmZmqzJmq/5nVAJnVM5nVZpnVmZnVzJnV/5n/AJn/M5n/Zpn/mZn/\r
+zJn//8wAAMwAM8wAZswAmcwAzMwA/8wrAMwrM8wrZswrmcwrzMwr/8xVAMxVM8xVZsxVmcxVzMxV\r
+/8yAAMyAM8yAZsyAmcyAzMyA/8yqAMyqM8yqZsyqmcyqzMyq/8zVAMzVM8zVZszVmczVzMzV/8z/\r
+AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8rAP8rM/8rZv8rmf8rzP8r//9VAP9V\r
+M/9VZv9Vmf9VzP9V//+AAP+AM/+AZv+Amf+AzP+A//+qAP+qM/+qZv+qmf+qzP+q///VAP/VM//V\r
+Zv/Vmf/VzP/V////AP//M///Zv//mf//zP///wAAAAAAAAAAAAAAACH5BAEAAPwALAAAAAA/AD4A\r
+AAjCAPcJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX\r
+IgHInAnT4MybOGvi3JmzJc+fNFcCHQpAJdCCP1HyVLjU5E6GT0tGhdpzZNWGV0NmXTgVZFesN62G\r
+jbi1Y1muY7WmfXh2Y9uEbzPGPTgXY92BXz/eFbjXYl6Ef/XODSz4bVOnh/EmRkx08cnGhKVClqmT\r
+aE2CSS9r3sy5s+fPoEOLHk26tOnTqFPXDAgAOw==\r
+--000000000000a2ad5f059325db35\r
+Content-Type: image/gif; name="a.gif"\r
+Content-Disposition: attachment; filename="a.gif"\r
+Content-Transfer-Encoding: base64\r
+X-Attachment-Id: f_k0v4qdiv0\r
+Content-ID: <f_k0v4qdiv0>\r
+\r
+R0lGODlhPwA+APcAAAAAAAAAMwAAZgAAmQAAzAAA/wArAAArMwArZgArmQArzAAr/wBVAABVMwBV\r
+ZgBVmQBVzABV/wCAAACAMwCAZgCAmQCAzACA/wCqAACqMwCqZgCqmQCqzACq/wDVAADVMwDVZgDV\r
+mQDVzADV/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMrADMrMzMrZjMrmTMr\r
+zDMr/zNVADNVMzNVZjNVmTNVzDNV/zOAADOAMzOAZjOAmTOAzDOA/zOqADOqMzOqZjOqmTOqzDOq\r
+/zPVADPVMzPVZjPVmTPVzDPV/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2Yr\r
+AGYrM2YrZmYrmWYrzGYr/2ZVAGZVM2ZVZmZVmWZVzGZV/2aAAGaAM2aAZmaAmWaAzGaA/2aqAGaq\r
+M2aqZmaqmWaqzGaq/2bVAGbVM2bVZmbVmWbVzGbV/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kA\r
+ZpkAmZkAzJkA/5krAJkrM5krZpkrmZkrzJkr/5lVAJlVM5lVZplVmZlVzJlV/5mAAJmAM5mAZpmA\r
+mZmAzJmA/5mqAJmqM5mqZpmqmZmqzJmq/5nVAJnVM5nVZpnVmZnVzJnV/5n/AJn/M5n/Zpn/mZn/\r
+zJn//8wAAMwAM8wAZswAmcwAzMwA/8wrAMwrM8wrZswrmcwrzMwr/8xVAMxVM8xVZsxVmcxVzMxV\r
+/8yAAMyAM8yAZsyAmcyAzMyA/8yqAMyqM8yqZsyqmcyqzMyq/8zVAMzVM8zVZszVmczVzMzV/8z/\r
+AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8rAP8rM/8rZv8rmf8rzP8r//9VAP9V\r
+M/9VZv9Vmf9VzP9V//+AAP+AM/+AZv+Amf+AzP+A//+qAP+qM/+qZv+qmf+qzP+q///VAP/VM//V\r
+Zv/Vmf/VzP/V////AP//M///Zv//mf//zP///wAAAAAAAAAAAAAAACH5BAEAAPwALAAAAAA/AD4A\r
+AAjCAPcJHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX\r
+IgHInAnT4MybOGvi3JmzJc+fNFcCHQpAJdCCP1HyVLjU5E6GT0tGhdpzZNWGV0NmXTgVZFesN62G\r
+jbi1Y1muY7WmfXh2Y9uEbzPGPTgXY92BXz/eFbjXYl6Ef/XODSz4bVOnh/EmRkx08cnGhKVClqmT\r
+aE2CSS9r3sy5s+fPoEOLHk26tOnTqFPXDAgAOw==\r
+--000000000000a2ad5f059325db35--\r
diff --git a/tests/phpunit/api/v4/Action/EventTest.php b/tests/phpunit/api/v4/Action/EventTest.php
new file mode 100644 (file)
index 0000000..052629c
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 5                                                  |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2019                                |
+ +--------------------------------------------------------------------+
+ | 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-2019
+ */
+
+use Civi\Api4\Event;
+
+/**
+ * @group headless
+ */
+class EventTest extends \api\v4\UnitTestCase {
+
+  /**
+   * Test that the event api filters out templates by default.
+   *
+   * @throws \Civi\API\Exception\UnauthorizedException
+   */
+  public function testTemplateFilterByDefault() {
+    Event::create()->setValues(['template_title' => 'Big Event', 'is_template' => 1, 'start_date' => 'now', 'event_type_id' => 'Meeting'])->execute();
+    Event::create()->setValues(['title' => 'Bigger Event', 'start_date' => 'now', 'event_type_id' => 'Meeting'])->execute();
+    $this->assertEquals(1, Event::get()->selectRowCount()->execute()->count());
+  }
+
+}
index 8c47a84fa8ed03d0141fad6f425ab90f5e397695..d2f5593b3de657f5ffd4b7ae7fa1511938f87ed7 100644 (file)
     </html>
     <add>4.7</add>
   </field>
+   <field>
+    <name>is_template</name>
+    <title>Is a Template Contribution</title>
+    <type>boolean</type>
+    <default>0</default>
+    <import>true</import>
+    <comment>Shows this is a template for recurring contributions.</comment>
+    <html>
+      <type>CheckBox</type>
+    </html>
+    <add>5.20</add>
+  </field>
 </table>
index 351eef9129f2837329f58afaabe2b6254cedea46..9c08b4738bce0bd87e43ba515ec21c6f1bfa79f0 100644 (file)
     <comment>if true - billing block is required for online contribution page</comment>
     <add>4.6</add>
   </field>
+  <field>
+    <name>frontend_title</name>
+    <title>Public Title</title>
+    <type>varchar</type>
+    <length>255</length>
+    <localizable>true</localizable>
+    <default>NULL</default>
+    <comment>Contribution Page Public title</comment>
+    <html>
+      <type>Text</type>
+    </html>
+    <add>5.20</add>
+    <uniqueName>contribution_page_frontend_title</uniqueName>
+  </field>
 </table>
index 55290a872ed0679caa009df562695193126c03c5..f7f0bb05d7b963b62f658268c1964a05fb9c90f3 100644 (file)
     <comment>Last 4 digits of credit card</comment>
     <add>4.7</add>
   </field>
+  <field>
+    <name>order_reference</name>
+    <uniqueName>financial_trxn_order_reference</uniqueName>
+    <title>Order Reference</title>
+    <type>varchar</type>
+    <length>255</length>
+    <html>
+      <type>Text</type>
+      <size>25</size>
+    </html>
+    <comment>Payment Processor external order reference</comment>
+    <add>5.20</add>
+  </field>
 </table>
index 5e17f30e9462f6e4804cf1fa578ee1257a03b845..e824915ca553921f828b05525ebc10e743b5eb6a 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="iso-8859-1" ?>
 <version>
-  <version_no>5.19.alpha1</version_no>
+  <version_no>5.20.alpha1</version_no>
 </version>