Merge pull request #8251 from eileenmcnaughton/merge_tests
authorEileen McNaughton <eileen@mcnaughty.com>
Thu, 19 May 2016 20:11:44 +0000 (08:11 +1200)
committerEileen McNaughton <eileen@mcnaughty.com>
Thu, 19 May 2016 20:11:44 +0000 (08:11 +1200)
Dedupe fixes CRM-18442, CRM-18539,  CRM-18480

15 files changed:
CRM/Batch/Form/Entry.php
CRM/Contact/BAO/ContactType.php
CRM/Contribute/Form/Task/PDFLetterCommon.php
CRM/Contribute/Form/UpdateSubscription.php
CRM/Core/BAO/CustomGroup.php
CRM/Core/BAO/UFField.php
CRM/Core/DAO.php
CRM/Mailing/BAO/Mailing.php
CRM/Upgrade/Incremental/sql/4.7.8.mysql.tpl
templates/CRM/Batch/Form/Entry.tpl
tests/phpunit/CRM/Batch/Form/EntryTest.php
tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php [new file with mode: 0644]
tests/phpunit/CRM/Core/BAO/CustomGroupTest.php
tests/phpunit/api/v3/SyntaxConformanceTest.php
xml/schema/Core/Address.xml

index 1eeed172b608cbb6eb017b80b0de9901dee57d21..b9047c230aaa5d6a942b180145ff1f102c26a3c7 100644 (file)
@@ -280,6 +280,11 @@ class CRM_Batch_Form_Entry extends CRM_Core_Form {
 
     //CRM-16480 if contact is selected, validate financial type and amount field.
     foreach ($params['field'] as $key => $value) {
+      if (isset($value['trxn_id'])) {
+        if (0 < CRM_Core_DAO::singleValueQuery('SELECT id FROM civicrm_contribution WHERE trxn_id = %1', array(1 => array($value['trxn_id'], 'String')))) {
+          $errors["field[$key][trxn_id]"] = ts('Transaction ID must be unique within the database');
+        }
+      }
       foreach ($fields as $field => $label) {
         if (!empty($params['primary_contact_id'][$key]) && empty($value[$field])) {
           $errors["field[$key][$field]"] = ts('%1 is a required field.', array(1 => $label));
index 48711b11e018ab13d9600f3aab1ea3c053deb042..efc0ca1f2c241ec4530b12d5cce65fbabd3c9613 100644 (file)
@@ -74,7 +74,7 @@ class CRM_Contact_BAO_ContactType extends CRM_Contact_DAO_ContactType {
    * @return array
    *   Array of basic contact types information.
    */
-  public static function &basicTypeInfo($all = FALSE) {
+  public static function basicTypeInfo($all = FALSE) {
     static $_cache = NULL;
 
     if ($_cache === NULL) {
@@ -153,7 +153,7 @@ WHERE  parent_id IS NULL
    * @return array
    *   Array of sub type information
    */
-  public static function &subTypeInfo($contactType = NULL, $all = FALSE, $ignoreCache = FALSE, $reset = FALSE) {
+  public static function subTypeInfo($contactType = NULL, $all = FALSE, $ignoreCache = FALSE, $reset = FALSE) {
     static $_cache = NULL;
 
     if ($reset === TRUE) {
index 56059052078d7ff15a5b6b2462d94bb8c2907633..4dcba8ef7e1c8ecac33f86c2205a907cb5f07da5 100644 (file)
@@ -49,8 +49,12 @@ class CRM_Contribute_Form_Task_PDFLetterCommon extends CRM_Contact_Form_Task_PDF
     // skip some contacts ?
     $skipOnHold = isset($form->skipOnHold) ? $form->skipOnHold : FALSE;
     $skipDeceased = isset($form->skipDeceased) ? $form->skipDeceased : TRUE;
-
-    list($contributions, $contacts) = self::buildContributionArray($groupBy, $form, $returnProperties, $skipOnHold, $skipDeceased, $messageToken, $task, $separator);
+    $contributionIDs = $form->getVar('_contributionIds');
+    if ($form->_includesSoftCredits) {
+      //@todo - comment on what is stored there
+      $contributionIDs = $form->getVar('_contributionContactIds');
+    }
+    list($contributions, $contacts) = self::buildContributionArray($groupBy, $contributionIDs, $returnProperties, $skipOnHold, $skipDeceased, $messageToken, $task, $separator, $form->_includesSoftCredits);
     $html = array();
     foreach ($contributions as $contributionId => $contribution) {
       $contact = &$contacts[$contribution['contact_id']];
@@ -204,23 +208,19 @@ class CRM_Contribute_Form_Task_PDFLetterCommon extends CRM_Contact_Form_Task_PDF
    * around contact_id of contribution_recur_id
    *
    * @param string $groupBy
-   * @param CRM_Contribute_Form_Task $form
+   * @param array $contributionIDs
    * @param array $returnProperties
    * @param bool $skipOnHold
    * @param bool $skipDeceased
    * @param array $messageToken
    * @param string $task
    * @param string $separator
+   * @param bool $isIncludeSoftCredits
    *
    * @return array
    */
-  public static function buildContributionArray($groupBy, $form, $returnProperties, $skipOnHold, $skipDeceased, $messageToken, $task, $separator) {
+  public static function buildContributionArray($groupBy, $contributionIDs, $returnProperties, $skipOnHold, $skipDeceased, $messageToken, $task, $separator, $isIncludeSoftCredits) {
     $contributions = $contacts = $notSent = array();
-    $contributionIDs = $form->getVar('_contributionIds');
-    if ($form->_includesSoftCredits) {
-      //@todo - comment on what is stored there
-      $contributionIDs = $form->getVar('_contributionContactIds');
-    }
     foreach ($contributionIDs as $item => $contributionId) {
       // get contribution information
       $contribution = CRM_Utils_Token::getContributionTokenDetails(array('contribution_id' => $contributionId),
@@ -230,7 +230,8 @@ class CRM_Contribute_Form_Task_PDFLetterCommon extends CRM_Contact_Form_Task_PDF
         $task
       );
       $contribution = $contributions[$contributionId] = $contribution[$contributionId];
-      if ($form->_includesSoftCredits) {
+
+      if ($isIncludeSoftCredits) {
         //@todo find out why this happens & add comments
         list($contactID) = explode('-', $item);
         $contactID = (int) $contactID;
@@ -239,15 +240,7 @@ class CRM_Contribute_Form_Task_PDFLetterCommon extends CRM_Contact_Form_Task_PDF
         $contactID = $contribution['contact_id'];
       }
       if (!isset($contacts[$contactID])) {
-        list($contact) = CRM_Utils_Token::getTokenDetails(array('contact_id' => $contactID),
-          $returnProperties,
-          $skipOnHold,
-          $skipDeceased,
-          NULL,
-          $messageToken,
-          $task
-        );
-        $contacts[$contactID] = $contact[$contactID];
+        $contacts[$contactID] = array();
         $contacts[$contactID]['contact_aggregate'] = 0;
         $contacts[$contactID]['combined'] = $contacts[$contactID]['contribution_ids'] = array();
       }
@@ -265,6 +258,22 @@ class CRM_Contribute_Form_Task_PDFLetterCommon extends CRM_Contact_Form_Task_PDF
         $contacts[$contactID]['aggregates'][$groupBy][$groupByID] += $contribution['total_amount'];
       }
     }
+    // Assign the available contributions before calling tokens so hooks parsing smarty can access it.
+    // Note that in core code you can only use smarty here if enable if for the whole site, incl
+    // CiviMail, with a big performance impact.
+    // Hooks allow more nuanced smarty usage here.
+    CRM_Core_Smarty::singleton()->assign('contributions', $contributions);
+    foreach ($contacts as $contactID => $contact) {
+      $tokenResolvedContacts = CRM_Utils_Token::getTokenDetails(array('contact_id' => $contactID),
+        $returnProperties,
+        $skipOnHold,
+        $skipDeceased,
+        NULL,
+        $messageToken,
+        $task
+      );
+      $contacts[$contactID] = array_merge($tokenResolvedContacts[0][$contactID], $contact);
+    }
     return array($contributions, $contacts);
   }
 
index a6837c5cdcafc72e3fbed3e3d086b1717e14049e..c3ff12ae30aa5b62cae7f9f0bacc6aaf8352b0ff 100644 (file)
@@ -77,6 +77,8 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form {
    */
   public function preProcess() {
 
+    $this->setAction(CRM_Core_Action::UPDATE);
+
     $this->contributionRecurID = CRM_Utils_Request::retrieve('crid', 'Integer', $this, FALSE);
     if ($this->contributionRecurID) {
       $this->_paymentProcessor = CRM_Contribute_BAO_ContributionRecur::getPaymentProcessor($this->contributionRecurID);
@@ -193,7 +195,7 @@ class CRM_Contribute_Form_UpdateSubscription extends CRM_Core_Form {
     }
 
     if (CRM_Contribute_BAO_ContributionRecur::supportsFinancialTypeChange($this->contributionRecurID)) {
-      $this->addEntityRef('financial_type_id', ts('Financial Type'), array('entity' => 'FinancialType'), TRUE);
+      $this->addEntityRef('financial_type_id', ts('Financial Type'), array('entity' => 'FinancialType'), !$this->_selfService);
     }
 
     $type = 'next';
index ee953fbff40f5ced03706d6e5bad53543e2e37b3..bd804af104e9a532c6bc1648f775b06eff4fba7c 100644 (file)
@@ -651,15 +651,13 @@ ORDER BY civicrm_custom_group.weight,
     if (is_numeric($subType)) {
       return $subType;
     }
-    $contactTypes = civicrm_api3('Contact', 'getoptions', array('field' => 'contact_type'));
-    if ($entityType != 'Contact' && !array_key_exists($entityType, $contactTypes['values'])) {
-      // Not quite sure if we want to fail this hard. But quiet ignore would be pretty bad too.
-      // Am inclined to go with this for RC release & considering softening.
+
+    $contactTypes = CRM_Contact_BAO_ContactType::basicTypeInfo(TRUE);
+    if ($entityType != 'Contact' && !array_key_exists($entityType, $contactTypes)) {
       throw new CRM_Core_Exception('Invalid Entity Filter');
     }
-    $subTypes = civicrm_api3('Contact', 'getoptions', array('field' => 'contact_sub_type'));
-    if (!isset($subTypes['values'][$subType])) {
-      // Same comments about fail hard as above.
+    $subTypes = CRM_Contact_BAO_ContactType::subTypeInfo($entityType, TRUE);
+    if (!array_key_exists($subType, $subTypes)) {
       throw new CRM_Core_Exception('Invalid Filter');
     }
     return $subType;
index ad86d2de9f12ffbdf5bce05906a50ba1e1279521..fe3c5c9d6030f670f18a504ebb2b7a8b1d98b4a7 100644 (file)
@@ -1125,6 +1125,10 @@ SELECT  id
           'name' => 'contribution_status_id',
           'title' => ts('Contribution Status'),
         ),
+        'trxn_id' => array(
+          'name' => 'contribution_trxn_id',
+          'title' => ts('Contribution Transaction ID'),
+        ),
       );
     }
     return self::$_memberBatchEntryFields;
index cb02a95c57335ff71943064581fa23d3b27b6b9a..a168da8b3e3b318e5ab760b579a7e2c8b3a097ea 100644 (file)
@@ -147,26 +147,26 @@ class CRM_Core_DAO extends DB_DataObject {
       if ($fkDAO->find(TRUE)) {
         $this->$dbName = $fkDAO->id;
       }
-      unset($fkDAO);
+      $fkDAO->free();
     }
 
     elseif (in_array($FKClassName, CRM_Core_DAO::$_testEntitiesToSkip)) {
       $depObject = new $FKClassName();
       $depObject->find(TRUE);
       $this->$dbName = $depObject->id;
-      unset($depObject);
+      $depObject->free();
     }
     elseif ($daoName == 'CRM_Member_DAO_MembershipType' && $fieldName == 'member_of_contact_id') {
       // FIXME: the fields() metadata is not specific enough
       $depObject = CRM_Core_DAO::createTestObject($FKClassName, array('contact_type' => 'Organization'));
       $this->$dbName = $depObject->id;
-      unset($depObject);
+      $depObject->free();
     }
     else {
       //if it is required we need to generate the dependency object first
       $depObject = CRM_Core_DAO::createTestObject($FKClassName, CRM_Utils_Array::value($dbName, $params, 1));
       $this->$dbName = $depObject->id;
-      unset($depObject);
+      $depObject->free();
     }
   }
 
@@ -520,6 +520,7 @@ class CRM_Core_DAO extends DB_DataObject {
 
     $event = new \Civi\Core\DAO\Event\PostDelete($this, $result);
     \Civi::service('dispatcher')->dispatch("DAO::post-delete", $event);
+    $this->free();
 
     return $result;
   }
index d3c6853636f86c876475a019b290de74b77717fb..bb3f95e46d718a927944be5fb50205294442b535 100644 (file)
@@ -784,7 +784,8 @@ ORDER BY   i.contact_id, i.{$tempColumn}
         $this->templates['text'] = implode("\n", $template);
       }
 
-      if ($this->body_html) {
+      // To check for an html part strip tags
+      if (trim(strip_tags($this->body_html))) {
 
         $template = array();
         if ($this->header) {
index 4f54df1002eba1d267362e2a7122c0225e7e3658..641b3335b7798b0a40b9100cf3438ab9f29b7541 100644 (file)
@@ -5,3 +5,7 @@ ALTER TABLE `civicrm_contact` CHANGE `image_URL` `image_URL` VARCHAR(512) CHARAC
 
 -- CRM-18537
 DELETE FROM civicrm_state_province WHERE name = 'Fernando de Noronha';
+
+-- CRM-17118 extend civicrm_address postal_code to accept full data strings from paypal etc.
+ALTER TABLE civicrm_address CHANGE `postal_code` `postal_code` varchar(64) ;
+
index 0e7b83691350cae28e614cc9d0e088853cf34f33..46718ba2edca0276eb10bfbc6c7a707843fc6366 100644 (file)
@@ -66,7 +66,7 @@
       {/if}
       {foreach from=$fields item=field key=fieldName}
         <div class="crm-grid-cell">
-          {if $field.name|substr:0:11 ne 'soft_credit'}
+          {if $field.name|substr:0:11 ne 'soft_credit' and $field.name ne 'trxn_id'}
           <img src="{$config->resourceBase}i/copy.png"
                alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}"
                fname="{$field.name}" class="action-icon"
index f93ae000b1b0531e71c87c73978a67766bf99d18..ad5e4c696ea591121bbf8850b521b97b440f8598 100644 (file)
@@ -174,14 +174,15 @@ class CRM_Batch_Form_EntryTest extends CiviUnitTestCase {
     $this->assertEquals(date('Y-m-d', strtotime('07/22/2013')), $result['values'][1]['join_date']);
     $this->assertEquals(date('Y-m-d', strtotime('07/03/2013')), $result['values'][2]['join_date']);
     $this->assertEquals(date('Y-m-d', strtotime('now')), $result['values'][3]['join_date']);
-    $result = $this->callAPISuccess('contribution', 'get', array('return' => 'total_amount'));
+    $result = $this->callAPISuccess('contribution', 'get', array('return' => array('total_amount', 'trxn_id')));
     $this->assertEquals(3, $result['count']);
-    foreach ($result['values'] as $contribution) {
+    foreach ($result['values'] as $key => $contribution) {
       $this->assertEquals($this->callAPISuccess('line_item', 'getvalue', array(
         'contribution_id' => $contribution['id'],
         'return' => 'line_total',
 
       )), $contribution['total_amount']);
+      $this->assertEquals($params['field'][$key]['trxn_id'], $contribution['trxn_id']);
     }
   }
 
@@ -274,6 +275,7 @@ class CRM_Batch_Form_EntryTest extends CiviUnitTestCase {
           'receive_date' => '07/24/2013',
           'receive_date_time' => NULL,
           'payment_instrument' => 1,
+          'trxn_id' => 'TX101',
           'check_number' => NULL,
           'contribution_status_id' => 1,
         ),
@@ -288,6 +290,7 @@ class CRM_Batch_Form_EntryTest extends CiviUnitTestCase {
           'receive_date' => '07/17/2013',
           'receive_date_time' => NULL,
           'payment_instrument' => NULL,
+          'trxn_id' => 'TX102',
           'check_number' => NULL,
           'contribution_status_id' => 1,
         ),
@@ -303,6 +306,7 @@ class CRM_Batch_Form_EntryTest extends CiviUnitTestCase {
           'receive_date' => '07/17/2013',
           'receive_date_time' => NULL,
           'payment_instrument' => NULL,
+          'trxn_id' => 'TX103',
           'check_number' => NULL,
           'contribution_status_id' => 1,
         ),
diff --git a/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php b/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php
new file mode 100644 (file)
index 0000000..297057b
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | CiviCRM version 4.7                                                |
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC (c) 2004-2016                                |
+ +--------------------------------------------------------------------+
+ | 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        |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *  Test APIv3 civicrm_contribute_* functions
+ *
+ * @package CiviCRM_APIv3
+ * @subpackage API_Contribution
+ * @group headless
+ */
+class CRM_Contribute_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase {
+
+  /**
+   * Assume empty database with just civicrm_data.
+   */
+  protected $_individualId;
+
+  /**
+   * Clean up after each test.
+   */
+  public function tearDown() {
+    $this->quickCleanUpFinancialEntities();
+    CRM_Utils_Hook::singleton()->reset();
+  }
+
+  /**
+   * Test the buildContributionArray function.
+   */
+  public function testBuildContributionArray() {
+    $this->_individualId = $this->individualCreate();
+    $params = array('contact_id' => $this->_individualId, 'total_amount' => 6, 'financial_type_id' => 'Donation');
+    $contributionIDs = $returnProperties = $messageToken = array();
+    $result = $this->callAPISuccess('Contribution', 'create', $params);
+    $contributionIDs[] = $result['id'];
+    $result = $this->callAPISuccess('Contribution', 'create', $params);
+    $contributionIDs[] = $result['id'];
+    $this->hookClass->setHook('civicrm_tokenValues', array($this, 'hookTokenValues'));
+
+    list($contributions, $contacts) = CRM_Contribute_Form_Task_PDFLetterCommon::buildContributionArray('contact_id', $contributionIDs, $returnProperties, TRUE, TRUE, $messageToken, 'test', '**', FALSE);
+
+    $this->assertEquals('Anthony', $contacts[$this->_individualId]['first_name']);
+    $this->assertEquals('emo', $contacts[$this->_individualId]['favourite_emoticon']);
+    $this->assertEquals('Donation', $contributions[$result['id']]['financial_type']);
+  }
+
+  /**
+   * Implement token values hook.
+   *
+   * @param array $details
+   * @param array $contactIDs
+   * @param int $jobID
+   * @param array $tokens
+   * @param string $className
+   */
+  public function hookTokenValues(&$details, $contactIDs, $jobID, $tokens, $className) {
+    foreach ($details as $index => $detail) {
+      $details[$index]['favourite_emoticon'] = 'emo';
+    }
+  }
+
+}
index c9dd9964bb1a5d09239a7169b6a6ee53a0868acb..03ef858c5ab4cf290859724f2db3fe0753f9c729 100644 (file)
@@ -87,6 +87,20 @@ class CRM_Core_BAO_CustomGroupTest extends CiviUnitTestCase {
     $this->callAPISuccess('ContactType', 'delete', array('id' => $contactType['id']));
   }
 
+  /**
+   * Test calling getTree for a custom field extending a disabled contact type.
+   */
+  public function testGetTreeContactSubTypeForDisabledChangedContactType() {
+    $contactType = $this->callAPISuccess('ContactType', 'create', array('name' => 'Big Bank', 'label' => 'biggee', 'parent_id' => 'Organization'));
+    $customGroup = $this->CustomGroupCreate(array('extends' => 'Organization', 'extends_entity_column_value' => array('Big_Bank')));
+    $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
+    $this->callAPISuccess('ContactType', 'create', array('id' => $contactType['id'], 'is_active' => 0));
+    $result1 = CRM_Core_BAO_CustomGroup::getTree('Organization', NULL, NULL, NULL, array('Big_Bank'));
+    $this->assertEquals('Custom Field', $result1[$customGroup['id']]['fields'][$customField['id']]['label']);
+    $this->customGroupDelete($customGroup['id']);
+    $this->callAPISuccess('ContactType', 'delete', array('id' => $contactType['id']));
+  }
+
   /**
    * Test calling getTree with contact subtype data.
    *
index 9463b5a17e2e31652d8a688a990de49946b7b230..e1af7dcfa7cb7d513a8b8bb7dc496625319a8de7 100644 (file)
@@ -899,6 +899,7 @@ class api_v3_SyntaxConformanceTest extends CiviUnitTestCase {
     for ($i = 0; $i < 30; $i++) {
       $baoObj = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
       $ids[] = $baoObj->id;
+      $baoObj->free();
     }
 
     // each case is array(0 => $inputtedApiOptions, 1 => $expectedResultCount)
@@ -945,6 +946,7 @@ class api_v3_SyntaxConformanceTest extends CiviUnitTestCase {
       for ($i = 0; $i < 3 - $totalEntities; $i++) {
         $baoObj = CRM_Core_DAO::createTestObject($baoString, array('currency' => 'USD'));
         $ids[] = $baoObj->id;
+        $baoObj->free();
       }
       $totalEntities = 3;
     }
index 028b4bed3e3b67115a7c3dac62a093e9528966e8..2af1739845fab4741aaaac20e64cc8cf117149e9 100644 (file)
     <name>postal_code</name>
     <title>Postal Code</title>
     <type>varchar</type>
-    <length>12</length>
+    <length>64</length>
     <import>true</import>
     <headerPattern>/postal|zip/i</headerPattern>
     <dataPattern>/\d?\d{4}(-\d{4})?/</dataPattern>