diff --git a/core/modules/layout_builder/layout_builder.post_update.php b/core/modules/layout_builder/layout_builder.post_update.php index 54e2f0355c..69c733a214 100644 --- a/core/modules/layout_builder/layout_builder.post_update.php +++ b/core/modules/layout_builder/layout_builder.post_update.php @@ -300,7 +300,6 @@ function _layout_builder_bundle_has_no_translations($entity_type_id, $bundle) { return FALSE; } - /** * Adds the layout translation settings field. */ diff --git a/core/modules/layout_builder/src/Element/LayoutBuilder.php b/core/modules/layout_builder/src/Element/LayoutBuilder.php index 9d6018443e..be0f2f2227 100644 --- a/core/modules/layout_builder/src/Element/LayoutBuilder.php +++ b/core/modules/layout_builder/src/Element/LayoutBuilder.php @@ -288,9 +288,7 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s $build[$region][$uuid]['#attributes']['class'][] = 'layout-builder-block'; $build[$region][$uuid]['#attributes']['data-layout-block-uuid'] = $uuid; $build[$region][$uuid]['#attributes']['data-layout-builder-highlight-id'] = $this->blockUpdateHighlightId($uuid); - if ($contextual_link_element = $this->createContextualLinkElement($section_storage, $delta, $region, $uuid)) { - $build[$region][$uuid]['#contextual_links'] = $contextual_link_element; - } + $build[$region][$uuid]['#contextual_links'] = $this->createContextualLinkElement($section_storage, $delta, $region, $uuid); } } @@ -438,10 +436,8 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s * * @return array|null * The contextual link render array or NULL if none. - * */ protected function createContextualLinkElement(SectionStorageInterface $section_storage, $delta, $region, $uuid) { - $contextual_link_element = NULL; $section = $section_storage->getSection($delta); $contextual_link_settings = [ 'route_parameters' => [ @@ -453,8 +449,8 @@ protected function createContextualLinkElement(SectionStorageInterface $section_ ], ]; if (static::isTranslation($section_storage)) { - $component = $section->getComponent($uuid); $contextual_group = 'layout_builder_block_translation'; + $component = $section->getComponent($uuid); /** @var \Drupal\Core\Language\LanguageInterface $language */ if ($language = $section_storage->getTranslationLanguage()) { $contextual_link_settings['route_parameters']['langcode'] = $language->getId(); @@ -473,6 +469,7 @@ protected function createContextualLinkElement(SectionStorageInterface $section_ } } else { + $contextual_group = 'layout_builder_block'; // Add metadata about the current operations available in // contextual links. This will invalidate the client-side cache of // links that were cached before the 'move' link was added. @@ -480,15 +477,10 @@ protected function createContextualLinkElement(SectionStorageInterface $section_ $contextual_link_settings['metadata'] = [ 'operations' => 'move:update:remove', ]; - $contextual_group = 'layout_builder_block'; } - if (isset($contextual_group)) { - $contextual_link_element = [ - $contextual_group => $contextual_link_settings, - ]; - - } - return $contextual_link_element; + return [ + $contextual_group => $contextual_link_settings, + ]; } } diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTranslationTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTranslationTest.php index 5e7e6da31d..65ce223d08 100644 --- a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTranslationTest.php +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTranslationTest.php @@ -156,7 +156,6 @@ public function testTranslatableLayoutField() { $field_config->setTranslatable(TRUE); $this->assertNotEmpty($field_config->save()); - $entity_url = $this->entity->toUrl('canonical')->toString(); $layout_url = $entity_url . '/layout'; $language = \Drupal::languageManager()->getLanguage($this->langcodes[2]); @@ -202,7 +201,6 @@ public function testTranslatableLayoutField() { $this->drupalGet($entity_url); $assert_session->pageTextContains('Powered by Drupal'); - // Confirm the translation layout is still not allowed. $this->drupalGet($translated_layout_url); @@ -219,6 +217,7 @@ public function testTranslatableLayoutField() { $assert_session->pageTextNotContains('Access denied'); $assert_session->buttonExists('Save layout'); } + /** * The entity used for testing. * diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/JavascriptTranslationTestTrait.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/JavascriptTranslationTestTrait.php index 6cf00e9e17..83a5d1de84 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/JavascriptTranslationTestTrait.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/JavascriptTranslationTestTrait.php @@ -7,27 +7,39 @@ */ trait JavascriptTranslationTestTrait { + /** + * Whether the test is using config_translation. + * + * @var bool + */ + protected $usingConfigTranslation = FALSE; + /** * Updates a block label translation. * * @param string $block_selector * The CSS selector for the block. - * @param string $expected_label - * The label that is expected. + * @param string $untranslated_label + * The label untranslated. * @param string $new_label * The new label to set. + * @param string $expected_label + * The expected existing translated label. * @param array $unexpected_element_selectors * A list of selectors for elements that should be present. */ protected function updateBlockTranslation($block_selector, $untranslated_label, $new_label, $expected_label = '', array $unexpected_element_selectors = []) { /** @var \Drupal\Tests\WebAssert $assert_session */ $assert_session = $this->assertSession(); + /** @var \Behat\Mink\Element\DocumentElement $page */ $page = $this->getSession()->getPage(); + + $translation_selector_prefix = $this->usingConfigTranslation ? '#drupal-off-canvas .translation-set ' : '#drupal-off-canvas '; $this->clickContextualLink($block_selector, 'Translate block'); - $label_input = $assert_session->waitForElementVisible('css', '#drupal-off-canvas [name="translation[label]"]'); + $label_input = $assert_session->waitForElementVisible('css', $translation_selector_prefix . '[name="translation[label]"]'); $this->assertNotEmpty($label_input); $this->assertEquals($expected_label, $label_input->getValue()); - $assert_session->elementTextContains('css', '#drupal-off-canvas .form-item-source-label', $untranslated_label); + $assert_session->elementTextContains('css', $translation_selector_prefix . '.form-item-source-label', $untranslated_label); $label_input->setValue($new_label); foreach ($unexpected_element_selectors as $unexpected_element_selector) { $assert_session->elementNotExists('css', $unexpected_element_selector); diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php index 541d9f1b5e..64b69b0c61 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/TranslationTest.php @@ -94,13 +94,30 @@ protected function setUp() { ); } + /** + * DataProvider for testLabelTranslation(). + */ + public function providerLabelTranslation() { + return [ + 'with config_translation' => [TRUE], + 'without config_translation' => [FALSE], + ]; + } + /** * Tests that block labels can be translated. + * + * @dataProvider providerLabelTranslation */ - public function testLabelTranslation() { + public function testLabelTranslation($install_config_translation) { $page = $this->getSession()->getPage(); $assert_session = $this->assertSession(); + $this->usingConfigTranslation = $install_config_translation; + if ($install_config_translation) { + $this->container->get('module_installer')->install(['config_translation']); + } + $this->drupalLogin($this->drupalCreateUser([ 'access contextual links', 'configure any layout', diff --git a/core/modules/media_library/media_library.module b/core/modules/media_library/media_library.module index f6aa3b4394..f0c8186d9d 100644 --- a/core/modules/media_library/media_library.module +++ b/core/modules/media_library/media_library.module @@ -70,7 +70,21 @@ function media_library_views_post_render(ViewExecutable $view, &$output, CachePl if ($view->id() === 'media_library') { $output['#attached']['library'][] = 'media_library/view'; if (strpos($view->current_display, 'widget') === 0) { - $query = MediaLibraryState::fromRequest($view->getRequest())->all(); + try { + $query = MediaLibraryState::fromRequest($view->getRequest())->all(); + } + catch (InvalidArgumentException $e) { + // MediaLibraryState::fromRequest() will throw an exception if the view + // is being previewed, since not all required query parameters will be + // present. In a preview, however, this can be omitted since we're + // merely previewing. + // @todo Use the views API for checking for the preview mode when it + // lands. https://www.drupal.org/project/drupal/issues/3060855 + if (empty($view->preview) && empty($view->live_preview)) { + throw $e; + } + } + // If the current query contains any parameters we use to contextually // filter the view, ensure they persist across AJAX rebuilds. // The ajax_path is shared for all AJAX views on the page, but our query diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php index 8667844e80..9d54f6a43a 100644 --- a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php +++ b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php @@ -26,7 +26,13 @@ class MediaLibraryTest extends WebDriverTestBase { /** * {@inheritdoc} */ - protected static $modules = ['block', 'media_library_test', 'field_ui']; + protected static $modules = [ + 'block', + 'media_library_test', + 'field_ui', + 'views', + 'views_ui', + ]; /** * {@inheritdoc} @@ -73,6 +79,7 @@ protected function setUp() { 'delete any media', 'view media', 'administer node form display', + 'administer views', ]); $this->drupalLogin($user); $this->drupalPlaceBlock('local_tasks_block'); @@ -272,6 +279,43 @@ public function testWidgetWithoutMediaTypes() { $assert_session->elementNotExists('css', '.media-library-open-button[name^="field_null_types_media"]'); } + /** + * Tests that the integration with Views works correctly. + */ + public function testViewsAdmin() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + // Assert that the widget can be seen and that there are 8 items. + $this->drupalGet('/admin/structure/views/view/media_library/edit/widget'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->elementsCount('css', '.media-library-item', 8); + + // Assert that filtering works in live preview. + $page->find('css', '.media-library-view .view-filters')->fillField('name', 'snake'); + $page->find('css', '.media-library-view .view-filters')->pressButton('Apply filters'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->elementsCount('css', '.media-library-item', 1); + + // Test the same routine but in the view for the table wiget. + $this->drupalGet('/admin/structure/views/view/media_library/edit/widget_table'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->elementsCount('css', '.media-library-item', 8); + + // Assert that filtering works in live preview. + $page->find('css', '.media-library-view .view-filters')->fillField('name', 'snake'); + $page->find('css', '.media-library-view .view-filters')->pressButton('Apply filters'); + $assert_session->assertWaitOnAjaxRequest(); + $assert_session->elementsCount('css', '.media-library-item', 1); + + // We cannot test clicking the 'Insert selected' button in either view + // because we expect an AJAX error, which would always throw an exception + // on ::tearDown even if we try to catch it here. If there is an API for + // marking certain elements 'unsuitable for previewing', we could test that + // here. + // @see https://www.drupal.org/project/drupal/issues/3060852 + } + /** * Tests that the widget access works as expected. */