From: eileen <emcnaughton@wikimedia.org>
Date: Thu, 2 May 2019 02:19:50 +0000 (+1200)
Subject: Fix failure to copy custom fields & add test provided by Agileware
X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=3fec1adc393f63bb7acc9d51ec43716f4d987b9d;p=civicrm-core.git

Fix failure to copy custom fields & add test provided by Agileware

Per https://github.com/civicrm/civicrm-core/pull/13470 custom fields are
inconsistently copied where copying entities. This makes the code from
BAO_Event called from the genericCopy function.

I did a bit of an audit and the places where this is currently called from don't appear
to call the copyGeneric function with the 'custom' param that would have activated the old
code. I also consistently removed the & when it was being called so I could take it
out of the signature.

The original PR handled tags as well, but not in a generic way. I've left that out of scope
but the test is present, commented out, so it would be easy enough to revist
---

diff --git a/CRM/Contribute/BAO/ContributionPage.php b/CRM/Contribute/BAO/ContributionPage.php
index 492afdb67c..fa6c55592e 100644
--- a/CRM/Contribute/BAO/ContributionPage.php
+++ b/CRM/Contribute/BAO/ContributionPage.php
@@ -672,33 +672,33 @@ class CRM_Contribute_BAO_ContributionPage extends CRM_Contribute_DAO_Contributio
         'title' => ts('Copy of') . ' ',
       ],
     ];
