dev/core#2115 Move financialacl code to a hook within the extension
authoreileen <emcnaughton@wikimedia.org>
Mon, 12 Oct 2020 00:29:32 +0000 (13:29 +1300)
committereileen <emcnaughton@wikimedia.org>
Mon, 12 Oct 2020 00:48:36 +0000 (13:48 +1300)
applyACLFinancialTypeStatusToFeeBlock is not doing anything that can't be done with a pre
hook.

This extends the application to one more code place but that doesn't seem like a bad thing

Test for success of filtering options by financial type

CRM/Member/Form/Membership.php
CRM/Price/BAO/PriceSet.php
ext/financialacls/financialacls.php
ext/financialacls/tests/phpunit/BuildAmountHookTest.php [new file with mode: 0644]

index cedf8eed66aa06deb27b1d1770d7e9f079e47a13..325a6a4c15ff2e354505d4def10310567e7a7acf 100644 (file)
@@ -1128,7 +1128,6 @@ class CRM_Member_Form_Membership extends CRM_Member_Form {
 
     // BEGIN Fix for dev/core/issues/860
     // Prepare fee block and call buildAmount hook - based on CRM_Price_BAO_PriceSet::buildPriceSet().
-    CRM_Price_BAO_PriceSet::applyACLFinancialTypeStatusToFeeBlock($this->_priceSet['fields']);
     CRM_Utils_Hook::buildAmount('membership', $this, $this->_priceSet['fields']);
     // END Fix for dev/core/issues/860
 
index e12716861383e02f28b418e3eeda14fb9d29c76d..54ab46980a3fcd2b3b20f3b2fbabff8ae84db90c 100644 (file)
@@ -880,7 +880,6 @@ WHERE  id = %1";
       $feeBlock = &$form->_priceSet['fields'];
     }
 
-    self::applyACLFinancialTypeStatusToFeeBlock($feeBlock);
     // Call the buildAmount hook.
     CRM_Utils_Hook::buildAmount($component, $form, $feeBlock);
 
@@ -941,9 +940,12 @@ WHERE  id = %1";
    * @param array $feeBlock
    *   Fee block: array of price fields.
    *
+   * @deprecated not used in civi universe as at Oct 2020.
+   *
    * @return void
    */
   public static function applyACLFinancialTypeStatusToFeeBlock(&$feeBlock) {
+    CRM_Core_Error::deprecatedFunctionWarning('enacted in financialtypeacl extension');
     if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
       foreach ($feeBlock as $key => $value) {
         foreach ($value['options'] as $k => $options) {
index c0edae5e58c12b4ff95002b722496cf4742fff0b..7c8e7e4eb46c56a0b315ec0f91572456bddaa8d4 100644 (file)
@@ -190,6 +190,30 @@ function financialacls_civicrm_selectWhereClause($entity, &$clauses) {
 
 }
 
+/**
+ * Remove un.
+ *
+ * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_buildAmount
+ *
+ * @param string $component
+ * @param \CRM_Core_Form $form
+ * @param array $feeBlock
+ */
+function financialacls_civicrm_buildAmount($component, $form, &$feeBlock) {
+  if (CRM_Financial_BAO_FinancialType::isACLFinancialTypeStatus()) {
+    foreach ($feeBlock as $key => $value) {
+      foreach ($value['options'] as $k => $options) {
+        if (!CRM_Core_Permission::check('add contributions of type ' . CRM_Contribute_PseudoConstant::financialType($options['financial_type_id']))) {
+          unset($feeBlock[$key]['options'][$k]);
+        }
+      }
+      if (empty($feeBlock[$key]['options'])) {
+        unset($feeBlock[$key]);
+      }
+    }
+  }
+}
+
 // --- Functions below this ship commented out. Uncomment as required. ---
 
 /**
diff --git a/ext/financialacls/tests/phpunit/BuildAmountHookTest.php b/ext/financialacls/tests/phpunit/BuildAmountHookTest.php
new file mode 100644 (file)
index 0000000..b240ac3
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+
+use Civi\Test\HeadlessInterface;
+use Civi\Test\HookInterface;
+use Civi\Test\TransactionalInterface;
+use Civi\Api4\PriceField;
+use Civi\Api4\PriceSet;
+use Civi\Api4\PriceFieldValue;
+
+/**
+ * Test that that financial acls are applied in the context of buildAmountHook.
+ *
+ * @group headless
+ */
+class BuildAmountHookTest extends \PHPUnit\Framework\TestCase implements HeadlessInterface, HookInterface, TransactionalInterface {
+
+  use Civi\Test\ContactTestTrait;
+  use Civi\Test\Api3TestTrait;
+
+  /**
+   * @return \Civi\Test\CiviEnvBuilder
+   * @throws \CRM_Extension_Exception_ParseException
+   */
+  public function setUpHeadless() {
+    // Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
+    // See: https://docs.civicrm.org/dev/en/latest/testing/phpunit/#civitest
+    return \Civi\Test::headless()
+      ->installMe(__DIR__)
+      ->apply();
+  }
+
+  /**
+   * Test api applies permissions on line item actions (delete & get).
+   */
+  public function testBuildAmount() {
+    $priceSet = PriceSet::create()->setValues(['name' => 'test', 'title' => 'test', 'extends' => 'CiviMember'])->execute()->first();
+    PriceField::create()->setValues([
+      'financial_type_id:name' => 'Donation',
+      'name' => 'donation',
+      'label' => 'donation',
+      'price_set_id' => $priceSet['id'],
+      'html_type' => 'Select',
+    ])->addChain('field_values', PriceFieldValue::save()->setRecords([
+      ['financial_type_id:name' => 'Donation', 'name' => 'a', 'label' => 'a', 'amount' => 1],
+      ['financial_type_id:name' => 'Member Dues', 'name' => 'b', 'label' => 'b', 'amount' => 2],
+    ])->setDefaults(['price_field_id' => '$id']))->execute();
+    Civi::settings()->set('acl_financial_type', TRUE);
+    $this->setPermissions([
+      'access CiviCRM',
+      'access CiviContribute',
+      'view contributions of type Donation',
+      'delete contributions of type Donation',
+      'add contributions of type Donation',
+      'edit contributions of type Donation',
+    ]);
+    $this->createLoggedInUser();
+    $form = new CRM_Member_Form_Membership();
+    $form->controller = new CRM_Core_Controller();
+    $form->set('priceSetId', $priceSet['id']);
+    CRM_Price_BAO_PriceSet::buildPriceSet($form);
+    $priceField = reset($form->_priceSet['fields']);
+    $this->assertCount(1, $priceField['options']);
+    $this->assertEquals('a', reset($priceField['options'])['name']);
+  }
+
+  /**
+   * Set ACL permissions, overwriting any existing ones.
+   *
+   * @param array $permissions
+   *   Array of permissions e.g ['access CiviCRM','access CiviContribute'],
+   */
+  protected function setPermissions(array $permissions) {
+    CRM_Core_Config::singleton()->userPermissionClass->permissions = $permissions;
+    if (isset(\Civi::$statics['CRM_Financial_BAO_FinancialType'])) {
+      unset(\Civi::$statics['CRM_Financial_BAO_FinancialType']);
+    }
+  }
+
+}