updated core to 8.6.1 via composer

This commit is contained in:
2018-09-12 13:58:26 +02:00
parent a9a219f2ed
commit ea56b9fba3
4443 changed files with 112098 additions and 40708 deletions
@@ -1,59 +0,0 @@
langcode: en
status: true
dependencies:
module:
- content_moderation
id: editorial
label: 'Editorial'
type: content_moderation
type_settings:
states:
archived:
label: Archived
weight: 5
published: false
default_revision: true
draft:
label: Draft
published: false
default_revision: false
weight: -5
published:
label: Published
published: true
default_revision: true
weight: 0
transitions:
archive:
label: Archive
from:
- published
to: archived
weight: 2
archived_draft:
label: 'Restore to Draft'
from:
- archived
to: draft
weight: 3
archived_published:
label: Restore
from:
- archived
to: published
weight: 4
create_new_draft:
label: 'Create New Draft'
to: draft
weight: 0
from:
- draft
- published
publish:
label: Publish
to: published
weight: 1
from:
- draft
- published
entity_types: { }
@@ -6,4 +6,4 @@ core: 8.x
package: Core
configure: entity.workflow.collection
dependencies:
- workflows
- drupal:workflows
@@ -5,6 +5,21 @@
* Install, update and uninstall functions for the Content Moderation module.
*/
/**
* Implements hook_requirements().
*/
function content_moderation_requirements($phase) {
$requirements = [];
if ($phase === 'install' && \Drupal::moduleHandler()->moduleExists('workspaces')) {
$requirements['workspaces_incompatibility'] = [
'severity' => REQUIREMENT_ERROR,
'description' => t('Content Moderation can not be installed when Workspaces is also installed.'),
];
}
return $requirements;
}
/**
* Remove the 'content_revision_tracker' table.
*/
@@ -196,7 +196,7 @@ function content_moderation_entity_access(EntityInterface $entity, $operation, A
$transition_validation = \Drupal::service('content_moderation.state_transition_validation');
$valid_transition_targets = $transition_validation->getValidTransitions($entity, $account);
$access_result = $valid_transition_targets ? AccessResult::neutral() : AccessResult::forbidden();
$access_result = $valid_transition_targets ? AccessResult::neutral() : AccessResult::forbidden('No valid transitions exist for given account.');
$access_result->addCacheableDependency($entity);
$access_result->addCacheableDependency($account);
@@ -224,7 +224,7 @@ function content_moderation_entity_field_access($operation, FieldDefinitionInter
// Deny edit access to the published field if the entity is being moderated.
if ($entity_type->hasKey('published') && $moderation_info->isModeratedEntity($entity) && $entity->moderation_state && $field_definition->getName() == $entity_type->getKey('published')) {
return AccessResult::forbidden();
return AccessResult::forbidden('Cannot edit the published field of moderated entities.');
}
}
@@ -20,6 +20,7 @@ function content_moderation_post_update_update_cms_default_revisions(&$sandbox)
$entity_type_id = &$sandbox['entity_type_id'];
if (!isset($entity_type_id)) {
$sandbox['bundles'] = [];
$sandbox['entity_type_ids'] = [];
/** @var \Drupal\workflows\WorkflowInterface $workflow */
foreach (Workflow::loadMultipleByType('content_moderation') as $workflow) {
/** @var \Drupal\content_moderation\Plugin\WorkflowType\ContentModeration $plugin */
@@ -68,7 +68,7 @@ class LatestRevisionCheck implements AccessInterface {
return $access_result->addCacheableDependency($entity);
}
return AccessResult::forbidden()->addCacheableDependency($entity);
return AccessResult::forbidden('No pending revision for moderated entity.')->addCacheableDependency($entity);
}
/**
@@ -25,12 +25,16 @@ class ContentModerationStateStorageSchema extends SqlContentEntityStorageSchema
'workflow',
'langcode',
];
$schema['content_moderation_state_field_data']['unique keys'] += [
'content_moderation_state__lookup' => $unique_keys,
];
$schema['content_moderation_state_field_revision']['unique keys'] += [
'content_moderation_state__lookup' => $unique_keys,
];
if ($data_table = $this->storage->getDataTable()) {
$schema[$data_table]['unique keys'] += [
'content_moderation_state__lookup' => $unique_keys,
];
}
if ($revision_data_table = $this->storage->getRevisionDataTable()) {
$schema[$revision_data_table]['unique keys'] += [
'content_moderation_state__lookup' => $unique_keys,
];
}
return $schema;
}
@@ -14,7 +14,8 @@ class ModeratedContentController extends ControllerBase {
* Provides the listing page for moderated nodes.
*
* @return array
* A render array as expected by drupal_render().
* A render array as expected by
* \Drupal\Core\Render\RendererInterface::render().
*/
public function nodeListing() {
$entity_type = $this->entityTypeManager()->getDefinition('node');
@@ -54,7 +54,7 @@ class NodeModerationHandler extends ModerationHandler {
*/
public function enforceRevisionsBundleFormAlter(array &$form, FormStateInterface $form_state, $form_id) {
// Force the revision checkbox on.
$form['workflow']['options']['#default_value']['revision'] = 'revision';
$form['workflow']['options']['#value']['revision'] = 'revision';
$form['workflow']['options']['revision']['#disabled'] = TRUE;
}
@@ -81,7 +81,7 @@ class EntityModerationRouteProvider implements EntityRouteProviderInterface, Ent
'_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title',
])
// If the entity type is a node, unpublished content will be visible
// if the user has the "view all unpublished content" permission.
// if the user has the "view any unpublished content" permission.
->setRequirement('_entity_access', "{$entity_type_id}.view")
->setRequirement('_content_moderation_latest_version', 'TRUE')
->setOption('_content_moderation_entity_type', $entity_type_id)
@@ -5,8 +5,10 @@ namespace Drupal\content_moderation;
use Drupal\content_moderation\Entity\ContentModerationState as ContentModerationStateEntity;
use Drupal\content_moderation\Entity\ContentModerationStateInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBuilderInterface;
@@ -203,7 +205,6 @@ class EntityOperations implements ContainerInjectionInterface {
$moderation_state = $workflow->getTypePlugin()->getInitialState($entity)->id();
}
// @todo what if $entity->moderation_state is null at this point?
$content_moderation_state->set('content_entity_revision_id', $entity_revision_id);
$content_moderation_state->set('moderation_state', $moderation_state);
ContentModerationStateEntity::updateOrCreateFromEntity($content_moderation_state);
@@ -279,17 +280,39 @@ class EntityOperations implements ContainerInjectionInterface {
// The moderation form should be displayed only when viewing the latest
// (translation-affecting) revision, unless it was created as published
// default revision.
if (!$entity->isLatestRevision() && !$entity->isLatestTranslationAffectedRevision()) {
if (($entity->isDefaultRevision() || $entity->wasDefaultRevision()) && $this->isPublished($entity)) {
return;
}
if (($entity->isDefaultRevision() || $entity->wasDefaultRevision()) && ($moderation_state = $entity->get('moderation_state')->value)) {
$workflow = $this->moderationInfo->getWorkflowForEntity($entity);
if ($workflow->getTypePlugin()->getState($moderation_state)->isPublishedState()) {
return;
}
if (!$entity->isLatestRevision() && !$entity->isLatestTranslationAffectedRevision()) {
return;
}
$build['content_moderation_control'] = $this->formBuilder->getForm(EntityModerationForm::class, $entity);
}
/**
* Checks if the entity is published.
*
* This method is optimized to not have to unnecessarily load the moderation
* state and workflow if it is not required.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity to check.
*
* @return bool
* TRUE if the entity is published, FALSE otherwise.
*/
protected function isPublished(ContentEntityInterface $entity) {
// If the entity implements EntityPublishedInterface directly, check that
// first, otherwise fall back to check through the workflow state.
if ($entity instanceof EntityPublishedInterface) {
return $entity->isPublished();
}
if ($moderation_state = $entity->get('moderation_state')->value) {
$workflow = $this->moderationInfo->getWorkflowForEntity($entity);
return $workflow->getTypePlugin()->getState($moderation_state)->isPublishedState();
}
return FALSE;
}
}
@@ -119,7 +119,6 @@ class EntityTypeInfo implements ContainerInjectionInterface {
);
}
/**
* Adds Moderation configuration to appropriate entity types.
*
@@ -131,7 +130,7 @@ class EntityTypeInfo implements ContainerInjectionInterface {
public function entityTypeAlter(array &$entity_types) {
foreach ($entity_types as $entity_type_id => $entity_type) {
// The ContentModerationState entity type should never be moderated.
if ($entity_type->isRevisionable() && $entity_type_id != 'content_moderation_state') {
if ($entity_type->isRevisionable() && !$entity_type->isInternal()) {
$entity_types[$entity_type_id] = $this->addModerationToEntityType($entity_type);
}
}
@@ -9,8 +9,10 @@ use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\workflows\WorkflowInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -57,6 +59,13 @@ class ContentModerationConfigureEntityTypesForm extends FormBase {
*/
protected $entityType;
/**
* The Messenger service.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* {@inheritdoc}
*/
@@ -64,17 +73,19 @@ class ContentModerationConfigureEntityTypesForm extends FormBase {
return new static(
$container->get('entity_type.manager'),
$container->get('entity_type.bundle.info'),
$container->get('content_moderation.moderation_information')
$container->get('content_moderation.moderation_information'),
$container->get('messenger')
);
}
/**
* {@inheritdoc}
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $bundle_info, ModerationInformationInterface $moderation_information) {
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $bundle_info, ModerationInformationInterface $moderation_information, MessengerInterface $messenger) {
$this->entityTypeManager = $entity_type_manager;
$this->bundleInfo = $bundle_info;
$this->moderationInformation = $moderation_information;
$this->messenger = $messenger;
}
/**
@@ -108,6 +119,7 @@ class ContentModerationConfigureEntityTypesForm extends FormBase {
// Add the bundle to the options if it's not enabled on a workflow,
// unless the workflow it's enabled on is this one.
$options[$bundle_id] = [
'title' => ['data' => ['#title' => $bundle['label']]],
'type' => $bundle['label'],
];
// Add the bundle to the list of default values if it's enabled on this
@@ -132,6 +144,17 @@ class ContentModerationConfigureEntityTypesForm extends FormBase {
];
}
// Get unsupported features for this entity type.
$warnings = $this->moderationInformation->getUnsupportedFeatures($this->entityType);
// Display message into the Ajax form returned.
if ($this->getRequest()->get(MainContentViewSubscriber::WRAPPER_FORMAT) == 'drupal_modal' && !empty($warnings)) {
$form['warnings'] = ['#type' => 'status_messages', '#weight' => -1];
}
// Set warning message.
foreach ($warnings as $warning) {
$this->messenger->addWarning($warning);
}
$form['actions'] = ['#type' => 'actions'];
$form['actions']['submit'] = [
'#type' => 'submit',
@@ -68,7 +68,7 @@ class ContentModerationConfigureForm extends WorkflowTypeConfigureFormBase imple
$header = [
'type' => $this->t('Items'),
'operations' => $this->t('Operations')
'operations' => $this->t('Operations'),
];
$form['entity_types_container'] = [
'#type' => 'details',
@@ -108,7 +108,7 @@ class ContentModerationConfigureForm extends WorkflowTypeConfigureFormBase imple
'label' => $this->t('@bundle types', ['@bundle' => $entity_type->getLabel()]),
'entity_type_id' => $entity_type->id(),
'selected_bundles' => $selected_bundles_list,
]
],
],
'operations' => [
'#type' => 'operations',
@@ -128,6 +128,7 @@ class EntityModerationForm extends FormBase {
];
$form['#theme'] = ['entity_moderation_form'];
$form['#attached']['library'][] = 'content_moderation/content_moderation';
return $form;
}
@@ -153,7 +154,7 @@ class EntityModerationForm extends FormBase {
}
$entity->save();
drupal_set_message($this->t('The moderation state has been updated.'));
$this->messenger()->addStatus($this->t('The moderation state has been updated.'));
$new_state = $this->moderationInfo->getWorkflowForEntity($entity)->getTypePlugin()->getState($new_state);
// The page we're on likely won't be visible if we just set the entity to
@@ -4,16 +4,20 @@ namespace Drupal\content_moderation;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\TypedData\TranslatableInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
/**
* General service for moderation-related questions about Entity API.
*/
class ModerationInformation implements ModerationInformationInterface {
use StringTranslationTrait;
/**
* The entity type manager.
*
@@ -171,6 +175,10 @@ class ModerationInformation implements ModerationInformationInterface {
public function isDefaultRevisionPublished(ContentEntityInterface $entity) {
$workflow = $this->getWorkflowForEntity($entity);
$default_revision = \Drupal::entityTypeManager()->getStorage($entity->getEntityTypeId())->load($entity->id());
// If no default revision could be loaded, the entity has not yet been
// saved. In this case the moderation_state of the unsaved entity can be
// used, since once saved it will become the default.
$default_revision = $default_revision ?: $entity;
// Ensure we are checking all translations of the default revision.
if ($default_revision instanceof TranslatableInterface && $default_revision->isTranslatable()) {
@@ -205,4 +213,16 @@ class ModerationInformation implements ModerationInformationInterface {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getUnsupportedFeatures(EntityTypeInterface $entity_type) {
$features = [];
// Test if entity is publishable.
if (!$entity_type->entityClassImplements(EntityPublishedInterface::class)) {
$features['publishing'] = $this->t("@entity_type_plural_label do not support publishing statuses. For example, even after transitioning from a published workflow state to an unpublished workflow state they will still be visible to site visitors.", ['@entity_type_plural_label' => $entity_type->getCollectionLabel()]);
}
return $features;
}
}
@@ -163,4 +163,15 @@ interface ModerationInformationInterface {
*/
public function getWorkflowForEntity(ContentEntityInterface $entity);
/**
* Gets unsupported features for a given entity type.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type to get the unsupported features for.
*
* @return array
* An array of unsupported features for this entity type.
*/
public function getUnsupportedFeatures(EntityTypeInterface $entity_type);
}
@@ -6,6 +6,7 @@ use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\Plugin\Action\PublishAction;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\content_moderation\ModerationInformationInterface;
@@ -32,6 +33,13 @@ class ModerationOptOutPublish extends PublishAction implements ContainerFactoryP
*/
protected $bundleInfo;
/**
* Messenger service.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* ModerationOptOutPublish constructor.
*
@@ -47,11 +55,14 @@ class ModerationOptOutPublish extends PublishAction implements ContainerFactoryP
* The moderation information service.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info
* Bundle info service.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* Messenger service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModerationInformationInterface $moderation_info, EntityTypeBundleInfoInterface $bundle_info) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModerationInformationInterface $moderation_info, EntityTypeBundleInfoInterface $bundle_info, MessengerInterface $messenger) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
$this->moderationInfo = $moderation_info;
$this->bundleInfo = $bundle_info;
$this->messenger = $messenger;
}
/**
@@ -62,7 +73,8 @@ class ModerationOptOutPublish extends PublishAction implements ContainerFactoryP
$configuration, $plugin_id, $plugin_definition,
$container->get('entity_type.manager'),
$container->get('content_moderation.moderation_information'),
$container->get('entity_type.bundle.info')
$container->get('entity_type.bundle.info'),
$container->get('messenger')
);
}
@@ -74,8 +86,11 @@ class ModerationOptOutPublish extends PublishAction implements ContainerFactoryP
if ($entity && $this->moderationInfo->isModeratedEntity($entity)) {
$bundle_info = $this->bundleInfo->getBundleInfo($entity->getEntityTypeId());
$bundle_label = $bundle_info[$entity->bundle()]['label'];
drupal_set_message($this->t("@bundle @label were skipped as they are under moderation and may not be directly published.", ['@bundle' => $bundle_label, '@label' => $entity->getEntityType()->getPluralLabel()]), 'warning');
$result = AccessResult::forbidden();
$this->messenger->addWarning($this->t("@bundle @label were skipped as they are under moderation and may not be directly published.", [
'@bundle' => $bundle_label,
'@label' => $entity->getEntityType()->getPluralLabel(),
]));
$result = AccessResult::forbidden('Cannot directly publish moderated entities.');
return $return_as_object ? $result : $result->isAllowed();
}
return parent::access($entity, $account, $return_as_object);
@@ -6,6 +6,7 @@ use Drupal\Core\Access\AccessResult;
use Drupal\Core\Action\Plugin\Action\UnpublishAction;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\content_moderation\ModerationInformationInterface;
@@ -32,6 +33,13 @@ class ModerationOptOutUnpublish extends UnpublishAction implements ContainerFact
*/
protected $bundleInfo;
/**
* Messenger service.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* ModerationOptOutUnpublish constructor.
*
@@ -47,11 +55,14 @@ class ModerationOptOutUnpublish extends UnpublishAction implements ContainerFact
* The moderation information service.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info
* Bundle info service.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* Messenger service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModerationInformationInterface $moderation_info, EntityTypeBundleInfoInterface $bundle_info) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModerationInformationInterface $moderation_info, EntityTypeBundleInfoInterface $bundle_info, MessengerInterface $messenger) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager);
$this->moderationInfo = $moderation_info;
$this->bundleInfo = $bundle_info;
$this->messenger = $messenger;
}
/**
@@ -62,7 +73,8 @@ class ModerationOptOutUnpublish extends UnpublishAction implements ContainerFact
$configuration, $plugin_id, $plugin_definition,
$container->get('entity_type.manager'),
$container->get('content_moderation.moderation_information'),
$container->get('entity_type.bundle.info')
$container->get('entity_type.bundle.info'),
$container->get('messenger')
);
}
@@ -74,8 +86,11 @@ class ModerationOptOutUnpublish extends UnpublishAction implements ContainerFact
if ($entity && $this->moderationInfo->isModeratedEntity($entity)) {
$bundle_info = $this->bundleInfo->getBundleInfo($entity->getEntityTypeId());
$bundle_label = $bundle_info[$entity->bundle()]['label'];
drupal_set_message($this->t("@bundle @label were skipped as they are under moderation and may not be directly unpublished.", ['@bundle' => $bundle_label, '@label' => $entity->getEntityType()->getPluralLabel()]), 'warning');
$result = AccessResult::forbidden();
$this->messenger->addWarning($this->t("@bundle @label were skipped as they are under moderation and may not be directly unpublished.", [
'@bundle' => $bundle_label,
'@label' => $entity->getEntityType()->getPluralLabel(),
]));
$result = AccessResult::forbidden('Cannot directly unpublish moderated entities.');
return $return_as_object ? $result : $result->isAllowed();
}
return parent::access($entity, $account, $return_as_object);
@@ -131,6 +131,9 @@ class ModerationStateWidget extends OptionsSelectWidget implements ContainerFact
foreach ($transitions as $transition) {
$transition_to_state = $transition->to();
$transition_labels[$transition_to_state->id()] = $transition_to_state->label();
if ($default->id() === $transition_to_state->id()) {
$default_value = $default->id();
}
}
$element += [
@@ -88,7 +88,7 @@ class ModerationStateFieldItemList extends FieldItemList {
$moderation_info = \Drupal::service('content_moderation.moderation_information');
$content_moderation_storage = \Drupal::entityTypeManager()->getStorage('content_moderation_state');
$revisions = \Drupal::service('entity.query')->get('content_moderation_state')
$revisions = $content_moderation_storage->getQuery()
->condition('content_entity_type_id', $entity->getEntityTypeId())
->condition('content_entity_id', $entity->id())
// Ensure the correct revision is loaded in scenarios where a revision is
@@ -141,11 +141,13 @@ class ModerationStateFieldItemList extends FieldItemList {
public function setValue($values, $notify = TRUE) {
parent::setValue($values, $notify);
if (isset($this->list[0])) {
$this->valueComputed = TRUE;
}
// If the parent created a field item and if the parent should be notified
// about the change (e.g. this is not initialized with the current value),
// update the moderated entity.
if (isset($this->list[0]) && $notify) {
$this->valueComputed = TRUE;
$this->updateModeratedEntity($this->list[0]->value);
}
}
@@ -98,7 +98,7 @@ class ModerationStateConstraintValidator extends ConstraintValidator implements
if (!$original_state->canTransitionTo($new_state->id())) {
$this->context->addViolation($constraint->message, [
'%from' => $original_state->label(),
'%to' => $new_state->label()
'%to' => $new_state->label(),
]);
}
}
@@ -1,4 +1,3 @@
{{ attach_library('content_moderation/content_moderation') }}
<ul class="entity-moderation-form">
<li class="entity-moderation-form__item">{{ form.current }}</li>
<li class="entity-moderation-form__item">{{ form.new_state }}</li>
@@ -5,5 +5,5 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- content_moderation
- node
- drupal:content_moderation
- drupal:node
@@ -258,4 +258,3 @@ display:
- user.permissions
tags:
- 'config:workflow_list'
@@ -165,4 +165,3 @@ display:
- 'languages:language_interface'
- url
tags: { }
@@ -215,4 +215,3 @@ display:
- 'user.node_grants:view'
- user.permissions
tags: { }
@@ -5,7 +5,7 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- content_moderation
- node
- views
- entity_test
- drupal:content_moderation
- drupal:node
- drupal:views
- drupal:entity_test
@@ -19,6 +19,7 @@ class ContentModerationWorkflowTypeTest extends BrowserTestBase {
public static $modules = [
'content_moderation',
'node',
'entity_test',
];
/**
@@ -92,10 +93,15 @@ class ContentModerationWorkflowTypeTest extends BrowserTestBase {
$session->fieldDisabled('type_settings[default_revision]');
$this->drupalGet('admin/config/workflow/workflows/manage/test/type/node');
$session->pageTextContains('Select the content type entities for the Test workflow');
$session->pageTextContains('Select the content types for the Test workflow');
foreach ($types as $type) {
$session->pageTextContains($type->label());
$session->elementContains('css', sprintf('.form-item-bundles-%s label', $type->id()), sprintf('Update %s', $type->label()));
}
// Ensure warning message are displayed for unsupported features.
$this->drupalGet('admin/config/workflow/workflows/manage/test/type/entity_test_rev');
$this->assertSession()->pageTextContains('Test entity - revisions entities do not support publishing statuses. For example, even after transitioning from a published workflow state to an unpublished workflow state they will still be visible to site visitors.');
}
}
@@ -9,6 +9,7 @@ use Drupal\FunctionalTests\Update\UpdatePathTestBase;
* Test updating the ContentModerationState entity default revisions.
*
* @group Update
* @group legacy
* @see content_moderation_post_update_update_cms_default_revisions
*/
class DefaultContentModerationStateRevisionUpdateTest extends UpdatePathTestBase {
@@ -20,7 +21,6 @@ class DefaultContentModerationStateRevisionUpdateTest extends UpdatePathTestBase
$this->databaseDumpFiles = [
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz',
__DIR__ . '/../../fixtures/update/drupal-8.4.0-content_moderation_installed.php',
__DIR__ . '/../../fixtures/update/drupal-8.default-cms-entity-id-2941736.php',
];
}
@@ -28,6 +28,11 @@ class DefaultContentModerationStateRevisionUpdateTest extends UpdatePathTestBase
* Test updating the default revision.
*/
public function testUpdateDefaultRevision() {
// Include the database fixture required to test updating the default
// revision. This is excluded from ::setDatabaseDumpFiles so that we can
// test the same post_update hook with no test content enabled.
require __DIR__ . '/../../fixtures/update/drupal-8.default-cms-entity-id-2941736.php';
$this->runUpdates();
foreach (['node', 'block_content'] as $entity_type_id) {
@@ -45,6 +50,14 @@ class DefaultContentModerationStateRevisionUpdateTest extends UpdatePathTestBase
}
}
/**
* Test the post_update hook when no entity types are being moderated.
*/
public function testNoEntitiesUnderModeration() {
// If any errors occur during the post_update hook, the test case will fail.
$this->runUpdates();
}
/**
* Assert for the given entity, the default revision ID matches.
*
@@ -3,7 +3,7 @@
namespace Drupal\Tests\content_moderation\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Tests moderated content administration page functionality.
@@ -12,6 +12,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ModeratedContentViewTest extends BrowserTestBase {
use ContentModerationTestTrait;
/**
* A user with permission to bypass access content.
*
@@ -34,7 +36,7 @@ class ModeratedContentViewTest extends BrowserTestBase {
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article'])->save();
$this->drupalCreateContentType(['type' => 'unmoderated_type', 'name' => 'Unmoderated type'])->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'page');
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'article');
$workflow->save();
@@ -5,7 +5,7 @@ namespace Drupal\Tests\content_moderation\Functional;
use Drupal\node\Entity\Node;
use Drupal\simpletest\ContentTypeCreationTrait;
use Drupal\Tests\BrowserTestBase;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Test the content moderation actions.
@@ -15,6 +15,7 @@ use Drupal\workflows\Entity\Workflow;
class ModerationActionsTest extends BrowserTestBase {
use ContentTypeCreationTrait;
use ContentModerationTestTrait;
/**
* Modules to enable.
@@ -38,7 +39,7 @@ class ModerationActionsTest extends BrowserTestBase {
$standard_bundle = $this->createContentType(['type' => 'standard_bundle']);
$standard_bundle->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'moderated_bundle');
$workflow->save();
@@ -3,7 +3,6 @@
namespace Drupal\Tests\content_moderation\Functional;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\workflows\Entity\Workflow;
use Drupal\Core\Url;
/**
@@ -107,6 +106,10 @@ class ModerationFormTest extends ModerationStateTestBase {
'moderation_state[0][state]' => 'published',
], t('Save'));
// Check widget default value.
$this->drupalGet($edit_path);
$this->assertFieldByName('moderation_state[0][state]', 'published', 'The moderation default value is set correctly.');
// The published view should not have a moderation form, because it is the
// live revision.
$this->drupalGet($canonical_path);
@@ -153,9 +156,8 @@ class ModerationFormTest extends ModerationStateTestBase {
*/
public function testNonBundleModerationForm() {
$this->drupalLogin($this->rootUser);
$workflow = Workflow::load('editorial');
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_mulrevpub', 'entity_test_mulrevpub');
$workflow->save();
$this->workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_mulrevpub', 'entity_test_mulrevpub');
$this->workflow->save();
// Create new moderated content in draft.
$this->drupalPostForm('entity_test_mulrevpub/add', ['moderation_state[0][state]' => 'draft'], t('Save'));
@@ -469,7 +471,7 @@ class ModerationFormTest extends ModerationStateTestBase {
'edit own moderated_content content',
'use editorial transition create_new_draft',
'use editorial transition publish',
'use editorial transition archive'
'use editorial transition archive',
]);
$this->drupalLogin($user);
$paths = [
@@ -482,6 +482,9 @@ class ModerationLocaleTest extends ModerationStateTestBase {
protected function loadTranslation(NodeInterface $node, $langcode) {
/** @var \Drupal\node\NodeStorageInterface $storage */
$storage = $this->container->get('entity_type.manager')->getStorage('node');
// Explicitly invalidate the cache for that node, as the call below is
// statically cached.
$storage->resetCache([$node->id()]);
/** @var \Drupal\node\NodeInterface $node */
$node = $storage->loadRevision($storage->getLatestRevisionId($node->id()));
return $node->getTranslation($langcode);
@@ -4,7 +4,7 @@ namespace Drupal\Tests\content_moderation\Functional;
use Drupal\simpletest\ContentTypeCreationTrait;
use Drupal\Tests\BrowserTestBase;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Test revision revert.
@@ -14,6 +14,7 @@ use Drupal\workflows\Entity\Workflow;
class ModerationRevisionRevertTest extends BrowserTestBase {
use ContentTypeCreationTrait;
use ContentModerationTestTrait;
/**
* Modules to enable.
@@ -34,7 +35,7 @@ class ModerationRevisionRevertTest extends BrowserTestBase {
$moderated_bundle = $this->createContentType(['type' => 'moderated_bundle']);
$moderated_bundle->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'moderated_bundle');
$workflow->save();
@@ -5,7 +5,7 @@ namespace Drupal\Tests\content_moderation\Functional;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\BrowserTestBase;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Tests the view access control handler for moderation state entities.
@@ -14,6 +14,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ModerationStateAccessTest extends BrowserTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -99,7 +101,7 @@ class ModerationStateAccessTest extends BrowserTestBase {
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', $machine_name);
$workflow->save();
return $node_type;
@@ -3,7 +3,9 @@
namespace Drupal\Tests\content_moderation\Functional;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
use Drupal\user\Entity\Role;
/**
@@ -11,6 +13,8 @@ use Drupal\user\Entity\Role;
*/
abstract class ModerationStateTestBase extends BrowserTestBase {
use ContentModerationTestTrait;
/**
* Profile to use.
*
@@ -45,6 +49,13 @@ abstract class ModerationStateTestBase extends BrowserTestBase {
'use editorial transition archived_published',
];
/**
* The editorial workflow entity.
*
* @var \Drupal\workflows\Entity\Workflow
*/
protected $workflow;
/**
* Modules to enable.
*
@@ -63,6 +74,7 @@ abstract class ModerationStateTestBase extends BrowserTestBase {
*/
protected function setUp() {
parent::setUp();
$this->workflow = $this->createEditorialWorkflow();
$this->adminUser = $this->drupalCreateUser($this->permissions);
$this->drupalPlaceBlock('local_tasks_block', ['id' => 'tabs_block']);
$this->drupalPlaceBlock('page_title_block');
@@ -110,6 +122,9 @@ abstract class ModerationStateTestBase extends BrowserTestBase {
];
$this->drupalPostForm(NULL, $edit, t('Save content type'));
// Check the content type has been set to create new revisions.
$this->assertTrue(NodeType::load($content_type_id)->isNewRevision());
if ($moderated) {
$this->enableModerationThroughUi($content_type_id, $workflow_id);
}
@@ -3,6 +3,7 @@
namespace Drupal\Tests\content_moderation\Functional;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
use Drupal\Tests\views\Functional\ViewTestBase;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
@@ -17,6 +18,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ViewsModerationStateFilterTest extends ViewTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -45,6 +48,8 @@ class ViewsModerationStateFilterTest extends ViewTestBase {
'type' => 'example_b',
])->save();
$this->createEditorialWorkflow();
$new_workflow = Workflow::create([
'type' => 'content_moderation',
'id' => 'new_workflow',
@@ -201,11 +206,11 @@ class ViewsModerationStateFilterTest extends ViewTestBase {
return [
'view on base table, filter on base table' => [
'test_content_moderation_state_filter_base_table',
'Content: Moderation state'
'Content: Moderation state',
],
'view on base table, filter on revision table' => [
'test_content_moderation_state_filter_base_table_filter_on_revision',
'Content revision: Moderation state'
'Content revision: Moderation state',
],
];
}
@@ -89,7 +89,7 @@ class ContentModerationPermissionsTest extends KernelTestBase {
],
],
],
[]
[],
],
];
}
@@ -6,7 +6,7 @@ use Drupal\content_moderation\Entity\ContentModerationState;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Test the ContentModerationState storage schema.
@@ -16,6 +16,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ContentModerationStateStorageSchemaTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -45,7 +47,7 @@ class ContentModerationStateStorageSchemaTest extends KernelTestBase {
NodeType::create([
'type' => 'example',
])->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
}
@@ -12,6 +12,7 @@ use Drupal\KernelTests\KernelTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
use Drupal\workflows\Entity\Workflow;
/**
@@ -21,6 +22,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ContentModerationStateTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -275,7 +278,7 @@ class ContentModerationStateTest extends KernelTestBase {
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -388,7 +391,7 @@ class ContentModerationStateTest extends KernelTestBase {
'type' => 'test_type',
])->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'test_type');
$workflow->save();
@@ -415,7 +418,7 @@ class ContentModerationStateTest extends KernelTestBase {
* Tests that entities with special languages can be moderated.
*/
public function testModerationWithSpecialLanguages() {
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
@@ -436,7 +439,7 @@ class ContentModerationStateTest extends KernelTestBase {
* Tests that a non-translatable entity type with a langcode can be moderated.
*/
public function testNonTranslatableEntityTypeModeration() {
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
@@ -470,7 +473,7 @@ class ContentModerationStateTest extends KernelTestBase {
// Update the entity type in order to remove the 'langcode' field.
\Drupal::entityDefinitionUpdateManager()->applyUpdates();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
@@ -500,7 +503,7 @@ class ContentModerationStateTest extends KernelTestBase {
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
// Test both a config and non-config based bundle and entity type.
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
@@ -520,7 +523,7 @@ class ContentModerationStateTest extends KernelTestBase {
$this->assertEquals([
'entity_test_no_bundle',
'entity_test_rev',
'node'
'node',
], $workflow->getTypePlugin()->getEntityTypes());
// Delete the node type and ensure it is removed from the workflow.
@@ -543,7 +546,7 @@ class ContentModerationStateTest extends KernelTestBase {
// Create a bundle not based on any particular configuration.
entity_test_create_bundle('test_bundle');
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test', 'test_bundle');
$workflow->save();
@@ -653,7 +656,7 @@ class ContentModerationStateTest extends KernelTestBase {
}
}
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle($entity_type_id, $bundle_id);
$workflow->save();
@@ -6,7 +6,7 @@ use Drupal\Core\Config\ConfigImporterException;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Tests how Content Moderation handles workflow config changes.
@@ -15,6 +15,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ContentModerationWorkflowConfigTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -57,13 +59,13 @@ class ContentModerationWorkflowConfigTest extends KernelTestBase {
$this->installEntitySchema('node');
$this->installEntitySchema('user');
$this->installEntitySchema('content_moderation_state');
$this->installConfig('content_moderation');
$this->installConfig(['system', 'content_moderation']);
NodeType::create([
'type' => 'example',
])->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()
->addState('test1', 'Test one')
->addState('test2', 'Test two')
@@ -118,7 +120,7 @@ class ContentModerationWorkflowConfigTest extends KernelTestBase {
$this->fail('ConfigImporterException not thrown, invalid import was not stopped due to deleted state.');
}
catch (ConfigImporterException $e) {
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.' . PHP_EOL . 'The moderation state Test two is being used, but is not in the source storage.');
$error_log = $this->configImporter->getErrors();
$expected = ['The moderation state Test two is being used, but is not in the source storage.'];
$this->assertEqual($expected, $error_log);
@@ -132,7 +134,7 @@ class ContentModerationWorkflowConfigTest extends KernelTestBase {
$this->fail('ConfigImporterException not thrown, invalid import was not stopped due to deleted workflow.');
}
catch (ConfigImporterException $e) {
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.');
$this->assertEqual($e->getMessage(), 'There were errors validating the config synchronization.' . PHP_EOL . 'The moderation state Test two is being used, but is not in the source storage.' . PHP_EOL . 'The workflow Editorial is being used, and cannot be deleted.');
$error_log = $this->configImporter->getErrors();
$expected = [
'The moderation state Test two is being used, but is not in the source storage.',
@@ -17,7 +17,7 @@ class ContentModerationWorkflowTypeApiTest extends KernelTestBase {
/**
* A workflow for testing.
*
* @var \Drupal\workflows\Entity\Workflow;
* @var \Drupal\workflows\Entity\Workflow
*/
protected $workflow;
@@ -6,7 +6,7 @@ use Drupal\KernelTests\KernelTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Tests the correct default revision is set.
@@ -15,6 +15,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class DefaultRevisionStateTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -68,7 +70,7 @@ class DefaultRevisionStateTest extends KernelTestBase {
$this->container->get('content_translation.manager')->setEnabled('node', 'example', TRUE);
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -5,7 +5,7 @@ namespace Drupal\Tests\content_moderation\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* @coversDefaultClass \Drupal\content_moderation\EntityOperations
@@ -14,6 +14,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class EntityOperationsTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -48,7 +50,7 @@ class EntityOperationsTest extends KernelTestBase {
'label' => 'Page',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'page');
$workflow->save();
}
@@ -6,7 +6,7 @@ use Drupal\KernelTests\KernelTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* @coversDefaultClass \Drupal\content_moderation\Plugin\Validation\Constraint\ModerationStateConstraintValidator
@@ -14,6 +14,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class EntityStateChangeValidationTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -50,7 +52,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
'type' => 'example',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -78,7 +80,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
'type' => 'example',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -104,7 +106,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
'type' => 'example',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -136,7 +138,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
// Enable moderation to test validation on existing content, with no
// explicit state.
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addState('deleted_state', 'Deleted state');
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -169,7 +171,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -232,7 +234,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
$nid = $node->id();
// Enable moderation for our node type.
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -278,7 +280,7 @@ class EntityStateChangeValidationTest extends KernelTestBase {
$node_fr->save();
// Enable moderation for our node type.
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -61,4 +61,34 @@ class EntityTypeInfoTest extends KernelTestBase {
$this->assertTrue($base_fields['moderation_state']->isTranslatable());
}
/**
* Test the correct entity types have moderation added.
*
* @covers ::entityTypeAlter
*
* @dataProvider providerTestEntityTypeAlter
*/
public function testEntityTypeAlter($entity_type_id, $moderatable) {
$entity_types = $this->entityTypeManager->getDefinitions();
$this->assertSame($moderatable, $entity_types[$entity_type_id]->hasHandlerClass('moderation'));
}
/**
* Provides test data for testEntityTypeAlter().
*
* @return array
* An array of test cases, where each test case is an array with the
* following values:
* - An entity type ID.
* - Whether the entity type is moderatable or not.
*/
public function providerTestEntityTypeAlter() {
$tests = [];
$tests['non_internal_non_revisionable'] = ['entity_test', FALSE];
$tests['non_internal_revisionable'] = ['entity_test_rev', TRUE];
$tests['internal_non_revisionable'] = ['entity_test_no_label', FALSE];
$tests['internal_revisionable'] = ['content_moderation_state', FALSE];
return $tests;
}
}
@@ -6,7 +6,7 @@ use Drupal\entity_test\Entity\EntityTestRev;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Tests the correct initial states are set on install.
@@ -15,6 +15,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class InitialStateTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -66,7 +68,7 @@ class InitialStateTest extends KernelTestBase {
$entity_test->save();
\Drupal::service('module_installer')->install(['content_moderation'], TRUE);
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
@@ -2,9 +2,11 @@
namespace Drupal\Tests\content_moderation\Kernel;
use Drupal\entity_test\Entity\EntityTestMulRevPub;
use Drupal\entity_test\Entity\EntityTestRev;
use Drupal\KernelTests\KernelTestBase;
use Drupal\workflows\Entity\Workflow;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* @coversDefaultClass \Drupal\content_moderation\ModerationInformation
@@ -12,10 +14,26 @@ use Drupal\workflows\Entity\Workflow;
*/
class ModerationInformationTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['content_moderation', 'entity_test', 'user', 'workflows'];
public static $modules = [
'content_moderation',
'entity_test',
'user',
'workflows',
'language',
'content_translation',
];
/**
* The moderation information service.
*
* @var \Drupal\content_moderation\ModerationInformationInterface
*/
protected $moderationInformation;
/**
* {@inheritdoc}
@@ -24,8 +42,20 @@ class ModerationInformationTest extends KernelTestBase {
parent::setUp();
$this->installEntitySchema('entity_test_rev');
$this->installEntitySchema('entity_test_mulrevpub');
$this->installEntitySchema('content_moderation_state');
$this->installConfig(['content_moderation']);
$this->moderationInformation = $this->container->get('content_moderation.moderation_information');
ConfigurableLanguage::createFromLangcode('de')->save();
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_mulrevpub', 'entity_test_mulrevpub');
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
$this->container->get('content_translation.manager')->setEnabled('entity_test_mulrevpub', 'entity_test_mulrevpub', TRUE);
}
/**
@@ -33,10 +63,6 @@ class ModerationInformationTest extends KernelTestBase {
* @covers ::getLatestRevisionId
*/
public function testDefaultAndLatestRevisionId() {
$workflow = Workflow::load('editorial');
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
$entity_test_rev = EntityTestRev::create([
'name' => 'Default Revision',
'moderation_state' => 'published',
@@ -47,18 +73,85 @@ class ModerationInformationTest extends KernelTestBase {
$entity_test_rev->moderation_state = 'draft';
$entity_test_rev->save();
/** @var \Drupal\content_moderation\ModerationInformationInterface $moderation_info */
$moderation_info = \Drupal::service('content_moderation.moderation_information');
// Check that moderation information service returns the correct default
// revision ID.
$default_revision_id = $moderation_info->getDefaultRevisionId('entity_test_rev', $entity_test_rev->id());
$default_revision_id = $this->moderationInformation->getDefaultRevisionId('entity_test_rev', $entity_test_rev->id());
$this->assertSame(1, $default_revision_id);
// Check that moderation information service returns the correct latest
// revision ID.
$latest_revision_id = $moderation_info->getLatestRevisionId('entity_test_rev', $entity_test_rev->id());
$latest_revision_id = $this->moderationInformation->getLatestRevisionId('entity_test_rev', $entity_test_rev->id());
$this->assertSame(2, $latest_revision_id);
}
/**
* @covers ::isDefaultRevisionPublished
* @dataProvider isDefaultRevisionPublishedTestCases
*/
public function testIsDefaultRevisionPublished($initial_state, $final_state, $initial_is_default_published, $final_is_default_published) {
$entity = EntityTestMulRevPub::create([
'moderation_state' => $initial_state,
]);
$entity->save();
$this->assertEquals($initial_is_default_published, $this->moderationInformation->isDefaultRevisionPublished($entity));
$entity->moderation_state = $final_state;
$entity->save();
$this->assertEquals($final_is_default_published, $this->moderationInformation->isDefaultRevisionPublished($entity));
}
/**
* Test cases for ::testIsDefaultRevisionPublished.
*/
public function isDefaultRevisionPublishedTestCases() {
return [
'Draft to draft' => [
'draft',
'draft',
FALSE,
FALSE,
],
'Draft to published' => [
'draft',
'published',
FALSE,
TRUE,
],
'Published to published' => [
'published',
'published',
TRUE,
TRUE,
],
'Published to draft' => [
'published',
'draft',
TRUE,
TRUE,
],
];
}
/**
* @covers ::isDefaultRevisionPublished
*/
public function testIsDefaultRevisionPublishedMultilingual() {
$entity = EntityTestMulRevPub::create([
'moderation_state' => 'draft',
]);
$entity->save();
$this->assertEquals('draft', $entity->moderation_state->value);
$translated = $entity->addTranslation('de');
$translated->moderation_state = 'published';
$translated->save();
$this->assertEquals('published', $translated->moderation_state->value);
// Test a scenario where the default revision exists with the default
// language in a draft state and a non-default language in a published
// state. The method returns TRUE if any of the languages for the default
// revision are in a published state.
$this->assertEquals(TRUE, $this->moderationInformation->isDefaultRevisionPublished($entity));
}
}
@@ -5,7 +5,7 @@ namespace Drupal\Tests\content_moderation\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* @coversDefaultClass \Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList
@@ -14,6 +14,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ModerationStateFieldItemListTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -51,7 +53,7 @@ class ModerationStateFieldItemListTest extends KernelTestBase {
'type' => 'example',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
@@ -111,6 +113,9 @@ class ModerationStateFieldItemListTest extends KernelTestBase {
unset($this->testNode->moderation_state);
$this->assertEquals('draft', $this->testNode->moderation_state->value);
$this->testNode->moderation_state = NULL;
$this->assertEquals('draft', $this->testNode->moderation_state->value);
}
/**
@@ -130,22 +135,58 @@ class ModerationStateFieldItemListTest extends KernelTestBase {
/**
* Tests that moderation state changes also change the related entity state.
*
* @dataProvider moderationStateChangesTestCases
*/
public function testModerationStateChanges() {
// Change the moderation state and check that the entity's
// 'isDefaultRevision' flag and the publishing status have also been
// updated.
$this->testNode->moderation_state->value = 'published';
$this->assertTrue($this->testNode->isPublished());
$this->assertTrue($this->testNode->isDefaultRevision());
public function testModerationStateChanges($initial_state, $final_state, $first_published, $first_is_default, $second_published, $second_is_default) {
$this->testNode->moderation_state->value = $initial_state;
$this->assertEquals($first_published, $this->testNode->isPublished());
$this->assertEquals($first_is_default, $this->testNode->isDefaultRevision());
$this->testNode->save();
// Repeat the checks using an 'unpublished' state.
$this->testNode->moderation_state->value = 'draft';
$this->assertFalse($this->testNode->isPublished());
$this->assertFalse($this->testNode->isDefaultRevision());
$this->testNode->moderation_state->value = $final_state;
$this->assertEquals($second_published, $this->testNode->isPublished());
$this->assertEquals($second_is_default, $this->testNode->isDefaultRevision());
}
/**
* Data provider for ::testModerationStateChanges
*/
public function moderationStateChangesTestCases() {
return [
'Draft to draft' => [
'draft',
'draft',
FALSE,
TRUE,
FALSE,
TRUE,
],
'Draft to published' => [
'draft',
'published',
FALSE,
TRUE,
TRUE,
TRUE,
],
'Published to published' => [
'published',
'published',
TRUE,
TRUE,
TRUE,
TRUE,
],
'Published to draft' => [
'published',
'draft',
TRUE,
TRUE,
FALSE,
FALSE,
],
];
}
/**
@@ -175,13 +216,69 @@ class ModerationStateFieldItemListTest extends KernelTestBase {
/**
* Test the moderation_state field after an entity has been serialized.
*
* @dataProvider entityUnserializeTestCases
*/
public function testEntityUnserialize() {
$this->testNode->moderation_state->value = 'draft';
public function testEntityUnserialize($state, $default, $published) {
$this->testNode->moderation_state->value = $state;
$this->assertEquals($state, $this->testNode->moderation_state->value);
$this->assertEquals($default, $this->testNode->isDefaultRevision());
$this->assertEquals($published, $this->testNode->isPublished());
$unserialized = unserialize(serialize($this->testNode));
$this->assertEquals('Test title', $unserialized->title->value);
$this->assertEquals('draft', $unserialized->moderation_state->value);
$this->assertEquals($state, $unserialized->moderation_state->value);
$this->assertEquals($default, $unserialized->isDefaultRevision());
$this->assertEquals($published, $unserialized->isPublished());
}
/**
* Test cases for ::testEntityUnserialize.
*/
public function entityUnserializeTestCases() {
return [
'Default draft state' => [
'draft',
TRUE,
FALSE,
],
'Non-default published state' => [
'published',
TRUE,
TRUE,
],
];
}
/**
* Test saving a moderated node with an existing ID.
*
* @dataProvider moderatedEntityWithExistingIdTestCases
*/
public function testModeratedEntityWithExistingId($state) {
$node = Node::create([
'title' => 'Test title',
'type' => 'example',
'nid' => 999,
'moderation_state' => $state,
]);
$node->save();
$this->assertEquals($state, $node->moderation_state->value);
}
/**
* Test cases for ::testModeratedEntityWithExistingId.
*/
public function moderatedEntityWithExistingIdTestCases() {
return [
'Draft non-default state' => [
'draft',
],
'Published default state' => [
'published',
],
];
}
}
@@ -8,7 +8,7 @@ use Drupal\Core\Form\FormState;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* @coversDefaultClass \Drupal\content_moderation\Plugin\Field\FieldWidget\ModerationStateWidget
@@ -16,6 +16,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ModerationStateWidgetTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* Modules to install.
*
@@ -46,7 +48,7 @@ class ModerationStateWidgetTest extends KernelTestBase {
'type' => 'unmoderated',
])->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'moderated');
$workflow->save();
}
@@ -4,9 +4,9 @@ namespace Drupal\Tests\content_moderation\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\Tests\user\Traits\UserCreationTrait;
use Drupal\workflows\Entity\Workflow;
/**
* Tests with node access enabled.
@@ -17,6 +17,7 @@ class NodeAccessTest extends KernelTestBase {
use NodeCreationTrait;
use UserCreationTrait;
use ContentModerationTestTrait;
/**
* The moderation information service.
@@ -58,7 +59,7 @@ class NodeAccessTest extends KernelTestBase {
'label' => 'Page',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'page');
$workflow->save();
@@ -5,7 +5,7 @@ namespace Drupal\Tests\content_moderation\Kernel;
use Drupal\Core\Render\RenderContext;
use Drupal\entity_test\Entity\EntityTestRev;
use Drupal\KernelTests\KernelTestBase;
use Drupal\workflows\Entity\Workflow;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
/**
* Test the state field formatter.
@@ -14,6 +14,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class StateFormatterTest extends KernelTestBase {
use ContentModerationTestTrait;
/**
* Modules to enable.
*
@@ -36,7 +38,7 @@ class StateFormatterTest extends KernelTestBase {
$this->installEntitySchema('content_moderation_state');
$this->installConfig('content_moderation');
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
$workflow->save();
}
@@ -4,9 +4,9 @@ namespace Drupal\Tests\content_moderation\Kernel;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Views;
use Drupal\workflows\Entity\Workflow;
/**
* Tests the views integration of content_moderation.
@@ -15,6 +15,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ViewsDataIntegrationTest extends ViewsKernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -44,7 +46,7 @@ class ViewsDataIntegrationTest extends ViewsKernelTestBase {
'type' => 'page',
]);
$node_type->save();
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'page');
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_mulrevpub', 'entity_test_mulrevpub');
$workflow->save();
@@ -6,6 +6,7 @@ use Drupal\entity_test\Entity\EntityTestNoBundle;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Views;
use Drupal\workflows\Entity\Workflow;
@@ -19,6 +20,8 @@ use Drupal\workflows\Entity\Workflow;
*/
class ViewsModerationStateFilterTest extends ViewsKernelTestBase {
use ContentModerationTestTrait;
/**
* {@inheritdoc}
*/
@@ -69,7 +72,7 @@ class ViewsModerationStateFilterTest extends ViewsKernelTestBase {
* Tests the content moderation state filter.
*/
public function testStateFilterViewsRelationship() {
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->getTypePlugin()->addState('translated_draft', 'Bar');
$configuration = $workflow->getTypePlugin()->getConfiguration();
@@ -156,7 +159,7 @@ class ViewsModerationStateFilterTest extends ViewsKernelTestBase {
* Test the moderation filter with a non-translatable entity type.
*/
public function testNonTranslatableEntityType() {
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_no_bundle', 'entity_test_no_bundle');
$workflow->save();
@@ -182,7 +185,7 @@ class ViewsModerationStateFilterTest extends ViewsKernelTestBase {
// Adding a content type to the editorial workflow will enable all of the
// editorial states.
$workflow = Workflow::load('editorial');
$workflow = $this->createEditorialWorkflow();
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
$workflow->save();
$this->assertPluginStates([
@@ -0,0 +1,88 @@
<?php
namespace Drupal\Tests\content_moderation\Traits;
use Drupal\workflows\Entity\Workflow;
/**
* Trait ContentModerationTestTraint.
*/
trait ContentModerationTestTrait {
/**
* Creates the editorial workflow.
*
* @return \Drupal\workflows\Entity\Workflow
* The editorial workflow entity.
*/
protected function createEditorialWorkflow() {
$workflow = Workflow::create([
'type' => 'content_moderation',
'id' => 'editorial',
'label' => 'Editorial',
'type_settings' => [
'states' => [
'archived' => [
'label' => 'Archived',
'weight' => 5,
'published' => FALSE,
'default_revision' => TRUE,
],
'draft' => [
'label' => 'Draft',
'published' => FALSE,
'default_revision' => FALSE,
'weight' => -5,
],
'published' => [
'label' => 'Published',
'published' => TRUE,
'default_revision' => TRUE,
'weight' => 0,
],
],
'transitions' => [
'archive' => [
'label' => 'Archive',
'from' => ['published'],
'to' => 'archived',
'weight' => 2,
],
'archived_draft' => [
'label' => 'Restore to Draft',
'from' => ['archived'],
'to' => 'draft',
'weight' => 3,
],
'archived_published' => [
'label' => 'Restore',
'from' => ['archived'],
'to' => 'published',
'weight' => 4,
],
'create_new_draft' => [
'label' => 'Create New Draft',
'to' => 'draft',
'weight' => 0,
'from' => [
'draft',
'published',
],
],
'publish' => [
'label' => 'Publish',
'to' => 'published',
'weight' => 1,
'from' => [
'draft',
'published',
],
],
],
],
]);
$workflow->save();
return $workflow;
}
}
@@ -78,7 +78,7 @@ class ContentModerationRouteSubscriberTest extends UnitTestCase {
],
'Entity parameter on an entity form' => [
[
'_entity_form' => 'entity_test_rev.edit'
'_entity_form' => 'entity_test_rev.edit',
],
[
'entity_test_rev' => [
@@ -94,7 +94,7 @@ class ContentModerationRouteSubscriberTest extends UnitTestCase {
],
'Entity form with no operation' => [
[
'_entity_form' => 'entity_test_rev'
'_entity_form' => 'entity_test_rev',
],
[
'entity_test_rev' => [
@@ -110,7 +110,7 @@ class ContentModerationRouteSubscriberTest extends UnitTestCase {
],
'Non-moderated entity form' => [
[
'_entity_form' => 'entity_test_mulrev'
'_entity_form' => 'entity_test_mulrev',
],
[
'entity_test_mulrev' => [
@@ -120,7 +120,7 @@ class ContentModerationRouteSubscriberTest extends UnitTestCase {
],
'Multiple entity parameters on an entity form' => [
[
'_entity_form' => 'entity_test_rev.edit'
'_entity_form' => 'entity_test_rev.edit',
],
[
'entity_test_rev' => [
@@ -142,7 +142,7 @@ class ContentModerationRouteSubscriberTest extends UnitTestCase {
],
'Overridden load_latest_revision flag does not change' => [
[
'_entity_form' => 'entity_test_rev.edit'
'_entity_form' => 'entity_test_rev.edit',
],
[
'entity_test_rev' => [
@@ -153,7 +153,7 @@ class ContentModerationRouteSubscriberTest extends UnitTestCase {
],
'Non-revisionable entity type will not change' => [
[
'_entity_form' => 'entity_test.edit'
'_entity_form' => 'entity_test.edit',
],
[
'entity_test' => [
@@ -165,7 +165,7 @@ class ContentModerationRouteSubscriberTest extends UnitTestCase {
],
'Overridden load_latest_revision flag does not change with multiple parameters' => [
[
'_entity_form' => 'entity_test_rev.edit'
'_entity_form' => 'entity_test_rev.edit',
],
[
'entity_test_rev' => [