-    $copy = &CRM_Core_DAO::copyGeneric('CRM_Contribute_DAO_ContributionPage', [
+    $copy = CRM_Core_DAO::copyGeneric('CRM_Contribute_DAO_ContributionPage', [
       'id' => $id,
     ], NULL, $fieldsFix);
 
     //copying all the blocks pertaining to the contribution page
-    $copyPledgeBlock = &CRM_Core_DAO::copyGeneric('CRM_Pledge_DAO_PledgeBlock', [
+    $copyPledgeBlock = CRM_Core_DAO::copyGeneric('CRM_Pledge_DAO_PledgeBlock', [
       'entity_id' => $id,
       'entity_table' => 'civicrm_contribution_page',
     ], [
       'entity_id' => $copy->id,
     ]);
 
-    $copyMembershipBlock = &CRM_Core_DAO::copyGeneric('CRM_Member_DAO_MembershipBlock', [
+    $copyMembershipBlock = CRM_Core_DAO::copyGeneric('CRM_Member_DAO_MembershipBlock', [
       'entity_id' => $id,
       'entity_table' => 'civicrm_contribution_page',
     ], [
       'entity_id' => $copy->id,
     ]);
 
-    $copyUFJoin = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin', [
+    $copyUFJoin = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin', [
       'entity_id' => $id,
       'entity_table' => 'civicrm_contribution_page',
     ], [
       'entity_id' => $copy->id,
     ]);
 
-    $copyWidget = &CRM_Core_DAO::copyGeneric('CRM_Contribute_DAO_Widget', [
+    $copyWidget = CRM_Core_DAO::copyGeneric('CRM_Contribute_DAO_Widget', [
       'contribution_page_id' => $id,
     ], [
       'contribution_page_id' => $copy->id,
@@ -707,14 +707,14 @@ class CRM_Contribute_BAO_ContributionPage extends CRM_Contribute_DAO_Contributio
     //copy price sets
     CRM_Price_BAO_PriceSet::copyPriceSet('civicrm_contribution_page', $id, $copy->id);
 
-    $copyTellFriend = &CRM_Core_DAO::copyGeneric('CRM_Friend_DAO_Friend', [
+    $copyTellFriend = CRM_Core_DAO::copyGeneric('CRM_Friend_DAO_Friend', [
       'entity_id' => $id,
       'entity_table' => 'civicrm_contribution_page',
     ], [
       'entity_id' => $copy->id,
     ]);
 
-    $copyPersonalCampaignPages = &CRM_Core_DAO::copyGeneric('CRM_PCP_DAO_PCPBlock', [
+    $copyPersonalCampaignPages = CRM_Core_DAO::copyGeneric('CRM_PCP_DAO_PCPBlock', [
       'entity_id' => $id,
       'entity_table' => 'civicrm_contribution_page',
     ], [
@@ -722,7 +722,7 @@ class CRM_Contribute_BAO_ContributionPage extends CRM_Contribute_DAO_Contributio
       'target_entity_id' => $copy->id,
     ]);
 
-    $copyPremium = &CRM_Core_DAO::copyGeneric('CRM_Contribute_DAO_Premium', [
+    $copyPremium = CRM_Core_DAO::copyGeneric('CRM_Contribute_DAO_Premium', [
       'entity_id' => $id,
       'entity_table' => 'civicrm_contribution_page',
     ], [
diff --git a/CRM/Core/BAO/Job.php b/CRM/Core/BAO/Job.php
index 0509a0af47..867a043375 100644
--- a/CRM/Core/BAO/Job.php
+++ b/CRM/Core/BAO/Job.php
@@ -159,7 +159,7 @@ class CRM_Core_BAO_Job extends CRM_Core_DAO_Job {
       ],
       'replace' => $params,
     ];
-    $copy = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_Job', ['id' => $id], NULL, $fieldsFix);
+    $copy = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_Job', ['id' => $id], NULL, $fieldsFix);
     $copy->save();
     CRM_Utils_Hook::copy('Job', $copy);
 
diff --git a/CRM/Core/BAO/Location.php b/CRM/Core/BAO/Location.php
index eecaab05c2..b0c68d1b8a 100644
--- a/CRM/Core/BAO/Location.php
+++ b/CRM/Core/BAO/Location.php
@@ -313,6 +313,7 @@ WHERE e.id = %1";
    *   newly created/updated location block id.
    */
   public static function copyLocBlock($locBlockId, $updateLocBlockId = NULL) {
+    CRM_Core_Error::deprecatedFunctionWarning('unused function which will be removed');
     //get the location info.
     $defaults = $updateValues = [];
     $locBlock = ['id' => $locBlockId];
@@ -344,7 +345,7 @@ WHERE e.id = %1";
       }
     }
 
-    $copyLocation = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_LocBlock',
+    $copyLocation = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_LocBlock',
       ['id' => $locBlock['id']],
       $copyLocationParams
     );
diff --git a/CRM/Core/BAO/UFGroup.php b/CRM/Core/BAO/UFGroup.php
index 5d7f256eb0..3adba27015 100644
--- a/CRM/Core/BAO/UFGroup.php
+++ b/CRM/Core/BAO/UFGroup.php
@@ -2692,7 +2692,7 @@ AND    ( entity_id IS NULL OR entity_id <= 0 )
       ),
     );
 
-    $copy = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFGroup',
+    $copy = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFGroup',
       array('id' => $id),
       NULL,
       $fieldsFix
@@ -2704,14 +2704,14 @@ AND    ( entity_id IS NULL OR entity_id <= 0 )
     $copy->name = CRM_Utils_String::munge($copy->name, '_', 56) . "_{$copy->id}";
     $copy->save();
 
-    $copyUFJoin = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin',
+    $copyUFJoin = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_UFJoin',
       array('uf_group_id' => $id),
       array('uf_group_id' => $copy->id),
       NULL,
       'entity_table'
     );
 
-    $copyUFField = &CRM_Core_DAO::copyGeneric('CRM_Core_BAO_UFField',
+    $copyUFField = CRM_Core_DAO::copyGeneric('CRM_Core_BAO_UFField',
       array('uf_group_id' => $id),
       array('uf_group_id' => $copy->id)
     );
diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php
index aab438e21a..09295bf028 100644
--- a/CRM/Core/DAO.php
+++ b/CRM/Core/DAO.php
@@ -1600,11 +1600,12 @@ FROM   civicrm_domain
    *   Fields that you want to block from.
    *   getting copied
    *
-   * @return CRM_Core_DAO
-   *   the newly created copy of the object
+   * @return CRM_Core_DAO|bool
+   *   the newly created copy of the object. False if none created.
    */
-  public static function &copyGeneric($daoName, $criteria, $newData = NULL, $fieldsFix = NULL, $blockCopyOfDependencies = NULL) {
+  public static function copyGeneric($daoName, $criteria, $newData = NULL, $fieldsFix = NULL, $blockCopyOfDependencies = NULL) {
     $object = new $daoName();
+    $newObject = FALSE;
     if (!$newData) {
       $object->id = $criteria['id'];
     }
@@ -1670,9 +1671,7 @@ FROM   civicrm_domain
         }
       }
       $newObject->save();
-      if (!empty($newData['custom'])) {
-        CRM_Core_BAO_CustomValueTable::store($newData['custom'], $newObject::getTableName(), $newObject->id);
-      }
+      $newObject->copyCustomFields($object->id, $newObject->id);
       CRM_Utils_Hook::post('create', CRM_Core_DAO_AllCoreTables::getBriefName($daoName), $newObject->id, $newObject);
     }
 
diff --git a/CRM/Event/BAO/Event.php b/CRM/Event/BAO/Event.php
index 35b7473632..22034dd9f5 100644
--- a/CRM/Event/BAO/Event.php
+++ b/CRM/Event/BAO/Event.php
@@ -986,7 +986,6 @@ WHERE civicrm_event.is_active = 1
       ['entity_value' => $id, 'mapping_id' => $oldMapping->getId()],
       ['entity_value' => $copyEvent->id, 'mapping_id' => $copyMapping->getId()]
     );
-    $copyEvent->copyCustomFields($id, $copyEvent->id);
 
     $copyEvent->save();
 
diff --git a/CRM/Price/BAO/PriceSet.php b/CRM/Price/BAO/PriceSet.php
index ff2e0c3b77..69e1f7fcd6 100644
--- a/CRM/Price/BAO/PriceSet.php
+++ b/CRM/Price/BAO/PriceSet.php
@@ -1559,7 +1559,7 @@ WHERE       ps.id = %1
         CRM_Price_BAO_PriceSet::addTo($baoName, $newId, $copyPriceSet->id);
       }
       else {
-        $copyPriceSet = &CRM_Core_DAO::copyGeneric('CRM_Price_DAO_PriceSetEntity',
+        $copyPriceSet = CRM_Core_DAO::copyGeneric('CRM_Price_DAO_PriceSetEntity',
           [
             'entity_id' => $id,
             'entity_table' => $baoName,
diff --git a/tests/phpunit/CRM/Core/BAO/RecurringEntityTest.php b/tests/phpunit/CRM/Core/BAO/RecurringEntityTest.php
index 7452e2cab1..73943396a3 100644
--- a/tests/phpunit/CRM/Core/BAO/RecurringEntityTest.php
+++ b/tests/phpunit/CRM/Core/BAO/RecurringEntityTest.php
@@ -318,4 +318,84 @@ class CRM_Core_BAO_RecurringEntityTest extends CiviUnitTestCase {
     $this->assertDBCompareValues('CRM_Friend_DAO_Friend', $searchActParams, $compareActParams);
   }
 
+  /**
+   * Testing Activity Generation through Entity Recursion with Custom Data and Tags.
+   */
+  public function testRecurringEntityGenerationWithCustomDataAndTags() {
+
+    // Create custom group and field
+    $customGroup = $this->customGroupCreate([
+      'extends' => 'Activity',
+    ]);
+    $customField = $this->customFieldCreate([
+        'custom_group_id' => $customGroup['id'],
+        'default_value' => '',
+      ]
+    );
+
+    // Create activity Tag
+    $tag = $this->tagCreate([
+      'used_for' => 'Activities',
+    ]);
+
+    // Create original activity
+    $customFieldValue = 'Custom Value';
+    $activityDateTime = date('YmdHis');
+    $activityId = $this->activityCreate([
+      'activity_date_time' => $activityDateTime,
+      'custom_' . $customField['id'] => $customFieldValue,
+    ]);
+
+    $activityId = $activityId['id'];
+
+    // Assign tag to a activity.
+    $this->callAPISuccess('EntityTag', 'create', [
+      'entity_table' => 'civicrm_activity',
+      'entity_id' => $activityId,
+      'tag_id' => $tag['id'],
+    ]);
+
+    // Create recurring activities.
+    $recursion = new CRM_Core_BAO_RecurringEntity();
+    $recursion->entity_id = $activityId;
+    $recursion->entity_table = 'civicrm_activity';
+    $recursion->dateColumns = ['activity_date_time'];
+    $recursion->schedule = [
+      'entity_value' => $activityId,
+      'start_action_date' => $activityDateTime,
+      'entity_status' => 'fourth saturday',
+      'repetition_frequency_unit' => 'month',
+      'repetition_frequency_interval' => 3,
+      'start_action_offset' => 3,
+      'used_for' => 'activity',
+    ];
+
+    $generatedEntities = $recursion->generate();
+    $generatedActivities = $generatedEntities['civicrm_activity'];
+
+    $this->assertEquals(3, count($generatedActivities), "Check if number of iterations are 3");
+
+    foreach ($generatedActivities as $generatedActivityId) {
+
+      /* Validate tag in recurring activity
+      // @todo - refer https://github.com/civicrm/civicrm-core/pull/13470
+      $this->callAPISuccess('EntityTag', 'getsingle', [
+      'entity_table' => 'civicrm_activity',
+      'entity_id' => $generatedActivityId,
+      ]);
+       */
+
+      // Validate custom data in recurring activity
+      $activity = $this->callAPISuccess('activity', 'getsingle', [
+        'return' => [
+          'custom_' . $customField['id'],
+        ],
+        'id' => $generatedActivityId,
+      ]);
+
+      $this->assertEquals($customFieldValue, $activity['custom_' . $customField['id']], 'Custom field value should be ' . $customFieldValue);
+
+    }
+  }
+
 }