Commit 6f29a328 authored by Crell's avatar Crell

Issue #2651084 by Crell, agentrickard: Allowed moderation states should be split

Merge branch '2651084-split-moderation-checkboxes' into 8.x-1.x
parents 5789f0e6 907fd4b5
......@@ -54,8 +54,8 @@ class BundleModerationConfigurationForm extends EntityForm {
$bundle = $form_state->getFormObject()->getEntity();
$form['enable_moderation_state'] = [
'#type' => 'checkbox',
'#title' => t('Enable moderation states.'),
'#description' => t('Content of this type must transition through moderation states in order to be published.'),
'#title' => $this->t('Enable moderation states.'),
'#description' => $this->t('Content of this type must transition through moderation states in order to be published.'),
'#default_value' => $bundle->getThirdPartySetting('workbench_moderation', 'enabled', FALSE),
];
......@@ -63,7 +63,7 @@ class BundleModerationConfigurationForm extends EntityForm {
if ($bundle->getThirdPartySetting('workbench_moderation', 'enabled', FALSE)) {
$form['enable_moderation_state_note'] = [
'#type' => 'item',
'#description' => t('After disabling moderation, any existing forward drafts will be accessible via the "Revisions" tab.'),
'#description' => $this->t('After disabling moderation, any existing forward drafts will be accessible via the "Revisions" tab.'),
'#states' => [
'visible' => [
':input[name=enable_moderation_state]' => ['checked' => FALSE],
......@@ -73,29 +73,59 @@ class BundleModerationConfigurationForm extends EntityForm {
}
$states = $this->entityTypeManager->getStorage('moderation_state')->loadMultiple();
$options = [];
/** @var ModerationState $state */
foreach ($states as $key => $state) {
$options[$key] = $state->label() . ' ' . ($state->isPublishedState() ? t('(published)') : t('(non-published)'));
}
$form['allowed_moderation_states'] = [
$label = function(ModerationState $state) {
return $state->label();
};
$options_published = array_map($label, array_filter($states, function(ModerationState $state) {
return $state->isPublishedState();
}));
$options_unpublished = array_map($label, array_filter($states, function(ModerationState $state) {
return !$state->isPublishedState();
}));
$form['allowed_moderation_states_unpublished'] = [
'#type' => 'checkboxes',
'#title' => t('Allowed moderation states.'),
'#description' => t('The allowed moderation states this content-type can be assigned. You must select at least one published and one non-published state.'),
'#default_value' => $bundle->getThirdPartySetting('workbench_moderation', 'allowed_moderation_states', array_keys($options)),
'#options' => $options,
'#title' => $this->t('Allowed moderation states (Unpublished)'),
'#description' => $this->t('The allowed unpublished moderation states this content-type can be assigned.'),
'#default_value' => $bundle->getThirdPartySetting('workbench_moderation', 'allowed_moderation_states', array_keys($options_unpublished)),
'#options' => $options_unpublished,
'#required' => TRUE,
'#states' => [
'visible' => [
':input[name=enable_moderation_state]' => ['checked' => TRUE],
],
],
];
$form['allowed_moderation_states_published'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Allowed moderation states (Published)'),
'#description' => $this->t('The allowed published moderation states this content-type can be assigned.'),
'#default_value' => $bundle->getThirdPartySetting('workbench_moderation', 'allowed_moderation_states', array_keys($options_published)),
'#options' => $options_published,
'#required' => TRUE,
'#states' => [
'visible' => [
':input[name=enable_moderation_state]' => ['checked' => TRUE],
],
],
];
// This is screwy, but the key of the array needs to be a user-facing string
// so we have to fully render the translatable string to a real string, or
// else PHP chokes on an object used as an array key.
$options = [
$this->t('Unpublished')->render() => $options_unpublished,
$this->t('Published')->render() => $options_published,
];
$form['default_moderation_state'] = [
'#type' => 'select',
'#title' => t('Default moderation state'),
'#empty_option' => t('-- Select --'),
'#title' => $this->t('Default moderation state'),
'#options' => $options,
'#description' => t('Select the moderation state for new content'),
'#description' => $this->t('Select the moderation state for new content'),
'#default_value' => $bundle->getThirdPartySetting('workbench_moderation', 'default_moderation_state', 'draft'),
'#states' => [
'visible' => [
......@@ -123,7 +153,7 @@ class BundleModerationConfigurationForm extends EntityForm {
public function formBuilderCallback($entity_type, ConfigEntityInterface $bundle, &$form, FormStateInterface $form_state) {
// @todo write a test for this.
$bundle->setThirdPartySetting('workbench_moderation', 'enabled', $form_state->getValue('enable_moderation_state'));
$bundle->setThirdPartySetting('workbench_moderation', 'allowed_moderation_states', array_keys(array_filter($form_state->getValue('allowed_moderation_states'))));
$bundle->setThirdPartySetting('workbench_moderation', 'allowed_moderation_states', array_keys(array_filter($form_state->getValue('allowed_moderation_states_published') + $form_state->getValue('allowed_moderation_states_unpublished'))));
$bundle->setThirdPartySetting('workbench_moderation', 'default_moderation_state', $form_state->getValue('default_moderation_state'));
}
......@@ -131,32 +161,11 @@ class BundleModerationConfigurationForm extends EntityForm {
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
// @todo write a test for this.
if ($form_state->getValue('enable_moderation_state')) {
$states = $this->entityTypeManager->getStorage('moderation_state')->loadMultiple();
$published = FALSE;
$non_published = TRUE;
$allowed = array_keys(array_filter($form_state->getValue('allowed_moderation_states')));
foreach ($allowed as $state_id) {
/** @var ModerationState $state */
$state = $states[$state_id];
if ($state->isPublishedState()) {
$published = TRUE;
}
else {
$non_published = TRUE;
}
}
if (!$published || !$non_published) {
$form_state->setErrorByName('allowed_moderation_states', t('You must select at least one published moderation and one non-published state.'));
}
if (($default = $form_state->getValue('default_moderation_state')) && !empty($default)) {
if (!in_array($default, $allowed, TRUE)) {
$form_state->setErrorByName('default_moderation_state', t('The default moderation state must be one of the allowed states.'));
}
}
else {
$form_state->setErrorByName('default_moderation_state', t('You must select a default moderation state.'));
$allowed = array_keys(array_filter($form_state->getValue('allowed_moderation_states_published') + $form_state->getValue('allowed_moderation_states_unpublished')));
if (($default = $form_state->getValue('default_moderation_state')) && !in_array($default, $allowed, TRUE)) {
$form_state->setErrorByName('default_moderation_state', $this->t('The default moderation state must be one of the allowed states.'));
}
}
}
......
......@@ -54,8 +54,8 @@ class ModerationStateBlockTest extends ModerationStateTestBase {
// Enable moderation for custom blocks at admin/structure/block/block-content/manage/basic/moderation.
$edit = [
'enable_moderation_state' => TRUE,
'allowed_moderation_states[draft]' => TRUE,
'allowed_moderation_states[published]' => TRUE,
'allowed_moderation_states_unpublished[draft]' => TRUE,
'allowed_moderation_states_published[published]' => TRUE,
'default_moderation_state' => 'draft',
];
$this->drupalPostForm('admin/structure/block/block-content/manage/basic/moderation', $edit, t('Save'));
......
......@@ -35,23 +35,23 @@ class ModerationStateNodeTypeTest extends ModerationStateTestBase {
* A node type without moderation state enabled.
*/
public function testEnablingOnExistingContent() {
// Create a node type that is not moderated.
$this->drupalLogin($this->adminUser);
$this->createContentTypeFromUI('Not moderated', 'not_moderated');
$this->grantUserPermissionToCreateContentOfType($this->adminUser, 'not_moderated');
// Create content.
$this->drupalGet('node/add/not_moderated');
$this->drupalPostForm(NULL, [
'title[0][value]' => 'Test',
], t('Save and publish'));
$this->assertText('Not moderated Test has been created.');
// Now enable moderation state.
$this->drupalGet('admin/structure/types/manage/not_moderated/moderation');
$this->drupalPostForm(NULL, [
'enable_moderation_state' => 1,
'allowed_moderation_states[draft]' => 1,
'allowed_moderation_states[needs_review]' => 1,
'allowed_moderation_states[published]' => 1,
'default_moderation_state' => 'draft',
], t('Save'));
$this->enableModerationThroughUI('not_moderated', ['draft', 'needs_review', 'published'], 'draft');
// And make sure it works.
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties([
'title' => 'Test'
]);
......@@ -68,60 +68,4 @@ class ModerationStateNodeTypeTest extends ModerationStateTestBase {
$this->assertRaw('Save and Create New Draft');
$this->assertNoRaw('Save and publish');
}
/**
* Creates a content-type from the UI.
*
* @param string $content_type_name
* Content type human name.
* @param string $content_type_id
* Machine name.
* @param bool $moderated
* TRUE if should be moderated
* @param string[] $allowed_states
* Array of allowed state IDs
* @param string $default_state
* Default state.
*/
protected function createContentTypeFromUI($content_type_name, $content_type_id, $moderated = FALSE, $allowed_states = [], $default_state = NULL) {
$this->drupalGet('admin/structure/types');
$this->clickLink('Add content type');
$edit = [
'name' => $content_type_name,
'type' => $content_type_id,
];
$this->drupalPostForm(NULL, $edit, t('Save content type'));
if ($moderated) {
$this->drupalGet('admin/structure/types/' . $content_type_id . '/moderation');
$this->assertFieldByName('enable_moderation_state');
$this->assertNoFieldChecked('edit-enable-moderation-state');
$edit['enable_moderation_state'] = 1;
foreach ($allowed_states as $state) {
$edit['allowed_moderation_states[' . $state . ']'] = 1;
}
$edit['default_moderation_state'] = $default_state;
$this->drupalPostForm('admin/structure/types/' . $content_type_id . '/moderation', $edit, t('Save'));
}
}
/**
* Grants given user permission to create content of given type.
*
* @param \Drupal\Core\Session\AccountInterface $account
* User to grant permission to.
* @param string $content_type_id
* Content type ID.
*/
protected function grantUserPermissionToCreateContentOfType(AccountInterface $account, $content_type_id) {
$role_ids = $account->getRoles(TRUE);
/* @var \Drupal\user\RoleInterface $role */
$role_id = reset($role_ids);
$role = Role::load($role_id);
$role->grantPermission(sprintf('create %s content', $content_type_id));
$role->grantPermission(sprintf('edit any %s content', $content_type_id));
$role->save();
}
}
......@@ -5,6 +5,7 @@ namespace Drupal\workbench_moderation\Tests;
use Drupal\Core\Session\AccountInterface;
use Drupal\simpletest\WebTestBase;
use Drupal\user\Entity\Role;
use Drupal\workbench_moderation\Entity\ModerationState;
/**
* Defines a base class for moderation state tests.
......@@ -83,7 +84,7 @@ abstract class ModerationStateTestBase extends WebTestBase {
* @param string $default_state
* Default state.
*/
protected function createContentTypeFromUI($content_type_name, $content_type_id, $moderated = FALSE, $allowed_states = [], $default_state = NULL) {
protected function createContentTypeFromUI($content_type_name, $content_type_id, $moderated = FALSE, array $allowed_states = [], $default_state = NULL) {
$this->drupalGet('admin/structure/types');
$this->clickLink('Add content type');
$edit = [
......@@ -92,20 +93,40 @@ abstract class ModerationStateTestBase extends WebTestBase {
];
$this->drupalPostForm(NULL, $edit, t('Save content type'));
if ($moderated) {
$this->enableModerationThroughUI($content_type_id, $allowed_states, $default_state);
}
}
/**
* Enable moderation for a specified content type, using the UI.
*
* @param string $content_type_id
* Machine name.
* @param string[] $allowed_states
* Array of allowed state IDs.
* @param string $default_state
* Default state.
*/
protected function enableModerationThroughUI($content_type_id, array $allowed_states, $default_state) {
$this->drupalGet('admin/structure/types/manage/' . $content_type_id . '/moderation');
$this->assertFieldByName('enable_moderation_state');
$this->assertNoFieldChecked('edit-enable-moderation-state');
$edit = [];
if ($moderated) {
$edit['enable_moderation_state'] = 1;
foreach ($allowed_states as $state) {
$edit['allowed_moderation_states[' . $state . ']'] = 1;
}
$edit['default_moderation_state'] = $default_state;
$edit['enable_moderation_state'] = 1;
/** @var ModerationState $state */
foreach (ModerationState::loadMultiple() as $id => $state) {
$key = $state->isPublishedState() ? 'allowed_moderation_states_published[' . $state->id() . ']' : 'allowed_moderation_states_unpublished[' . $state->id() . ']';
$edit[$key] = (int)in_array($id, $allowed_states);
}
$edit['default_moderation_state'] = $default_state;
$this->drupalPostForm(NULL, $edit, t('Save'));
}
/**
* Grants given user permission to create content of given type.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment