Split shared function with mostly unshared code
authorEileen McNaughton <emcnaughton@wikimedia.org>
Thu, 12 Oct 2023 21:11:14 +0000 (10:11 +1300)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Fri, 13 Oct 2023 00:52:10 +0000 (13:52 +1300)
Almost all the code in this function is specific to the online form - we don't gain
much by sharing but it is harder to make changes because of
having to check the impact of each change on both forms.

Note both forms have test cover over this

CRM/Contribute/Form/Contribution.php
CRM/Contribute/Form/Contribution/Main.php
CRM/Price/BAO/PriceSet.php

index 50f54285ca5417d8ff0714a24fe749df21148d86..7e6f3da3c5b853bc3630ccbc5691be16241b7d23 100644 (file)
@@ -605,8 +605,7 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
         $getOnlyPriceSetElements = FALSE;
       }
 
-      $this->set('priceSetId', $this->_priceSetId);
-      CRM_Price_BAO_PriceSet::buildPriceSet($this, 'contribution', FALSE);
+      $this->buildPriceSet($this, 'contribution', FALSE);
 
       // get only price set form elements.
       if ($getOnlyPriceSetElements) {
@@ -925,6 +924,54 @@ class CRM_Contribute_Form_Contribution extends CRM_Contribute_Form_AbstractEditP
     }
   }
 
