Core and composer updates
This commit is contained in:
parent
a82634bb98
commit
62cac30480
1118 changed files with 21770 additions and 6306 deletions
|
@ -3,6 +3,7 @@ status: true
|
|||
dependencies:
|
||||
module:
|
||||
- aggregator
|
||||
- user
|
||||
id: aggregator_rss_feed
|
||||
label: 'Aggregator RSS feed'
|
||||
module: aggregator
|
||||
|
@ -137,6 +138,8 @@ display:
|
|||
- url.query_args
|
||||
- user.permissions
|
||||
cacheable: false
|
||||
max-age: -1
|
||||
tags: { }
|
||||
feed_items:
|
||||
display_plugin: feed
|
||||
id: feed_items
|
||||
|
@ -154,3 +157,5 @@ display:
|
|||
- 'languages:language_interface'
|
||||
- user.permissions
|
||||
cacheable: false
|
||||
max-age: -1
|
||||
tags: { }
|
||||
|
|
|
@ -143,7 +143,8 @@ display:
|
|||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
max-age: -1
|
||||
tags: { }
|
||||
feed_1:
|
||||
display_plugin: feed
|
||||
id: feed_1
|
||||
|
@ -401,7 +402,8 @@ display:
|
|||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
max-age: -1
|
||||
tags: { }
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
|
@ -423,4 +425,5 @@ display:
|
|||
- 'languages:language_interface'
|
||||
- url.query_args
|
||||
- user.permissions
|
||||
max-age: 0
|
||||
max-age: -1
|
||||
tags: { }
|
||||
|
|
|
@ -7,7 +7,7 @@ source:
|
|||
process:
|
||||
iid: iid
|
||||
fid:
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d6_aggregator_feed
|
||||
source: fid
|
||||
title: title
|
||||
|
|
|
@ -7,7 +7,7 @@ source:
|
|||
process:
|
||||
iid: iid
|
||||
fid:
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d7_aggregator_feed
|
||||
source: fid
|
||||
title: title
|
||||
|
|
|
@ -60,4 +60,14 @@ class FeedAdminDisplayTest extends AggregatorTestBase {
|
|||
$this->assertNoText('left', 'The feed is not scheduled. It does not show a timeframe "x x left" for next update.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function randomMachineName($length = 8) {
|
||||
$value = parent::randomMachineName($length);
|
||||
// See expected values in testFeedUpdateFields().
|
||||
$value = str_replace(['never', 'imminently', 'ago', 'left'], 'x', $value);
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -59,29 +59,29 @@ class BigPipePlaceholderTestCases {
|
|||
],
|
||||
]
|
||||
);
|
||||
$status_messages->bigPipePlaceholderId = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA';
|
||||
$status_messages->bigPipePlaceholderId = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA';
|
||||
$status_messages->bigPipePlaceholderRenderArray = [
|
||||
'#markup' => '<span data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>',
|
||||
'#markup' => '<span data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>',
|
||||
'#cache' => $cacheability_depends_on_session_and_nojs_cookie,
|
||||
'#attached' => [
|
||||
'library' => ['big_pipe/big_pipe'],
|
||||
'drupalSettings' => [
|
||||
'bigPipePlaceholderIds' => [
|
||||
'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => TRUE,
|
||||
'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => TRUE,
|
||||
],
|
||||
],
|
||||
'big_pipe_placeholders' => [
|
||||
'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => $status_messages->placeholderRenderArray,
|
||||
'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA' => $status_messages->placeholderRenderArray,
|
||||
],
|
||||
],
|
||||
];
|
||||
$status_messages->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>';
|
||||
$status_messages->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>';
|
||||
$status_messages->bigPipeNoJsPlaceholderRenderArray = [
|
||||
'#markup' => '<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>',
|
||||
'#markup' => '<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>',
|
||||
'#cache' => $cacheability_depends_on_session_and_nojs_cookie,
|
||||
'#attached' => [
|
||||
'big_pipe_nojs_placeholders' => [
|
||||
'<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>' => $status_messages->placeholderRenderArray,
|
||||
'<span data-big-pipe-nojs-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>' => $status_messages->placeholderRenderArray,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
@ -109,7 +109,7 @@ class BigPipePlaceholderTestCases {
|
|||
[
|
||||
'command' => 'insert',
|
||||
'method' => 'replaceWith',
|
||||
'selector' => '[data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"]',
|
||||
'selector' => '[data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"]',
|
||||
'data' => "\n" . ' <div role="contentinfo" aria-label="Status message" class="messages messages--status">' . "\n" . ' <h2 class="visually-hidden">Status message</h2>' . "\n" . ' Hello from BigPipe!' . "\n" . ' </div>' . "\n ",
|
||||
'settings' => NULL,
|
||||
],
|
||||
|
@ -272,24 +272,24 @@ class BigPipePlaceholderTestCases {
|
|||
'#lazy_builder' => ['\Drupal\big_pipe_test\BigPipeTestController::exception', ['llamas', 'suck']],
|
||||
]
|
||||
);
|
||||
$exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args[0]=llamas&args[1]=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU';
|
||||
$exception->bigPipePlaceholderId = 'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU';
|
||||
$exception->bigPipePlaceholderRenderArray = [
|
||||
'#markup' => '<span data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args[0]=llamas&args[1]=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></span>',
|
||||
'#markup' => '<span data-big-pipe-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></span>',
|
||||
'#cache' => $cacheability_depends_on_session_and_nojs_cookie,
|
||||
'#attached' => [
|
||||
'library' => ['big_pipe/big_pipe'],
|
||||
'drupalSettings' => [
|
||||
'bigPipePlaceholderIds' => [
|
||||
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args[0]=llamas&args[1]=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => TRUE,
|
||||
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => TRUE,
|
||||
],
|
||||
],
|
||||
'big_pipe_placeholders' => [
|
||||
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args[0]=llamas&args[1]=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => $exception->placeholderRenderArray,
|
||||
'callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU' => $exception->placeholderRenderArray,
|
||||
],
|
||||
],
|
||||
];
|
||||
$exception->embeddedAjaxResponseCommands = NULL;
|
||||
$exception->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args[0]=llamas&args[1]=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></span>';
|
||||
$exception->bigPipeNoJsPlaceholder = '<span data-big-pipe-nojs-placeholder-id="callback=%5CDrupal%5Cbig_pipe_test%5CBigPipeTestController%3A%3Aexception&args%5B0%5D=llamas&args%5B1%5D=suck&token=uhKFNfT4eF449_W-kDQX8E5z4yHyt0-nSHUlwaGAQeU"></span>';
|
||||
$exception->bigPipeNoJsPlaceholderRenderArray = [
|
||||
'#markup' => $exception->bigPipeNoJsPlaceholder,
|
||||
'#cache' => $cacheability_depends_on_session_and_nojs_cookie,
|
||||
|
|
|
@ -293,7 +293,7 @@ class BigPipeTest extends WebTestBase {
|
|||
// @see performMetaRefresh()
|
||||
|
||||
$this->drupalGet(Url::fromRoute('big_pipe_test_multi_occurrence'));
|
||||
$big_pipe_placeholder_id = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args[0]&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA';
|
||||
$big_pipe_placeholder_id = 'callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA';
|
||||
$expected_placeholder_replacement = '<script type="application/vnd.drupal-ajax" data-big-pipe-replacement-for-placeholder-with-id="' . $big_pipe_placeholder_id . '">';
|
||||
$this->assertRaw('The count is 1.');
|
||||
$this->assertNoRaw('The count is 2.');
|
||||
|
|
|
@ -13,7 +13,8 @@ process:
|
|||
source: status
|
||||
id:
|
||||
# We need something unique, so aggregator, aggregator_1 etc will do.
|
||||
plugin: dedupe_entity
|
||||
plugin: make_unique_entity_field
|
||||
|
||||
entity_type: block
|
||||
field: id
|
||||
postfix: _
|
||||
|
|
|
@ -21,6 +21,12 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
'comment',
|
||||
'menu_ui',
|
||||
'block_content',
|
||||
'taxonomy',
|
||||
'node',
|
||||
'aggregator',
|
||||
'book',
|
||||
'forum',
|
||||
'statistics',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -30,15 +36,14 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
parent::setUp();
|
||||
|
||||
// Install the themes used for this test.
|
||||
$this->container->get('theme_installer')->install(['bartik', 'seven', 'test_theme']);
|
||||
$this->container->get('theme_installer')->install(['bartik', 'test_theme']);
|
||||
|
||||
$this->installConfig(['block_content']);
|
||||
$this->installEntitySchema('block_content');
|
||||
|
||||
// Set Bartik and Seven as the default public and admin theme.
|
||||
// Set Bartik as the default public theme.
|
||||
$config = $this->config('system.theme');
|
||||
$config->set('default', 'bartik');
|
||||
$config->set('admin', 'seven');
|
||||
$config->save();
|
||||
|
||||
$this->executeMigrations([
|
||||
|
@ -46,7 +51,6 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'd6_custom_block',
|
||||
'menu',
|
||||
'd6_user_role',
|
||||
'd6_block',
|
||||
]);
|
||||
|
@ -66,14 +70,12 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
* The theme.
|
||||
* @param string $weight
|
||||
* The block weight.
|
||||
* @param string $label
|
||||
* The block label.
|
||||
* @param string $label_display
|
||||
* The block label display setting.
|
||||
* @param array $settings
|
||||
* (optional) The block settings.
|
||||
* @param bool $status
|
||||
* Whether the block is expected to be enabled or disabled.
|
||||
*/
|
||||
public function assertEntity($id, $visibility, $region, $theme, $weight, $label, $label_display, $status = TRUE) {
|
||||
public function assertEntity($id, $visibility, $region, $theme, $weight, array $settings = NULL, $status = TRUE) {
|
||||
$block = Block::load($id);
|
||||
$this->assertTrue($block instanceof Block);
|
||||
$this->assertSame($visibility, $block->getVisibility());
|
||||
|
@ -81,10 +83,11 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
$this->assertSame($theme, $block->getTheme());
|
||||
$this->assertSame($weight, $block->getWeight());
|
||||
$this->assertSame($status, $block->status());
|
||||
|
||||
$config = $this->config('block.block.' . $id);
|
||||
$this->assertSame($label, $config->get('settings.label'));
|
||||
$this->assertSame($label_display, $config->get('settings.label_display'));
|
||||
if ($settings) {
|
||||
$block_settings = $block->get('settings');
|
||||
$block_settings['id'] = current(explode(':', $block_settings['id']));
|
||||
$this->assertEquals($settings, $block_settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,62 +95,209 @@ class MigrateBlockTest extends MigrateDrupal6TestBase {
|
|||
*/
|
||||
public function testBlockMigration() {
|
||||
$blocks = Block::loadMultiple();
|
||||
$this->assertIdentical(9, count($blocks));
|
||||
$this->assertCount(14, $blocks);
|
||||
|
||||
// User blocks
|
||||
$visibility = [];
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = TRUE;
|
||||
$visibility['request_path']['pages'] = "<front>\n/node/1\n/blog/*";
|
||||
$this->assertEntity('user', $visibility, 'sidebar_first', 'bartik', 0, '', '0');
|
||||
|
||||
$visibility = [];
|
||||
$this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', 0, '', '0');
|
||||
|
||||
$visibility['user_role']['id'] = 'user_role';
|
||||
$roles['authenticated'] = 'authenticated';
|
||||
$visibility['user_role']['roles'] = $roles;
|
||||
$context_mapping['user'] = '@user.current_user_context:current_user';
|
||||
$visibility['user_role']['context_mapping'] = $context_mapping;
|
||||
$visibility['user_role']['negate'] = FALSE;
|
||||
$this->assertEntity('user_2', $visibility, 'sidebar_second', 'bartik', -9, '', '0');
|
||||
|
||||
$visibility = [];
|
||||
$visibility['user_role']['id'] = 'user_role';
|
||||
$visibility['user_role']['roles'] = [
|
||||
'migrate_test_role_1' => 'migrate_test_role_1'
|
||||
// Check user blocks.
|
||||
$visibility = [
|
||||
'request_path' => [
|
||||
'id' => 'request_path',
|
||||
'negate' => TRUE,
|
||||
'pages' => "<front>\n/node/1\n/blog/*",
|
||||
],
|
||||
];
|
||||
$context_mapping['user'] = '@user.current_user_context:current_user';
|
||||
$visibility['user_role']['context_mapping'] = $context_mapping;
|
||||
$visibility['user_role']['negate'] = FALSE;
|
||||
$this->assertEntity('user_3', $visibility, 'sidebar_second', 'bartik', -6, '', '0');
|
||||
$settings = [
|
||||
'id' => 'user_login_block',
|
||||
'label' => '',
|
||||
'provider' => 'user',
|
||||
'label_display' => '0',
|
||||
];
|
||||
$this->assertEntity('user', $visibility, 'sidebar_first', 'bartik', -10, $settings);
|
||||
|
||||
// Check system block
|
||||
$visibility = [];
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = TRUE;
|
||||
$visibility['request_path']['pages'] = '/node/1';
|
||||
$this->assertEntity('system', $visibility, 'footer_fifth', 'bartik', -5, '', '0');
|
||||
$settings = [
|
||||
'id' => 'system_menu_block',
|
||||
'label' => '',
|
||||
'provider' => 'system',
|
||||
'label_display' => '0',
|
||||
'level' => 1,
|
||||
'depth' => 0,
|
||||
];
|
||||
$this->assertEntity('user_1', $visibility, 'sidebar_first', 'bartik', -11, $settings);
|
||||
|
||||
// Check menu blocks
|
||||
$visibility = [];
|
||||
$this->assertEntity('menu', $visibility, 'header', 'bartik', -5, '', '0');
|
||||
$visibility = [
|
||||
'user_role' => [
|
||||
'id' => 'user_role',
|
||||
'roles' => [
|
||||
'authenticated' => 'authenticated',
|
||||
],
|
||||
'context_mapping' => [
|
||||
'user' => '@user.current_user_context:current_user',
|
||||
],
|
||||
'negate' => FALSE,
|
||||
],
|
||||
];
|
||||
$settings = [
|
||||
'id' => 'broken',
|
||||
'label' => '',
|
||||
'provider' => 'core',
|
||||
'label_display' => '0',
|
||||
'items_per_page' => '5',
|
||||
];
|
||||
$this->assertEntity('user_2', $visibility, 'sidebar_second', 'bartik', -11, $settings);
|
||||
|
||||
// Check custom blocks
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = FALSE;
|
||||
$visibility['request_path']['pages'] = '<front>';
|
||||
$this->assertEntity('block', $visibility, 'content', 'bartik', 0, 'Static Block', 'visible');
|
||||
$visibility = [
|
||||
'user_role' => [
|
||||
'id' => 'user_role',
|
||||
'roles' => [
|
||||
'migrate_test_role_1' => 'migrate_test_role_1',
|
||||
],
|
||||
'context_mapping' => [
|
||||
'user' => '@user.current_user_context:current_user',
|
||||
],
|
||||
'negate' => FALSE,
|
||||
],
|
||||
];
|
||||
$settings = [
|
||||
'id' => 'broken',
|
||||
'label' => '',
|
||||
'provider' => 'core',
|
||||
'label_display' => '0',
|
||||
'items_per_page' => '10',
|
||||
];
|
||||
$this->assertEntity('user_3', $visibility, 'sidebar_second', 'bartik', -10, $settings);
|
||||
|
||||
$visibility['request_path']['id'] = 'request_path';
|
||||
$visibility['request_path']['negate'] = FALSE;
|
||||
$visibility['request_path']['pages'] = '/node';
|
||||
// Check system block.
|
||||
$visibility = [
|
||||
'request_path' => [
|
||||
'id' => 'request_path',
|
||||
'negate' => TRUE,
|
||||
'pages' => '/node/1',
|
||||
],
|
||||
];
|
||||
$settings = [
|
||||
'id' => 'system_powered_by_block',
|
||||
'label' => '',
|
||||
'provider' => 'system',
|
||||
'label_display' => '0',
|
||||
];
|
||||
$this->assertEntity('system', $visibility, 'footer_fifth', 'bartik', -5, $settings);
|
||||
|
||||
// Check menu blocks.
|
||||
$settings = [
|
||||
'id' => 'broken',
|
||||
'label' => '',
|
||||
'provider' => 'core',
|
||||
'label_display' => '0',
|
||||
];
|
||||
$this->assertEntity('menu', [], 'header', 'bartik', -5, $settings);
|
||||
|
||||
// Check aggregator block.
|
||||
$settings = [
|
||||
'id' => 'aggregator_feed_block',
|
||||
'label' => '',
|
||||
'provider' => 'aggregator',
|
||||
'label_display' => '0',
|
||||
'block_count' => 7,
|
||||
'feed' => '5',
|
||||
];
|
||||
$this->assertEntity('aggregator', [], 'sidebar_second', 'bartik', -2, $settings);
|
||||
|
||||
// Check book block.
|
||||
$settings = [
|
||||
'id' => 'book_navigation',
|
||||
'label' => '',
|
||||
'provider' => 'book',
|
||||
'label_display' => '0',
|
||||
'block_mode' => 'book pages',
|
||||
];
|
||||
$this->assertEntity('book', [], 'sidebar_second', 'bartik', -4, $settings);
|
||||
|
||||
// Check forum block settings.
|
||||
$settings = [
|
||||
'id' => 'forum_active_block',
|
||||
'label' => '',
|
||||
'provider' => 'forum',
|
||||
'label_display' => '0',
|
||||
'block_count' => 3,
|
||||
'properties' => [
|
||||
'administrative' => '1',
|
||||
],
|
||||
];
|
||||
$this->assertEntity('forum', [], 'sidebar_first', 'bartik', -8, $settings);
|
||||
|
||||
$settings = [
|
||||
'id' => 'forum_new_block',
|
||||
'label' => '',
|
||||
'provider' => 'forum',
|
||||
'label_display' => '0',
|
||||
'block_count' => 4,
|
||||
'properties' => [
|
||||
'administrative' => '1',
|
||||
],
|
||||
];
|
||||
$this->assertEntity('forum_1', [], 'sidebar_first', 'bartik', -9, $settings);
|
||||
|
||||
// Check statistic block settings.
|
||||
$settings = [
|
||||
'id' => 'broken',
|
||||
'label' => '',
|
||||
'provider' => 'core',
|
||||
'label_display' => '0',
|
||||
'top_day_num' => 7,
|
||||
'top_all_num' => 8,
|
||||
'top_last_num' => 9,
|
||||
];
|
||||
$this->assertEntity('statistics', [], 'sidebar_second', 'bartik', 0, $settings);
|
||||
|
||||
// Check custom blocks.
|
||||
$visibility = [
|
||||
'request_path' => [
|
||||
'id' => 'request_path',
|
||||
'negate' => FALSE,
|
||||
'pages' => '<front>',
|
||||
],
|
||||
];
|
||||
$settings = [
|
||||
'id' => 'block_content',
|
||||
'label' => 'Static Block',
|
||||
'provider' => 'block_content',
|
||||
'label_display' => 'visible',
|
||||
'status' => TRUE,
|
||||
'info' => '',
|
||||
'view_mode' => 'full',
|
||||
];
|
||||
$this->assertEntity('block', $visibility, 'content', 'bartik', 0, $settings);
|
||||
|
||||
$visibility = [
|
||||
'request_path' => [
|
||||
'id' => 'request_path',
|
||||
'negate' => FALSE,
|
||||
'pages' => '/node',
|
||||
],
|
||||
];
|
||||
$settings = [
|
||||
'id' => 'block_content',
|
||||
'label' => 'Another Static Block',
|
||||
'provider' => 'block_content',
|
||||
'label_display' => 'visible',
|
||||
'status' => TRUE,
|
||||
'info' => '',
|
||||
'view_mode' => 'full',
|
||||
];
|
||||
// We expect this block to be disabled because '' is not a valid region,
|
||||
// and block_rebuild() will disable any block in an invalid region.
|
||||
$this->assertEntity('block_1', $visibility, '', 'bluemarine', -4, 'Another Static Block', 'visible', FALSE);
|
||||
$this->assertEntity('block_1', $visibility, '', 'bluemarine', -4, $settings, FALSE);
|
||||
|
||||
$visibility = [];
|
||||
$this->assertEntity('block_2', $visibility, 'right', 'test_theme', -7, '', '0');
|
||||
$settings = [
|
||||
'id' => 'block_content',
|
||||
'label' => '',
|
||||
'provider' => 'block_content',
|
||||
'label_display' => '0',
|
||||
'status' => TRUE,
|
||||
'info' => '',
|
||||
'view_mode' => 'full',
|
||||
];
|
||||
$this->assertEntity('block_2', [], 'right', 'test_theme', -7, $settings);
|
||||
|
||||
// Custom block with php code is not migrated.
|
||||
$block = Block::load('block_3');
|
||||
|
|
|
@ -18,7 +18,7 @@ function block_content_help($route_name, RouteMatchInterface $route_match) {
|
|||
$field_ui = \Drupal::moduleHandler()->moduleExists('field_ui') ? \Drupal::url('help.page', ['name' => 'field_ui']) : '#';
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Custom Block module allows you to create and manage custom <em>block types</em> and <em>content-containing blocks</em> from the <a href = ":block-library" >Custom block library<a/> page. Custom block types have fields; see the <a href=":field-help">Field module help</a> for more information. Once created, custom blocks can be placed in regions just like blocks provided by other modules; see the <a href=":blocks">Block module help</a> page for details. For more information, see the <a href=":online-help">online documentation for the Custom Block module</a>.', [':block-library' => \Drupal::url('entity.block_content.collection'), ':block-content' => \Drupal::url('entity.block_content.collection'), ':field-help' => \Drupal::url('help.page', ['name' => 'field']), ':blocks' => \Drupal::url('help.page', ['name' => 'block']), ':online-help' => 'https://www.drupal.org/documentation/modules/block_content']) . '</p>';
|
||||
$output .= '<p>' . t('The Custom Block module allows you to create and manage custom <em>block types</em> and <em>content-containing blocks</em> from the <a href = ":block-library" >Custom block library</a> page. Custom block types have fields; see the <a href=":field-help">Field module help</a> for more information. Once created, custom blocks can be placed in regions just like blocks provided by other modules; see the <a href=":blocks">Block module help</a> page for details. For more information, see the <a href=":online-help">online documentation for the Custom Block module</a>.', [':block-library' => \Drupal::url('entity.block_content.collection'), ':block-content' => \Drupal::url('entity.block_content.collection'), ':field-help' => \Drupal::url('help.page', ['name' => 'field']), ':blocks' => \Drupal::url('help.page', ['name' => 'block']), ':online-help' => 'https://www.drupal.org/documentation/modules/block_content']) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Creating and managing custom block types') . '</dt>';
|
||||
|
|
|
@ -79,6 +79,7 @@ entity.block_content_type.edit_form:
|
|||
path: '/admin/structure/block/block-content/manage/{block_content_type}'
|
||||
defaults:
|
||||
_entity_form: 'block_content_type.edit'
|
||||
_title_callback: '\Drupal\Core\Entity\Controller\EntityController::title'
|
||||
requirements:
|
||||
_entity_access: 'block_content_type.update'
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
id: block_content_entity_display
|
||||
label: Body field display configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
entity_type: block_content
|
||||
bundle: basic
|
||||
view_mode: default
|
||||
field_name: body
|
||||
options:
|
||||
label: hidden
|
||||
ids:
|
||||
entity_type:
|
||||
type: string
|
||||
bundle:
|
||||
type: string
|
||||
view_mode:
|
||||
type: string
|
||||
field_name:
|
||||
type: string
|
||||
process:
|
||||
entity_type: entity_type
|
||||
bundle: bundle
|
||||
view_mode: view_mode
|
||||
field_name: field_name
|
||||
options: options
|
||||
destination:
|
||||
plugin: component_entity_display
|
||||
migration_dependencies:
|
||||
required:
|
||||
- block_content_body_field
|
||||
provider:
|
||||
- block_content
|
||||
- migrate_drupal
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
id: block_content_entity_form_display
|
||||
label: Body field form display configuration
|
||||
migration_tags:
|
||||
- Drupal 6
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: embedded_data
|
||||
data_rows:
|
||||
-
|
||||
entity_type: block_content
|
||||
bundle: basic
|
||||
form_mode: default
|
||||
field_name: body
|
||||
ids:
|
||||
entity_type:
|
||||
type: string
|
||||
bundle:
|
||||
type: string
|
||||
form_mode:
|
||||
type: string
|
||||
field_name:
|
||||
type: string
|
||||
process:
|
||||
entity_type: entity_type
|
||||
bundle: bundle
|
||||
form_mode: form_mode
|
||||
field_name: field_name
|
||||
destination:
|
||||
plugin: component_entity_form_display
|
||||
migration_dependencies:
|
||||
required:
|
||||
- block_content_body_field
|
||||
provider:
|
||||
- block_content
|
||||
- migrate_drupal
|
||||
|
|
@ -8,7 +8,7 @@ process:
|
|||
id: bid
|
||||
info: info
|
||||
'body/format':
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d6_filter_format
|
||||
source: format
|
||||
'body/value': body
|
||||
|
|
|
@ -8,7 +8,7 @@ process:
|
|||
id: bid
|
||||
info: info
|
||||
'body/format':
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d7_filter_format
|
||||
source: format
|
||||
'body/value': body
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace Drupal\block_content\Tests;
|
|||
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\system\Tests\Menu\AssertBreadcrumbTrait;
|
||||
|
||||
/**
|
||||
* Ensures that custom block type functions work correctly.
|
||||
|
@ -12,6 +14,7 @@ use Drupal\Component\Utility\Html;
|
|||
*/
|
||||
class BlockContentTypeTest extends BlockContentTestBase {
|
||||
|
||||
use AssertBreadcrumbTrait;
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
|
@ -91,6 +94,7 @@ class BlockContentTypeTest extends BlockContentTestBase {
|
|||
* Tests editing a block type using the UI.
|
||||
*/
|
||||
public function testBlockContentTypeEditing() {
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
// Now create an initial block-type.
|
||||
$this->createBlockContentType('basic', TRUE);
|
||||
|
||||
|
@ -113,6 +117,13 @@ class BlockContentTypeTest extends BlockContentTestBase {
|
|||
$this->drupalGet('admin/structure/block/block-content/manage/basic');
|
||||
$this->assertTitle(format_string('Edit @type custom block type | Drupal', ['@type' => 'basic']));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$front_page_path = Url::fromRoute('<front>')->toString();
|
||||
$this->assertBreadcrumb('admin/structure/block/block-content/manage/basic/fields', [
|
||||
$front_page_path => 'Home',
|
||||
'admin/structure/block' => 'Block layout',
|
||||
'admin/structure/block/block-content' => 'Custom block library',
|
||||
'admin/structure/block/block-content/manage/basic' => 'Bar',
|
||||
]);
|
||||
\Drupal::entityManager()->clearCachedFieldDefinitions();
|
||||
|
||||
$this->drupalGet('block/add');
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of block content body field display configuration.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentEntityDisplayTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block', 'block_content', 'filter', 'text'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(static::$modules);
|
||||
$this->executeMigrations([
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'block_content_entity_display',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a display entity.
|
||||
*
|
||||
* @param string $id
|
||||
* The entity ID.
|
||||
* @param string $component_id
|
||||
* The ID of the display component.
|
||||
*/
|
||||
protected function assertDisplay($id, $component_id) {
|
||||
$component = EntityViewDisplay::load($id)->getComponent($component_id);
|
||||
$this->assertInternalType('array', $component);
|
||||
$this->assertSame('hidden', $component['label']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the migrated display configuration.
|
||||
*/
|
||||
public function testMigration() {
|
||||
$this->assertDisplay('block_content.basic.default', 'body');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\block_content\Kernel\Migrate;
|
||||
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
||||
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of block content body field form display configuration.
|
||||
*
|
||||
* @group block_content
|
||||
*/
|
||||
class MigrateBlockContentEntityFormDisplayTest extends MigrateDrupal7TestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block', 'block_content', 'filter', 'text'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(static::$modules);
|
||||
$this->executeMigrations([
|
||||
'block_content_type',
|
||||
'block_content_body_field',
|
||||
'block_content_entity_form_display',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts a display entity.
|
||||
*
|
||||
* @param string $id
|
||||
* The entity ID.
|
||||
* @param string $component
|
||||
* The ID of the form component.
|
||||
*/
|
||||
protected function assertDisplay($id, $component_id) {
|
||||
$component = EntityFormDisplay::load($id)->getComponent($component_id);
|
||||
$this->assertInternalType('array', $component);
|
||||
$this->assertSame('text_textarea_with_summary', $component['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the migrated display configuration.
|
||||
*/
|
||||
public function testMigration() {
|
||||
$this->assertDisplay('block_content.basic.default', 'body');
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@ process:
|
|||
method: process
|
||||
source: plid
|
||||
-
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d6_book
|
||||
destination:
|
||||
plugin: book
|
||||
|
|
|
@ -33,7 +33,7 @@ class MigrateBookConfigsTest extends MigrateDrupal6TestBase {
|
|||
public function testBookSettings() {
|
||||
$config = $this->config('book.settings');
|
||||
$this->assertIdentical('book', $config->get('child_type'));
|
||||
$this->assertIdentical('all pages', $config->get('block.navigation.mode'));
|
||||
$this->assertSame('book pages', $config->get('block.navigation.mode'));
|
||||
$this->assertIdentical(['book'], $config->get('allowed_types'));
|
||||
$this->assertConfigSchema(\Drupal::service('config.typed'), 'book.settings', $config->get());
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class MigrateBookTest extends MigrateDrupal6TestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['book'];
|
||||
public static $modules = ['book', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -21,7 +21,7 @@ use Drupal\editor\Entity\Editor;
|
|||
* @param $plugins
|
||||
* An array of all the existing plugin definitions, passed by reference.
|
||||
*
|
||||
* @see CKEditorPluginManager
|
||||
* @see \Drupal\ckeditor\CKEditorPluginManager
|
||||
*/
|
||||
function hook_ckeditor_plugin_info_alter(array &$plugins) {
|
||||
$plugins['someplugin']['label'] = t('Better name');
|
||||
|
|
|
@ -10,6 +10,7 @@ drupal.ckeditor:
|
|||
- core/drupal
|
||||
- core/drupalSettings
|
||||
- core/drupal.debounce
|
||||
- core/drupal.displace
|
||||
- core/ckeditor
|
||||
- editor/drupal.editor
|
||||
# Ensure to run after core/matchmedia.
|
||||
|
|
|
@ -35,8 +35,9 @@ interface CKEditorPluginButtonsInterface extends CKEditorPluginInterface {
|
|||
* @return array
|
||||
* An array of buttons that are provided by this plugin. This will
|
||||
* only be used in the administrative section for assembling the toolbar.
|
||||
* Each button should by keyed by its CKEditor button name, and should
|
||||
* contain an array of button properties, including:
|
||||
* Each button should be keyed by its CKEditor button name (you can look up
|
||||
* the button name up in the plugin.js file), and should contain an array of
|
||||
* button properties, including:
|
||||
* - label: A human-readable, translated button name.
|
||||
* - image: An image for the button to be used in the toolbar.
|
||||
* - image_rtl: If the image needs to have a right-to-left version, specify
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ckeditor\Tests;
|
||||
namespace Drupal\Tests\ckeditor\Functional;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\editor\Entity\Editor;
|
||||
use Drupal\filter\FilterFormatInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests administration of CKEditor.
|
||||
*
|
||||
* @group ckeditor
|
||||
*/
|
||||
class CKEditorAdminTest extends WebTestBase {
|
||||
class CKEditorAdminTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
|
@ -62,12 +62,12 @@ class CKEditorAdminTest extends WebTestBase {
|
|||
$select = $this->xpath('//select[@name="editor[editor]"]');
|
||||
$select_is_disabled = $this->xpath('//select[@name="editor[editor]" and @disabled="disabled"]');
|
||||
$options = $this->xpath('//select[@name="editor[editor]"]/option');
|
||||
$this->assertTrue(count($select) === 1, 'The Text Editor select exists.');
|
||||
$this->assertTrue(count($select_is_disabled) === 0, 'The Text Editor select is not disabled.');
|
||||
$this->assertTrue(count($options) === 2, 'The Text Editor select has two options.');
|
||||
$this->assertTrue(((string) $options[0]) === 'None', 'Option 1 in the Text Editor select is "None".');
|
||||
$this->assertTrue(((string) $options[1]) === 'CKEditor', 'Option 2 in the Text Editor select is "CKEditor".');
|
||||
$this->assertTrue(((string) $options[0]['selected']) === 'selected', 'Option 1 ("None") is selected.');
|
||||
$this->assertCount(1, $select, 'The Text Editor select exists.');
|
||||
$this->assertCount(0, $select_is_disabled, 'The Text Editor select is not disabled.');
|
||||
$this->assertCount(2, $options, 'The Text Editor select has two options.');
|
||||
$this->assertSame('None', $options[0]->getText(), 'Option 1 in the Text Editor select is "None".');
|
||||
$this->assertSame('CKEditor', $options[1]->getText(), 'Option 2 in the Text Editor select is "CKEditor".');
|
||||
$this->assertSame('selected', $options[0]->getAttribute('selected'), 'Option 1 ("None") is selected.');
|
||||
|
||||
// Select the "CKEditor" editor and click the "Save configuration" button.
|
||||
$edit = [
|
||||
|
@ -110,7 +110,7 @@ class CKEditorAdminTest extends WebTestBase {
|
|||
$this->assertIdentical($this->castSafeStrings($ckeditor->getDefaultSettings()), $expected_default_settings);
|
||||
|
||||
// Keep the "CKEditor" editor selected and click the "Configure" button.
|
||||
$this->drupalPostAjaxForm(NULL, $edit, 'editor_configure');
|
||||
$this->drupalPostForm(NULL, $edit, 'editor_configure');
|
||||
$editor = Editor::load('filtered_html');
|
||||
$this->assertFalse($editor, 'No Editor config entity exists yet.');
|
||||
|
||||
|
@ -120,8 +120,10 @@ class CKEditorAdminTest extends WebTestBase {
|
|||
'#editor' => Editor::create(['editor' => 'ckeditor']),
|
||||
'#plugins' => $this->container->get('plugin.manager.ckeditor.plugin')->getButtons(),
|
||||
];
|
||||
$settings = $this->getDrupalSettings();
|
||||
$expected = $settings['ckeditor']['toolbarAdmin'];
|
||||
$this->assertEqual(
|
||||
$this->drupalSettings['ckeditor']['toolbarAdmin'],
|
||||
$expected,
|
||||
$this->container->get('renderer')->renderPlain($ckeditor_settings_toolbar),
|
||||
'CKEditor toolbar settings are rendered as part of drupalSettings.'
|
||||
);
|
||||
|
@ -230,12 +232,12 @@ class CKEditorAdminTest extends WebTestBase {
|
|||
$select = $this->xpath('//select[@name="editor[editor]"]');
|
||||
$select_is_disabled = $this->xpath('//select[@name="editor[editor]" and @disabled="disabled"]');
|
||||
$options = $this->xpath('//select[@name="editor[editor]"]/option');
|
||||
$this->assertTrue(count($select) === 1, 'The Text Editor select exists.');
|
||||
$this->assertTrue(count($select_is_disabled) === 0, 'The Text Editor select is not disabled.');
|
||||
$this->assertTrue(count($options) === 2, 'The Text Editor select has two options.');
|
||||
$this->assertTrue(((string) $options[0]) === 'None', 'Option 1 in the Text Editor select is "None".');
|
||||
$this->assertTrue(((string) $options[1]) === 'CKEditor', 'Option 2 in the Text Editor select is "CKEditor".');
|
||||
$this->assertTrue(((string) $options[0]['selected']) === 'selected', 'Option 1 ("None") is selected.');
|
||||
$this->assertCount(1, $select, 'The Text Editor select exists.');
|
||||
$this->assertCount(0, $select_is_disabled, 'The Text Editor select is not disabled.');
|
||||
$this->assertCount(2, $options, 'The Text Editor select has two options.');
|
||||
$this->assertSame('None', $options[0]->getText(), 'Option 1 in the Text Editor select is "None".');
|
||||
$this->assertSame('CKEditor', $options[1]->getText(), 'Option 2 in the Text Editor select is "CKEditor".');
|
||||
$this->assertSame('selected', $options[0]->getAttribute('selected'), 'Option 1 ("None") is selected.');
|
||||
|
||||
// Name our fancy new text format, select the "CKEditor" editor and click
|
||||
// the "Configure" button.
|
||||
|
@ -244,7 +246,7 @@ class CKEditorAdminTest extends WebTestBase {
|
|||
'format' => 'amazing_format',
|
||||
'editor[editor]' => 'ckeditor',
|
||||
];
|
||||
$this->drupalPostAjaxForm(NULL, $edit, 'editor_configure');
|
||||
$this->drupalPostForm(NULL, $edit, 'editor_configure');
|
||||
$filter_format = FilterFormat::load('amazing_format');
|
||||
$this->assertFalse($filter_format, 'No FilterFormat config entity exists yet.');
|
||||
$editor = Editor::load('amazing_format');
|
||||
|
@ -258,7 +260,9 @@ class CKEditorAdminTest extends WebTestBase {
|
|||
$this->assertFieldByName('editor[settings][toolbar][button_groups]', $expected_buttons_value);
|
||||
|
||||
// Regression test for https://www.drupal.org/node/2606460.
|
||||
$this->assertTrue(strpos($this->drupalSettings['ckeditor']['toolbarAdmin'], '<li data-drupal-ckeditor-button-name="Bold" class="ckeditor-button"><a href="#" class="cke-icon-only cke_ltr" role="button" title="bold" aria-label="bold"><span class="cke_button_icon cke_button__bold_icon">bold</span></a></li>') !== FALSE);
|
||||
$settings = $this->getDrupalSettings();
|
||||
$expected = $settings['ckeditor']['toolbarAdmin'];
|
||||
$this->assertTrue(strpos($expected, '<li data-drupal-ckeditor-button-name="Bold" class="ckeditor-button"><a href="#" class="cke-icon-only cke_ltr" role="button" title="bold" aria-label="bold"><span class="cke_button_icon cke_button__bold_icon">bold</span></a></li>') !== FALSE);
|
||||
|
||||
// Ensure the styles textarea exists and is initialized empty.
|
||||
$styles_textarea = $this->xpath('//textarea[@name="editor[settings][plugins][stylescombo][styles]"]');
|
|
@ -1,17 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ckeditor\Tests;
|
||||
namespace Drupal\Tests\ckeditor\Functional;
|
||||
|
||||
use Drupal\editor\Entity\Editor;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests loading of CKEditor.
|
||||
*
|
||||
* @group ckeditor
|
||||
*/
|
||||
class CKEditorLoadingTest extends WebTestBase {
|
||||
class CKEditorLoadingTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
|
@ -1,17 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\ckeditor\Tests;
|
||||
namespace Drupal\Tests\ckeditor\Functional;
|
||||
|
||||
use Drupal\editor\Entity\Editor;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests administration of the CKEditor StylesCombo plugin.
|
||||
*
|
||||
* @group ckeditor
|
||||
*/
|
||||
class CKEditorStylesComboAdminTest extends WebTestBase {
|
||||
class CKEditorStylesComboAdminTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
|
@ -11,7 +11,7 @@ process:
|
|||
# the cid field to allow incremental migrations.
|
||||
cid: cid
|
||||
pid:
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d6_comment
|
||||
source: pid
|
||||
entity_id: nid
|
||||
|
@ -32,7 +32,7 @@ process:
|
|||
thread: thread
|
||||
'comment_body/value': comment
|
||||
'comment_body/format':
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d6_filter_format
|
||||
source: format
|
||||
destination:
|
||||
|
|
|
@ -11,7 +11,7 @@ process:
|
|||
# the cid field to allow incremental migrations.
|
||||
cid: cid
|
||||
pid:
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: d7_comment
|
||||
source: pid
|
||||
entity_id: nid
|
||||
|
|
|
@ -10,7 +10,7 @@ use Drupal\Core\Session\AnonymousUserSession;
|
|||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
|
||||
use Drupal\simpletest\TestBase;
|
||||
use Drupal\Tests\Traits\Core\GeneratePermutationsTrait;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
|
@ -23,6 +23,7 @@ use Drupal\user\RoleInterface;
|
|||
class CommentFieldAccessTest extends EntityKernelTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
use GeneratePermutationsTrait;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
|
@ -203,7 +204,7 @@ class CommentFieldAccessTest extends EntityKernelTestBase {
|
|||
'comment' => [$comment1, $comment2, $comment3, $comment4],
|
||||
'user' => [$comment_admin_user, $comment_enabled_user, $comment_no_edit_user, $comment_disabled_user, $anonymous_user]
|
||||
];
|
||||
$permutations = TestBase::generatePermutations($combinations);
|
||||
$permutations = $this->generatePermutations($combinations);
|
||||
|
||||
// Check access to administrative fields.
|
||||
foreach ($this->administrativeFields as $field) {
|
||||
|
|
|
@ -17,7 +17,7 @@ class MigrateCommentTest extends MigrateDrupal6TestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment'];
|
||||
public static $modules = ['comment', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -11,6 +11,11 @@ use Drupal\Core\Entity\Entity\EntityViewDisplay;
|
|||
*/
|
||||
class MigrateCommentVariableEntityDisplayTest extends MigrateCommentVariableDisplayBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,11 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay;
|
|||
*/
|
||||
class MigrateCommentVariableEntityFormDisplayTest extends MigrateCommentVariableDisplayBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -15,7 +15,7 @@ class MigrateCommentVariableFieldTest extends MigrateDrupal6TestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment'];
|
||||
public static $modules = ['comment', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -16,7 +16,7 @@ class MigrateCommentVariableInstanceTest extends MigrateDrupal6TestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment'];
|
||||
public static $modules = ['comment', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -12,7 +12,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateCommentEntityDisplayTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['node', 'comment', 'text'];
|
||||
public static $modules = ['node', 'comment', 'text', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -12,7 +12,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateCommentEntityFormDisplaySubjectTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['node', 'comment', 'text'];
|
||||
public static $modules = ['node', 'comment', 'text', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -12,7 +12,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateCommentEntityFormDisplayTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['node', 'comment', 'text'];
|
||||
public static $modules = ['node', 'comment', 'text', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -15,7 +15,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateCommentFieldInstanceTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['node', 'comment', 'text'];
|
||||
public static $modules = ['node', 'comment', 'text', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -14,7 +14,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateCommentFieldTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['node', 'comment', 'text'];
|
||||
public static $modules = ['node', 'comment', 'text', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -14,7 +14,7 @@ use Drupal\node\NodeInterface;
|
|||
*/
|
||||
class MigrateCommentTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['filter', 'node', 'comment', 'text'];
|
||||
public static $modules = ['filter', 'node', 'comment', 'text', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -13,7 +13,7 @@ use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
|
|||
*/
|
||||
class MigrateCommentTypeTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['node', 'comment', 'text'];
|
||||
public static $modules = ['node', 'comment', 'text', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests the Drupal 6 comment source w/ high water handling.
|
||||
*
|
||||
* @covers \Drupal\comment\Plugin\migrate\source\d6\Comment
|
||||
*
|
||||
* @group comment
|
||||
*/
|
||||
class CommentSourceWithHighWaterTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['comments'] = [
|
||||
[
|
||||
'cid' => 1,
|
||||
'pid' => 0,
|
||||
'nid' => 2,
|
||||
'uid' => 3,
|
||||
'subject' => 'subject value 1',
|
||||
'comment' => 'comment value 1',
|
||||
'hostname' => 'hostname value 1',
|
||||
'timestamp' => 1382255613,
|
||||
'status' => 0,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat1',
|
||||
'type' => 'story',
|
||||
],
|
||||
[
|
||||
'cid' => 2,
|
||||
'pid' => 1,
|
||||
'nid' => 3,
|
||||
'uid' => 4,
|
||||
'subject' => 'subject value 2',
|
||||
'comment' => 'comment value 2',
|
||||
'hostname' => 'hostname value 2',
|
||||
'timestamp' => 1382255662,
|
||||
'status' => 0,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat2',
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['node'] = [
|
||||
[
|
||||
'nid' => 2,
|
||||
'type' => 'story',
|
||||
],
|
||||
[
|
||||
'nid' => 3,
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'cid' => 2,
|
||||
'pid' => 1,
|
||||
'nid' => 3,
|
||||
'uid' => 4,
|
||||
'subject' => 'subject value 2',
|
||||
'comment' => 'comment value 2',
|
||||
'hostname' => 'hostname value 2',
|
||||
'timestamp' => 1382255662,
|
||||
'status' => 1,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat2',
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected count is the count returned by the query before the query
|
||||
// is modified by SqlBase::initializeIterator().
|
||||
$tests[0]['expected_count'] = 2;
|
||||
|
||||
$tests[0]['configuration']['high_water_property']['name'] = 'timestamp';
|
||||
$tests[0]['high_water'] = $tests[0]['source_data']['comments'][0]['timestamp'];
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D6 comment source plugin.
|
||||
*
|
||||
* @covers \Drupal\comment\Plugin\migrate\source\d6\Comment
|
||||
* @group comment
|
||||
*/
|
||||
class CommentTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['comments'] = [
|
||||
[
|
||||
'cid' => 1,
|
||||
'pid' => 0,
|
||||
'nid' => 2,
|
||||
'uid' => 3,
|
||||
'subject' => 'subject value 1',
|
||||
'comment' => 'comment value 1',
|
||||
'hostname' => 'hostname value 1',
|
||||
'timestamp' => 1382255613,
|
||||
'status' => 0,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat1',
|
||||
'type' => 'story',
|
||||
],
|
||||
[
|
||||
'cid' => 2,
|
||||
'pid' => 1,
|
||||
'nid' => 3,
|
||||
'uid' => 4,
|
||||
'subject' => 'subject value 2',
|
||||
'comment' => 'comment value 2',
|
||||
'hostname' => 'hostname value 2',
|
||||
'timestamp' => 1382255662,
|
||||
'status' => 0,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat2',
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['node'] = [
|
||||
[
|
||||
'nid' => 2,
|
||||
'type' => 'story',
|
||||
],
|
||||
[
|
||||
'nid' => 3,
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'cid' => 1,
|
||||
'pid' => 0,
|
||||
'nid' => 2,
|
||||
'uid' => 3,
|
||||
'subject' => 'subject value 1',
|
||||
'comment' => 'comment value 1',
|
||||
'hostname' => 'hostname value 1',
|
||||
'timestamp' => 1382255613,
|
||||
'status' => 1,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat1',
|
||||
'type' => 'story',
|
||||
],
|
||||
[
|
||||
'cid' => 2,
|
||||
'pid' => 1,
|
||||
'nid' => 3,
|
||||
'uid' => 4,
|
||||
'subject' => 'subject value 2',
|
||||
'comment' => 'comment value 2',
|
||||
'hostname' => 'hostname value 2',
|
||||
'timestamp' => 1382255662,
|
||||
'status' => 1,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat2',
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests comment variable per comment type source plugin.
|
||||
*
|
||||
* @covers \Drupal\comment\Plugin\migrate\source\d6\CommentVariablePerCommentType
|
||||
* @group comment
|
||||
*/
|
||||
class CommentVariablePerCommentTypeTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['node_type'] = [
|
||||
[
|
||||
'type' => 'page',
|
||||
],
|
||||
[
|
||||
'type' => 'story',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['variable'] = [
|
||||
[
|
||||
'name' => 'comment_subject_field_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_subject_field_story',
|
||||
'value' => serialize(0),
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
// Each result will also include a label and description, but those are
|
||||
// static values set by the source plugin and don't need to be asserted.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'comment_type' => 'comment',
|
||||
],
|
||||
[
|
||||
'comment_type' => 'comment_no_subject',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Kernel\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests d6_comment_variable source plugin.
|
||||
*
|
||||
* @covers \Drupal\comment\Plugin\migrate\source\d6\CommentVariable
|
||||
* @group comment
|
||||
*/
|
||||
class CommentVariableTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['node_type'] = [
|
||||
[
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
$tests[0]['source_data']['variable'] = [
|
||||
[
|
||||
'name' => 'comment_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_default_mode_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_default_order_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_default_per_page_page',
|
||||
'value' => serialize(50),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_controls_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_anonymous_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_subject_field_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_preview_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_form_location_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'comment' => '1',
|
||||
'comment_default_mode' => '1',
|
||||
'comment_default_order' => '1',
|
||||
'comment_default_per_page' => '50',
|
||||
'comment_controls' => '1',
|
||||
'comment_anonymous' => '1',
|
||||
'comment_subject_field' => '1',
|
||||
'comment_preview' => '1',
|
||||
'comment_form_location' => '1',
|
||||
'node_type' => 'page',
|
||||
'comment_type' => 'comment',
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D7 comment source plugin.
|
||||
*
|
||||
* @covers \Drupal\comment\Plugin\migrate\source\d7\Comment
|
||||
* @group comment
|
||||
*/
|
||||
class CommentTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['comment', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['comment'] = [
|
||||
[
|
||||
'cid' => '1',
|
||||
'pid' => '0',
|
||||
'nid' => '1',
|
||||
'uid' => '1',
|
||||
'subject' => 'A comment',
|
||||
'hostname' => '::1',
|
||||
'created' => '1421727536',
|
||||
'changed' => '1421727536',
|
||||
'status' => '1',
|
||||
'thread' => '01/',
|
||||
'name' => 'admin',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'language' => 'und',
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['node'] = [
|
||||
[
|
||||
'nid' => '1',
|
||||
'vid' => '1',
|
||||
'type' => 'test_content_type',
|
||||
'language' => 'en',
|
||||
'title' => 'A Node',
|
||||
'uid' => '1',
|
||||
'status' => '1',
|
||||
'created' => '1421727515',
|
||||
'changed' => '1421727515',
|
||||
'comment' => '2',
|
||||
'promote' => '1',
|
||||
'sticky' => '0',
|
||||
'tnid' => '0',
|
||||
'translate' => '0',
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['field_config_instance'] = [
|
||||
[
|
||||
'id' => '14',
|
||||
'field_id' => '1',
|
||||
'field_name' => 'comment_body',
|
||||
'entity_type' => 'comment',
|
||||
'bundle' => 'comment_node_test_content_type',
|
||||
'data' => 'a:0:{}',
|
||||
'deleted' => '0',
|
||||
],
|
||||
];
|
||||
$tests[0]['source_data']['field_data_comment_body'] = [
|
||||
[
|
||||
'entity_type' => 'comment',
|
||||
'bundle' => 'comment_node_test_content_type',
|
||||
'deleted' => '0',
|
||||
'entity_id' => '1',
|
||||
'revision_id' => '1',
|
||||
'language' => 'und',
|
||||
'delta' => '0',
|
||||
'comment_body_value' => 'This is a comment',
|
||||
'comment_body_format' => 'filtered_html',
|
||||
],
|
||||
];
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'cid' => '1',
|
||||
'pid' => '0',
|
||||
'nid' => '1',
|
||||
'uid' => '1',
|
||||
'subject' => 'A comment',
|
||||
'hostname' => '::1',
|
||||
'created' => '1421727536',
|
||||
'changed' => '1421727536',
|
||||
'status' => '1',
|
||||
'thread' => '01/',
|
||||
'name' => 'admin',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'language' => 'und',
|
||||
'comment_body' => [
|
||||
[
|
||||
'value' => 'This is a comment',
|
||||
'format' => 'filtered_html',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Migrate\d7;
|
||||
namespace Drupal\Tests\comment\Kernel\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
|
||||
|
||||
/**
|
||||
* Tests D7 comment type source plugin.
|
||||
*
|
||||
* @covers \Drupal\comment\Plugin\migrate\source\d7\CommentType
|
||||
* @group comment
|
||||
*/
|
||||
class CommentTypeTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\comment\Plugin\migrate\source\d7\CommentType';
|
||||
|
||||
protected $migrationConfiguration = [
|
||||
'id' => 'test',
|
||||
'source' => [
|
||||
'plugin' => 'd7_comment_type',
|
||||
],
|
||||
];
|
||||
|
||||
protected $expectedResults = [
|
||||
[
|
||||
'bundle' => 'comment_node_article',
|
||||
'node_type' => 'article',
|
||||
'default_mode' => '1',
|
||||
'per_page' => '50',
|
||||
'anonymous' => '0',
|
||||
'form_location' => '1',
|
||||
'preview' => '0',
|
||||
'subject' => '1',
|
||||
'label' => 'Article comment',
|
||||
],
|
||||
];
|
||||
class CommentTypeTest extends MigrateSqlSourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['node_type'] = [
|
||||
public static $modules = ['comment', 'migrate_drupal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function providerSource() {
|
||||
$tests = [];
|
||||
|
||||
// The source data.
|
||||
$tests[0]['source_data']['node_type'] = [
|
||||
[
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
|
@ -55,7 +41,7 @@ class CommentTypeTest extends MigrateSqlSourceTestCase {
|
|||
'orig_type' => 'article',
|
||||
],
|
||||
];
|
||||
$this->databaseContents['field_config_instance'] = [
|
||||
$tests[0]['source_data']['field_config_instance'] = [
|
||||
[
|
||||
'id' => '14',
|
||||
'field_id' => '1',
|
||||
|
@ -66,7 +52,7 @@ class CommentTypeTest extends MigrateSqlSourceTestCase {
|
|||
'deleted' => '0',
|
||||
],
|
||||
];
|
||||
$this->databaseContents['variable'] = [
|
||||
$tests[0]['source_data']['variable'] = [
|
||||
[
|
||||
'name' => 'comment_default_mode_article',
|
||||
'value' => serialize(1),
|
||||
|
@ -92,7 +78,22 @@ class CommentTypeTest extends MigrateSqlSourceTestCase {
|
|||
'value' => serialize(1),
|
||||
],
|
||||
];
|
||||
parent::setUp();
|
||||
|
||||
// The expected results.
|
||||
$tests[0]['expected_data'] = [
|
||||
[
|
||||
'bundle' => 'comment_node_article',
|
||||
'node_type' => 'article',
|
||||
'default_mode' => '1',
|
||||
'per_page' => '50',
|
||||
'anonymous' => '0',
|
||||
'form_location' => '1',
|
||||
'preview' => '0',
|
||||
'subject' => '1',
|
||||
'label' => 'Article comment',
|
||||
],
|
||||
];
|
||||
return $tests;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@ use Drupal\comment\CommentLinkBuilder;
|
|||
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\node\NodeInterface;
|
||||
use Drupal\simpletest\TestBase;
|
||||
use Drupal\Tests\Traits\Core\GeneratePermutationsTrait;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,8 @@ use Drupal\Tests\UnitTestCase;
|
|||
*/
|
||||
class CommentLinkBuilderTest extends UnitTestCase {
|
||||
|
||||
use GeneratePermutationsTrait;
|
||||
|
||||
/**
|
||||
* Comment manager mock.
|
||||
*
|
||||
|
@ -195,7 +197,7 @@ class CommentLinkBuilderTest extends UnitTestCase {
|
|||
'teaser', 'rss', 'full',
|
||||
],
|
||||
];
|
||||
$permutations = TestBase::generatePermutations($combinations);
|
||||
$permutations = $this->generatePermutations($combinations);
|
||||
foreach ($permutations as $combination) {
|
||||
$case = [
|
||||
$this->getMockNode(TRUE, $combination['comments'], $combination['form_location'], $combination['comment_count']),
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Migrate\d6;
|
||||
|
||||
/**
|
||||
* Tests the Drupal 6 comment source w/ high water handling.
|
||||
*
|
||||
* @group comment
|
||||
*/
|
||||
class CommentSourceWithHighWaterTest extends CommentTestBase {
|
||||
|
||||
const ORIGINAL_HIGH_WATER = 1382255613;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->migrationConfiguration['source']['high_water_property']['name'] = 'timestamp';
|
||||
array_shift($this->expectedResults);
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Migrate\d6;
|
||||
|
||||
/**
|
||||
* Tests D6 comment source plugin.
|
||||
*
|
||||
* @group comment
|
||||
*/
|
||||
class CommentTest extends CommentTestBase {
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Migrate\d6;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Base class for comment source unit tests.
|
||||
*/
|
||||
abstract class CommentTestBase extends MigrateSqlSourceTestCase {
|
||||
|
||||
// The plugin system is not working during unit testing so the source plugin
|
||||
// class needs to be manually specified.
|
||||
const PLUGIN_CLASS = 'Drupal\comment\Plugin\migrate\source\d6\Comment';
|
||||
|
||||
// The fake Migration configuration entity.
|
||||
protected $migrationConfiguration = [
|
||||
// The ID of the entity, can be any string.
|
||||
'id' => 'test',
|
||||
// This needs to be the identifier of the actual key: cid for comment, nid
|
||||
// for node and so on.
|
||||
'source' => [
|
||||
'plugin' => 'd6_comment',
|
||||
],
|
||||
];
|
||||
|
||||
// We need to set up the database contents; it's easier to do that below.
|
||||
|
||||
protected $expectedResults = [
|
||||
[
|
||||
'cid' => 1,
|
||||
'pid' => 0,
|
||||
'nid' => 2,
|
||||
'uid' => 3,
|
||||
'subject' => 'subject value 1',
|
||||
'comment' => 'comment value 1',
|
||||
'hostname' => 'hostname value 1',
|
||||
'timestamp' => 1382255613,
|
||||
'status' => 1,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat1',
|
||||
'type' => 'story',
|
||||
],
|
||||
[
|
||||
'cid' => 2,
|
||||
'pid' => 1,
|
||||
'nid' => 3,
|
||||
'uid' => 4,
|
||||
'subject' => 'subject value 2',
|
||||
'comment' => 'comment value 2',
|
||||
'hostname' => 'hostname value 2',
|
||||
'timestamp' => 1382255662,
|
||||
'status' => 1,
|
||||
'thread' => '',
|
||||
'name' => '',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'format' => 'testformat2',
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
foreach ($this->expectedResults as $k => $row) {
|
||||
$this->databaseContents['comments'][$k] = $row;
|
||||
$this->databaseContents['comments'][$k]['status'] = 1 - $this->databaseContents['comments'][$k]['status'];
|
||||
}
|
||||
// Add node table data.
|
||||
$this->databaseContents['node'][] = ['nid' => 2, 'type' => 'story'];
|
||||
$this->databaseContents['node'][] = ['nid' => 3, 'type' => 'page'];
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Migrate\d6;
|
||||
|
||||
use Drupal\comment\Plugin\migrate\source\d6\CommentVariablePerCommentType;
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\comment\Plugin\migrate\source\d6\CommentVariablePerCommentType
|
||||
* @group comment
|
||||
*/
|
||||
class CommentVariablePerCommentTypeTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = CommentVariablePerCommentType::class;
|
||||
|
||||
protected $migrationConfiguration = [
|
||||
'id' => 'test',
|
||||
'source' => [
|
||||
'plugin' => 'd6_comment_variable_per_comment_type',
|
||||
],
|
||||
];
|
||||
|
||||
protected $expectedResults = [
|
||||
// Each result will also include a label and description, but those are
|
||||
// static values set by the source plugin and don't need to be asserted.
|
||||
[
|
||||
'comment_type' => 'comment',
|
||||
],
|
||||
[
|
||||
'comment_type' => 'comment_no_subject',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['node_type'] = [
|
||||
[
|
||||
'type' => 'page',
|
||||
],
|
||||
[
|
||||
'type' => 'story',
|
||||
],
|
||||
];
|
||||
$this->databaseContents['variable'] = [
|
||||
[
|
||||
'name' => 'comment_subject_field_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_subject_field_story',
|
||||
'value' => serialize(0),
|
||||
],
|
||||
];
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Migrate\d6;
|
||||
|
||||
use Drupal\comment\Plugin\migrate\source\d6\CommentVariable;
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\comment\Plugin\migrate\source\d6\CommentVariable
|
||||
* @group comment
|
||||
*/
|
||||
class CommentVariableTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = CommentVariable::class;
|
||||
|
||||
protected $migrationConfiguration = [
|
||||
'id' => 'test',
|
||||
'source' => [
|
||||
'plugin' => 'd6_comment_variable',
|
||||
],
|
||||
];
|
||||
|
||||
protected $expectedResults = [
|
||||
[
|
||||
'comment' => '1',
|
||||
'comment_default_mode' => '1',
|
||||
'comment_default_order' => '1',
|
||||
'comment_default_per_page' => '50',
|
||||
'comment_controls' => '1',
|
||||
'comment_anonymous' => '1',
|
||||
'comment_subject_field' => '1',
|
||||
'comment_preview' => '1',
|
||||
'comment_form_location' => '1',
|
||||
'node_type' => 'page',
|
||||
'comment_type' => 'comment',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['node_type'] = [
|
||||
[
|
||||
'type' => 'page',
|
||||
],
|
||||
];
|
||||
$this->databaseContents['variable'] = [
|
||||
[
|
||||
'name' => 'comment_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_default_mode_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_default_order_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_default_per_page_page',
|
||||
'value' => serialize(50),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_controls_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_anonymous_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_subject_field_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_preview_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
[
|
||||
'name' => 'comment_form_location_page',
|
||||
'value' => serialize(1),
|
||||
],
|
||||
];
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\comment\Unit\Migrate\d7;
|
||||
|
||||
use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
|
||||
|
||||
/**
|
||||
* Tests D7 comment source plugin.
|
||||
*
|
||||
* @group comment
|
||||
*/
|
||||
class CommentTest extends MigrateSqlSourceTestCase {
|
||||
|
||||
const PLUGIN_CLASS = 'Drupal\comment\Plugin\migrate\source\d7\Comment';
|
||||
|
||||
protected $migrationConfiguration = [
|
||||
'id' => 'test',
|
||||
'source' => [
|
||||
'plugin' => 'd7_comment',
|
||||
],
|
||||
];
|
||||
|
||||
protected $expectedResults = [
|
||||
[
|
||||
'cid' => '1',
|
||||
'pid' => '0',
|
||||
'nid' => '1',
|
||||
'uid' => '1',
|
||||
'subject' => 'A comment',
|
||||
'hostname' => '::1',
|
||||
'created' => '1421727536',
|
||||
'changed' => '1421727536',
|
||||
'status' => '1',
|
||||
'thread' => '01/',
|
||||
'name' => 'admin',
|
||||
'mail' => '',
|
||||
'homepage' => '',
|
||||
'language' => 'und',
|
||||
'comment_body' => [
|
||||
[
|
||||
'value' => 'This is a comment',
|
||||
'format' => 'filtered_html',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->databaseContents['comment'] = $this->expectedResults;
|
||||
unset($this->databaseContents['comment'][0]['comment_body']);
|
||||
|
||||
$this->databaseContents['node'] = [
|
||||
[
|
||||
'nid' => '1',
|
||||
'vid' => '1',
|
||||
'type' => 'test_content_type',
|
||||
'language' => 'en',
|
||||
'title' => 'A Node',
|
||||
'uid' => '1',
|
||||
'status' => '1',
|
||||
'created' => '1421727515',
|
||||
'changed' => '1421727515',
|
||||
'comment' => '2',
|
||||
'promote' => '1',
|
||||
'sticky' => '0',
|
||||
'tnid' => '0',
|
||||
'translate' => '0',
|
||||
],
|
||||
];
|
||||
$this->databaseContents['field_config_instance'] = [
|
||||
[
|
||||
'id' => '14',
|
||||
'field_id' => '1',
|
||||
'field_name' => 'comment_body',
|
||||
'entity_type' => 'comment',
|
||||
'bundle' => 'comment_node_test_content_type',
|
||||
'data' => 'a:0:{}',
|
||||
'deleted' => '0',
|
||||
],
|
||||
];
|
||||
$this->databaseContents['field_data_comment_body'] = [
|
||||
[
|
||||
'entity_type' => 'comment',
|
||||
'bundle' => 'comment_node_test_content_type',
|
||||
'deleted' => '0',
|
||||
'entity_id' => '1',
|
||||
'revision_id' => '1',
|
||||
'language' => 'und',
|
||||
'delta' => '0',
|
||||
'comment_body_value' => 'This is a comment',
|
||||
'comment_body_format' => 'filtered_html',
|
||||
],
|
||||
];
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
}
|
|
@ -155,6 +155,29 @@ EOD;
|
|||
];
|
||||
$this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import'));
|
||||
$this->assertRaw(t('Configuration %name depends on the %owner module that will not be installed after import.', ['%name' => 'config_test.dynamic.second', '%owner' => 'does_not_exist']));
|
||||
|
||||
// Try to preform an update which would create a PHP object if Yaml parsing
|
||||
// not securely set up.
|
||||
// Perform an update.
|
||||
$import = <<<EOD
|
||||
id: second
|
||||
uuid: $second_uuid
|
||||
label: !php/object "O:36:\"Drupal\\\Core\\\Test\\\ObjectSerialization\":0:{}"
|
||||
weight: 0
|
||||
style: ''
|
||||
status: '0'
|
||||
EOD;
|
||||
$edit = [
|
||||
'config_type' => 'config_test',
|
||||
'import' => $import,
|
||||
];
|
||||
$this->drupalPostForm('admin/config/development/configuration/single/import', $edit, t('Import'));
|
||||
$this->assertRaw(t('Are you sure you want to update the %name @type?', ['%name' => 'second', '@type' => 'test configuration']));
|
||||
$this->drupalPostForm(NULL, [], t('Confirm'));
|
||||
$entity = $storage->load('second');
|
||||
$this->assertRaw(t('The configuration was imported successfully.'));
|
||||
$this->assertTrue(is_string($entity->label()), 'Entity label is a string');
|
||||
$this->assertTrue(strpos($entity->label(), 'ObjectSerialization') > 0, 'Label contains serialized object');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
id: other_module_test_with_dependency
|
||||
label: 'Other module test with dependency'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
module:
|
||||
- config_other_module_config_test
|
||||
config:
|
||||
- config_test.dynamic.dotted.english
|
|
@ -0,0 +1,13 @@
|
|||
id: yet_another_module_test_with_dependency
|
||||
label: 'Yet anther module test with dependency'
|
||||
weight: 0
|
||||
style: ''
|
||||
status: true
|
||||
langcode: en
|
||||
protected_property: Default
|
||||
dependencies:
|
||||
enforced:
|
||||
module:
|
||||
- config_other_module_config_test
|
||||
config:
|
||||
- config_test.dynamic.dotted.english
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Config install double dependency test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -197,7 +197,7 @@ abstract class ConfigTranslationFormBase extends FormBase implements BaseFormIdI
|
|||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$form_values = $form_state->getValue(['translation', 'config_names']);
|
||||
|
||||
foreach ($this->mapper->getConfigNames() as $name) {
|
||||
foreach ($form_values as $name => $value) {
|
||||
$schema = $this->typedConfigManager->get($name);
|
||||
|
||||
// Set configuration values based on form submission and source values.
|
||||
|
@ -205,7 +205,7 @@ abstract class ConfigTranslationFormBase extends FormBase implements BaseFormIdI
|
|||
$config_translation = $this->languageManager->getLanguageConfigOverride($this->language->getId(), $name);
|
||||
|
||||
$element = $this->createFormElement($schema);
|
||||
$element->setConfig($base_config, $config_translation, $form_values[$name]);
|
||||
$element->setConfig($base_config, $config_translation, $value);
|
||||
|
||||
// If no overrides, delete language specific configuration file.
|
||||
$saved_config = $config_translation->get();
|
||||
|
|
|
@ -12,6 +12,7 @@ use Drupal\field\Entity\FieldConfig;
|
|||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
|
@ -1033,6 +1034,45 @@ class ConfigTranslationUiTest extends WebTestBase {
|
|||
$this->assertEqual($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests field translation for node fields.
|
||||
*/
|
||||
public function testNodeFieldTranslation() {
|
||||
NodeType::create(['type' => 'article', 'name' => 'Article'])->save();
|
||||
|
||||
$field_name = 'translatable_field';
|
||||
$field_storage = FieldStorageConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'type' => 'text',
|
||||
]);
|
||||
|
||||
$field_storage->setSetting('translatable_storage_setting', 'translatable_storage_setting');
|
||||
$field_storage->save();
|
||||
$field = FieldConfig::create([
|
||||
'field_name' => $field_name,
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'article',
|
||||
]);
|
||||
$field->save();
|
||||
|
||||
$this->drupalLogin($this->translatorUser);
|
||||
|
||||
$this->drupalGet("/entity_test/structure/article/fields/node.article.$field_name/translate");
|
||||
$this->clickLink('Add');
|
||||
|
||||
$form_values = [
|
||||
'translation[config_names][field.field.node.article.translatable_field][description]' => 'FR Help text.',
|
||||
'translation[config_names][field.field.node.article.translatable_field][label]' => 'FR label',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $form_values, 'Save translation');
|
||||
$this->assertText('Successfully saved French translation.');
|
||||
|
||||
// Check that the translations are saved.
|
||||
$this->clickLink('Add');
|
||||
$this->assertRaw('FR label');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets translation from locale storage.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\config_translation\Functional;
|
||||
namespace Drupal\config_translation\Tests;
|
||||
|
||||
use Drupal\views_ui\Tests\UITestBase;
|
||||
|
|
@ -11,7 +11,7 @@ process:
|
|||
plugin: machine_name
|
||||
source: category
|
||||
-
|
||||
plugin: dedupe_entity
|
||||
plugin: make_unique_entity_field
|
||||
entity_type: contact_form
|
||||
field: id
|
||||
length: 32
|
||||
|
|
|
@ -11,7 +11,7 @@ process:
|
|||
user_default_enabled: contact_default_status
|
||||
'flood/limit': contact_hourly_threshold
|
||||
default_form:
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: contact_category
|
||||
source: default_category
|
||||
destination:
|
||||
|
|
|
@ -11,7 +11,7 @@ process:
|
|||
user_default_enabled: contact_default_status
|
||||
'flood/limit': contact_threshold_limit
|
||||
default_form:
|
||||
plugin: migration
|
||||
plugin: migration_lookup
|
||||
migration: contact_category
|
||||
source: default_category
|
||||
destination:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
entity-moderation-form:
|
||||
content_moderation:
|
||||
version: VERSION
|
||||
css:
|
||||
layout:
|
||||
css/entity-moderation-form.css: {}
|
||||
component:
|
||||
css/content_moderation.module.css: {}
|
||||
theme:
|
||||
css/content_moderation.theme.css: {}
|
||||
|
|
|
@ -10,7 +10,6 @@ use Drupal\content_moderation\EntityTypeInfo;
|
|||
use Drupal\content_moderation\ContentPreprocess;
|
||||
use Drupal\content_moderation\Plugin\Action\ModerationOptOutPublishNode;
|
||||
use Drupal\content_moderation\Plugin\Action\ModerationOptOutUnpublishNode;
|
||||
use Drupal\content_moderation\Plugin\Menu\EditTab;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
@ -99,22 +98,6 @@ function content_moderation_entity_update(EntityInterface $entity) {
|
|||
->entityUpdate($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_local_tasks_alter().
|
||||
*/
|
||||
function content_moderation_local_tasks_alter(&$local_tasks) {
|
||||
$content_entity_type_ids = array_keys(array_filter(\Drupal::entityTypeManager()->getDefinitions(), function (EntityTypeInterface $entity_type) {
|
||||
return $entity_type->isRevisionable();
|
||||
}));
|
||||
|
||||
foreach ($content_entity_type_ids as $content_entity_type_id) {
|
||||
if (isset($local_tasks["entity.$content_entity_type_id.edit_form"])) {
|
||||
$local_tasks["entity.$content_entity_type_id.edit_form"]['class'] = EditTab::class;
|
||||
$local_tasks["entity.$content_entity_type_id.edit_form"]['entity_type_id'] = $content_entity_type_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_alter().
|
||||
*/
|
||||
|
|
|
@ -2,7 +2,7 @@ view any unpublished content:
|
|||
title: 'View any unpublished content'
|
||||
description: 'This permission is necessary for any users that may moderate content.'
|
||||
|
||||
'view content moderation':
|
||||
view content moderation:
|
||||
title: 'View content moderation'
|
||||
description: 'View content moderation.'
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
/**
|
||||
* @file
|
||||
* Component styles for the content_moderation module.
|
||||
*/
|
||||
ul.entity-moderation-form {
|
||||
list-style: none;
|
||||
display: -webkit-flex; /* Safari */
|
||||
display: flex;
|
||||
-webkit-flex-wrap: wrap; /* Safari */
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-justify-content: space-around; /* Safari */
|
||||
justify-content: space-around;
|
||||
justify-content: space-around;
|
||||
-webkit-align-items: flex-end; /* Safari */
|
||||
align-items: flex-end;
|
||||
border-bottom: 1px solid gray;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
ul.entity-moderation-form input[type=submit] {
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* @file
|
||||
* Theme styles for the content_moderation module.
|
||||
*/
|
||||
ul.entity-moderation-form {
|
||||
border-bottom: 1px solid gray;
|
||||
}
|
|
@ -7,6 +7,8 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
use Drupal\Core\Routing\Access\AccessInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\content_moderation\ModerationInformationInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\user\EntityOwnerInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
|
@ -41,18 +43,31 @@ class LatestRevisionCheck implements AccessInterface {
|
|||
* The route to check against.
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The parametrized route.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The current user account.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*
|
||||
* @see \Drupal\Core\Entity\EntityAccessCheck
|
||||
*/
|
||||
public function access(Route $route, RouteMatchInterface $route_match) {
|
||||
public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) {
|
||||
// This tab should not show up unless there's a reason to show it.
|
||||
$entity = $this->loadEntity($route, $route_match);
|
||||
return $this->moderationInfo->hasForwardRevision($entity)
|
||||
? AccessResult::allowed()->addCacheableDependency($entity)
|
||||
: AccessResult::forbidden()->addCacheableDependency($entity);
|
||||
if ($this->moderationInfo->hasForwardRevision($entity)) {
|
||||
// Check the global permissions first.
|
||||
$access_result = AccessResult::allowedIfHasPermissions($account, ['view latest version', 'view any unpublished content']);
|
||||
if (!$access_result->isAllowed()) {
|
||||
// Check entity owner access.
|
||||
$owner_access = AccessResult::allowedIfHasPermissions($account, ['view latest version', 'view own unpublished content']);
|
||||
$owner_access = $owner_access->andIf((AccessResult::allowedIf($entity instanceof EntityOwnerInterface && ($entity->getOwnerId() == $account->id()))));
|
||||
$access_result = $access_result->orIf($owner_access);
|
||||
}
|
||||
|
||||
return $access_result->addCacheableDependency($entity);
|
||||
}
|
||||
|
||||
return AccessResult::forbidden()->addCacheableDependency($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\content_moderation;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Entity\EntityAccessControlHandler;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* The access control handler for the content_moderation_state entity type.
|
||||
*
|
||||
* @see \Drupal\content_moderation\Entity\ContentModerationState
|
||||
*/
|
||||
class ContentModerationStateAccessControlHandler extends EntityAccessControlHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
// ContentModerationState is an internal entity type. Access is denied for
|
||||
// viewing, updating, and deleting. In order to update an entity's
|
||||
// moderation state use its moderation_state field.
|
||||
return AccessResult::forbidden('ContentModerationState is an internal entity type.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
|
||||
// ContentModerationState is an internal entity type. Access is denied for
|
||||
// creating. In order to update an entity's moderation state use its
|
||||
// moderation_state field.
|
||||
return AccessResult::forbidden('ContentModerationState is an internal entity type.');
|
||||
}
|
||||
|
||||
}
|
|
@ -16,11 +16,20 @@ class ContentModerationStateStorageSchema extends SqlContentEntityStorageSchema
|
|||
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
|
||||
$schema = parent::getEntitySchema($entity_type, $reset);
|
||||
|
||||
// Creates an index to ensure that the lookup in
|
||||
// \Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList::getModerationState()
|
||||
// is performant.
|
||||
$schema['content_moderation_state_field_data']['indexes'] += [
|
||||
'content_moderation_state__lookup' => ['content_entity_type_id', 'content_entity_id', 'content_entity_revision_id'],
|
||||
// Creates unique keys to guarantee the integrity of the entity and to make
|
||||
// the lookup in ModerationStateFieldItemList::getModerationState() fast.
|
||||
$unique_keys = [
|
||||
'content_entity_type_id',
|
||||
'content_entity_id',
|
||||
'content_entity_revision_id',
|
||||
'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,
|
||||
];
|
||||
|
||||
return $schema;
|
||||
|
|
|
@ -24,6 +24,7 @@ use Drupal\user\UserInterface;
|
|||
* handlers = {
|
||||
* "storage_schema" = "Drupal\content_moderation\ContentModerationStateStorageSchema",
|
||||
* "views_data" = "\Drupal\views\EntityViewsData",
|
||||
* "access" = "Drupal\content_moderation\ContentModerationStateAccessControlHandler",
|
||||
* },
|
||||
* base_table = "content_moderation_state",
|
||||
* revision_table = "content_moderation_state_revision",
|
||||
|
@ -74,6 +75,7 @@ class ContentModerationState extends ContentEntityBase implements ContentModerat
|
|||
->setLabel(t('Content entity type ID'))
|
||||
->setDescription(t('The ID of the content entity type this moderation state is for.'))
|
||||
->setRequired(TRUE)
|
||||
->setSetting('max_length', EntityTypeInterface::ID_MAX_LENGTH)
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
$fields['content_entity_id'] = BaseFieldDefinition::create('integer')
|
||||
|
@ -82,10 +84,6 @@ class ContentModerationState extends ContentEntityBase implements ContentModerat
|
|||
->setRequired(TRUE)
|
||||
->setRevisionable(TRUE);
|
||||
|
||||
// @todo https://www.drupal.org/node/2779931 Add constraint that enforces
|
||||
// unique content_entity_type_id, content_entity_id and
|
||||
// content_entity_revision_id.
|
||||
|
||||
$fields['content_entity_revision_id'] = BaseFieldDefinition::create('integer')
|
||||
->setLabel(t('Content entity revision ID'))
|
||||
->setDescription(t('The revision ID of the content entity this moderation state is for.'))
|
||||
|
|
|
@ -105,9 +105,10 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
/** @var \Drupal\content_moderation\ContentModerationState $current_state */
|
||||
$current_state = $workflow->getState($entity->moderation_state->value);
|
||||
|
||||
// This entity is default if it is new, the default revision, or the
|
||||
// default revision is not published.
|
||||
// This entity is default if it is new, a new translation, the default
|
||||
// revision, or the default revision is not published.
|
||||
$update_default_revision = $entity->isNew()
|
||||
|| $entity->isNewTranslation()
|
||||
|| $current_state->isDefaultRevisionState()
|
||||
|| !$this->isDefaultRevisionPublished($entity, $workflow);
|
||||
|
||||
|
@ -157,7 +158,7 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
$workflow = $this->moderationInfo->getWorkflowForEntity($entity);
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
if (!$moderation_state) {
|
||||
$moderation_state = $workflow->getInitialState()->id();
|
||||
$moderation_state = $workflow->getTypePlugin()->getInitialState($workflow, $entity)->id();
|
||||
}
|
||||
|
||||
// @todo what if $entity->moderation_state is null at this point?
|
||||
|
@ -181,8 +182,9 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
]);
|
||||
$content_moderation_state->workflow->target_id = $workflow->id();
|
||||
}
|
||||
else {
|
||||
// Create a new revision.
|
||||
elseif ($content_moderation_state->content_entity_revision_id->value != $entity_revision_id) {
|
||||
// If a new revision of the content has been created, add a new content
|
||||
// moderation state revision.
|
||||
$content_moderation_state->setNewRevision(TRUE);
|
||||
}
|
||||
|
||||
|
@ -234,8 +236,7 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
if (!$this->moderationInfo->isLatestRevision($entity)) {
|
||||
return;
|
||||
}
|
||||
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
|
||||
if ($entity->isDefaultRevision()) {
|
||||
if ($this->moderationInfo->isLiveRevision($entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -250,8 +251,8 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* Check if the default revision for the given entity is published.
|
||||
*
|
||||
* The default revision is the same as the entity retrieved by "default" from
|
||||
* the storage handler. If the entity is translated, use the default revision
|
||||
* of the same language as the given entity.
|
||||
* the storage handler. If the entity is translated, check if any of the
|
||||
* translations are published.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity being saved.
|
||||
|
@ -262,21 +263,22 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* TRUE if the default revision is published. FALSE otherwise.
|
||||
*/
|
||||
protected function isDefaultRevisionPublished(EntityInterface $entity, WorkflowInterface $workflow) {
|
||||
$storage = $this->entityTypeManager->getStorage($entity->getEntityTypeId());
|
||||
$default_revision = $storage->load($entity->id());
|
||||
$default_revision = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->load($entity->id());
|
||||
|
||||
// Ensure we are comparing the same translation as the current entity.
|
||||
// Ensure we are checking all translations of the default revision.
|
||||
if ($default_revision instanceof TranslatableInterface && $default_revision->isTranslatable()) {
|
||||
// If there is no translation, then there is no default revision and is
|
||||
// therefore not published.
|
||||
if (!$default_revision->hasTranslation($entity->language()->getId())) {
|
||||
return FALSE;
|
||||
// Loop through each language that has a translation.
|
||||
foreach ($default_revision->getTranslationLanguages() as $language) {
|
||||
// Load the translated revision.
|
||||
$language_revision = $default_revision->getTranslation($language->getId());
|
||||
// Return TRUE if a translation with a published state is found.
|
||||
if ($workflow->getState($language_revision->moderation_state->value)->isPublishedState()) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
$default_revision = $default_revision->getTranslation($entity->language()->getId());
|
||||
}
|
||||
|
||||
return $default_revision && $workflow->getState($default_revision->moderation_state->value)->isPublishedState();
|
||||
return $workflow->getState($default_revision->moderation_state->value)->isPublishedState();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\content_moderation\Form;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\RevisionLogInterface;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\content_moderation\ModerationInformationInterface;
|
||||
|
@ -127,8 +128,11 @@ class EntityModerationForm extends FormBase {
|
|||
$new_state = $form_state->getValue('new_state');
|
||||
|
||||
$entity->set('moderation_state', $new_state);
|
||||
$entity->revision_log = $form_state->getValue('revision_log');
|
||||
|
||||
if ($entity instanceof RevisionLogInterface) {
|
||||
$entity->setRevisionLogMessage($form_state->getValue('revision_log'));
|
||||
$entity->setRevisionUserId($this->currentUser()->id());
|
||||
}
|
||||
$entity->save();
|
||||
|
||||
drupal_set_message($this->t('The moderation state has been updated.'));
|
||||
|
|
|
@ -98,7 +98,7 @@ class EntityRevisionConverter extends EntityConverter {
|
|||
$latest_revision = $this->entityManager->getTranslationFromContext($latest_revision, NULL, ['operation' => 'entity_upcast']);
|
||||
}
|
||||
|
||||
if ($latest_revision->isRevisionTranslationAffected()) {
|
||||
if ($latest_revision instanceof EntityInterface && $latest_revision->isRevisionTranslationAffected()) {
|
||||
$entity = $latest_revision;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,18 +109,13 @@ class ModerationStateWidget extends OptionsSelectWidget implements ContainerFact
|
|||
/** @var ContentEntityInterface $entity */
|
||||
$entity = $items->getEntity();
|
||||
|
||||
/* @var \Drupal\Core\Config\Entity\ConfigEntityInterface $bundle_entity */
|
||||
$bundle_entity = $this->entityTypeManager->getStorage($entity->getEntityType()->getBundleEntityType())->load($entity->bundle());
|
||||
if (!$this->moderationInformation->isModeratedEntity($entity)) {
|
||||
// @todo https://www.drupal.org/node/2779933 write a test for this.
|
||||
return $element + ['#access' => FALSE];
|
||||
}
|
||||
|
||||
$workflow = $this->moderationInformation->getWorkflowForEntity($entity);
|
||||
$default = $items->get($delta)->value ? $workflow->getState($items->get($delta)->value) : $workflow->getInitialState();
|
||||
if (!$default) {
|
||||
throw new \UnexpectedValueException(sprintf('The %s bundle has an invalid moderation state configuration, moderation states are enabled but no default is set.', $bundle_entity->label()));
|
||||
}
|
||||
$default = $items->get($delta)->value ? $workflow->getState($items->get($delta)->value) : $workflow->getTypePlugin()->getInitialState($workflow, $entity);
|
||||
|
||||
/** @var \Drupal\workflows\Transition[] $transitions */
|
||||
$transitions = $this->validator->getValidTransitions($entity, $this->currentUser);
|
||||
|
|
|
@ -37,8 +37,8 @@ class ModerationStateFieldItemList extends FieldItemList {
|
|||
// It is possible that the bundle does not exist at this point. For example,
|
||||
// the node type form creates a fake Node entity to get default values.
|
||||
// @see \Drupal\node\NodeTypeForm::form()
|
||||
$workflow = $moderation_info->getWorkflowForEntity($entity);
|
||||
return $workflow ? $workflow->getInitialState()->id() : NULL;
|
||||
$workflow = $moderation_info->getWorkFlowForEntity($entity);
|
||||
return $workflow ? $workflow->getTypePlugin()->getInitialState($workflow, $entity)->id() : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\content_moderation\Plugin\Menu;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Menu\LocalTaskDefault;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\content_moderation\ModerationInformation;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines a class for making the edit tab use 'Edit draft' or 'New draft'.
|
||||
*/
|
||||
class EditTab extends LocalTaskDefault implements ContainerFactoryPluginInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The moderation information service.
|
||||
*
|
||||
* @var \Drupal\content_moderation\ModerationInformation
|
||||
*/
|
||||
protected $moderationInfo;
|
||||
|
||||
/**
|
||||
* The entity if determinable from the route or FALSE.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\ContentEntityInterface|FALSE
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* Constructs a new EditTab object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* Plugin configuration.
|
||||
* @param string $plugin_id
|
||||
* Plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* Plugin definition.
|
||||
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
|
||||
* The translation service.
|
||||
* @param \Drupal\content_moderation\ModerationInformation $moderation_information
|
||||
* The moderation information.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, TranslationInterface $string_translation, ModerationInformation $moderation_information) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->stringTranslation = $string_translation;
|
||||
$this->moderationInfo = $moderation_information;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('string_translation'),
|
||||
$container->get('content_moderation.moderation_information')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRouteParameters(RouteMatchInterface $route_match) {
|
||||
$entity_parameter = $route_match->getParameter($this->pluginDefinition['entity_type_id']);
|
||||
$this->entity = $entity_parameter instanceof ContentEntityInterface ? $route_match->getParameter($this->pluginDefinition['entity_type_id']) : FALSE;
|
||||
return parent::getRouteParameters($route_match);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTitle() {
|
||||
// If the entity couldn't be loaded or moderation isn't enabled.
|
||||
if (!$this->entity || !$this->moderationInfo->isModeratedEntity($this->entity)) {
|
||||
return parent::getTitle();
|
||||
}
|
||||
|
||||
return $this->moderationInfo->isLiveRevision($this->entity)
|
||||
? $this->t('New draft')
|
||||
: $this->t('Edit draft');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTags() {
|
||||
$tags = parent::getCacheTags();
|
||||
// Tab changes if node or node-type is modified.
|
||||
if ($this->entity) {
|
||||
$tags = array_merge($tags, $this->entity->getCacheTags());
|
||||
$tags[] = $this->entity->getEntityType()->getBundleEntityType() . ':' . $this->entity->bundle();
|
||||
}
|
||||
return $tags;
|
||||
}
|
||||
|
||||
}
|
|
@ -117,7 +117,9 @@ class ModerationStateConstraintValidator extends ConstraintValidator implements
|
|||
protected function isFirstTimeModeration(EntityInterface $entity) {
|
||||
$original_entity = $this->moderationInformation->getLatestRevision($entity->getEntityTypeId(), $entity->id());
|
||||
|
||||
$original_id = $original_entity->moderation_state;
|
||||
if ($original_entity) {
|
||||
$original_id = $original_entity->moderation_state;
|
||||
}
|
||||
|
||||
return !($entity->moderation_state && $original_entity && $original_id);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Drupal\content_moderation\Plugin\WorkflowType;
|
|||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
@ -289,4 +290,14 @@ class ContentModeration extends WorkflowTypeBase implements ContainerFactoryPlug
|
|||
return $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInitialState(WorkflowInterface $workflow, $entity = NULL) {
|
||||
if ($entity instanceof EntityPublishedInterface) {
|
||||
return $workflow->getState($entity->isPublished() ? 'published' : 'draft');
|
||||
}
|
||||
return parent::getInitialState($workflow);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -81,7 +81,6 @@ class EntityModerationRouteProvider implements EntityRouteProviderInterface, Ent
|
|||
// If the entity type is a node, unpublished content will be visible
|
||||
// if the user has the "view all unpublished content" permission.
|
||||
->setRequirement('_entity_access', "{$entity_type_id}.view")
|
||||
->setRequirement('_permission', 'view latest version,view any unpublished content')
|
||||
->setRequirement('_content_moderation_latest_version', 'TRUE')
|
||||
->setOption('_content_moderation_entity_type', $entity_type_id)
|
||||
->setOption('parameters', [
|
||||
|
|
|
@ -40,7 +40,7 @@ class StateTransitionValidation implements StateTransitionValidationInterface {
|
|||
*/
|
||||
public function getValidTransitions(ContentEntityInterface $entity, AccountInterface $user) {
|
||||
$workflow = $this->moderationInfo->getWorkflowForEntity($entity);
|
||||
$current_state = $entity->moderation_state->value ? $workflow->getState($entity->moderation_state->value) : $workflow->getInitialState();
|
||||
$current_state = $entity->moderation_state->value ? $workflow->getState($entity->moderation_state->value) : $workflow->getTypePlugin()->getInitialState($workflow, $entity);
|
||||
|
||||
return array_filter($current_state->getTransitions(), function(Transition $transition) use ($workflow, $user) {
|
||||
return $user->hasPermission('use ' . $workflow->id() . ' transition ' . $transition->id());
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\content_moderation\Tests;
|
||||
|
||||
/**
|
||||
* Tests the moderation form, specifically on nodes.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ModerationFormTest extends ModerationStateTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->createContentTypeFromUi('Moderated content', 'moderated_content', TRUE);
|
||||
$this->grantUserPermissionToCreateContentOfType($this->adminUser, 'moderated_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the moderation form that shows on the latest version page.
|
||||
*
|
||||
* The latest version page only shows if there is a forward revision. There
|
||||
* is only a forward revision if a draft revision is created on a node where
|
||||
* the default revision is not a published moderation state.
|
||||
*
|
||||
* @see \Drupal\content_moderation\EntityOperations
|
||||
* @see \Drupal\content_moderation\Tests\ModerationStateBlockTest::testCustomBlockModeration
|
||||
*/
|
||||
public function testModerationForm() {
|
||||
// Create new moderated content in draft.
|
||||
$this->drupalPostForm('node/add/moderated_content', [
|
||||
'title[0][value]' => 'Some moderated content',
|
||||
'body[0][value]' => 'First version of the content.',
|
||||
], t('Save and Create New Draft'));
|
||||
|
||||
$node = $this->drupalGetNodeByTitle('Some moderated content');
|
||||
$canonical_path = sprintf('node/%d', $node->id());
|
||||
$edit_path = sprintf('node/%d/edit', $node->id());
|
||||
$latest_version_path = sprintf('node/%d/latest', $node->id());
|
||||
|
||||
$this->assertTrue($this->adminUser->hasPermission('edit any moderated_content content'));
|
||||
|
||||
// The latest version page should not show, because there is no forward
|
||||
// revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Update the draft.
|
||||
$this->drupalPostForm($edit_path, [
|
||||
'body[0][value]' => 'Second version of the content.',
|
||||
], t('Save and Create New Draft'));
|
||||
|
||||
// The latest version page should not show, because there is still no
|
||||
// forward revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Publish the draft.
|
||||
$this->drupalPostForm($edit_path, [
|
||||
'body[0][value]' => 'Third version of the content.',
|
||||
], t('Save and Publish'));
|
||||
|
||||
// The published view should not have a moderation form, because it is the
|
||||
// default revision.
|
||||
$this->drupalGet($canonical_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoText('Status', 'The node view page has no moderation form.');
|
||||
|
||||
// The latest version page should not show, because there is still no
|
||||
// forward revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Make a forward revision.
|
||||
$this->drupalPostForm($edit_path, [
|
||||
'body[0][value]' => 'Fourth version of the content.',
|
||||
], t('Save and Create New Draft'));
|
||||
|
||||
// The published view should not have a moderation form, because it is the
|
||||
// default revision.
|
||||
$this->drupalGet($canonical_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoText('Status', 'The node view page has no moderation form.');
|
||||
|
||||
// The latest version page should show the moderation form and have "Draft"
|
||||
// status, because the forward revision is in "Draft".
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Status', 'Form text found on the latest-version page.');
|
||||
$this->assertText('Draft', 'Correct status found on the latest-version page.');
|
||||
|
||||
// Submit the moderation form to change status to published.
|
||||
$this->drupalPostForm($latest_version_path, [
|
||||
'new_state' => 'published',
|
||||
], t('Apply'));
|
||||
|
||||
// The latest version page should not show, because there is no
|
||||
// forward revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\content_moderation\Tests;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Defines a base class for moderation state tests.
|
||||
*
|
||||
* @deprecated Scheduled for removal in Drupal 9.0.0.
|
||||
* Use \Drupal\Tests\content_moderation\Functional\ModerationStateTestBase instead.
|
||||
*/
|
||||
abstract class ModerationStateTestBase extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Profile to use.
|
||||
*/
|
||||
protected $profile = 'testing';
|
||||
|
||||
/**
|
||||
* Admin user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer content moderation',
|
||||
'access administration pages',
|
||||
'administer content types',
|
||||
'administer nodes',
|
||||
'view latest version',
|
||||
'view any unpublished content',
|
||||
'access content overview',
|
||||
'use editorial transition create_new_draft',
|
||||
'use editorial transition publish',
|
||||
];
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'content_moderation',
|
||||
'block',
|
||||
'block_content',
|
||||
'node',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sets the test up.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->adminUser = $this->drupalCreateUser($this->permissions);
|
||||
$this->drupalPlaceBlock('local_tasks_block', ['id' => 'tabs_block']);
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
$this->drupalPlaceBlock('local_actions_block', ['id' => 'actions_block']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the permission machine name for a transition.
|
||||
*
|
||||
* @param string $workflow_id
|
||||
* The workflow ID.
|
||||
* @param string $transition_id
|
||||
* The transition ID.
|
||||
*
|
||||
* @return string
|
||||
* The permission machine name for a transition.
|
||||
*/
|
||||
protected function getWorkflowTransitionPermission($workflow_id, $transition_id) {
|
||||
return 'use ' . $workflow_id . ' transition ' . $transition_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $workflow_id
|
||||
* The workflow to attach to the bundle.
|
||||
*/
|
||||
protected function createContentTypeFromUi($content_type_name, $content_type_id, $moderated = FALSE, $workflow_id = 'editorial') {
|
||||
$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->enableModerationThroughUi($content_type_id, $workflow_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable moderation for a specified content type, using the UI.
|
||||
*
|
||||
* @param string $content_type_id
|
||||
* Machine name.
|
||||
* @param string $workflow_id
|
||||
* The workflow to attach to the bundle.
|
||||
*/
|
||||
protected function enableModerationThroughUi($content_type_id, $workflow_id = 'editorial') {
|
||||
$edit['workflow'] = $workflow_id;
|
||||
$this->drupalPostForm('admin/structure/types/manage/' . $content_type_id . '/moderation', $edit, t('Save'));
|
||||
// Ensure the parent environment is up-to-date.
|
||||
// @see content_moderation_workflow_insert()
|
||||
\Drupal::service('entity_type.bundle.info')->clearCachedBundles();
|
||||
\Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->grantPermission(sprintf('delete any %s content', $content_type_id));
|
||||
$role->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{{ attach_library('content_moderation/entity-moderation-form') }}
|
||||
{{ attach_library('content_moderation/content_moderation') }}
|
||||
<ul class="entity-moderation-form">
|
||||
<li>{{ form.current }}</li>
|
||||
<li>{{ form.new_state }}</li>
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Functional;
|
||||
|
||||
use Drupal\simpletest\ContentTypeCreationTrait;
|
||||
use Drupal\simpletest\NodeCreationTrait;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Test the content moderation local task.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class LocalTaskTest extends BrowserTestBase {
|
||||
|
||||
use ContentTypeCreationTrait;
|
||||
use NodeCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'content_moderation_test_local_task',
|
||||
'content_moderation',
|
||||
'block',
|
||||
];
|
||||
|
||||
/**
|
||||
* A test node.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $testNode;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('local_tasks_block', ['id' => 'tabs_block']);
|
||||
$this->drupalLogin($this->createUser(['bypass node access']));
|
||||
|
||||
$node_type = $this->createContentType([
|
||||
'type' => 'test_content_type',
|
||||
]);
|
||||
|
||||
// Now enable moderation for subsequent nodes.
|
||||
$workflow = Workflow::load('editorial');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', $node_type->id());
|
||||
$workflow->save();
|
||||
|
||||
$this->testNode = $this->createNode([
|
||||
'type' => $node_type->id(),
|
||||
'moderation_state' => 'draft',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests local tasks behave with content_moderation enabled.
|
||||
*/
|
||||
public function testLocalTasks() {
|
||||
// The default state is a draft.
|
||||
$this->drupalGet(sprintf('node/%s', $this->testNode->id()));
|
||||
$this->assertTasks('Edit draft');
|
||||
|
||||
// When published as the live revision, the label changes.
|
||||
$this->testNode->moderation_state = 'published';
|
||||
$this->testNode->save();
|
||||
$this->drupalGet(sprintf('node/%s', $this->testNode->id()));
|
||||
$this->assertTasks('New draft');
|
||||
|
||||
$tags = $this->drupalGetHeader('X-Drupal-Cache-Tags');
|
||||
$this->assertContains('node:1', $tags);
|
||||
$this->assertContains('node_type:test_content_type', $tags);
|
||||
|
||||
// Without an upcast node, the state cannot be determined.
|
||||
$this->clickLink('Task Without Upcast Node');
|
||||
$this->assertTasks('Edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the correct tasks appear.
|
||||
*
|
||||
* @param string $edit_tab_label
|
||||
* The edit tab label to assert.
|
||||
*/
|
||||
protected function assertTasks($edit_tab_label) {
|
||||
$this->assertSession()->linkExists('View');
|
||||
$this->assertSession()->linkExists('Task Without Upcast Node');
|
||||
$this->assertSession()->linkExists($edit_tab_label);
|
||||
$this->assertSession()->linkExists('Delete');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Functional;
|
||||
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Tests the moderation form, specifically on nodes.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ModerationFormTest extends ModerationStateTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->createContentTypeFromUi('Moderated content', 'moderated_content', TRUE);
|
||||
$this->grantUserPermissionToCreateContentOfType($this->adminUser, 'moderated_content');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the moderation form that shows on the latest version page.
|
||||
*
|
||||
* The latest version page only shows if there is a forward revision. There
|
||||
* is only a forward revision if a draft revision is created on a node where
|
||||
* the default revision is not a published moderation state.
|
||||
*
|
||||
* @see \Drupal\content_moderation\EntityOperations
|
||||
* @see \Drupal\Tests\content_moderation\Functional\ModerationStateBlockTest::testCustomBlockModeration
|
||||
*/
|
||||
public function testModerationForm() {
|
||||
// Create new moderated content in draft.
|
||||
$this->drupalPostForm('node/add/moderated_content', [
|
||||
'title[0][value]' => 'Some moderated content',
|
||||
'body[0][value]' => 'First version of the content.',
|
||||
], t('Save and Create New Draft'));
|
||||
|
||||
$node = $this->drupalGetNodeByTitle('Some moderated content');
|
||||
$canonical_path = sprintf('node/%d', $node->id());
|
||||
$edit_path = sprintf('node/%d/edit', $node->id());
|
||||
$latest_version_path = sprintf('node/%d/latest', $node->id());
|
||||
|
||||
$this->assertTrue($this->adminUser->hasPermission('edit any moderated_content content'));
|
||||
|
||||
// The canonical view should have a moderation form, because it is not the
|
||||
// live revision.
|
||||
$this->drupalGet($canonical_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertField('edit-new-state', 'The node view page has a moderation form.');
|
||||
|
||||
// The latest version page should not show, because there is no forward
|
||||
// revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Update the draft.
|
||||
$this->drupalPostForm($edit_path, [
|
||||
'body[0][value]' => 'Second version of the content.',
|
||||
], t('Save and Create New Draft'));
|
||||
|
||||
// The canonical view should have a moderation form, because it is not the
|
||||
// live revision.
|
||||
$this->drupalGet($canonical_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertField('edit-new-state', 'The node view page has a moderation form.');
|
||||
|
||||
// The latest version page should not show, because there is still no
|
||||
// forward revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Publish the draft.
|
||||
$this->drupalPostForm($edit_path, [
|
||||
'body[0][value]' => 'Third version of the content.',
|
||||
], t('Save and Publish'));
|
||||
|
||||
// The published view should not have a moderation form, because it is the
|
||||
// live revision.
|
||||
$this->drupalGet($canonical_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoField('edit-new-state', 'The node view page has no moderation form.');
|
||||
|
||||
// The latest version page should not show, because there is still no
|
||||
// forward revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Make a forward revision.
|
||||
$this->drupalPostForm($edit_path, [
|
||||
'body[0][value]' => 'Fourth version of the content.',
|
||||
], t('Save and Create New Draft'));
|
||||
|
||||
// The published view should not have a moderation form, because it is the
|
||||
// live revision.
|
||||
$this->drupalGet($canonical_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoField('edit-new-state', 'The node view page has no moderation form.');
|
||||
|
||||
// The latest version page should show the moderation form and have "Draft"
|
||||
// status, because the forward revision is in "Draft".
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(200);
|
||||
$this->assertField('edit-new-state', 'The latest-version page has a moderation form.');
|
||||
$this->assertText('Draft', 'Correct status found on the latest-version page.');
|
||||
|
||||
// Submit the moderation form to change status to published.
|
||||
$this->drupalPostForm($latest_version_path, [
|
||||
'new_state' => 'published',
|
||||
], t('Apply'));
|
||||
|
||||
// The latest version page should not show, because there is no
|
||||
// forward revision.
|
||||
$this->drupalGet($latest_version_path);
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test moderation non-bundle entity type.
|
||||
*/
|
||||
public function testNonBundleModerationForm() {
|
||||
$this->drupalLogin($this->rootUser);
|
||||
$workflow = Workflow::load('editorial');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_mulrevpub', 'entity_test_mulrevpub');
|
||||
$workflow->save();
|
||||
|
||||
// Create new moderated content in draft.
|
||||
$this->drupalPostForm('entity_test_mulrevpub/add', [], t('Save and Create New Draft'));
|
||||
|
||||
// The latest version page should not show, because there is no forward
|
||||
// revision.
|
||||
$this->drupalGet('/entity_test_mulrevpub/manage/1/latest');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Update the draft.
|
||||
$this->drupalPostForm('entity_test_mulrevpub/manage/1/edit', [], t('Save and Create New Draft'));
|
||||
|
||||
// The latest version page should not show, because there is still no
|
||||
// forward revision.
|
||||
$this->drupalGet('/entity_test_mulrevpub/manage/1/latest');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Publish the draft.
|
||||
$this->drupalPostForm('entity_test_mulrevpub/manage/1/edit', [], t('Save and Publish'));
|
||||
|
||||
// The published view should not have a moderation form, because it is the
|
||||
// default revision.
|
||||
$this->drupalGet('entity_test_mulrevpub/manage/1');
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoText('Status', 'The node view page has no moderation form.');
|
||||
|
||||
// The latest version page should not show, because there is still no
|
||||
// forward revision.
|
||||
$this->drupalGet('entity_test_mulrevpub/manage/1/latest');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Make a forward revision.
|
||||
$this->drupalPostForm('entity_test_mulrevpub/manage/1/edit', [], t('Save and Create New Draft'));
|
||||
|
||||
// The published view should not have a moderation form, because it is the
|
||||
// default revision.
|
||||
$this->drupalGet('entity_test_mulrevpub/manage/1');
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoText('Status', 'The node view page has no moderation form.');
|
||||
|
||||
// The latest version page should show the moderation form and have "Draft"
|
||||
// status, because the forward revision is in "Draft".
|
||||
$this->drupalGet('entity_test_mulrevpub/manage/1/latest');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Status', 'Form text found on the latest-version page.');
|
||||
$this->assertText('Draft', 'Correct status found on the latest-version page.');
|
||||
|
||||
// Submit the moderation form to change status to published.
|
||||
$this->drupalPostForm('entity_test_mulrevpub/manage/1/latest', [
|
||||
'new_state' => 'published',
|
||||
], t('Apply'));
|
||||
|
||||
// The latest version page should not show, because there is no
|
||||
// forward revision.
|
||||
$this->drupalGet('entity_test_mulrevpub/manage/1/latest');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the revision author is updated when the moderation form is used.
|
||||
*/
|
||||
public function testModerationFormSetsRevisionAuthor() {
|
||||
// Create new moderated content in published.
|
||||
$node = $this->createNode(['type' => 'moderated_content', 'moderation_state' => 'published']);
|
||||
// Make a forward revision.
|
||||
$node->title = $this->randomMachineName();
|
||||
$node->moderation_state->value = 'draft';
|
||||
$node->save();
|
||||
|
||||
$another_user = $this->drupalCreateUser($this->permissions);
|
||||
$this->grantUserPermissionToCreateContentOfType($another_user, 'moderated_content');
|
||||
$this->drupalLogin($another_user);
|
||||
$this->drupalPostForm(sprintf('node/%d/latest', $node->id()), [
|
||||
'new_state' => 'published',
|
||||
], t('Apply'));
|
||||
|
||||
$this->drupalGet(sprintf('node/%d/revisions', $node->id()));
|
||||
$this->assertText('by ' . $another_user->getAccountName());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Functional;
|
||||
|
||||
use Drupal\simpletest\ContentTypeCreationTrait;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Test revision revert.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ModerationRevisionRevertTest extends BrowserTestBase {
|
||||
|
||||
use ContentTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'content_moderation',
|
||||
'node',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$moderated_bundle = $this->createContentType(['type' => 'moderated_bundle']);
|
||||
$moderated_bundle->save();
|
||||
|
||||
$workflow = Workflow::load('editorial');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'moderated_bundle');
|
||||
$workflow->save();
|
||||
|
||||
$admin = $this->drupalCreateUser([
|
||||
'access content overview',
|
||||
'administer nodes',
|
||||
'bypass node access',
|
||||
'view all revisions',
|
||||
'view content moderation',
|
||||
'use editorial transition create_new_draft',
|
||||
'use editorial transition publish',
|
||||
]);
|
||||
$this->drupalLogin($admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that reverting a revision works.
|
||||
*/
|
||||
public function testEditingAfterRevertRevision() {
|
||||
// Create a draft.
|
||||
$this->drupalPostForm('node/add/moderated_bundle', ['title[0][value]' => 'First draft node'], t('Save and Create New Draft'));
|
||||
|
||||
// Now make it published.
|
||||
$this->drupalPostForm('node/1/edit', ['title[0][value]' => 'Published node'], t('Save and Publish'));
|
||||
|
||||
// Check the editing form that show the published title.
|
||||
$this->drupalGet('node/1/edit');
|
||||
$this->assertSession()
|
||||
->pageTextContains('Published node');
|
||||
|
||||
// Revert the first revision.
|
||||
$revision_url = 'node/1/revisions/1/revert';
|
||||
$this->drupalGet($revision_url);
|
||||
$this->assertSession()->elementExists('css', '.form-submit');
|
||||
$this->click('.form-submit');
|
||||
|
||||
// Check that it reverted.
|
||||
$this->drupalGet('node/1/edit');
|
||||
$this->assertSession()
|
||||
->pageTextContains('First draft node');
|
||||
// Try to save the node.
|
||||
$this->click('.moderation-state-draft > input');
|
||||
|
||||
// Check if the submission passed the EntityChangedConstraintValidator.
|
||||
$this->assertSession()
|
||||
->pageTextNotContains('The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.');
|
||||
|
||||
// Check the node has been saved.
|
||||
$this->assertSession()
|
||||
->pageTextContains('moderated_bundle First draft node has been updated');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\content_moderation\Tests;
|
||||
namespace Drupal\Tests\content_moderation\Functional;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\content_moderation\Tests;
|
||||
namespace Drupal\Tests\content_moderation\Functional;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\node\Entity\Node;
|
||||
|
@ -132,7 +132,7 @@ class ModerationStateNodeTest extends ModerationStateTestBase {
|
|||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/content');
|
||||
$element = $this->cssSelect('nav.pager li.is-active a');
|
||||
$url = (string) $element[0]['href'];
|
||||
$url = $element[0]->getAttribute('href');
|
||||
$query = [];
|
||||
parse_str(parse_url($url, PHP_URL_QUERY), $query);
|
||||
$this->assertEqual(0, $query['page']);
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\content_moderation\Tests;
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Functional;
|
||||
|
||||
/**
|
||||
* Tests moderation state node type integration.
|
||||
|
@ -30,10 +29,25 @@ class ModerationStateNodeTypeTest extends ModerationStateTestBase {
|
|||
* Tests enabling moderation on an existing node-type, with content.
|
||||
*/
|
||||
public function testEnablingOnExistingContent() {
|
||||
$editor_permissions = [
|
||||
'administer content moderation',
|
||||
'access administration pages',
|
||||
'administer content types',
|
||||
'administer nodes',
|
||||
'view latest version',
|
||||
'view any unpublished content',
|
||||
'access content overview',
|
||||
'use editorial transition create_new_draft',
|
||||
];
|
||||
$publish_permissions = array_merge($editor_permissions, ['use editorial transition publish']);
|
||||
$editor = $this->drupalCreateUser($editor_permissions);
|
||||
$editor_with_publish = $this->drupalCreateUser($publish_permissions);
|
||||
|
||||
// Create a node type that is not moderated.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalLogin($editor);
|
||||
$this->createContentTypeFromUi('Not moderated', 'not_moderated');
|
||||
$this->grantUserPermissionToCreateContentOfType($this->adminUser, 'not_moderated');
|
||||
$this->grantUserPermissionToCreateContentOfType($editor, 'not_moderated');
|
||||
$this->grantUserPermissionToCreateContentOfType($editor_with_publish, 'not_moderated');
|
||||
|
||||
// Create content.
|
||||
$this->drupalGet('node/add/not_moderated');
|
||||
|
@ -68,7 +82,13 @@ class ModerationStateNodeTypeTest extends ModerationStateTestBase {
|
|||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertResponse(200);
|
||||
$this->assertRaw('Save and Create New Draft');
|
||||
$this->assertNoRaw('Save and publish');
|
||||
$this->assertNoRaw('Save and Publish');
|
||||
|
||||
$this->drupalLogin($editor_with_publish);
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->assertResponse(200);
|
||||
$this->assertRaw('Save and Create New Draft');
|
||||
$this->assertRaw('Save and Publish');
|
||||
}
|
||||
|
||||
}
|
|
@ -50,6 +50,7 @@ abstract class ModerationStateTestBase extends BrowserTestBase {
|
|||
'block',
|
||||
'block_content',
|
||||
'node',
|
||||
'entity_test',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,37 @@ namespace Drupal\Tests\content_moderation\Functional;
|
|||
*/
|
||||
class NodeAccessTest extends ModerationStateTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'content_moderation',
|
||||
'block',
|
||||
'block_content',
|
||||
'node',
|
||||
'node_access_test_empty',
|
||||
];
|
||||
|
||||
/**
|
||||
* Permissions to grant admin user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'administer content moderation',
|
||||
'access administration pages',
|
||||
'administer content types',
|
||||
'administer nodes',
|
||||
'view latest version',
|
||||
'view any unpublished content',
|
||||
'access content overview',
|
||||
'use editorial transition create_new_draft',
|
||||
'use editorial transition publish',
|
||||
'bypass node access',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -17,6 +48,10 @@ class NodeAccessTest extends ModerationStateTestBase {
|
|||
$this->drupalLogin($this->adminUser);
|
||||
$this->createContentTypeFromUi('Moderated content', 'moderated_content', TRUE);
|
||||
$this->grantUserPermissionToCreateContentOfType($this->adminUser, 'moderated_content');
|
||||
|
||||
// Rebuild permissions because hook_node_grants() is implemented by the
|
||||
// node_access_test_empty module.
|
||||
node_access_rebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,7 +73,24 @@ class NodeAccessTest extends ModerationStateTestBase {
|
|||
$edit_path = 'node/' . $node->id() . '/edit';
|
||||
$latest_path = 'node/' . $node->id() . '/latest';
|
||||
|
||||
// Now make a new user and verify that the new user's access is correct.
|
||||
$user = $this->createUser([
|
||||
'use editorial transition create_new_draft',
|
||||
'view latest version',
|
||||
'view any unpublished content',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$this->drupalGet($edit_path);
|
||||
$this->assertResponse(403);
|
||||
|
||||
$this->drupalGet($latest_path);
|
||||
$this->assertResponse(403);
|
||||
$this->drupalGet($view_path);
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Publish the node.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalPostForm($edit_path, [], t('Save and Publish'));
|
||||
|
||||
// Ensure access works correctly for anonymous users.
|
||||
|
@ -58,12 +110,6 @@ class NodeAccessTest extends ModerationStateTestBase {
|
|||
'title[0][value]' => 'moderated content revised',
|
||||
], t('Save and Create New Draft'));
|
||||
|
||||
// Now make a new user and verify that the new user's access is correct.
|
||||
$user = $this->createUser([
|
||||
'use editorial transition create_new_draft',
|
||||
'view latest version',
|
||||
'view any unpublished content',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$this->drupalGet($edit_path);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
use Drupal\content_moderation\Entity\ContentModerationState;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\content_moderation\ContentModerationStateAccessControlHandler
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ContentModerationStateAccessControlHandlerTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'content_moderation',
|
||||
'workflows',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The content_moderation_state access control handler.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface
|
||||
*/
|
||||
protected $accessControlHandler;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
$this->installEntitySchema('user');
|
||||
$this->accessControlHandler = $this->container->get('entity_type.manager')->getAccessControlHandler('content_moderation_state');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::checkAccess
|
||||
* @covers ::checkCreateAccess
|
||||
*/
|
||||
public function testHandler() {
|
||||
$entity = ContentModerationState::create([]);
|
||||
$this->assertFalse($this->accessControlHandler->access($entity, 'view'));
|
||||
$this->assertFalse($this->accessControlHandler->access($entity, 'update'));
|
||||
$this->assertFalse($this->accessControlHandler->access($entity, 'delete'));
|
||||
$this->assertFalse($this->accessControlHandler->createAccess());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Test the ContentModerationState storage schema.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\content_moderation\ContentModerationStateStorageSchema
|
||||
* @group content_moderation
|
||||
*/
|
||||
class ContentModerationStateStorageSchemaTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'node',
|
||||
'content_moderation',
|
||||
'user',
|
||||
'system',
|
||||
'text',
|
||||
'workflows',
|
||||
'entity_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installSchema('node', 'node_access');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('entity_test');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
$this->installConfig('content_moderation');
|
||||
|
||||
NodeType::create([
|
||||
'type' => 'example',
|
||||
])->save();
|
||||
$workflow = Workflow::load('editorial');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
|
||||
$workflow->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the ContentModerationState unique keys.
|
||||
*
|
||||
* @covers ::getEntitySchema
|
||||
*/
|
||||
public function testUniqueKeys() {
|
||||
// Create a node which will create a new ContentModerationState entity.
|
||||
$node = Node::create([
|
||||
'title' => 'Test title',
|
||||
'type' => 'example',
|
||||
'moderation_state' => 'draft',
|
||||
]);
|
||||
$node->save();
|
||||
|
||||
// Ensure an exception when all values match.
|
||||
$this->assertStorageException([
|
||||
'content_entity_type_id' => $node->getEntityTypeId(),
|
||||
'content_entity_id' => $node->id(),
|
||||
'content_entity_revision_id' => $node->getRevisionId(),
|
||||
], TRUE);
|
||||
|
||||
// No exception for the same values, with a different langcode.
|
||||
$this->assertStorageException([
|
||||
'content_entity_type_id' => $node->getEntityTypeId(),
|
||||
'content_entity_id' => $node->id(),
|
||||
'content_entity_revision_id' => $node->getRevisionId(),
|
||||
'langcode' => 'de',
|
||||
], FALSE);
|
||||
|
||||
// A different workflow should not trigger an exception.
|
||||
$this->assertStorageException([
|
||||
'content_entity_type_id' => $node->getEntityTypeId(),
|
||||
'content_entity_id' => $node->id(),
|
||||
'content_entity_revision_id' => $node->getRevisionId(),
|
||||
'workflow' => 'foo',
|
||||
], FALSE);
|
||||
|
||||
// Different entity types should not trigger an exception.
|
||||
$this->assertStorageException([
|
||||
'content_entity_type_id' => 'entity_test',
|
||||
'content_entity_id' => $node->id(),
|
||||
'content_entity_revision_id' => $node->getRevisionId(),
|
||||
], FALSE);
|
||||
|
||||
// Different entity and revision IDs should not trigger an exception.
|
||||
$this->assertStorageException([
|
||||
'content_entity_type_id' => $node->getEntityTypeId(),
|
||||
'content_entity_id' => 9999,
|
||||
'content_entity_revision_id' => 9999,
|
||||
], FALSE);
|
||||
|
||||
// Creating a version of the entity with a previously used, but not current
|
||||
// revision ID should trigger an exception.
|
||||
$old_revision_id = $node->getRevisionId();
|
||||
$node->setNewRevision(TRUE);
|
||||
$node->title = 'Updated title';
|
||||
$node->moderation_state = 'published';
|
||||
$node->save();
|
||||
$this->assertStorageException([
|
||||
'content_entity_type_id' => $node->getEntityTypeId(),
|
||||
'content_entity_id' => $node->id(),
|
||||
'content_entity_revision_id' => $old_revision_id,
|
||||
], TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert if a storage exception is triggered when saving a given entity.
|
||||
*
|
||||
* @param array $values
|
||||
* An array of entity values.
|
||||
* @param bool $has_exception
|
||||
* If an exception should be triggered when saving the entity.
|
||||
*/
|
||||
protected function assertStorageException(array $values, $has_exception) {
|
||||
$defaults = [
|
||||
'moderation_state' => 'draft',
|
||||
'workflow' => 'editorial',
|
||||
];
|
||||
$entity = ContentModerationState::create($values + $defaults);
|
||||
$exception_triggered = FALSE;
|
||||
try {
|
||||
ContentModerationState::updateOrCreateFromEntity($entity);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$exception_triggered = TRUE;
|
||||
}
|
||||
$this->assertEquals($has_exception, $exception_triggered);
|
||||
}
|
||||
|
||||
}
|
|
@ -53,6 +53,7 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('entity_test_with_bundle');
|
||||
$this->installEntitySchema('entity_test_rev');
|
||||
$this->installEntitySchema('entity_test_no_bundle');
|
||||
$this->installEntitySchema('entity_test_mulrevpub');
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
|
@ -94,6 +95,9 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
'title' => 'Test title',
|
||||
$this->entityTypeManager->getDefinition($entity_type_id)->getKey('bundle') => $bundle_id,
|
||||
]);
|
||||
if ($entity instanceof EntityPublishedInterface) {
|
||||
$entity->setUnpublished();
|
||||
}
|
||||
$entity->save();
|
||||
$entity = $this->reloadEntity($entity);
|
||||
$this->assertEquals('draft', $entity->moderation_state->value);
|
||||
|
@ -178,7 +182,10 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
],
|
||||
'Entity Test with revisions' => [
|
||||
'entity_test_rev',
|
||||
]
|
||||
],
|
||||
'Entity without bundle' => [
|
||||
'entity_test_no_bundle',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -400,6 +407,7 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
// 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');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_no_bundle', 'entity_test_no_bundle');
|
||||
$workflow->save();
|
||||
|
||||
$this->assertEquals([
|
||||
|
@ -412,9 +420,11 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
],
|
||||
], $workflow->getDependencies());
|
||||
|
||||
$entity_types = $workflow->getTypePlugin()->getEntityTypes();
|
||||
$this->assertTrue(in_array('node', $entity_types));
|
||||
$this->assertTrue(in_array('entity_test_rev', $entity_types));
|
||||
$this->assertEquals([
|
||||
'entity_test_no_bundle',
|
||||
'entity_test_rev',
|
||||
'node'
|
||||
], $workflow->getTypePlugin()->getEntityTypes());
|
||||
|
||||
// Delete the node type and ensure it is removed from the workflow.
|
||||
$node_type->delete();
|
||||
|
@ -426,7 +436,7 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
$this->container->get('config.manager')->uninstall('module', 'entity_test');
|
||||
$workflow = Workflow::load('editorial');
|
||||
$entity_types = $workflow->getTypePlugin()->getEntityTypes();
|
||||
$this->assertFalse(in_array('entity_test_rev', $entity_types));
|
||||
$this->assertEquals([], $entity_types);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Tests the correct default revision is set.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class DefaultRevisionStateTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'entity_test',
|
||||
'node',
|
||||
'block_content',
|
||||
'content_moderation',
|
||||
'user',
|
||||
'system',
|
||||
'language',
|
||||
'content_translation',
|
||||
'text',
|
||||
'workflows',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityTypeManager
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installSchema('node', 'node_access');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('entity_test_with_bundle');
|
||||
$this->installEntitySchema('entity_test_rev');
|
||||
$this->installEntitySchema('entity_test_mulrevpub');
|
||||
$this->installEntitySchema('block_content');
|
||||
$this->installEntitySchema('content_moderation_state');
|
||||
$this->installConfig('content_moderation');
|
||||
|
||||
$this->entityTypeManager = $this->container->get('entity_type.manager');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a translatable Node.
|
||||
*/
|
||||
public function testMultilingual() {
|
||||
// Enable French.
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
$node_type = NodeType::create([
|
||||
'type' => 'example',
|
||||
]);
|
||||
$node_type->save();
|
||||
|
||||
$this->container->get('content_translation.manager')->setEnabled('node', 'example', TRUE);
|
||||
|
||||
$workflow = Workflow::load('editorial');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
|
||||
$workflow->save();
|
||||
|
||||
$english_node = Node::create([
|
||||
'type' => 'example',
|
||||
'title' => 'Test title',
|
||||
]);
|
||||
// Revision 1 (en).
|
||||
$english_node
|
||||
->setUnpublished()
|
||||
->save();
|
||||
$this->assertEquals('draft', $english_node->moderation_state->value);
|
||||
$this->assertFalse($english_node->isPublished());
|
||||
$this->assertTrue($english_node->isDefaultRevision());
|
||||
|
||||
// Revision 2 (fr)
|
||||
$french_node = $english_node->addTranslation('fr', ['title' => 'French title']);
|
||||
$french_node->moderation_state->value = 'published';
|
||||
$french_node->save();
|
||||
$this->assertTrue($french_node->isPublished());
|
||||
$this->assertTrue($french_node->isDefaultRevision());
|
||||
|
||||
// Revision 3 (fr)
|
||||
$node = Node::load($english_node->id())->getTranslation('fr');
|
||||
$node->moderation_state->value = 'draft';
|
||||
$node->save();
|
||||
$this->assertFalse($node->isPublished());
|
||||
$this->assertFalse($node->isDefaultRevision());
|
||||
|
||||
// Revision 4 (en)
|
||||
$latest_revision = $this->entityTypeManager->getStorage('node')->loadRevision(3);
|
||||
$latest_revision->moderation_state->value = 'draft';
|
||||
$latest_revision->save();
|
||||
$this->assertFalse($latest_revision->isPublished());
|
||||
$this->assertFalse($latest_revision->isDefaultRevision());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\content_moderation\Kernel;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests the correct initial states are set on install.
|
||||
*
|
||||
* @group content_moderation
|
||||
*/
|
||||
class InitialStateTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'entity_test',
|
||||
'node',
|
||||
'user',
|
||||
'system',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installSchema('node', 'node_access');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installEntitySchema('entity_test_rev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the correct initial state.
|
||||
*/
|
||||
public function testInitialState() {
|
||||
$node_type = NodeType::create([
|
||||
'type' => 'example',
|
||||
]);
|
||||
$node_type->save();
|
||||
|
||||
// Test with an entity type that implements EntityPublishedInterface.
|
||||
$unpublished_node = Node::create([
|
||||
'type' => 'example',
|
||||
'title' => 'Unpublished node',
|
||||
'status' => 0,
|
||||
]);
|
||||
$unpublished_node->save();
|
||||
|
||||
$published_node = Node::create([
|
||||
'type' => 'example',
|
||||
'title' => 'Published node',
|
||||
'status' => 1,
|
||||
]);
|
||||
$published_node->save();
|
||||
|
||||
// Test with an entity type that doesn't implement EntityPublishedInterface.
|
||||
$entity_test = EntityTestRev::create();
|
||||
$entity_test->save();
|
||||
|
||||
\Drupal::service('module_installer')->install(['content_moderation'], TRUE);
|
||||
$workflow = Workflow::load('editorial');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
|
||||
$workflow->save();
|
||||
|
||||
$loaded_unpublished_node = Node::load($unpublished_node->id());
|
||||
$loaded_published_node = Node::load($published_node->id());
|
||||
$loaded_entity_test = EntityTestRev::load($entity_test->id());
|
||||
$this->assertEquals('draft', $loaded_unpublished_node->moderation_state->value);
|
||||
$this->assertEquals('published', $loaded_published_node->moderation_state->value);
|
||||
$this->assertEquals('draft', $loaded_entity_test->moderation_state->value);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue