updated contrib modules : translation_views, views_bulk_edit, views_bulk_operations, workflow, addtoany, redis, url_to_video_filter
This commit is contained in:
@@ -66,17 +66,7 @@ field.storage_settings.workflow:
|
||||
label:
|
||||
type: label
|
||||
label: 'Label'
|
||||
allowed_values_function:
|
||||
type: string
|
||||
label: 'Allowed values function'
|
||||
|
||||
field.field_settings.workflow:
|
||||
type: mapping
|
||||
label: 'Workflow settings'
|
||||
|
||||
workflow.settings:
|
||||
type: config_object
|
||||
mapping:
|
||||
workflow_states_per_page:
|
||||
type: integer
|
||||
label: 'Number of workflow states displayed per page.'
|
||||
|
||||
+3
-3
@@ -6,8 +6,8 @@ package: Workflow
|
||||
# core: 8.x
|
||||
type: module
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-12-17
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-04-29
|
||||
version: '8.x-1.1'
|
||||
core: '8.x'
|
||||
project: 'workflow'
|
||||
datestamp: 1513552400
|
||||
datestamp: 1525039388
|
||||
|
||||
+4
-5
@@ -66,7 +66,7 @@ function workflow_access_workflow_operations($op, EntityInterface $entity = NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_insert().
|
||||
* Implements hook_ENTITY_TYPE_insert().
|
||||
*
|
||||
* We use the Role weight as an id.
|
||||
* In contrary to content_access module, that uses a 'content_access_roles_gids'
|
||||
@@ -78,11 +78,11 @@ function workflow_access_user_role_insert(EntityInterface $entity) {
|
||||
// Attend user to Rebuild data, because the weight of a role
|
||||
// is the key for workflow_Access.
|
||||
/** @var $entity \Drupal\user\RoleInterface */
|
||||
node_access_needs_rebuild(TRUE);
|
||||
node_access_needs_rebuild(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_access_entity_update().
|
||||
* Implements hook_access_ENTITY_TYPE_update().
|
||||
*
|
||||
* @param EntityInterface $entity
|
||||
*/
|
||||
@@ -167,8 +167,7 @@ function workflow_access_node_access_records(\Drupal\node\NodeInterface $node) {
|
||||
// - when rebuilding permissions via batch for Workflow Fields.
|
||||
// In that case, we need to create the workflow_transitions ourselves to
|
||||
// calculate the grants.
|
||||
foreach (_workflow_info_fields($node, $entity_type) as $field) {
|
||||
$field_name = $field->getName(); // Do not use id().
|
||||
foreach (workflow_get_workflow_field_names($node, $entity_type) as $field_name) {
|
||||
$old_sid = $new_sid = $node->$field_name->value;
|
||||
|
||||
// Create a dummy transition, just to set $node->workflow_transitions.
|
||||
|
||||
+3
-3
@@ -6,8 +6,8 @@ package: Workflow
|
||||
dependencies:
|
||||
- workflow
|
||||
configure: workflow.cleanup.settings
|
||||
# Information added by Drupal.org packaging script on 2017-12-17
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-04-29
|
||||
version: '8.x-1.1'
|
||||
core: '8.x'
|
||||
project: 'workflow'
|
||||
datestamp: 1513552400
|
||||
datestamp: 1525039388
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@ type: module
|
||||
dependencies:
|
||||
- workflow
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-12-17
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-04-29
|
||||
version: '8.x-1.1'
|
||||
core: '8.x'
|
||||
project: 'workflow'
|
||||
datestamp: 1513552400
|
||||
datestamp: 1525039388
|
||||
|
||||
+3
-3
@@ -5,8 +5,8 @@ type: module
|
||||
# core: 8.x
|
||||
|
||||
hidden: TRUE
|
||||
# Information added by Drupal.org packaging script on 2017-12-17
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-04-29
|
||||
version: '8.x-1.1'
|
||||
core: '8.x'
|
||||
project: 'workflow'
|
||||
datestamp: 1513552400
|
||||
datestamp: 1525039388
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@ type: module
|
||||
dependencies:
|
||||
- workflow
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-12-17
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-04-29
|
||||
version: '8.x-1.1'
|
||||
core: '8.x'
|
||||
project: 'workflow'
|
||||
datestamp: 1513552400
|
||||
datestamp: 1525039388
|
||||
|
||||
+3
-3
@@ -24,16 +24,16 @@ class WorkflowStateListBuilder extends DraggableListBuilder {
|
||||
$entities = [];
|
||||
|
||||
// Get the Workflow from the page.
|
||||
/** @var $workflow \Drupal\workflow\Entity\Workflow */
|
||||
if (!$workflow = workflow_url_get_workflow()) {
|
||||
// @todo: Generate error message.
|
||||
return $entities;
|
||||
}
|
||||
$wid = $url_wid = $workflow->id();
|
||||
|
||||
$wid = $workflow->id();
|
||||
/** @var WorkflowState[] $entities */
|
||||
$entities = parent::load();
|
||||
foreach ($entities as $key => $entity) {
|
||||
if (!isset($entity->wid) || $entity->wid != $wid) {
|
||||
if ($entity->getWorkflowId() != $wid) {
|
||||
unset($entities[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-17
@@ -99,20 +99,19 @@ class WorkflowConfigTransitionRoleForm extends WorkflowConfigTransitionFormBase
|
||||
continue;
|
||||
}
|
||||
$to_sid = $to_state->id();
|
||||
$stay_on_this_state = ($to_sid == $from_sid);
|
||||
|
||||
// Load existing config_transitions. Create if not found.
|
||||
$config_transitions = $workflow->getTransitionsByStateId($from_sid, $to_sid);
|
||||
if (!$config_transition = reset($config_transitions)) {
|
||||
$config_transition = $workflow->createTransition($from_sid, $to_sid);
|
||||
}
|
||||
$stay_on_this_state = !$config_transition->hasStateChange();
|
||||
|
||||
$row[$to_sid]['workflow_config_transition'] = ['#type' => 'value', '#value' => $config_transition, ];
|
||||
$row[$to_sid]['workflow_config_transition'] = ['#type' => 'value', '#value' => $config_transition,];
|
||||
$row[$to_sid]['roles'] = [
|
||||
'#type' => $stay_on_this_state ? 'checkboxes' : 'checkboxes',
|
||||
'#type' => 'checkboxes',
|
||||
'#options' => $stay_on_this_state ? [] : $roles,
|
||||
'#disabled' => $stay_on_this_state,
|
||||
// When $stay_on_this_state, allow all roles.
|
||||
'#default_value' => $stay_on_this_state ? $allow_all_roles : $config_transition->roles,
|
||||
];
|
||||
}
|
||||
@@ -127,24 +126,30 @@ class WorkflowConfigTransitionRoleForm extends WorkflowConfigTransitionFormBase
|
||||
*/
|
||||
public function validateForm(array &$form, FormStateInterface $form_state) {
|
||||
$workflow = $this->workflow;
|
||||
|
||||
// If only the 'Creation' state is available,
|
||||
if (count($form_state->getValue($this->entitiesKey)) < 2) {
|
||||
$form_state->setErrorByName('id', t('Please create at least one other state.',
|
||||
[]));
|
||||
}
|
||||
|
||||
// Make sure 'author' is checked for (creation) -> [something].
|
||||
$creation_state = $workflow->getCreationState();
|
||||
$creation_state_id = $workflow->getCreationState()->id();
|
||||
$author_has_permission = FALSE;
|
||||
foreach ($form_state->getValue($this->entitiesKey) as $from_sid => $to_data) {
|
||||
foreach ($to_data as $to_sid => $transition_data) {
|
||||
|
||||
if (empty($form_state->getValue($this->entitiesKey))) {
|
||||
$author_has_permission = TRUE;
|
||||
}
|
||||
else {
|
||||
$author_has_permission = FALSE;
|
||||
foreach ($form_state->getValue($this->entitiesKey) as $from_sid => $to_data) {
|
||||
foreach ($to_data as $to_sid => $transition_data) {
|
||||
if ($from_sid == $to_sid) {
|
||||
// Same-state-transition do not count.
|
||||
}
|
||||
elseif (!empty($transition_data['roles'][WORKFLOW_ROLE_AUTHOR_RID])) {
|
||||
$author_has_permission = TRUE;
|
||||
if ($from_sid == $creation_state_id) {
|
||||
// Same-state-transitions do not count.
|
||||
if ($from_sid != $to_sid) {
|
||||
if (!empty($transition_data['roles'][WORKFLOW_ROLE_AUTHOR_RID])) {
|
||||
$author_has_permission = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (!$author_has_permission) {
|
||||
@@ -152,7 +157,7 @@ class WorkflowConfigTransitionRoleForm extends WorkflowConfigTransitionFormBase
|
||||
['%creation' => $creation_state->label()]));
|
||||
}
|
||||
|
||||
return;
|
||||
parent::validateForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,8 +10,8 @@ configure: entity.workflow_type.collection
|
||||
dependencies:
|
||||
- workflow
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-12-17
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-04-29
|
||||
version: '8.x-1.1'
|
||||
core: '8.x'
|
||||
project: 'workflow'
|
||||
datestamp: 1513552400
|
||||
datestamp: 1525039388
|
||||
|
||||
@@ -70,8 +70,8 @@ function workflow_ui_help($route_name, RouteMatchInterface $route_match) {
|
||||
*
|
||||
* @deprecated : @see workflow_url_get_workflow .
|
||||
*/
|
||||
function workflow_ui_url_get_workflow($url = '' ) {
|
||||
return workflow_url_get_workflow($url);
|
||||
function workflow_ui_url_get_workflow() {
|
||||
return workflow_url_get_workflow();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,6 +88,6 @@ function workflow_ui_url_get_title() {
|
||||
*
|
||||
* @deprecated : @see workflow_url_get_form_type .
|
||||
*/
|
||||
function workflow_ui_url_get_form_type($url = '' ) {
|
||||
function workflow_ui_url_get_form_type($url = '') {
|
||||
return workflow_url_get_form_type($url);
|
||||
}
|
||||
|
||||
+12
-1
@@ -23,7 +23,10 @@ entity.workflow_state.collection:
|
||||
_title_callback: 'workflow_url_get_title'
|
||||
requirements:
|
||||
_permission: 'administer workflow'
|
||||
|
||||
options:
|
||||
parameters:
|
||||
workflow_type:
|
||||
type: entity:workflow_type
|
||||
|
||||
### Workflow Transitions
|
||||
entity.workflow_transition.collection:
|
||||
@@ -34,6 +37,10 @@ entity.workflow_transition.collection:
|
||||
_title_callback: 'workflow_url_get_title'
|
||||
requirements:
|
||||
_permission: 'administer workflow'
|
||||
options:
|
||||
parameters:
|
||||
workflow_type:
|
||||
type: entity:workflow_type
|
||||
|
||||
### Workflow Labels
|
||||
entity.workflow_label.collection:
|
||||
@@ -44,3 +51,7 @@ entity.workflow_label.collection:
|
||||
_title_callback: 'workflow_url_get_title'
|
||||
requirements:
|
||||
_permission: 'administer workflow'
|
||||
options:
|
||||
parameters:
|
||||
workflow_type:
|
||||
type: entity:workflow_type
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\workflow\Access;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Routing\Access\AccessInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\workflow\Entity\WorkflowManager;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Checks access to Workflow tab.
|
||||
*/
|
||||
class WorkflowHistoryAccess implements AccessInterface {
|
||||
|
||||
/**
|
||||
* Check if the user has permissions to view this workflow.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* Current user account.
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
|
||||
* Current routeMatch.
|
||||
* @param \Symfony\Component\Routing\Route $route
|
||||
* Current route.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden
|
||||
* If the user can access to this workflow.
|
||||
*/
|
||||
public function access(AccountInterface $account, RouteMatchInterface $routeMatch, Route $route) {
|
||||
static $access = [];
|
||||
|
||||
$uid = ($account) ? $account->id() : -1;
|
||||
|
||||
$entity = workflow_url_get_entity();
|
||||
$entity_id = $entity->id();
|
||||
$entity_type = $entity->getEntityTypeId();
|
||||
$entity_bundle = $entity->bundle();
|
||||
$field_name = workflow_url_get_parameter('field_name'); // @todo: this doesn't work.
|
||||
|
||||
if (isset($access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'])) {
|
||||
return $access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'];
|
||||
}
|
||||
|
||||
$access_result = AccessResult::forbidden();
|
||||
|
||||
// When having multiple workflows per bundle, use Views display
|
||||
// 'Workflow history per entity' instead!
|
||||
$fields = _workflow_info_fields($entity, $entity_type, $entity_bundle, $field_name);
|
||||
if (!$fields) {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
// @todo: Keep below code aligned between WorkflowState, ~Transition, ~TransitionListController
|
||||
// Determine if user is owner of the entity.
|
||||
$is_owner = WorkflowManager::isOwner($account, $entity);
|
||||
|
||||
/*
|
||||
* Determine if user has Access. Fill the cache.
|
||||
*/
|
||||
// @todo: what to do with multiple workflow_fields per bundle? Use Views instead! Or introduce a setting.
|
||||
// @todo D8-port: workflow_tab_access: use proper 'WORKFLOW_TYPE' permissions
|
||||
foreach ($fields as $definition) {
|
||||
$type_id = $definition->getSetting('workflow_type');
|
||||
if ($account->hasPermission("access any $type_id workflow_transion overview")) {
|
||||
$access_result = AccessResult::allowed();
|
||||
}
|
||||
elseif ($is_owner && $account->hasPermission("access own $type_id workflow_transion overview")) {
|
||||
$access_result = AccessResult::allowed();
|
||||
}
|
||||
elseif ($account->hasPermission('administer nodes')) {
|
||||
$access_result = AccessResult::allowed();
|
||||
}
|
||||
$access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'] = $access_result;
|
||||
}
|
||||
|
||||
return $access_result;
|
||||
}
|
||||
}
|
||||
+1
-78
@@ -58,7 +58,7 @@ class WorkflowTransitionListController extends EntityListController implements C
|
||||
|
||||
/**
|
||||
* Generates an overview table of older revisions of a node,
|
||||
* but only if this::historyAccess() allows it.
|
||||
* but only if WorkflowHistoryAccess::access() allows it.
|
||||
*
|
||||
* @param EntityInterface $node
|
||||
* A node object.
|
||||
@@ -137,81 +137,4 @@ class WorkflowTransitionListController extends EntityListController implements C
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu access control callback. Checks access to Workflow tab.
|
||||
*
|
||||
* This used to be D7-function workflow_tab_access($user, $entity).
|
||||
*
|
||||
* The History tab should not be used with multiple workflows per entity.
|
||||
* Use the dedicated view for this use case.
|
||||
* @todo D8: remove this in favour of View 'Workflow history per entity'.
|
||||
* @todo D8-port: make this workflow for non-Node entity types.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* Run access checks for this account.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResult
|
||||
*/
|
||||
public function historyAccess(AccountInterface $account) {
|
||||
static $access = [];
|
||||
|
||||
$uid = ($account) ? $account->id() : -1;
|
||||
|
||||
// @todo D8-port: make Workflow History tab happen for every entity_type.
|
||||
// @see workflow.routing.yml, workflow.links.task.yml, WorkflowTransitionListController.
|
||||
// ATM it only works for Nodes and Terms.
|
||||
// This is a hack. The Route should always pass an object.
|
||||
// On view tab, $entity is object,
|
||||
// On workflow tab, $entity is id().
|
||||
// Get the entity for this form.
|
||||
$entity = workflow_url_get_entity();
|
||||
|
||||
/* @var $entity EntityInterface */
|
||||
// Figure out the $entity's bundle and id.
|
||||
$entity_type = $entity->getEntityTypeId();
|
||||
$entity_bundle = $entity->bundle();
|
||||
$entity_id = ($entity) ? $entity->id() : '';
|
||||
$field_name = workflow_url_get_field_name();
|
||||
|
||||
if (isset($access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'])) {
|
||||
return $access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'];
|
||||
}
|
||||
|
||||
$access_result = AccessResult::forbidden();
|
||||
|
||||
// When having multiple workflows per bundle, use Views display
|
||||
// 'Workflow history per entity' instead!
|
||||
$fields = _workflow_info_fields($entity, $entity_type, $entity_bundle, $field_name);
|
||||
if (!$fields) {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
else {
|
||||
// @todo: Keep below code aligned between WorkflowState, ~Transition, ~TransitionListController
|
||||
$uid = ($account) ? $account->id() : -1;
|
||||
$entity_id = ($entity) ? $entity->id() : '';
|
||||
// Determine if user is owner of the entity.
|
||||
$is_owner = WorkflowManager::isOwner($account, $entity);
|
||||
|
||||
/**
|
||||
* Determine if user has Access. Fill the cache.
|
||||
*/
|
||||
// @todo: what to do with multiple workflow_fields per bundle? Use Views instead! Or introduce a setting.
|
||||
// @todo D8-port: workflow_tab_access: use proper 'WORKFLOW_TYPE' permissions
|
||||
foreach ($fields as $definition) {
|
||||
$type_id = $definition->getSetting('workflow_type');
|
||||
if ($account->hasPermission("access any $type_id workflow_transion overview")) {
|
||||
$access_result = AccessResult::allowed();
|
||||
}
|
||||
elseif ($is_owner && $account->hasPermission("access own $type_id workflow_transion overview")) {
|
||||
$access_result = AccessResult::allowed();
|
||||
}
|
||||
elseif ($account->hasPermission('administer nodes')) {
|
||||
$access_result = AccessResult::allowed();
|
||||
}
|
||||
$access[$uid][$entity_type][$entity_id][$field_name ? $field_name : 'no_field'] = $access_result;
|
||||
}
|
||||
}
|
||||
return $access_result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-15
@@ -41,7 +41,7 @@ class WorkflowTransitionElement extends FormElement {
|
||||
* @param array $complete_form
|
||||
*/
|
||||
public static function validateTransition(&$element, FormStateInterface $form_state, &$complete_form) {
|
||||
workflow_debug( __FILE__, __FUNCTION__, __LINE__); // @todo D8-port: still test this snippet.
|
||||
workflow_debug(__FILE__, __FUNCTION__, __LINE__); // @todo D8-port: still test this snippet.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ class WorkflowTransitionElement extends FormElement {
|
||||
* The Workflow element
|
||||
*/
|
||||
public static function processTransition(&$element, FormStateInterface $form_state, &$complete_form) {
|
||||
workflow_debug( __FILE__, __FUNCTION__, __LINE__); // @todo D8-port: still test this snippet.
|
||||
workflow_debug(__FILE__, __FUNCTION__, __LINE__); // @todo D8-port: still test this snippet.
|
||||
return self::transitionElement($element, $form_state, $complete_form);
|
||||
}
|
||||
|
||||
@@ -159,13 +159,6 @@ class WorkflowTransitionElement extends FormElement {
|
||||
$default_value = FALSE;
|
||||
}
|
||||
|
||||
// Fetch the form ID. This is unique for each entity, to allow multiple form per page (Views, etc.).
|
||||
// Make it uniquer by adding the field name, or else the scheduling of
|
||||
// multiple workflow_fields is not independent of each other.
|
||||
// If we are indeed on a Transition form (so, not a Node Form with widget)
|
||||
// then change the form id, too.
|
||||
$form_id = self::getFormId();
|
||||
|
||||
/*
|
||||
* Output: generate the element.
|
||||
*/
|
||||
@@ -230,7 +223,7 @@ class WorkflowTransitionElement extends FormElement {
|
||||
|
||||
// Add a state formatter before the rest of the form,
|
||||
// when transition is scheduled or widget is hidden.
|
||||
if ( (!$show_widget) || $transition_is_scheduled || $transition->isExecuted()) {
|
||||
if ((!$show_widget) || $transition_is_scheduled || $transition->isExecuted()) {
|
||||
$element['workflow_current_state'] = workflow_state_formatter($entity, $field_name, $current_sid);
|
||||
// Set a proper weight, which works for Workflow Options in select list AND action buttons.
|
||||
$element['workflow_current_state']['#weight'] = -0.005;
|
||||
@@ -316,6 +309,14 @@ class WorkflowTransitionElement extends FormElement {
|
||||
'#type' => 'container',
|
||||
'#tree' => TRUE,
|
||||
];
|
||||
// Define class for '#states' behaviour.
|
||||
// Fetch the form ID. This is unique for each entity, to allow multiple form per page (Views, etc.).
|
||||
// Make it uniquer by adding the field name, or else the scheduling of
|
||||
// multiple workflow_fields is not independent of each other.
|
||||
// If we are indeed on a Transition form (so, not a Node Form with widget)
|
||||
// then change the form id, too.
|
||||
$form_id = $form_state->getBuildInfo()['form_id'];
|
||||
$class_identifier = Html::getClass('scheduled_' . Html::getUniqueId($form_id).'-'.$field_name);
|
||||
$element['workflow_scheduling']['scheduled'] = [
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Schedule'),
|
||||
@@ -326,7 +327,7 @@ class WorkflowTransitionElement extends FormElement {
|
||||
'#default_value' => $transition_is_scheduled ? '1' : '0',
|
||||
'#attributes' => [
|
||||
// 'id' => 'scheduled_' . $form_id,
|
||||
'class' => [Html::getClass('scheduled_' . $form_id)],
|
||||
'class' => [$class_identifier],
|
||||
],
|
||||
];
|
||||
$element['workflow_scheduling']['date_time'] = [
|
||||
@@ -337,18 +338,18 @@ class WorkflowTransitionElement extends FormElement {
|
||||
'#suffix' => '</div>',
|
||||
'#states' => [
|
||||
//'visible' => array(':input[id="' . 'scheduled_' . $form_id . '"]' => array('value' => '1')),
|
||||
'visible' => ['input.' . Html::getClass('scheduled_' . $form_id) => ['value' => '1']],
|
||||
'visible' => ['input.' . $class_identifier => ['value' => '1']],
|
||||
],
|
||||
];
|
||||
$element['workflow_scheduling']['date_time']['workflow_scheduled_date'] = [
|
||||
'#type' => 'date',
|
||||
'#prefix' => t('At'),
|
||||
'#default_value' => implode( '-', [
|
||||
'#default_value' => implode('-', [
|
||||
'year' => date('Y', $timestamp),
|
||||
'month' => date('m', $timestamp),
|
||||
'day' => date('d', $timestamp),
|
||||
]
|
||||
)
|
||||
),
|
||||
];
|
||||
$element['workflow_scheduling']['date_time']['workflow_scheduled_hour'] = [
|
||||
'#type' => 'textfield',
|
||||
@@ -419,7 +420,7 @@ class WorkflowTransitionElement extends FormElement {
|
||||
return 'workflow_transition_form'; //@todo D8-port: add $form_id for widget and History tab.
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Implements ContentEntityForm::copyFormValuesToEntity(), and is called from:
|
||||
* - WorkflowTransitionForm::copyFormValuesToEntity()
|
||||
* - WorkflowDefaultWidget
|
||||
|
||||
@@ -84,6 +84,13 @@ class Workflow extends ConfigEntityBase implements WorkflowInterface {
|
||||
public $states = [];
|
||||
public $transitions = [];
|
||||
|
||||
/**
|
||||
* The module implementing this object, for config_export.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $module = 'workflow';
|
||||
|
||||
/**
|
||||
* CRUD functions.
|
||||
*/
|
||||
@@ -135,7 +142,10 @@ class Workflow extends ConfigEntityBase implements WorkflowInterface {
|
||||
*/
|
||||
public function delete() {
|
||||
if (!$this->isDeletable()) {
|
||||
// @todo: throw error if not workflow->isDeletable().
|
||||
$message = t('Workflow %workflow is not Deletable. Please delete the field where this workflow type is reffered',
|
||||
['%workflow' => $this->label()]);
|
||||
drupal_set_message($message, 'error');
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// Delete associated state (also deletes any associated transitions).
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Drupal\workflow\Entity;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityBase;
|
||||
use Drupal\Core\Config\Entity\ConfigEntityInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Drupal\workflow\WorkflowTypeAttributeTrait;
|
||||
|
||||
/**
|
||||
* Workflow configuration entity to persistently store configuration.
|
||||
@@ -45,6 +46,10 @@ use Drupal\user\UserInterface;
|
||||
* )
|
||||
*/
|
||||
class WorkflowConfigTransition extends ConfigEntityBase implements WorkflowConfigTransitionInterface {
|
||||
/*
|
||||
* Add variables and get/set methods for Workflow property.
|
||||
*/
|
||||
use WorkflowTypeAttributeTrait;
|
||||
|
||||
// Transition data.
|
||||
public $id;
|
||||
@@ -52,11 +57,12 @@ class WorkflowConfigTransition extends ConfigEntityBase implements WorkflowConfi
|
||||
public $to_sid;
|
||||
public $roles = [];
|
||||
|
||||
// Extra fields.
|
||||
protected $wid;
|
||||
// The following must explicitly defined, and not be public, to avoid errors
|
||||
// when exporting with json_encode().
|
||||
protected $workflow = NULL;
|
||||
/**
|
||||
* The module implementing this object, for config_export.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $module = 'workflow';
|
||||
|
||||
/*
|
||||
* Entity class functions.
|
||||
@@ -67,7 +73,11 @@ class WorkflowConfigTransition extends ConfigEntityBase implements WorkflowConfi
|
||||
*/
|
||||
public function __construct(array $values = [], $entityType = NULL) {
|
||||
// Please be aware that $entity_type and $entityType are different things!
|
||||
return parent::__construct($values, $entity_type = 'workflow_config_transition');
|
||||
parent::__construct($values, $entity_type = 'workflow_config_transition');
|
||||
$state = WorkflowState::load($this->to_sid ? $this->to_sid : $this->from_sid);
|
||||
if($state) {
|
||||
$this->setWorkflow($state->getWorkflow());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,8 +86,10 @@ class WorkflowConfigTransition extends ConfigEntityBase implements WorkflowConfi
|
||||
* @param $to_sid
|
||||
*/
|
||||
public function setValues($from_sid, $to_sid) {
|
||||
$this->from_sid = $from_sid;
|
||||
$this->to_sid = $to_sid;
|
||||
$state = WorkflowState::load($this->to_sid ? $this->to_sid : $this->from_sid);
|
||||
if($state) {
|
||||
$this->setWorkflow($state->getWorkflow());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,29 +160,6 @@ class WorkflowConfigTransition extends ConfigEntityBase implements WorkflowConfi
|
||||
* Property functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWorkflow() {
|
||||
if (!$this->workflow && $wid = $this->getWorkflowId()) {
|
||||
$this->workflow = Workflow::load($wid);
|
||||
}
|
||||
return $this->workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWorkflowId() {
|
||||
if (!$this->wid) {
|
||||
$from_sid = $this->getFromSid();
|
||||
$to_sid = $this->getToSid();
|
||||
$state = WorkflowState::load($to_sid ? $to_sid : $from_sid);
|
||||
$this->wid = $state->getWorkflowId();
|
||||
}
|
||||
return $this->wid;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -219,4 +208,15 @@ class WorkflowConfigTransition extends ConfigEntityBase implements WorkflowConfi
|
||||
return TRUE == array_intersect($user->getRoles(), $this->roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the State changes by this Transition.
|
||||
* @return bool
|
||||
*/
|
||||
public function hasStateChange() {
|
||||
if ($this->from_sid == $this->to_sid) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-3
@@ -31,7 +31,7 @@ interface WorkflowConfigTransitionInterface {
|
||||
public function isAllowed(UserInterface $user, $force = FALSE);
|
||||
|
||||
/**
|
||||
* Returns the Workflow object of this State.
|
||||
* Returns the Workflow object of this object.
|
||||
*
|
||||
* @return Workflow
|
||||
* Workflow object.
|
||||
@@ -39,10 +39,10 @@ interface WorkflowConfigTransitionInterface {
|
||||
public function getWorkflow();
|
||||
|
||||
/**
|
||||
* Returns the Workflow ID of this Transition
|
||||
* Returns the Workflow ID of this object.
|
||||
*
|
||||
* @return string
|
||||
* Workflow Id.
|
||||
* Workflow ID.
|
||||
*/
|
||||
public function getWorkflowId();
|
||||
|
||||
@@ -66,4 +66,9 @@ interface WorkflowConfigTransitionInterface {
|
||||
*/
|
||||
public function getToSid();
|
||||
|
||||
/**
|
||||
* Determines if the State changes by this Transition.
|
||||
* @return bool
|
||||
*/
|
||||
public function hasStateChange();
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ interface WorkflowInterface {
|
||||
* @param string $to_sid
|
||||
* @param array $values
|
||||
*
|
||||
* @return mixed|null|static
|
||||
* @return WorkflowConfigTransitionInterface
|
||||
*/
|
||||
public function createTransition($from_sid, $to_sid, $values = []);
|
||||
|
||||
|
||||
@@ -140,21 +140,13 @@ class WorkflowManager implements WorkflowManagerInterface {
|
||||
public static function executeTransitionsOfEntity(EntityInterface $entity) {
|
||||
|
||||
// Avoid this hook on workflow objects.
|
||||
if (in_array($entity->getEntityTypeId(), [
|
||||
'workflow_type',
|
||||
'workflow_state',
|
||||
'workflow_config_transition',
|
||||
'workflow_transition',
|
||||
'workflow_scheduled_transition',
|
||||
])) {
|
||||
if (WorkflowManager::isWorkflowEntityType($entity->getEntityTypeId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = workflow_current_user();
|
||||
|
||||
foreach (_workflow_info_fields($entity) as $field_info) {
|
||||
$field_name = $field_info->getName();
|
||||
|
||||
foreach (workflow_get_workflow_field_names($entity) as $field_name) {
|
||||
// Transition is created in widget or WorkflowTransitionForm.
|
||||
/** @var $transition WorkflowTransitionInterface */
|
||||
$transition = $entity->$field_name->__get('workflow_transition');
|
||||
@@ -345,7 +337,7 @@ class WorkflowManager implements WorkflowManagerInterface {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getWorkflowTransitionForm(EntityInterface $entity, string $field_name) {
|
||||
public static function getWorkflowTransitionForm(EntityInterface $entity, $field_name, array $form_state_additions = []) {
|
||||
// Create a transition, to pass to the form. No need to use setValues().
|
||||
$current_sid = workflow_node_current_state($entity, $field_name);
|
||||
$transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
|
||||
@@ -353,7 +345,7 @@ class WorkflowManager implements WorkflowManagerInterface {
|
||||
// Create the WorkflowTransitionForm.
|
||||
/** @var \Drupal\Core\Entity\EntityFormBuilder $entity_form_builder */
|
||||
$entity_form_builder = \Drupal::getContainer()->get('entity.form_builder');
|
||||
$form = $entity_form_builder->getForm($transition, 'add');
|
||||
$form = $entity_form_builder->getForm($transition, 'add', $form_state_additions);
|
||||
return $form;
|
||||
}
|
||||
|
||||
@@ -455,7 +447,7 @@ class WorkflowManager implements WorkflowManagerInterface {
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function isWorkflowEntityType(string $entity_type_id) {
|
||||
public static function isWorkflowEntityType($entity_type_id) {
|
||||
return in_array($entity_type_id, [
|
||||
'workflow_type',
|
||||
'workflow_state',
|
||||
|
||||
@@ -108,7 +108,7 @@ interface WorkflowManagerInterface {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static function getWorkflowTransitionForm(EntityInterface $entity, string $field_name);
|
||||
public static function getWorkflowTransitionForm(EntityInterface $entity, $field_name, array $form_state_additions = []);
|
||||
|
||||
/**
|
||||
* Returns the attached fields (via Field UI)
|
||||
@@ -168,6 +168,6 @@ interface WorkflowManagerInterface {
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isWorkflowEntityType(string $entity_type_id);
|
||||
public static function isWorkflowEntityType($entity_type_id);
|
||||
|
||||
}
|
||||
|
||||
+13
-4
@@ -47,7 +47,7 @@ use Drupal\Core\Field\BaseFieldDefinition;
|
||||
class WorkflowScheduledTransition extends WorkflowTransition {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @inheritdoc.
|
||||
*/
|
||||
public function __construct(array $values = [], $entityType = 'workflow_scheduled_transition', $bundle = FALSE, $translations = []) {
|
||||
// Please be aware that $entity_type and $entityType are different things!
|
||||
@@ -70,7 +70,7 @@ class WorkflowScheduledTransition extends WorkflowTransition {
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This is a hack to avoid the following error, because ScheduledTransition is not a bundle of Workflow:
|
||||
* Drupal\Component\Plugin\Exception\PluginNotFoundException: The "entity:workflow_scheduled_transition:eerste" plugin does not exist. in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 60 of core\lib\Drupal\Component\Plugin\Discovery\DiscoveryTrait.php).
|
||||
* Drupal\Component\Plugin\Exception\PluginNotFoundException: The "entity:workflow_scheduled_transition:first" plugin does not exist. in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 60 of core\lib\Drupal\Component\Plugin\Discovery\DiscoveryTrait.php).
|
||||
*/
|
||||
function validate() {
|
||||
// Since this function generates an error in one use case (using WorkflowTransitionForm)
|
||||
@@ -176,11 +176,13 @@ class WorkflowScheduledTransition extends WorkflowTransition {
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @param string $from_sid
|
||||
* @param string $to_sid
|
||||
*
|
||||
* @return WorkflowScheduledTransition[]
|
||||
* An array of transitions.
|
||||
*/
|
||||
public static function loadBetween($start = 0, $end = 0) {
|
||||
public static function loadBetween($start = 0, $end = 0, $from_sid = '', $to_sid = '') {
|
||||
$transition_type = 'workflow_scheduled_transition'; // @todo: get this from annotation.
|
||||
|
||||
/* @var $query \Drupal\Core\Entity\Query\QueryInterface */
|
||||
@@ -193,6 +195,12 @@ class WorkflowScheduledTransition extends WorkflowTransition {
|
||||
if ($end) {
|
||||
$query->condition('timestamp', $end, '<');
|
||||
}
|
||||
if ($from_sid) {
|
||||
$query->condition('from_sid', $from_sid, '=');
|
||||
}
|
||||
if ($to_sid) {
|
||||
$query->condition('to_sid', $from_sid, '=');
|
||||
}
|
||||
|
||||
$ids = $query->execute();
|
||||
$transitions = self::loadMultiple($ids);
|
||||
@@ -233,7 +241,8 @@ class WorkflowScheduledTransition extends WorkflowTransition {
|
||||
$fields['timestamp'] = BaseFieldDefinition::create('created')
|
||||
->setLabel(t('Scheduled'))
|
||||
->setDescription(t('The date+time this transition is scheduled for.'))
|
||||
->setQueryable(FALSE)
|
||||
// ->setQueryable(FALSE)
|
||||
// ->setCustomStorage(FALSE)
|
||||
// ->setTranslatable(TRUE)
|
||||
// ->setDisplayOptions('view', array(
|
||||
// 'label' => 'hidden',
|
||||
|
||||
@@ -8,6 +8,7 @@ use Drupal\Core\Entity\Entity;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\workflow\WorkflowTypeAttributeTrait;
|
||||
|
||||
/**
|
||||
* Workflow configuration entity to persistently store configuration.
|
||||
@@ -54,6 +55,11 @@ use Drupal\Core\Language\LanguageInterface;
|
||||
*/
|
||||
class WorkflowState extends ConfigEntityBase {
|
||||
|
||||
/*
|
||||
* Add variables and get/set methods for Workflow property.
|
||||
*/
|
||||
use WorkflowTypeAttributeTrait;
|
||||
|
||||
/**
|
||||
* The machine name.
|
||||
*
|
||||
@@ -68,13 +74,6 @@ class WorkflowState extends ConfigEntityBase {
|
||||
*/
|
||||
public $label;
|
||||
|
||||
/**
|
||||
* The machine_name of the attached Workflow.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $wid;
|
||||
|
||||
/**
|
||||
* The weight of this Workflow state.
|
||||
*
|
||||
@@ -89,11 +88,11 @@ class WorkflowState extends ConfigEntityBase {
|
||||
public $status = 1;
|
||||
|
||||
/**
|
||||
* The attached Workflow.
|
||||
* The module implementing this object, for config_export.
|
||||
*
|
||||
* @var Workflow
|
||||
* @var string
|
||||
*/
|
||||
protected $workflow;
|
||||
protected $module = 'workflow';
|
||||
|
||||
/**
|
||||
* CRUD functions.
|
||||
@@ -133,7 +132,7 @@ class WorkflowState extends ConfigEntityBase {
|
||||
// Create the machine_name for new states.
|
||||
// N.B.: Keep machine_name in WorkflowState and ~ListBuilder aligned.
|
||||
$sid = $this->id();
|
||||
$wid = $this->wid;
|
||||
$wid = $this->getWorkflowId();
|
||||
$label = $this->label();
|
||||
|
||||
// Set the workflow-including machine_name.
|
||||
@@ -185,7 +184,7 @@ class WorkflowState extends ConfigEntityBase {
|
||||
$result = [];
|
||||
foreach ($states as $state) {
|
||||
/** @var WorkflowState $state */
|
||||
if ((!$wid) || ($wid == $state->wid)) {
|
||||
if ((!$wid) || ($wid == $state->getWorkflowId())) {
|
||||
$result[$state->id()] = $state;
|
||||
}
|
||||
}
|
||||
@@ -198,8 +197,8 @@ class WorkflowState extends ConfigEntityBase {
|
||||
public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
|
||||
/** @var WorkflowState $a */
|
||||
/** @var WorkflowState $b */
|
||||
$a_wid = $a->wid;
|
||||
$b_wid = $b->wid;
|
||||
$a_wid = $a->getWorkflowId();
|
||||
$b_wid = $b->getWorkflowId();
|
||||
if ($a_wid == $b_wid) {
|
||||
$a_weight = $a->getWeight();
|
||||
$b_weight = $b->getWeight();
|
||||
@@ -263,7 +262,7 @@ class WorkflowState extends ConfigEntityBase {
|
||||
}
|
||||
|
||||
// Delete the transitions this state is involved in.
|
||||
$workflow = Workflow::load($this->wid);
|
||||
$workflow = Workflow::load($this->getWorkflowId());
|
||||
/** @var WorkflowInterface $workflow */
|
||||
/** @var WorkflowTransitionInterface $transition */
|
||||
foreach ($workflow->getTransitionsByStateId($current_sid, '') as $transition) {
|
||||
@@ -295,39 +294,6 @@ class WorkflowState extends ConfigEntityBase {
|
||||
return $this->weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Workflow ID of this State.
|
||||
*
|
||||
* @return string
|
||||
* Workflow Id.
|
||||
*/
|
||||
public function getWorkflowId() {
|
||||
return $this->wid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Workflow object of this State.
|
||||
*
|
||||
* @return Workflow
|
||||
* Workflow object.
|
||||
*/
|
||||
public function getWorkflow() {
|
||||
if (!isset($this->workflow)) {
|
||||
$this->workflow = Workflow::load($this->wid);
|
||||
}
|
||||
return $this->workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Workflow $workflow
|
||||
*/
|
||||
public function setWorkflow(Workflow $workflow) {
|
||||
workflow_debug(__FILE__, __FUNCTION__, __LINE__); // @todo D8-port: still test this snippet.
|
||||
|
||||
$this->wid = $workflow->id();
|
||||
$this->workflow = $workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Workflow object of this State.
|
||||
*
|
||||
@@ -396,15 +362,16 @@ class WorkflowState extends ConfigEntityBase {
|
||||
// No workflow, no options ;-)
|
||||
return $transitions;
|
||||
}
|
||||
// Load a User object, since we cannot add Roles to AccountInterface.
|
||||
if (!$user = workflow_current_user($account)) {
|
||||
// In some edge cases, no user is provided.
|
||||
return $transitions;
|
||||
}
|
||||
|
||||
// @todo: Keep below code aligned between WorkflowState, ~Transition, ~TransitionListController
|
||||
|
||||
/**
|
||||
* Get permissions of user, adding a Role to user, depending on situation.
|
||||
*/
|
||||
// Load a User object, since we cannot add Roles to AccountInterface.
|
||||
/** @var \Drupal\user\UserInterface $user */
|
||||
$user = workflow_current_user($account);
|
||||
// Determine if user is owner of the entity.
|
||||
$is_owner = WorkflowManager::isOwner($user, $entity);
|
||||
|
||||
@@ -423,6 +390,7 @@ class WorkflowState extends ConfigEntityBase {
|
||||
* Get the object and its permissions.
|
||||
*/
|
||||
/** @var WorkflowConfigTransition[] $transitions */
|
||||
/** @var Workflow $workflow */
|
||||
$transitions = $workflow->getTransitionsByStateId($this->id(), '');
|
||||
|
||||
/**
|
||||
@@ -518,6 +486,7 @@ class WorkflowState extends ConfigEntityBase {
|
||||
// We cannot use getTransitions, since there are no ConfigTransitions
|
||||
// from State with ID 0, and we do not want to repeat States.
|
||||
/** @var WorkflowState $state */
|
||||
/** @var Workflow $workflow */
|
||||
foreach ($workflow->getStates() as $state) {
|
||||
$options[$state->id()] = html_entity_decode(t('@label', ['@label' => $state->label()]));
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drupal\user\UserInterface;
|
||||
use Drupal\workflow\WorkflowTypeAttributeTrait;
|
||||
|
||||
/**
|
||||
* Implements an actual, executed, Transition.
|
||||
@@ -57,6 +58,11 @@ use Drupal\user\UserInterface;
|
||||
*/
|
||||
class WorkflowTransition extends ContentEntityBase implements WorkflowTransitionInterface {
|
||||
|
||||
/*
|
||||
* Add variables and get/set methods for Workflow property.
|
||||
*/
|
||||
use WorkflowTypeAttributeTrait;
|
||||
|
||||
/*
|
||||
* Transition data: are provided via baseFieldDefinitions().
|
||||
*/
|
||||
@@ -64,7 +70,6 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
/*
|
||||
* Cache data.
|
||||
*/
|
||||
protected $workflow; // Use WorkflowTransition->getWorkflow() to fetch this.
|
||||
protected $entity = NULL; // Use WorkflowTransition->getTargetEntity() to fetch this.
|
||||
protected $user = NULL; // Use WorkflowTransition->getOwner() to fetch this.
|
||||
|
||||
@@ -116,17 +121,15 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
public static function create(array $values = []) {
|
||||
if (is_array($values) && isset($values[0])) {
|
||||
$value = $values[0];
|
||||
$values['wid'] = '';
|
||||
$values['from_sid'] = '';
|
||||
if (is_string($value) && $state = WorkflowState::load($value)) {
|
||||
$values['wid'] = $state->getWorkflowId();
|
||||
$values['from_sid'] = $state->id();
|
||||
$state = NULL;
|
||||
if (is_string($value)) {
|
||||
$state = WorkflowState::load($value);
|
||||
}
|
||||
elseif (is_object($value) && $value instanceof WorkflowState) {
|
||||
$state = $value;
|
||||
$values['wid'] = $state->getWorkflowId();
|
||||
$values['from_sid'] = $state->id();
|
||||
}
|
||||
$values['wid'] = $state ? $state->getWorkflowId() : '';
|
||||
$values['from_sid'] = $state ? $state->id() : '';
|
||||
}
|
||||
|
||||
// Add default values.
|
||||
@@ -185,6 +188,10 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
public function save() {
|
||||
// return parent::save();
|
||||
|
||||
// Set Target Entity to be used by Rules.
|
||||
$reference = $this->get('entity_id')->first();
|
||||
$reference->set('entity', $this->getTargetEntity());
|
||||
|
||||
// Avoid custom actions for subclass WorkflowScheduledTransition.
|
||||
if ($this->isScheduled()) {
|
||||
return parent::save();
|
||||
@@ -257,7 +264,7 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
/** @var $query \Drupal\Core\Entity\Query\QueryInterface */
|
||||
$query = \Drupal::entityQuery($transition_type)
|
||||
->condition('entity_type', $entity_type)
|
||||
->sort('timestamp', $sort) // 'DESC' || 'ASC'
|
||||
->sort('timestamp', $sort)// 'DESC' || 'ASC'
|
||||
->addTag($transition_type);
|
||||
if (!empty($entity_ids)) {
|
||||
$query->condition('entity_id', $entity_ids, 'IN');
|
||||
@@ -387,6 +394,17 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the State changes by this Transition.
|
||||
* @return bool
|
||||
*/
|
||||
public function hasStateChange() {
|
||||
if ($this->from_sid->target_id == $this->to_sid->target_id) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -409,7 +427,7 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
|
||||
static $static_info = NULL;
|
||||
|
||||
if (isset($static_info[$entity_id][$field_name][$label])) {
|
||||
if (isset($static_info[$entity_id][$field_name][$label]) && !$this->isEmpty()) {
|
||||
// Error: this Transition is already executed.
|
||||
// On the development machine, execute() is called twice, when
|
||||
// on an Edit Page, the entity has a scheduled transition, and
|
||||
@@ -451,8 +469,7 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
// @todo: move below code to $this->isAllowed().
|
||||
// If the state has changed, check the permissions.
|
||||
// No need to check if Comments or attached fields are filled.
|
||||
$state_changed = ($from_sid != $to_sid);
|
||||
if ($state_changed) {
|
||||
if ($this->hasStateChange()) {
|
||||
// Make sure this transition is allowed by workflow module Admin UI.
|
||||
if (!$force) {
|
||||
$user->addRole(WORKFLOW_ROLE_AUTHOR_RID);
|
||||
@@ -503,7 +520,7 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
$this->save();
|
||||
|
||||
// Register state change with watchdog.
|
||||
if ($state_changed && !empty($this->getWorkflow()->options['watchdog_log'])) {
|
||||
if ($this->hasStateChange() && !empty($this->getWorkflow()->options['watchdog_log'])) {
|
||||
if ($this->getEntityTypeId() == 'workflow_scheduled_transition') {
|
||||
$message = 'Scheduled state change of @entity_type_label %entity_label to %sid2 executed';
|
||||
}
|
||||
@@ -597,31 +614,6 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWorkflow() {
|
||||
if (!$this->workflow && $wid = $this->getWorkflowId()) {
|
||||
$this->workflow = Workflow::load($wid);
|
||||
}
|
||||
return $this->workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getWorkflowId() {
|
||||
|
||||
if (!$this->wid->target_id && $state = $this->getFromState()) {
|
||||
// Fallback.
|
||||
$state = ($state) ? $state : $this->getToState();
|
||||
$wid = ($state) ? $state->getWorkflowId() : '';
|
||||
|
||||
$this->set('wid', $wid);
|
||||
}
|
||||
return $this->wid->target_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -1074,12 +1066,14 @@ class WorkflowTransition extends ContentEntityBase implements WorkflowTransition
|
||||
$user = $transition->getOwner();
|
||||
$user_name = ($user) ? $user->getAccountName() : 'unknown username';
|
||||
$t_string = $this->getEntityTypeId() . ' ' . $this->id() . ' for workflow_type <i>' . $this->getWorkflowId() . '</i> ' . ($function ? ("in function '$function'") : '');
|
||||
$output[] = 'Entity = ' . $this->getTargetEntityTypeId() . '/' . (($entity) ? ($entity->bundle() . '/' . $entity->id()) : '___/0') ;
|
||||
$output[] = 'Entity = ' . $this->getTargetEntityTypeId() . '/' . (($entity) ? ($entity->bundle() . '/' . $entity->id()) : '___/0');
|
||||
$output[] = 'Field = ' . $transition->getFieldName();
|
||||
$output[] = 'From/To = ' . $transition->getFromSid() . ' > ' . $transition->getToSid() . ' @ ' . $time;
|
||||
$output[] = 'Comment = ' . $user_name . ' says: ' . $transition->getComment();
|
||||
$output[] = 'Forced = ' . ($transition->isForced() ? 'yes' : 'no') .'; ' . 'Scheduled = ' . ($transition->isScheduled() ? 'yes' : 'no');
|
||||
if (function_exists('dpm')) { dpm($output, $t_string); }
|
||||
$output[] = 'Forced = ' . ($transition->isForced() ? 'yes' : 'no') . '; ' . 'Scheduled = ' . ($transition->isScheduled() ? 'yes' : 'no');
|
||||
if (function_exists('dpm')) { // in Workflow->dpm().
|
||||
dpm($output, $t_string); // in Workflow->dpm().
|
||||
} // in Workflow->dpm().
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,13 +45,11 @@ class WorkflowTransitionForm extends ContentEntityForm {
|
||||
// $entity_type = $transition->getTargetEntityTypeId();
|
||||
// $entity_id = $transition->getTargetEntityId();;
|
||||
|
||||
$suffix = 'form';
|
||||
// Emulate nodeForm convention.
|
||||
if ($transition->id()) {
|
||||
$suffix = 'edit_form';
|
||||
}
|
||||
else {
|
||||
$suffix = 'form';
|
||||
}
|
||||
$form_id = implode('_', ['workflow_transition', $field_name, $suffix]);
|
||||
$form_id = Html::getUniqueId($form_id);
|
||||
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ class WorkflowNodeGivenStateAction extends WorkflowStateActionBase {
|
||||
}
|
||||
|
||||
// Fire the transition.
|
||||
workflow_execute_transition($transition, $force);
|
||||
workflow_execute_transition($transition, $force = FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-7
@@ -109,7 +109,6 @@ abstract class WorkflowStateActionBase extends ConfigurableActionBase implements
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$form = [];
|
||||
|
||||
// If we are on admin/config/system/actions and use CREATE AN ADVANCED ACTION
|
||||
// Then $context only contains:
|
||||
@@ -126,18 +125,18 @@ abstract class WorkflowStateActionBase extends ConfigurableActionBase implements
|
||||
$wids = workflow_get_workflow_names();
|
||||
|
||||
if (empty($field_name) && count($wids) > 1) {
|
||||
drupal_set_message('You have more then one workflow in the system. Please first select the field name
|
||||
drupal_set_message('You have multiple workflows in the system. Please first select the field name
|
||||
and save the form. Then, revisit the form to set the correct state value.', 'warning');
|
||||
}
|
||||
if (empty($field_name)) {
|
||||
$wid = count($wids) ? array_keys($wids)[0] : '';
|
||||
}
|
||||
else {
|
||||
|
||||
$wid = count($wids) ? array_keys($wids)[0] : '';
|
||||
if (!empty($field_name)) {
|
||||
$fields = _workflow_info_fields($entity = NULL, $entity_type = '', $entity_bundle = '', $field_name);
|
||||
$wid = count($fields) ? reset($fields)->getSetting('workflow_type') : '';
|
||||
}
|
||||
|
||||
// Get the common Workflow, or create a dummy Workflow.
|
||||
/** @var Workflow $workflow */
|
||||
$workflow = $wid ? Workflow::load($wid) : Workflow::create(['id' => 'dummy_action', 'label' => 'dummy_action']);
|
||||
$current_state = $workflow->getCreationState();
|
||||
|
||||
@@ -183,7 +182,7 @@ abstract class WorkflowStateActionBase extends ConfigurableActionBase implements
|
||||
\Drupal::time()->getRequestTime(),
|
||||
$comment = $config['comment'],
|
||||
$force = $config['force']
|
||||
);
|
||||
);
|
||||
|
||||
// Add the WorkflowTransitionForm to the page. @todo
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\workflow\Plugin\Derivative;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides local task definitions for all entity bundles.
|
||||
*
|
||||
* @see \Drupal\workflow\Controller\EntityDebugController
|
||||
* @see \Drupal\workflow\Routing\RouteSubscriber
|
||||
*/
|
||||
class WorkflowLocalTask extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The entity manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Creates an WorkflowLocalTask object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The translation manager.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->stringTranslation = $string_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('string_translation')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$this->derivatives = [];
|
||||
|
||||
$field_list = workflow_get_workflow_fields_by_entity_type();
|
||||
foreach ($field_list as $entity_type_id => $fields) {
|
||||
$this->derivatives["entity.$entity_type_id.workflow_history"] = [
|
||||
'route_name' => "entity.$entity_type_id.workflow_history",
|
||||
'title' => $this->t('Workflow'),
|
||||
'base_route' => "entity.$entity_type_id.canonical",
|
||||
'weight' => 100,
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->derivatives as &$entry) {
|
||||
$entry += $base_plugin_definition;
|
||||
}
|
||||
|
||||
return $this->derivatives;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -156,7 +156,6 @@ class WorkflowItem extends ListItemBase {
|
||||
|
||||
return [
|
||||
'workflow_type' => '',
|
||||
'allowed_values_function' => 'workflow_state_allowed_values',
|
||||
] + parent::defaultStorageSettings();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ class WorkflowDefaultWidget extends WidgetBase {
|
||||
$field_storage = $field_config->getFieldStorageDefinition();
|
||||
|
||||
$entity = $item->getEntity();
|
||||
$field_name = $field_storage->get('field_name');
|
||||
$field_name = $field_storage->getName();
|
||||
|
||||
// Create a transition, to pass to the form. No need to use setValues().
|
||||
$from_sid = workflow_node_current_state($entity, $field_name);
|
||||
|
||||
+2
-3
@@ -3,10 +3,8 @@
|
||||
namespace Drupal\workflow\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\user\UserStorageInterface;
|
||||
use Drupal\workflow\Entity\WorkflowTransitionInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
@@ -54,6 +52,7 @@ class WorkflowFieldConstraintValidator extends ConstraintValidator implements Co
|
||||
*/
|
||||
public function validate($entity, Constraint $constraint) {
|
||||
// Workflow field name on CommentForm has special requirements.
|
||||
/** @var FieldStorageConfig $field_storage */
|
||||
$field_storage = $entity->getFieldDefinition()->getFieldStorageDefinition();
|
||||
if ($field_storage->getTargetEntityTypeId() == 'comment') {
|
||||
if (!$this->isValidFieldname($field_storage)) {
|
||||
@@ -76,7 +75,7 @@ class WorkflowFieldConstraintValidator extends ConstraintValidator implements Co
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$field_name = $field_storage->get('field_name');
|
||||
$field_name = $field_storage->getName();
|
||||
|
||||
// Check if the 'comment' field name exists on the 'commented' entity type.
|
||||
// @todo: Still not waterproof. You could have a field on a non-relevant entity_type.
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\workflow\Routing;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Routing\RouteSubscriberBase;
|
||||
use Drupal\Core\Routing\RoutingEvents;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Subscriber for Workflow routes.
|
||||
*
|
||||
* @see \Drupal\workflow\Plugin\Derivative\WorkflowLocalTask
|
||||
*/
|
||||
class RouteSubscriber extends RouteSubscriberBase {
|
||||
|
||||
/**
|
||||
* The entity type manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a new RouteSubscriber object.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_manager) {
|
||||
$this->entityTypeManager = $entity_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function alterRoutes(RouteCollection $collection) {
|
||||
|
||||
$field_list = workflow_get_workflow_fields_by_entity_type();
|
||||
foreach ($field_list as $entityTypeId => $fields) {
|
||||
|
||||
/*
|
||||
* @todo Create a Entity workflow field list page and a route
|
||||
* that redirect to the page when a entity have more than
|
||||
* one workflow fields.
|
||||
*/
|
||||
|
||||
// Only 1 field. Workflow is redirect to workflow/{field_name}.
|
||||
if (count($fields) < 2) {
|
||||
$path = "/$entityTypeId/{{$entityTypeId}}/workflow";
|
||||
$route = $this->getEntityLoadRoute($entityTypeId, $path);
|
||||
$collection->add("entity.$entityTypeId.workflow_history", $route);
|
||||
}
|
||||
|
||||
// Generate one route for each workflow field.
|
||||
foreach ($fields as $field_name => $field) {
|
||||
$path = "/$entityTypeId/{{$entityTypeId}}/workflow/$field_name";
|
||||
$route = $this->getEntityLoadRoute($entityTypeId, $path);
|
||||
$collection->add("entity.$entityTypeId.workflow_history.$field_name", $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity load route.
|
||||
*
|
||||
* @param string $entityTypeId
|
||||
* The entity type id.
|
||||
* @param string $path
|
||||
* The Path of the route.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\Route|null
|
||||
* The generated route, if available.
|
||||
*/
|
||||
protected function getEntityLoadRoute($entityTypeId, $path) {
|
||||
|
||||
/*
|
||||
* @todo Create the Route for taxonomy term like
|
||||
* '/taxonomy/term/{taxonomy_term}/workflow/{field_name}'
|
||||
*
|
||||
*/
|
||||
$route = new Route(
|
||||
$path,
|
||||
[
|
||||
'_controller' => '\Drupal\workflow\Controller\WorkflowTransitionListController::historyOverview',
|
||||
'_title' => 'Workflow history',
|
||||
],
|
||||
[
|
||||
'_custom_access' => '\Drupal\workflow\Access\WorkflowHistoryAccess::access',
|
||||
],
|
||||
[
|
||||
'_admin_route' => TRUE,
|
||||
'_workflow_entity_type_id' => $entityTypeId, // @todo: remove
|
||||
'parameters' => [
|
||||
$entityTypeId => ['type' => 'entity:' . $entityTypeId],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events = parent::getSubscribedEvents();
|
||||
$events[RoutingEvents::ALTER] = ['onAlterRoutes', 100];
|
||||
return $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all field of type workflow.
|
||||
*
|
||||
* @return array
|
||||
* Return all workflow fields.
|
||||
*
|
||||
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
|
||||
*/
|
||||
public function listWorkflowFields() {
|
||||
$fieldType = 'workflow';
|
||||
$fieldStorageConfigs = $this->entityTypeManager->getStorage('field_storage_config')->loadByProperties(['type' => $fieldType]);
|
||||
if (!$fieldStorageConfigs) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$availableItems = [];
|
||||
foreach ($fieldStorageConfigs as $fieldStorage) {
|
||||
$availableItems[] = $fieldStorage;
|
||||
}
|
||||
|
||||
return $availableItems;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
namespace Drupal\workflow;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Entity\EntityListBuilder;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityListBuilder;
|
||||
use Drupal\workflow\Entity\WorkflowTransition;
|
||||
|
||||
/**
|
||||
@@ -55,6 +55,7 @@ class WorkflowTransitionListBuilder extends EntityListBuilder {
|
||||
$field_name = workflow_url_get_field_name();
|
||||
|
||||
// @todo D8-port: document $limit. Should be used in pager, not in load().
|
||||
// N.B. Using the provided default History view is recommended.
|
||||
$this->limit = \Drupal::config('workflow.settings')->get('workflow_states_per_page');
|
||||
$limit = $this->limit;
|
||||
// Get Transitions with highest timestamp first.
|
||||
@@ -202,7 +203,7 @@ class WorkflowTransitionListBuilder extends EntityListBuilder {
|
||||
'class' => ['footer-class'],
|
||||
'data' => [
|
||||
[
|
||||
'data' => WORKFLOW_MARK_STATE_IS_DELETED . ' ' . t('State is no longer available.'),
|
||||
'data' => self::WORKFLOW_MARK_STATE_IS_DELETED . ' ' . t('State is no longer available.'),
|
||||
'colspan' => count($build['table']['#header']),
|
||||
],
|
||||
],
|
||||
@@ -210,7 +211,7 @@ class WorkflowTransitionListBuilder extends EntityListBuilder {
|
||||
];
|
||||
*/
|
||||
$build['workflow_footer'] = [
|
||||
'#markup' => WORKFLOW_MARK_STATE_IS_DELETED . ' ' . t('State is no longer available.'),
|
||||
'#markup' => self::WORKFLOW_MARK_STATE_IS_DELETED . ' ' . t('State is no longer available.'),
|
||||
'#weight' => 500, // @todo Make this better.
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\workflow;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityBase;
|
||||
use Drupal\workflow\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Wrapper methods for Workflow* objects
|
||||
*
|
||||
* Using this trait will add getWorkflow(), getWorkflowID() and setWorkflow()
|
||||
* methods to the class.
|
||||
*
|
||||
* @ingroup workflow
|
||||
*/
|
||||
trait WorkflowTypeAttributeTrait {
|
||||
|
||||
/**
|
||||
* The machine_name of the attached Workflow.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $wid = '';
|
||||
|
||||
/**
|
||||
* The attached Workflow.
|
||||
* It must explicitly be defined, and not be public, to avoid errors
|
||||
* when exporting with json_encode().
|
||||
*
|
||||
* @var Workflow
|
||||
*/
|
||||
protected $workflow = NULL;
|
||||
|
||||
/**
|
||||
* @param Workflow $workflow
|
||||
*/
|
||||
public function setWorkflow(Workflow $workflow) {
|
||||
$this->wid = '';
|
||||
$this->workflow = NULL;
|
||||
if ($workflow) {
|
||||
$this->wid = $workflow->id();
|
||||
$this->workflow = $workflow;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Workflow object of this object.
|
||||
*
|
||||
* @return Workflow
|
||||
* Workflow object.
|
||||
*/
|
||||
public function getWorkflow() {
|
||||
if (!empty($this->workflow)) {
|
||||
return $this->workflow;
|
||||
}
|
||||
|
||||
/** @noinspection PhpAssignmentInConditionInspection */
|
||||
if ($wid = $this->getWorkflowId()) {
|
||||
$this->workflow = Workflow::load($wid);
|
||||
}
|
||||
return $this->workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Workflow ID of this object.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function setWorkflowId($wid) {
|
||||
$this->wid = $wid;
|
||||
$this->workflow = NULL;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Workflow ID of this object.
|
||||
*
|
||||
* @return string
|
||||
* Workflow Id.
|
||||
*/
|
||||
public function getWorkflowId() {
|
||||
/** @var ContentEntityBase $this */
|
||||
if (!empty($this->wid)) {
|
||||
return $this->wid;
|
||||
}
|
||||
|
||||
$value = $this->get('wid');
|
||||
if (is_string($value)) {
|
||||
$this->wid = $value;
|
||||
}
|
||||
elseif (is_object($value)) {
|
||||
$wid = isset($value->getValue()[0]['target_id']) ? $value->getValue()[0]['target_id'] : '';
|
||||
// or: $this->set('wid', $wid);
|
||||
$this->wid = $wid; // in WorkflowTransition.
|
||||
}
|
||||
else {
|
||||
workflow_debug(__FILE__, __FUNCTION__, __LINE__, '', '');
|
||||
}
|
||||
|
||||
return $this->wid;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -95,6 +95,7 @@ function workflow_state_formatter($entity, $field_name, $current_sid = '') {
|
||||
// If user creates a node, and only 1 option is available, the formatter
|
||||
// is shown with key, not value, because creation state does not count.
|
||||
// In this case, hide the formatter.
|
||||
/** @var \Drupal\workflow\Entity\WorkflowState $state */
|
||||
$state = \Drupal\workflow\Entity\WorkflowState::load($current_sid);
|
||||
if ($state->isCreationState()) {
|
||||
return $element;
|
||||
@@ -117,3 +118,18 @@ function workflow_state_formatter($entity, $field_name, $current_sid = '') {
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is a residue for installations that have v8.x-1.0
|
||||
* The setting for options_allowed_values is still in the Field confuguration
|
||||
* Saving the field data again does not remove the settings.
|
||||
* So, we copy code from options_allowed_values().
|
||||
*
|
||||
* @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function workflow_state_allowed_values(\Drupal\Core\Field\FieldStorageDefinitionInterface $definition) {
|
||||
$values = $definition->getSetting('allowed_values');
|
||||
return $values;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ function _workflow_transition_form_get_action_buttons(array $form, array $workfl
|
||||
if (isset($form['#form_id']) && substr($form['#form_id'], 0, 24) == 'workflow_transition_form') {
|
||||
// Hide same-state-button on the transition-form (that is:
|
||||
// view page or workflow history tab) if there is nothing to do.
|
||||
// However, a Transition may be fieldable.
|
||||
// However, a Transition may be fieldable (have attached fields).
|
||||
if ($form['comment']['#access'] == FALSE) {
|
||||
$workflow_submit_action['#access'] = FALSE;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ dependencies:
|
||||
- options
|
||||
- user
|
||||
|
||||
# Information added by Drupal.org packaging script on 2017-12-17
|
||||
version: '8.x-1.0'
|
||||
# Information added by Drupal.org packaging script on 2018-04-29
|
||||
version: '8.x-1.1'
|
||||
core: '8.x'
|
||||
project: 'workflow'
|
||||
datestamp: 1513552400
|
||||
datestamp: 1525039388
|
||||
|
||||
@@ -18,13 +18,6 @@ function workflow_install() {
|
||||
drupal_set_message($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_uninstall().
|
||||
*/
|
||||
function workflow_uninstall() {
|
||||
// \Drupal::config('workflow.settings')->clear('workflow_states_per_page')->save(); // @FIXME
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_requirements().
|
||||
*
|
||||
|
||||
@@ -18,15 +18,6 @@ entity.workflow_type.delete_form:
|
||||
title: 'Delete'
|
||||
weight: 10
|
||||
|
||||
# @todo D8-port: make Workflow History tab happen for every entity_type.
|
||||
# @see workflow.routing.yml, workflow.links.task.yml, WorkflowTransitionListController.
|
||||
entity.node.workflow_history:
|
||||
route_name: entity.node.workflow_history
|
||||
base_route: entity.node.canonical
|
||||
title: 'Workflow'
|
||||
weight: 30
|
||||
entity.taxonomy_term.edit_form:
|
||||
route_name: entity.taxonomy_term.workflow_history
|
||||
base_route: entity.taxonomy_term.canonical
|
||||
title: 'Workflow'
|
||||
weight: 30
|
||||
workflow.entities:
|
||||
deriver: 'Drupal\workflow\Plugin\Derivative\WorkflowLocalTask'
|
||||
weight: 100
|
||||
|
||||
@@ -176,9 +176,9 @@ function workflow_entity_delete(\Drupal\Core\Entity\EntityInterface $entity) {
|
||||
elseif (!WorkflowManager::isWorkflowEntityType($entity->getEntityTypeId())) {
|
||||
// A 'normal' entity is deleted.
|
||||
foreach ($fields = _workflow_info_fields($entity) as $field_id => $field_storage) {
|
||||
$entity_type = $field_storage->getTargetEntityTypeId();
|
||||
$entity_id = $entity->id();
|
||||
$field_name = $field_storage->get('field_name');
|
||||
$entity_type = $field_storage->getTargetEntityTypeId();
|
||||
$field_name = $field_storage->getName();
|
||||
/** @var $transition Drupal\workflow\Entity\WorkflowTransitionInterface */
|
||||
foreach (WorkflowScheduledTransition::loadMultipleByProperties($entity_type, [$entity_id], [], $field_name) as $transition) {
|
||||
$transition->delete();
|
||||
@@ -347,8 +347,8 @@ function workflow_get_workflow_names($required = TRUE) {
|
||||
function workflow_get_workflow_field_names($entity = NULL, $entity_type = '', $entity_bundle = '', $field_name = '') {
|
||||
$result = [];
|
||||
foreach (_workflow_info_fields($entity, $entity_type, $entity_bundle, $field_name) as $definition) {
|
||||
$field_name = $definition->getName();
|
||||
$result[$field_name] = $definition->getName();
|
||||
$field_name2 = $definition->getName();
|
||||
$result[$field_name2] = $field_name2;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
@@ -397,10 +397,8 @@ function workflow_get_field_name(\Drupal\Core\Entity\EntityInterface $entity, $f
|
||||
if ($field_name) {
|
||||
return $field_name;
|
||||
}
|
||||
|
||||
$fields = _workflow_info_fields($entity);
|
||||
$field = reset($fields);
|
||||
$field_name = $field->getName();
|
||||
$fields = workflow_get_workflow_field_names($entity);
|
||||
$field_name = reset($fields);
|
||||
return $field_name;
|
||||
}
|
||||
|
||||
@@ -428,8 +426,6 @@ function workflow_current_user(\Drupal\Core\Session\AccountInterface $account =
|
||||
* @param string $field_name
|
||||
*
|
||||
* @return string $current_sid
|
||||
*
|
||||
* @deprecated : use WorkflowManager::getCurrentStateId()
|
||||
*/
|
||||
function workflow_node_current_state(\Drupal\Core\Entity\EntityInterface $entity, $field_name = '') {
|
||||
return WorkflowManager::getCurrentStateId($entity, $field_name);
|
||||
@@ -442,8 +438,6 @@ function workflow_node_current_state(\Drupal\Core\Entity\EntityInterface $entity
|
||||
* @param string $field_name
|
||||
*
|
||||
* @return string $previous_sid
|
||||
*
|
||||
* @deprecated : use WorkflowManager::getPreviousStateId()
|
||||
*/
|
||||
function workflow_node_previous_state(\Drupal\Core\Entity\EntityInterface $entity, $field_name = '') {
|
||||
return WorkflowManager::getPreviousStateId($entity, $field_name);
|
||||
@@ -486,6 +480,10 @@ function workflow_get_workflows_by_type($entity_bundle, $entity_type) {
|
||||
return $map[$entity_type][$entity_bundle];
|
||||
}
|
||||
|
||||
function workflow_get_workflow_fields_by_entity_type() {
|
||||
return \Drupal::service('entity_field.manager')->getFieldMapByFieldType('workflow');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the workflow field names, if not known already.
|
||||
*
|
||||
@@ -522,7 +520,24 @@ function _workflow_info_fields($entity = NULL, $entity_type = '', $entity_bundle
|
||||
// Do not use the field_name as ID, but the unique <entity_type>.<field_name>
|
||||
// since you cannot share the same field on multiple entity_types (unlike D7).
|
||||
$field_config = \Drupal\field\Entity\FieldStorageConfig::loadByName($e_type, $f_name);
|
||||
$field_info[$field_config->id()] = $field_config;
|
||||
if ($field_config) {
|
||||
$field_info[$field_config->id()] = $field_config;
|
||||
}
|
||||
else {
|
||||
// The field is a base/extra field not a configurable Field via Field UI.
|
||||
|
||||
// Refetch the field definitions, with extra data.
|
||||
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($e_type, $entity_bundle);
|
||||
// @todo ?? Loop over bundles?
|
||||
/** @var \Drupal\Core\Field\BaseFieldDefinition $field_config */
|
||||
$field_config = $field_definitions[$f_name];
|
||||
if ($field_config) {
|
||||
$field_info[$field_config->getUniqueStorageIdentifier()] = $field_config;
|
||||
}
|
||||
else {
|
||||
// @todo ?? Loop over bundles?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -545,36 +560,27 @@ function workflow_url_get_entity(\Drupal\Core\Entity\EntityInterface $entity = N
|
||||
return $entity;
|
||||
}
|
||||
|
||||
$route_match = \Drupal::routeMatch();
|
||||
|
||||
// @todo: get entity for any route.
|
||||
// On node pages, we'd get an object.
|
||||
$entity = $route_match->getParameter('node');
|
||||
if ($entity && is_object($entity)) {
|
||||
return $entity;
|
||||
$entities = [];
|
||||
foreach (\Drupal::routeMatch()->getParameters() as $param) {
|
||||
if ($param instanceof \Drupal\Core\Entity\EntityInterface) {
|
||||
$entities[] = $param;
|
||||
}
|
||||
}
|
||||
if ($entity && !is_object($entity)) {
|
||||
$value = reset($entities);
|
||||
|
||||
if ($value && is_object($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($value && !is_object($value)) {
|
||||
// On workflow tab, we'd get an id.
|
||||
$entity = \Drupal\node\Entity\Node::load($entity);
|
||||
// This is an indicator that the route is mal-configured.
|
||||
workflow_debug(__FILE__, __FUNCTION__, __LINE__, 'route declaration is not optimal.');
|
||||
$entity = \Drupal::entityTypeManager()->getStorage($entity_type)->load($value);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
// It was not a Node, try a Term.
|
||||
// On term pages, we get objects, or id's.
|
||||
$entity = $route_match->getParameter('taxonomy_term');
|
||||
if ($entity && is_object($entity)) {
|
||||
return $entity;
|
||||
}
|
||||
elseif ($entity && !is_object($entity)) {
|
||||
$entity = \Drupal\taxonomy\Entity\Term::load($entity);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
if (!$entity) {
|
||||
// We may be on a entity add page/
|
||||
// Or we may be on a page of some unknown entity.
|
||||
}
|
||||
return $entity;
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -585,10 +591,7 @@ function workflow_url_get_entity(\Drupal\Core\Entity\EntityInterface $entity = N
|
||||
* @return string|null $field_name
|
||||
*/
|
||||
function workflow_url_get_field_name() {
|
||||
/** @var $route_match \Drupal\Core\Routing\RouteMatchInterface */
|
||||
$route_match = \Drupal::routeMatch();
|
||||
$field_name = $route_match->getParameter('field_name');
|
||||
return $field_name;
|
||||
return workflow_url_get_parameter('field_name');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -609,32 +612,37 @@ function workflow_url_get_operation() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to determine Workflow from Workflow UI URL.
|
||||
* Helper function to get arbitrary parameter from a route.
|
||||
*
|
||||
* @param string $url
|
||||
* @param $parameter
|
||||
* The requested parameter.
|
||||
* @return string $field_name
|
||||
*/
|
||||
function workflow_url_get_parameter($parameter) {
|
||||
return \Drupal::routeMatch()->getParameter($parameter);
|
||||
// return \Drupal::request()->get($parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to determine Workflow from Workflow UI URL.
|
||||
* @return Workflow
|
||||
*/
|
||||
function workflow_url_get_workflow($url = '' ) {
|
||||
function workflow_url_get_workflow() {
|
||||
/** @var $workflows \Drupal\workflow\Entity\Workflow[] */
|
||||
static $workflows = [];
|
||||
|
||||
// For some reason, $_SERVER is not allowed as default.
|
||||
$url = ($url == '') ? $_SERVER['REQUEST_URI'] : $url;
|
||||
|
||||
// The URL may have prefixes: /
|
||||
// ex.1: /en/admin/config/workflow/workflow/MY_WORKFLOW/states
|
||||
// ex.2: /admin/config/workflow/workflow/MY_WORKFLOW/states
|
||||
$base_url = '/config/workflow/workflow/';
|
||||
$string = substr($url, strpos($url, $base_url) + strlen($base_url));
|
||||
$wid = explode('/', $string)[0];
|
||||
if (!isset($workflows[$wid])) {
|
||||
$workflows[$wid] = Workflow::load($wid);
|
||||
$wid = workflow_url_get_parameter('workflow_type');
|
||||
if (is_object($wid)) { // $wid is a Workflow object.
|
||||
return $wid;
|
||||
}
|
||||
|
||||
// $wid is a string
|
||||
if (!isset($workflows[$wid])) {
|
||||
$workflows[$wid] = $wid ? Workflow::load($wid) : NULL;
|
||||
}
|
||||
return $workflows[$wid];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to determine the title of the page.
|
||||
*
|
||||
|
||||
@@ -109,36 +109,3 @@ entity.workflow_scheduled_transition.delete_form:
|
||||
_admin_route: TRUE
|
||||
requirements:
|
||||
_entity_access: 'workflow_transition.delete'
|
||||
|
||||
### The Workflow Transition History List (Tab)
|
||||
# @todo D8-port: make Workflow History tab happen for every entity_type.
|
||||
# @see workflow.routing.yml, workflow.links.task.yml, WorkflowTransitionListController.
|
||||
# A route for showing the Workflow history tab.
|
||||
entity.node.workflow_history:
|
||||
path: '/node/{node}/workflow/{field_name}'
|
||||
defaults:
|
||||
_title: 'Workflow history'
|
||||
_controller: '\Drupal\workflow\Controller\WorkflowTransitionListController::historyOverview'
|
||||
field_name: ~
|
||||
requirements:
|
||||
_custom_access: '\Drupal\workflow\Controller\WorkflowTransitionListController::historyAccess'
|
||||
_module_dependencies: 'node'
|
||||
options:
|
||||
_admin_route: TRUE
|
||||
parameters:
|
||||
entity:
|
||||
type: entity:{entity_type}
|
||||
|
||||
entity.taxonomy_term.workflow_history:
|
||||
path: '/taxonomy/term/{taxonomy_term}/workflow/{field_name}'
|
||||
defaults:
|
||||
_title: 'Workflow history'
|
||||
_controller: '\Drupal\workflow\Controller\WorkflowTransitionListController::historyOverview'
|
||||
field_name: ~
|
||||
requirements:
|
||||
_custom_access: '\Drupal\workflow\Controller\WorkflowTransitionListController::historyAccess'
|
||||
_module_dependencies: 'taxonomy'
|
||||
options:
|
||||
parameters:
|
||||
entity:
|
||||
type: entity:{entity_type}
|
||||
|
||||
@@ -3,8 +3,8 @@ services:
|
||||
class: Drupal\workflow\Entity\WorkflowManager
|
||||
arguments: ['@entity_type.manager', '@entity.query', '@config.factory', '@string_translation', '@module_handler', '@current_user']
|
||||
|
||||
# workflow.route_subscriber:
|
||||
# class: Drupal\workflow\Routing\RouteSubscriber
|
||||
# arguments: ['@entity.manager']
|
||||
# tags:
|
||||
# - { name: event_subscriber }
|
||||
workflow.route_subscriber:
|
||||
class: Drupal\workflow\Routing\RouteSubscriber
|
||||
arguments: ['@entity.manager']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
||||
Reference in New Issue
Block a user