Asset state change actions support any workflow with the target state.

This commit is contained in:
paul121 2021-10-18 12:42:22 -07:00 committed by Michael Stenta
parent 9d4a7a756f
commit 268cac91dc
3 changed files with 89 additions and 46 deletions

View File

@ -2,10 +2,6 @@
namespace Drupal\asset\Plugin\Action;
use Drupal\Core\Action\Plugin\Action\EntityActionBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\asset\Entity\AssetInterface;
/**
* Action that makes an asset active.
*
@ -15,28 +11,11 @@ use Drupal\asset\Entity\AssetInterface;
* type = "asset"
* )
*/
class AssetActivate extends EntityActionBase {
class AssetActivate extends AssetStateChangeBase {
/**
* {@inheritdoc}
*/
public function execute(AssetInterface $asset = NULL) {
if ($asset) {
$asset->get('status')->first()->applyTransitionById('to_active');
$asset->setNewRevision(TRUE);
$asset->save();
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\asset\Entity\AssetInterface $object */
$result = $object->get('status')->access('edit', $account, TRUE)
->andIf($object->access('update', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
protected $targetState = 'active';
}

View File

@ -2,10 +2,6 @@
namespace Drupal\asset\Plugin\Action;
use Drupal\Core\Action\Plugin\Action\EntityActionBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\asset\Entity\AssetInterface;
/**
* Action that archives an asset.
*
@ -15,28 +11,11 @@ use Drupal\asset\Entity\AssetInterface;
* type = "asset"
* )
*/
class AssetArchive extends EntityActionBase {
class AssetArchive extends AssetStateChangeBase {
/**
* {@inheritdoc}
*/
public function execute(AssetInterface $asset = NULL) {
if ($asset) {
$asset->get('status')->first()->applyTransitionById('archive');
$asset->setNewRevision(TRUE);
$asset->save();
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\asset\Entity\AssetInterface $object */
$result = $object->get('status')->access('edit', $account, TRUE)
->andIf($object->access('update', $account, TRUE));
return $return_as_object ? $result : $result->isAllowed();
}
protected $targetState = 'archived';
}

View File

@ -0,0 +1,85 @@
<?php
namespace Drupal\asset\Plugin\Action;
use Drupal\asset\Entity\AssetInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\Plugin\Action\EntityActionBase;
use Drupal\Core\Session\AccountInterface;
/**
* Base class for actions that change the asset status state.
*/
abstract class AssetStateChangeBase extends EntityActionBase {
/**
* The target state to transition to.
*
* @var string
*/
protected $targetState;
/**
* {@inheritdoc}
*/
public function execute(AssetInterface $asset = NULL) {
// Bail if there is no asset.
if (empty($asset)) {
return;
}
// Apply the transition to target state if not already the current state.
/** @var \Drupal\state_machine\Plugin\Field\FieldType\StateItemInterface $state_item */
$state_item = $asset->get('status')->first();
if ($state_item->getOriginalId() !== $this->targetState && $transition = $state_item->getWorkflow()->findTransition($state_item->getOriginalId(), $this->targetState)) {
$state_item->applyTransition($transition);
$asset->setNewRevision(TRUE);
$asset->save();
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
/** @var \Drupal\asset\Entity\AssetInterface $object */
// First check entity and state field access.
$result = $object->get('status')->access('edit', $account, TRUE)
->andIf($object->access('update', $account, TRUE));
// Save the state field.
/** @var \Drupal\state_machine\Plugin\Field\FieldType\StateItemInterface $state_item */
$state_item = $object->get('status')->first();
// If the state field is already in the target state, return early.
// The workflow will not allow a transition to the same state but the
// action itself does not need to fail.
if ($state_item->getOriginalId() === $this->targetState) {
return $return_as_object ? $result : $result->isAllowed();
}
// Check that the target state exists for the workflow.
$workflow = $state_item->getWorkflow();
$target_state = $workflow->getState($this->targetState);
// Deny access if the workflow does not support the target state.
if (empty($target_state)) {
$result = $result->orif(AccessResult::forbiddenIf(
empty($target_state),
$this->t('The %workflow workflow does not support the %target_state state.', ['%workflow' => $workflow->getLabel(), '%target_state' => $this->targetState]),
));
}
// Else check that a transition exists to the desired target state.
else {
$transition = $workflow->findTransition($state_item->getOriginalId(), $this->targetState);
$result = $result->orIf(AccessResult::forbiddenIf(
empty($transition) || !$state_item->isTransitionAllowed($transition->getId()),
$this->t('The state transition from %original_state to %target_state is not allowed.', ['%original' => $state_item->getOriginalLabel(), '%target_state' => $target_state->getLabel()]),
));
}
return $return_as_object ? $result : $result->isAllowed();
}
}