Problem/Motivation
PaymentAccessControlHandler::checkAccess() throws a TypeError when checking access for the capture or refund operations:
TypeError: Drupal\Core\Access\AccessResult::allowedIf(): Argument #1 ($condition)
must be of type bool, Drupal\Core\Access\AccessResultForbidden given, called in
.../payment/src/Entity/Payment/PaymentAccessControlHandler.php on line 35
in Drupal\Core\Access\AccessResult::allowedIf() (line 82 of
core/lib/Drupal/Core/Access/AccessResult.php).
In PaymentAccessControlHandler::checkAccess(), the capture and refund branches wrap the results of PaymentMethodInterface::capturePaymentAccess() and PaymentMethodInterface::refundPaymentAccess() in AccessResult::allowedIf().
For example:
return AccessResult::allowedIf($payment_method instanceof PaymentMethodCapturePaymentInterface)
->andIf(AccessResult::allowedIf($payment_method->capturePaymentAccess($account)))
->andIf($this->checkAccessPermission($payment, $operation, $account));
However, according to the interfaces' docblocks (PaymentMethodCapturePaymentInterface::capturePaymentAccess() and PaymentMethodRefundPaymentInterface::refundPaymentAccess()) and the default implementations in PaymentMethodBase, both methods return an AccessResultInterface object rather than a bool.
AccessResult::allowedIf() requires a boolean $condition. Passing an AccessResultInterface to it therefore results in a TypeError.
This affects sites using a payment method that implements PaymentMethodCapturePaymentInterface or PaymentMethodRefundPaymentInterface when a capture or refund access check is performed, for example:
$payment->access('capture');
Steps to reproduce
- Enable a payment method plugin implementing
PaymentMethodCapturePaymentInterfaceorPaymentMethodRefundPaymentInterface. - Create or load a payment entity using that payment method.
- Call
$payment->access('capture')or$payment->access('refund'). - Observe the
TypeErrorcaused by passing anAccessResultInterfaceobject toAccessResult::allowedIf().
Proposed resolution
Since capturePaymentAccess() and refundPaymentAccess() already return an AccessResultInterface, pass their results directly to andIf() instead of wrapping them in AccessResult::allowedIf().
Remaining tasks
- Review and test the proposed patch.
- Add automated test coverage for
captureaccess checks. - Add automated test coverage for
refundaccess checks. - Verify the fix against the supported Drupal core versions.
- Verify whether the issue also exists in
2.x-dev.
User interface changes
None.
API changes
None. The existing PaymentMethodCapturePaymentInterface::capturePaymentAccess() and PaymentMethodRefundPaymentInterface::refundPaymentAccess() return types and behavior are preserved.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| payment-access-control-handler-typeerror.patch | 1.39 KB | carolpettirossi |
Comments
Comment #2
carolpettirossi commentedComment #3
carolpettirossi commented