+  /**
+   * Build the price set form.
+   *
+   * @param CRM_Core_Form $form
+   * @param string|null $component
+   * @param bool $validFieldsOnly
+   */
+  private function buildPriceSet($form, $component = NULL, $validFieldsOnly = TRUE): void {
+    $priceSetId = $this->getPriceSetID();
+
+    $priceSet = CRM_Price_BAO_PriceSet::getSetDetail($priceSetId, TRUE, $validFieldsOnly);
+    $form->_priceSet = $priceSet[$priceSetId] ?? NULL;
+    $validPriceFieldIds = array_keys($form->_priceSet['fields']);
+
+    // @todo - this code is from previously shared function - can probaly go.
+    // Mark which field should have the auto-renew checkbox, if any. CRM-18305
+    if (!empty($form->_membershipTypeValues) && is_array($form->_membershipTypeValues)) {
+      $autoRenewMembershipTypes = [];
+      foreach ($form->_membershipTypeValues as $membershipTypeValue) {
+        if ($membershipTypeValue['auto_renew']) {
+          $autoRenewMembershipTypes[] = $membershipTypeValue['id'];
+        }
+      }
+      foreach ($form->_priceSet['fields'] as $field) {
+        if (array_key_exists('options', $field) && is_array($field['options'])) {
+          foreach ($field['options'] as $option) {
+            if (!empty($option['membership_type_id'])) {
+              if (in_array($option['membership_type_id'], $autoRenewMembershipTypes)) {
+                $form->_priceSet['auto_renew_membership_field'] = $field['id'];
+                // Only one field can offer auto_renew memberships, so break here.
+                break;
+              }
+            }
+          }
+        }
+      }
+    }
+    $form->_priceSet['id'] = $form->_priceSet['id'] ?? $priceSetId;
+    $form->assign('priceSet', $form->_priceSet);
+
+    $feeBlock = &$form->_priceSet['fields'];
+
+    // Call the buildAmount hook.
+    CRM_Utils_Hook::buildAmount($component ?? 'contribution', $form, $feeBlock);
+
+    CRM_Price_BAO_PriceSet::addPriceFieldsToForm($form, $feeBlock, $validFieldsOnly, __CLASS__, $validPriceFieldIds);
+  }
+
   /**
    * Global form rule.
    *
index e05211d3f5d3be864f92496594f4418aa918617a..b03a742bda38cf7d377f0fe76d5f54aa80951056 100644 (file)
@@ -349,7 +349,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
       // build price set form.
       $this->set('priceSetId', $this->_priceSetId);
       if (empty($this->_ccid)) {
-        CRM_Price_BAO_PriceSet::buildPriceSet($this, $this->getFormContext());
+        $this->buildPriceSet($this, $this->getFormContext());
       }
       if ($this->_values['is_monetary'] &&
         $this->_values['is_recur'] && empty($this->_values['pledge_id'])
@@ -468,6 +468,55 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
     $this->addFormRule(['CRM_Contribute_Form_Contribution_Main', 'formRule'], $this);
   }
 
+  /**
+   * Build the price set form.
+   *
+   * @param CRM_Core_Form $form
+   * @param string|null $component
+   * @param bool $validFieldsOnly
+   *
+   * @return void
+   * @throws \CRM_Core_Exception
+   */
+  private function buildPriceSet(&$form, $component = NULL, $validFieldsOnly = TRUE) {
+    $priceSetId = $this->getPriceSetID();
+    $priceSet = CRM_Price_BAO_PriceSet::getSetDetail($priceSetId, TRUE, $validFieldsOnly);
+    $form->_priceSet = $priceSet[$priceSetId] ?? NULL;
+    $validPriceFieldIds = array_keys($form->_priceSet['fields']);
+
+    // Mark which field should have the auto-renew checkbox, if any. CRM-18305
+    if (!empty($form->_membershipTypeValues) && is_array($form->_membershipTypeValues)) {
+      $autoRenewMembershipTypes = [];
+      foreach ($form->_membershipTypeValues as $membershipTypeValue) {
+        if ($membershipTypeValue['auto_renew']) {
+          $autoRenewMembershipTypes[] = $membershipTypeValue['id'];
+        }
+      }
+      foreach ($form->_priceSet['fields'] as $field) {
+        if (array_key_exists('options', $field) && is_array($field['options'])) {
+          foreach ($field['options'] as $option) {
+            if (!empty($option['membership_type_id'])) {
+              if (in_array($option['membership_type_id'], $autoRenewMembershipTypes)) {
+                $form->_priceSet['auto_renew_membership_field'] = $field['id'];
+                // Only one field can offer auto_renew memberships, so break here.
+                break;
+              }
+            }
+          }
+        }
+      }
+    }
+    $form->_priceSet['id'] = $form->_priceSet['id'] ?? $priceSetId;
+    $form->assign('priceSet', $form->_priceSet);
+
+    $feeBlock = &$form->_values['fee'];
+
+    // Call the buildAmount hook.
+    CRM_Utils_Hook::buildAmount($component ?? 'contribution', $form, $feeBlock);
+
+    CRM_Price_BAO_PriceSet::addPriceFieldsToForm($form, $feeBlock, $validFieldsOnly, __CLASS__, $validPriceFieldIds);
+  }
+
   /**
    * Build Membership  Block in Contribution Pages.
    * @todo this was shared on CRM_Contribute_Form_ContributionBase but we are refactoring and simplifying for each
index 874fcd208547351c79f571fa97f20217e8291fcf..2d66eac6c84d069e4375f58614ced7a19528791a 100644 (file)
@@ -791,9 +791,11 @@ WHERE  id = %1";
    * @param bool $validFieldsOnly
    *
    * @return void
-   * @throws \CRM_Core_Exception
+   *
+   * @deprecated since 5.68. Will be removed around 5.80.
    */
   public static function buildPriceSet(&$form, $component = NULL, $validFieldsOnly = TRUE) {
+    CRM_Core_Error::deprecatedFunctionWarning('copy & paste ....');
     $priceSetId = $form->get('priceSetId');
     if (!$priceSetId) {
       return;
@@ -840,7 +842,49 @@ WHERE  id = %1";
     // Call the buildAmount hook.
     CRM_Utils_Hook::buildAmount($component ?? 'contribution', $form, $feeBlock);
 
-    self::addPriceFieldsToForm($form, $feeBlock, $validFieldsOnly, $className, $validPriceFieldIds);
+    $hideAdminValues = !CRM_Core_Permission::check('edit contributions');
+    // CRM-14492 Admin price fields should show up on event registration if user has 'administer CiviCRM' permissions
+    $adminFieldVisible = CRM_Core_Permission::check('administer CiviCRM');
+    $checklifetime = FALSE;
+    foreach ($feeBlock as $id => $field) {
+      if (($field['visibility'] ?? NULL) == 'public' ||
+        (($field['visibility'] ?? NULL) == 'admin' && $adminFieldVisible == TRUE) ||
+        !$validFieldsOnly
+      ) {
+        $options = $field['options'] ?? NULL;
+        if ($className == 'CRM_Contribute_Form_Contribution_Main' && $component = 'membership') {
+          $contactId = $form->getVar('_membershipContactID');
+          if ($contactId && $options) {
+            $checklifetime = $checklifetime ?: self::checkCurrentMembership($options, $contactId);
+          }
+        }
+
+        $formClasses = ['CRM_Contribute_Form_Contribution', 'CRM_Member_Form_Membership'];
+
+        if (!is_array($options) || !in_array($id, $validPriceFieldIds)) {
+          continue;
+        }
+        elseif ($hideAdminValues && !in_array($className, $formClasses)) {
+          foreach ($options as $key => $currentOption) {
+            if ($currentOption['visibility_id'] == CRM_Price_BAO_PriceField::getVisibilityOptionID('admin')) {
+              unset($options[$key]);
+            }
+          }
+        }
+        if (!empty($options)) {
+          CRM_Price_BAO_PriceField::addQuickFormElement($form,
+            'price_' . $field['id'],
+            $field['id'],
+            FALSE,
+            CRM_Utils_Array::value('is_required', $field, FALSE),
+            NULL,
+            $options
+          );
+        }
+      }
+    }
+    $form->assign('ispricelifetime', $checklifetime);
+
   }
 
   /**
@@ -1616,13 +1660,18 @@ WHERE     ct.id = cp.financial_type_id AND
   /**
    * Add the relevant price fields to the form.
    *
+   * DO NOT use form outside core tested code - function is public for
+   * refactoring purposes only.
+   *
+   * @internal
+   *
    * @param \CRM_Core_Form $form
    * @param array $feeBlock
    * @param bool $validFieldsOnly
    * @param string $className
    * @param array $validPriceFieldIds
    */
-  protected static function addPriceFieldsToForm(CRM_Core_Form $form, $feeBlock, bool $validFieldsOnly, string $className, array $validPriceFieldIds) {
+  public static function addPriceFieldsToForm(CRM_Core_Form $form, $feeBlock, bool $validFieldsOnly, string $className, array $validPriceFieldIds) {
     $hideAdminValues = !CRM_Core_Permission::check('edit contributions');
     // CRM-14492 Admin price fields should show up on event registration if user has 'administer CiviCRM' permissions
     $adminFieldVisible = CRM_Core_Permission::check('administer CiviCRM');