mutual_credit-5.0.x-dev/src/Entity/Access/TransactionAccessControlHandler.php
src/Entity/Access/TransactionAccessControlHandler.php
<?php
namespace Drupal\mcapi\Entity\Access;
use Drupal\mcapi\Entity\Workflow;
use Drupal\mcapi\Entity\Wallet;
use Drupal\mcapi\Entity\Query\WalletQuery;
use Drupal\Core\Entity\EntityAccessControlHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityHandlerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Messenger\Messenger;
use Drupal\Core\Config\Config;
use Symfony\Component\DependencyInjection\ContainerInterface;
use CreditCommons\Workflow as CCWorkflowInterface;
/**
* Defines an access controller option for the mc_transaction entity.
*/
class TransactionAccessControlHandler extends EntityAccessControlHandler implements EntityHandlerInterface {
/**
* @var Drupal\mcapi\Entity\Query\WalletQuery
*/
protected $walletQuery;
/**
* @var Drupal\Core\Messenger\Messenger
*/
protected $messenger;
/**
* @var Drupal\Core\Messenger\Messenger
*/
protected $mcapiConfig;
/**
*
* @param EntityTypeInterface $entity_type
* @param WalletQuery $wallet_query
* @param Messenger $messenger
* @param Config $mcapi_settings
*/
public function __construct(EntityTypeInterface $entity_type, WalletQuery $wallet_query, Messenger $messenger, Config $mcapi_settings) {
parent::__construct($entity_type);
$this->walletQuery = $wallet_query;
$this->messenger = $messenger;
$this->mcapiConfig = $mcapi_settings;
}
/**
*
* @param ContainerInterface $container
* @param EntityTypeInterface $entity_type
* @return \static
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$entity_type,
$container->get('entity_type.manager')->getStorage('mc_wallet')->getQuery(),
$container->get('messenger'),
$container->get('config.factory')->get('mcapi.settings'),
);
}
/**
* {@inheritDoc}
*
* @note There are only 2 operations, view and transition.
*/
public function access(EntityInterface $transaction, $operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
$account = $this->prepareUser($account);
$result = AccessResult::forbidden('Access forbidden by TransactionAccessControlHandler')->cachePerUser();
if ($operation == 'view label' or $operation == 'view') {
$operation = 'view';
$cid = 'mc_transaction:' . $transaction->id();
if (($return = $this->getCache($cid, $operation, 'und', $account)) !== NULL) {
// Cache hit, no work necessary.
return $return_as_object ? $return : $return->isAllowed();
}
if ($account->hasPermission('view all transactions') or $account->hasPermission('manage mcapi')) {
$result = AccessResult::allowed()->cachePerUser();
}
else {
// You can view this transaction if you own any of the wallets in it.
foreach (array_chunk($transaction->allWalletIds(), 50) as $wids) {
foreach (Wallet::loadMultiple($wids) as $wallet) {
if ($wallet->getOwnerId() == $account->id()) {
$result = AccessResult::allowed()->cachePerUser();
break 2;
}
}
}
}
}
elseif ($transaction->state->value == CCWorkflowInterface::STATE_VALIDATED) {
// grant access to the use who created the transaction
$result = AccessResult::allowedif($transaction->getOwnerId() == $account->id());
}
elseif ($operation == 'transition') {
$curr_state = $transaction->state->value;
$dest_state = \Drupal::request()->attributes->get('dest_state'); // Shame we can't get this from context.
$workflow = $transaction->workflow->entity;
$pathways = $workflow->transitions[$curr_state] ?? [];
if ($curr_state == 'V') {
}
elseif ($curr_state == CCWorkflowInterface::STATE_VALIDATED and $transaction->getOwnerId() == $account->id()) {
$result = AccessResult::allowed();
}
elseif ($dest_state == 'X') {// todo this should be a constant
$result = AccessResult::allowedIf($account->hasPermission('manage mcapi') and $this->mcapiConfig->get('delete_transactions'));
}
elseif (isset($pathways[$dest_state])) {
if ($account->hasPermission('manage mcapi')) {
// Only allowed because the transition is actually defined.
$result = AccessResult::allowed()->cachePerUser();
}
else{
$role = $pathways[$dest_state];
if ($transaction->payee->getOwner()->id() == $account->id() and CCWorkflowInterface::PARTY_PAYEE == $role) {
$result = AccessResult::allowed();
}
elseif ($transaction->payer->getOwner()->id() == $account->id() and CCWorkflowInterface::PARTY_PAYER == $role) {
$result = AccessResult::allowed();
}
}
}
}
$others = $this->moduleHandler()->invokeAll('mc_transaction_access', [$transaction, $operation, $account]);
$return = $this->processAccessHookResults(array_merge($others, [$result]));
if ($operation == 'view') {
$result = $this->setCache($return, $cid, 'view', 'und', $account);
}
return $return_as_object ? $result : $result->isAllowed();
}
/**
* @deprecated
*/
public function createAccess($entity_bundle = NULL, ?AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) {
@trigger_error('hook_old_hook is deprecated in drupal:10 and is removed from drupal:11. Use service mcapi.mc_transaction.create_access instead', E_USER_DEPRECATED);
return \Drupal::service('mcapi.mc_transaction.create_access')->access(Workflow::load('fallback'), $account);
}
}
