diff --git a/config/optional/block.block.oe_whitelabel_branding.yml b/config/optional/block.block.oe_whitelabel_branding.yml index 4964f51fab8952fea9d923b0c807aac2a3c83e69..e860d6197e4cf0911984eb98b465d32a735fa3b6 100644 --- a/config/optional/block.block.oe_whitelabel_branding.yml +++ b/config/optional/block.block.oe_whitelabel_branding.yml @@ -14,8 +14,8 @@ plugin: system_branding_block settings: id: system_branding_block label: 'Site branding' - provider: system label_display: '0' + provider: system use_site_logo: true use_site_name: true use_site_slogan: true diff --git a/config/optional/block.block.oe_whitelabel_breadcrumbs.yml b/config/optional/block.block.oe_whitelabel_breadcrumbs.yml index 23f53fc397172940c16e33bbde491d518679315b..6f028eaf455e6ff1486758fdaac6e5ac5db26ae4 100644 --- a/config/optional/block.block.oe_whitelabel_breadcrumbs.yml +++ b/config/optional/block.block.oe_whitelabel_breadcrumbs.yml @@ -14,6 +14,6 @@ plugin: system_breadcrumb_block settings: id: system_breadcrumb_block label: Breadcrumbs - provider: system label_display: '0' + provider: system visibility: { } diff --git a/config/optional/block.block.oe_whitelabel_ec_corporate_footer.yml b/config/optional/block.block.oe_whitelabel_ec_corporate_footer.yml index d52ef57935895e1a13ef3600f215c23beb2f1393..b671493d2a4c2185ff9aa9690ad571b7211ac4c6 100644 --- a/config/optional/block.block.oe_whitelabel_ec_corporate_footer.yml +++ b/config/optional/block.block.oe_whitelabel_ec_corporate_footer.yml @@ -3,6 +3,7 @@ status: true dependencies: module: - oe_corporate_blocks + - oe_whitelabel_helper theme: - oe_whitelabel id: oe_whitelabel_ec_corporate_footer @@ -14,11 +15,11 @@ plugin: oe_corporate_blocks_ec_footer settings: id: oe_corporate_blocks_ec_footer label: 'EC Footer block' - provider: oe_corporate_blocks label_display: '0' + provider: oe_corporate_blocks visibility: oe_whitelabel_helper_current_component_library: id: oe_whitelabel_helper_current_component_library - component_library: ec negate: false context_mapping: { } + component_library: ec diff --git a/config/optional/block.block.oe_whitelabel_eu_corporate_footer.yml b/config/optional/block.block.oe_whitelabel_eu_corporate_footer.yml index 1eaa3c403d45bc92ae949f091172175b662a3107..700c5fee4256da7864451c7a01addbaf8681688a 100644 --- a/config/optional/block.block.oe_whitelabel_eu_corporate_footer.yml +++ b/config/optional/block.block.oe_whitelabel_eu_corporate_footer.yml @@ -3,6 +3,7 @@ status: true dependencies: module: - oe_corporate_blocks + - oe_whitelabel_helper theme: - oe_whitelabel id: oe_whitelabel_eu_corporate_footer @@ -14,11 +15,11 @@ plugin: oe_corporate_blocks_eu_footer settings: id: oe_corporate_blocks_eu_footer label: 'EU Footer block' - provider: oe_corporate_blocks label_display: '0' + provider: oe_corporate_blocks visibility: oe_whitelabel_helper_current_component_library: id: oe_whitelabel_helper_current_component_library - component_library: eu negate: false context_mapping: { } + component_library: eu diff --git a/config/optional/block.block.oe_whitelabel_eulogin.yml b/config/optional/block.block.oe_whitelabel_eulogin.yml index 8bb5a39b509d42a597fdbccce6e54e187e777f8d..80d9e261ba57c05dcc38e795533046dfc9ac25e9 100644 --- a/config/optional/block.block.oe_whitelabel_eulogin.yml +++ b/config/optional/block.block.oe_whitelabel_eulogin.yml @@ -14,6 +14,6 @@ plugin: oe_authentication_login_block settings: id: oe_authentication_login_block label: 'EU Login Link Block' - provider: oe_authentication label_display: '0' + provider: oe_authentication visibility: { } diff --git a/config/optional/block.block.oe_whitelabel_language_switcher.yml b/config/optional/block.block.oe_whitelabel_language_switcher.yml index df32e08a388b561e592246a9c63c0a4b38406992..b8b46125bd968ded5de0972c16ddd2fb1f1a640a 100644 --- a/config/optional/block.block.oe_whitelabel_language_switcher.yml +++ b/config/optional/block.block.oe_whitelabel_language_switcher.yml @@ -14,6 +14,6 @@ plugin: 'language_block:language_interface' settings: id: 'language_block:language_interface' label: 'Language switcher (Interface text)' - provider: language label_display: '0' + provider: language visibility: { } diff --git a/config/optional/block.block.oe_whitelabel_local_actions.yml b/config/optional/block.block.oe_whitelabel_local_actions.yml index 0368285449e27dae2a8b5b252af528e0d16f01da..094fbea4d5915a4f01524c2fa8613b644b1aa503 100644 --- a/config/optional/block.block.oe_whitelabel_local_actions.yml +++ b/config/optional/block.block.oe_whitelabel_local_actions.yml @@ -6,12 +6,12 @@ dependencies: id: oe_whitelabel_local_actions theme: oe_whitelabel region: content -weight: 0 +weight: -4 provider: null plugin: local_actions_block settings: id: local_actions_block label: 'Primary admin actions' - provider: core label_display: '0' + provider: core visibility: { } diff --git a/config/optional/block.block.oe_whitelabel_local_tasks.yml b/config/optional/block.block.oe_whitelabel_local_tasks.yml index 5a719a4870d9e1e8b3b22faf31fbdee384a2056a..7d5478116111febcd2f1bca899ddbc0bbebf5f04 100644 --- a/config/optional/block.block.oe_whitelabel_local_tasks.yml +++ b/config/optional/block.block.oe_whitelabel_local_tasks.yml @@ -6,14 +6,14 @@ dependencies: id: oe_whitelabel_local_tasks theme: oe_whitelabel region: content -weight: -1 +weight: -5 provider: null plugin: local_tasks_block settings: id: local_tasks_block label: Tabs - provider: core label_display: '0' + provider: core primary: true secondary: true visibility: { } diff --git a/config/optional/block.block.oe_whitelabel_main_page_content.yml b/config/optional/block.block.oe_whitelabel_main_page_content.yml new file mode 100755 index 0000000000000000000000000000000000000000..8987832c02a8892287f54c88d659bdb6fecbbd76 --- /dev/null +++ b/config/optional/block.block.oe_whitelabel_main_page_content.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - system + theme: + - oe_whitelabel +id: oe_whitelabel_main_page_content +theme: oe_whitelabel +region: content +weight: -2 +provider: null +plugin: system_main_block +settings: + id: system_main_block + label: 'Main page content' + label_display: '0' + provider: system +visibility: { } diff --git a/config/optional/block.block.oe_whitelabel_messages.yml b/config/optional/block.block.oe_whitelabel_messages.yml index cf33398e4b14d9dad84415b964c4d0c4001ae520..cf87516d5ca37d9357378bf7359f4ecc18be75d6 100644 --- a/config/optional/block.block.oe_whitelabel_messages.yml +++ b/config/optional/block.block.oe_whitelabel_messages.yml @@ -8,12 +8,12 @@ dependencies: id: oe_whitelabel_messages theme: oe_whitelabel region: content -weight: -3 +weight: -6 provider: null plugin: system_messages_block settings: id: system_messages_block label: 'Status messages' - provider: system label_display: '0' + provider: system visibility: { } diff --git a/config/optional/block.block.oe_whitelabel_neutral_footer.yml b/config/optional/block.block.oe_whitelabel_neutral_footer.yml index 372470a5a8658bf797abe514987b4515e33607a6..b1cf2e875e022df87b5dbc073e4b91ba7c1274bd 100644 --- a/config/optional/block.block.oe_whitelabel_neutral_footer.yml +++ b/config/optional/block.block.oe_whitelabel_neutral_footer.yml @@ -14,11 +14,11 @@ plugin: oe_corporate_blocks_neutral_footer settings: id: oe_corporate_blocks_neutral_footer label: 'Neutral Footer block' - provider: oe_whitelabel_helper label_display: '0' + provider: oe_whitelabel_helper visibility: oe_whitelabel_helper_current_component_library: id: oe_whitelabel_helper_current_component_library - component_library: neutral negate: false context_mapping: { } + component_library: neutral diff --git a/config/optional/block.block.oe_whitelabel_search_form.yml b/config/optional/block.block.oe_whitelabel_search_form.yml index c45778cf7f4dce05d8011495774a6f92efb5c4d1..22437b3aa239c48894a9d02b76966da4cc4fdd8e 100644 --- a/config/optional/block.block.oe_whitelabel_search_form.yml +++ b/config/optional/block.block.oe_whitelabel_search_form.yml @@ -14,8 +14,8 @@ plugin: whitelabel_search_block settings: id: whitelabel_search_block label: 'Whitelabel Search Block' - provider: oe_whitelabel_search label_display: '0' + provider: oe_whitelabel_search form: action: '#' input: @@ -26,7 +26,7 @@ settings: button: classes: '' view_options: + enable_autocomplete: false id: null display: null - enable_autocomplete: false visibility: { } diff --git a/modules/oe_whitelabel_multilingual/oe_whitelabel_multilingual.info.yml b/modules/oe_whitelabel_multilingual/oe_whitelabel_multilingual.info.yml new file mode 100755 index 0000000000000000000000000000000000000000..467182d49203cbfccc06b5cdde0269c7fc99c622 --- /dev/null +++ b/modules/oe_whitelabel_multilingual/oe_whitelabel_multilingual.info.yml @@ -0,0 +1,7 @@ +name: OpenEuropa Whitelabel Multilingual +type: module +description: Adds additional functionality to the Multilingual module +package: OpenEuropa Whitelabel Theme +core_version_requirement: ^9.2 +dependencies: + - openeuropa:oe_multilingual diff --git a/modules/oe_whitelabel_multilingual/oe_whitelabel_multilingual.module b/modules/oe_whitelabel_multilingual/oe_whitelabel_multilingual.module new file mode 100755 index 0000000000000000000000000000000000000000..203182b58c16d7c40216aa5ad50d05c5e4734196 --- /dev/null +++ b/modules/oe_whitelabel_multilingual/oe_whitelabel_multilingual.module @@ -0,0 +1,123 @@ +<?php + +/** + * @file + * OE Whitelabel theme Multilingual. + */ + +declare(strict_types = 1); + +use Drupal\Component\Utility\Html; + +/** + * Implements hook_preprocess_links(). + */ +function oe_whitelabel_multilingual_preprocess_links__oe_multilingual_content_language_block(array &$variables): void { + // Generate the label for the unavailable language. + /** @var \Drupal\Core\Language\LanguageInterface[] $languages */ + $languages = \Drupal::service('language_manager')->getNativeLanguages(); + $variables['unavailable_language'] = $languages[$variables['current_language_id']]->getName(); + + // Normalize the links to an array of optional languages suitable for the BCL. + $variables['languages'] = []; + foreach ($variables['links'] as $language_code => $link) { + /** @var \Drupal\Core\Url $url */ + $url = $link['link']['#url']; + $href = $url + ->setOptions($link['link']['#options']) + ->setAbsolute(TRUE) + ->toString(); + + $variables['languages'][] = [ + 'path' => $href, + 'hreflang' => $language_code, + 'label' => $link['link']['#title'], + 'current' => FALSE, + ]; + } + + // Add the current language to the list. + /** @var \Drupal\oe_multilingual\MultilingualHelper $multilingual_helper */ + $multilingual_helper = \Drupal::service('oe_multilingual.helper'); + $entity = $multilingual_helper->getEntityFromCurrentRoute(); + $translation = $multilingual_helper->getCurrentLanguageEntityTranslation($entity); + // If we don't have a language id defined yet, the current translation wasn't + // saved, so we don't add it to the list. + if ($translation->language()->getId() !== 'und') { + $variables['languages'][] = [ + 'path' => $translation->toUrl()->setAbsolute(TRUE)->toString(), + 'hreflang' => $translation->language()->getId(), + 'label' => $languages[$translation->language()->getId()]->getName(), + 'current' => TRUE, + 'icon_position' => 'before', + 'remove_icon_spacers' => FALSE, + 'icon' => [ + 'name' => 'check-lg', + 'path' => $variables['bcl_icon_path'], + 'size' => 'xs', + '#attributes' => ['class' => ['me-2']], + ], + ]; + } + + // Generate required ids. + $variables['expandable_id'] = Html::getUniqueId('bcl-expandable'); +} + +/** + * Implements hook_preprocess_links__language_block(). + */ +function oe_whitelabel_multilingual_preprocess_links__language_block(&$variables) { + $currentLanguage = \Drupal::languageManager()->getCurrentLanguage(); + $current_language_id = $currentLanguage->getId(); + $language_config_storage = \Drupal::entityTypeManager()->getStorage('configurable_language'); + $eu_links = []; + $non_eu_links = []; + + foreach ($variables['links'] as $language_code => $link) { + /** @var \Drupal\Core\Url $url */ + $url = $link['link']['#url']; + $href = $url + ->setOptions($link['link']['#options']) + ->setAbsolute(TRUE) + ->toString(); + $label = $link['link']['#title']; + + $link = [ + 'href' => $href, + 'name' => $label, + 'id' => 'link_' . $language_code, + 'hreflang' => $language_code, + ]; + + if (!empty($current_language_id) && $language_code === $current_language_id) { + $variables['language']['link'] = $link; + $variables['language']['link']['target'] = 'languageModal'; + $link['active'] = TRUE; + } + + $language_config = $language_config_storage->load($language_code); + $category = $language_config->getThirdPartySetting('oe_multilingual', 'category'); + + if ($category === 'eu') { + $eu_links[$language_code] = $link; + } + else { + $non_eu_links[$language_code] = $link; + } + } + + $variables['language']['modal'] = [ + 'id' => 'languageModal', + 'size' => 'fullscreen', + 'header' => [ + 'title' => t('Select your language'), + 'label' => t('Close'), + ], + 'eu_links' => $eu_links, + 'non_eu_links' => $non_eu_links, + 'footer' => [ + 'label' => t('Close'), + ], + ]; +} diff --git a/modules/oe_whitelabel_starter_event/oe_whitelabel_starter_event.info.yml b/modules/oe_whitelabel_starter_event/oe_whitelabel_starter_event.info.yml index 29c37b071d3889a1b88ae9bc1cae2d4c894dab7c..ce2617f0d2bca0068c5a541a1eaf402eb709bdf6 100755 --- a/modules/oe_whitelabel_starter_event/oe_whitelabel_starter_event.info.yml +++ b/modules/oe_whitelabel_starter_event/oe_whitelabel_starter_event.info.yml @@ -10,6 +10,6 @@ dependencies: config_devel: install: + - core.date_format.oe_whitelabel_starter_event_date - core.entity_view_display.node.oe_sc_event.full - core.entity_view_display.node.oe_sc_event.teaser - - core.date_format.oe_whitelabel_starter_event_date diff --git a/modules/oe_whitelabel_starter_news/oe_whitelabel_starter_news.info.yml b/modules/oe_whitelabel_starter_news/oe_whitelabel_starter_news.info.yml index cd71e3993dcd798a149aadd9f76d900f8d41fd51..dc47e64bec603cea4cd4c9ec6b326c38a048c4ee 100644 --- a/modules/oe_whitelabel_starter_news/oe_whitelabel_starter_news.info.yml +++ b/modules/oe_whitelabel_starter_news/oe_whitelabel_starter_news.info.yml @@ -10,6 +10,6 @@ dependencies: config_devel: install: - - core.date_format.oe_whitelabel_starter_news_date.yml - - core.entity_view_display.node.oe_sc_news.full.yml - - core.entity_view_display.node.oe_sc_news.teaser.yml + - core.date_format.oe_whitelabel_starter_news_date + - core.entity_view_display.node.oe_sc_news.full + - core.entity_view_display.node.oe_sc_news.teaser diff --git a/oe_whitelabel.info.yml b/oe_whitelabel.info.yml index c334912dc62032627690574f5c9ec676aab85fa1..c3e080e884438a020a217aed4881782cf78fd42a 100644 --- a/oe_whitelabel.info.yml +++ b/oe_whitelabel.info.yml @@ -35,15 +35,16 @@ config_devel: install: - oe_whitelabel.settings optional: - - block.block.breadcrumbs - - block.block.corporateeclogoblock - - block.block.ecfooterblock - - block.block.euloginlinkblock.yml - - block.block.languageswitcherinterfacetext - block.block.oe_whitelabel_branding + - block.block.oe_whitelabel_breadcrumbs + - block.block.oe_whitelabel_ec_corporate_footer + - block.block.oe_whitelabel_eu_corporate_footer + - block.block.oe_whitelabel_eulogin + - block.block.oe_whitelabel_language_switcher - block.block.oe_whitelabel_local_actions - block.block.oe_whitelabel_local_tasks + - block.block.oe_whitelabel_main_navigation + - block.block.oe_whitelabel_main_page_content - block.block.oe_whitelabel_messages - - block.block.oe_whitelabel_page_title - - block.block.whitelabelsearchblock - - cas.settings.yml + - block.block.oe_whitelabel_neutral_footer + - block.block.oe_whitelabel_search_form diff --git a/oe_whitelabel.theme b/oe_whitelabel.theme index bb3573db88c1c8272ed4c67c45aacaa350bf9519..3da1f38601b763077e2430d595823bb79a5cf0e3 100644 --- a/oe_whitelabel.theme +++ b/oe_whitelabel.theme @@ -11,64 +11,6 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; use Drupal\oe_whitelabel_helper\EuropeanUnionLanguages; -/** - * Implements hook__preprocess_links__language_block(). - */ -function oe_whitelabel_preprocess_links__language_block(&$variables) { - $currentLanguage = \Drupal::languageManager()->getCurrentLanguage(); - $current_language_id = $currentLanguage->getId(); - $language_config_storage = \Drupal::entityTypeManager()->getStorage('configurable_language'); - $eu_links = []; - $non_eu_links = []; - - foreach ($variables['links'] as $language_code => $link) { - /** @var \Drupal\Core\Url $url */ - $url = $link['link']['#url']; - $href = $url - ->setOptions($link['link']['#options']) - ->setAbsolute(TRUE) - ->toString(); - $label = $link['link']['#title']; - - $link = [ - 'href' => $href, - 'name' => $label, - 'id' => 'link_' . $language_code, - 'hreflang' => $language_code, - ]; - - if (!empty($current_language_id) && $language_code === $current_language_id) { - $variables['language']['link'] = $link; - $variables['language']['link']['target'] = 'languageModal'; - $link['active'] = TRUE; - } - - $language_config = $language_config_storage->load($language_code); - $category = $language_config->getThirdPartySetting('oe_multilingual', 'category'); - - if ($category === 'eu') { - $eu_links[$language_code] = $link; - } - else { - $non_eu_links[$language_code] = $link; - } - } - - $variables['language']['modal'] = [ - 'id' => 'languageModal', - 'size' => 'fullscreen', - 'header' => [ - 'title' => t('Select your language'), - 'label' => t('Close'), - ], - 'eu_links' => $eu_links, - 'non_eu_links' => $non_eu_links, - 'footer' => [ - 'label' => t('Close'), - ], - ]; -} - /** * Implements hook_form_FORM_ID_alter() for facets_forms. */ diff --git a/runner.yml.dist b/runner.yml.dist index 782e6c99dbdcafe22c050d559f0d0bc253915bee..e607338df2475eb3c8c3430bedf5ddd3a1a2ba30 100644 --- a/runner.yml.dist +++ b/runner.yml.dist @@ -19,7 +19,7 @@ drupal: - "./vendor/bin/drush en field_ui -y" - "./vendor/bin/drush en oe_authentication -y" - "./vendor/bin/drush en oe_corporate_blocks -y" - - "./vendor/bin/drush en oe_multilingual -y" + - "./vendor/bin/drush en oe_whitelabel_multilingual -y" - "./vendor/bin/drush en oe_whitelabel_contact_forms -y" - "./vendor/bin/drush en oe_whitelabel_helper -y" - "./vendor/bin/drush en oe_whitelabel_search -y" diff --git a/templates/overrides/navigation/links--oe-multilingual-content-language-block.html.twig b/templates/overrides/navigation/links--oe-multilingual-content-language-block.html.twig new file mode 100644 index 0000000000000000000000000000000000000000..784fbbf2f9324630b427745ad00fbc88dbf4d79f --- /dev/null +++ b/templates/overrides/navigation/links--oe-multilingual-content-language-block.html.twig @@ -0,0 +1,51 @@ +{% apply spaceless %} + {# This template uses the BCL composition for the + language switcher. + _id, _message and _expandable are overwritten. + @todo Call include once BCL 0.20 is available. + #} + {% set _id = expandable_id %} + {% set _message = { + message: "This page is not available in @language."|t({'@language': unavailable_language}), + path: bcl_icon_path, + variant: "warning", + }%} + {% set _expandable = { + label: "Choose another language"|t, + icon: { + name: "caret-down-fill", + path: bcl_icon_path, + }, + outline: "true", + } %} + + {% set _languages = languages|default([]) %} + {% set _expandable_attributes = _expandable.attributes ?: create_attribute() %} + {% set _expandable_attributes = _expandable_attributes + .setAttribute('data-bs-toggle', 'collapse') + .setAttribute('autocomplete', 'off') + .setAttribute('aria-expanded', 'false') + .setAttribute('aria-controls', _id) + .setAttribute('data-bs-target', '#' ~ _id) + %} + + {% include '@oe-bcl/bcl-alert/alert.html.twig' with _message only %} + <div class="mb-3"> + {% include '@oe-bcl/bcl-button/button.html.twig' with _expandable|merge({ + attributes: _expandable_attributes + }) only %} + + <div class="collapse mt-3" id="{{ _id }}"> + <div + class="d-md-grid" + style="grid-auto-flow: column; grid-template-rows: repeat(4, 1fr)" + > + {% for language in languages %} + {% include '@oe-bcl/bcl-link/link.html.twig' with language|merge({ + attributes: create_attribute().addClass(["btn", "btn-link", "d-block", "ps-0", "text-start"]) + }) only %} + {% endfor %} + </div> + </div> + </div> +{% endapply %} diff --git a/tests/src/Kernel/ContentLanguageSwitcherTest.php b/tests/src/Kernel/ContentLanguageSwitcherTest.php new file mode 100644 index 0000000000000000000000000000000000000000..49c72b792642ca7b70fc5614f2d389164e03b4f5 --- /dev/null +++ b/tests/src/Kernel/ContentLanguageSwitcherTest.php @@ -0,0 +1,215 @@ +<?php + +declare(strict_types = 1); + +namespace Drupal\Tests\oe_whitelabel\Kernel; + +use Drupal\node\Entity\Node; +use Drupal\KernelTests\KernelTestBase; +use Symfony\Component\DomCrawler\Crawler; +use Symfony\Component\HttpFoundation\Request; + +/** + * Test content language switcher rendering. + */ +class ContentLanguageSwitcherTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + 'block', + 'content_translation', + 'language', + 'locale', + 'node', + 'oe_bootstrap_theme_helper', + 'oe_corporate_blocks', + 'oe_multilingual', + 'oe_whitelabel_helper', + 'oe_whitelabel_multilingual', + 'system', + 'user', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->installEntitySchema('user'); + $this->installSchema('system', 'sequences'); + $this->installSchema('user', ['users_data']); + $this->installConfig(['user']); + + $this->installSchema('locale', [ + 'locales_location', + 'locales_source', + 'locales_target', + ]); + + $this->installEntitySchema('node'); + $this->installSchema('node', 'node_access'); + $this->installConfig([ + 'content_translation', + 'language', + 'locale', + 'oe_multilingual', + 'oe_whitelabel_helper', + 'system', + ]); + $this->container->get('module_handler')->loadInclude('oe_multilingual', 'install'); + oe_multilingual_install(FALSE); + + $this->container->get('theme_installer')->install(['oe_whitelabel']); + $this->config('system.theme')->set('default', 'oe_whitelabel')->save(); + + // Call the installation hook of the User module which creates the + // Anonymous user and User 1. This is needed because the Anonymous user + // is loaded to provide the current User context which is needed + // in places like route enhancers. + // @see CurrentUserContext::getRuntimeContexts(). + // @see EntityConverter::convert(). + module_load_include('install', 'user'); + user_install(); + + \Drupal::service('kernel')->rebuildContainer(); + } + + /** + * Tests the rendering of the language switcher block. + */ + public function testMultilingualLanguageSwitcherBlockRendering(): void { + $node = Node::create([ + 'title' => 'Hello, world!', + 'type' => 'oe_demo_translatable_page', + ]); + /** @var \Drupal\Core\Entity\EntityInterface $translation */ + $node->addTranslation('es', ['title' => '¡Hola mundo!'])->save(); + + // Simulate a request to the canonical route of the node with Bulgarian + // language prefix. + $this->setCurrentRequest('/bg/node/' . $node->id()); + + // Setup and render language switcher block. + $block_manager = \Drupal::service('plugin.manager.block'); + $config = [ + 'id' => 'oe_multilingual_content_language_switcher', + 'label' => 'Content language switcher', + 'provider' => 'oe_multilingual', + 'label_display' => '0', + ]; + + /** @var \Drupal\Core\Block\BlockBase $plugin_block */ + $plugin_block = $block_manager->createInstance('oe_multilingual_content_language_switcher', $config); + $render = $plugin_block->build(); + + $html = (string) $this->container->get('renderer')->renderRoot($render); + $crawler = new Crawler($html); + + // Make sure that content language switcher block is present. + $actual = $crawler->filter('div.collapse.mt-3'); + $this->assertCount(1, $actual); + + // Warning message doesn't contain the unavailable language, the translation + // will have it. + $this->assertUnavailableLanguage($crawler, 'This page is not available in българÑки.'); + + // Make sure that selected language is properly rendered. + $this->assertSelectedLanguage($crawler, 'English'); + + // Make sure that available languages are properly rendered. + $this->assertTranslationLinks($crawler, ['español']); + + // Remove the spanish translation. + $node->removeTranslation('es'); + $node->save(); + + // Re-render the block assuming a request to the Spanish version of the + // node. + $this->setCurrentRequest('/es/node/' . $node->id()); + $render = $plugin_block->build(); + + $html = (string) $this->container->get('renderer')->renderRoot($render); + $crawler = new Crawler($html); + + // Verify that the requested language is set as unavailable. + $this->assertUnavailableLanguage($crawler, 'This page is not available in español.'); + + // Verify that the content has been rendered in the fallback language. + $this->assertSelectedLanguage($crawler, 'English'); + + // Make sure that no language links are rendered. + $this->assertTranslationLinks($crawler, []); + } + + /** + * Asserts that a language is marked as the current rendered. + * + * @param \Symfony\Component\DomCrawler\Crawler $crawler + * The content language block crawler. + * @param string $expected + * The label of the language. + */ + protected function assertSelectedLanguage(Crawler $crawler, string $expected): void { + // The selected language link will contain a svg, so we target that. + $actual = $crawler->filter('div.collapse.mt-3 > div > a > svg')->parents()->first()->text(); + $this->assertEquals($expected, trim($actual)); + } + + /** + * Asserts that a language is marked as unavailable. + * + * @param \Symfony\Component\DomCrawler\Crawler $crawler + * The content language block crawler. + * @param string $expected + * The label of the language. + */ + protected function assertUnavailableLanguage(Crawler $crawler, string $expected): void { + $actual = $crawler->filter('div.alert div.alert-content')->text(); + $this->assertStringContainsString($expected, trim($actual)); + } + + /** + * Asserts the rendered translation links in the content language switcher. + * + * @param \Symfony\Component\DomCrawler\Crawler $crawler + * The content language block crawler. + * @param array $expected + * The labels of the translations that should be rendered as links. + */ + protected function assertTranslationLinks(Crawler $crawler, array $expected): void { + $elements = $crawler->filter('div.collapse.mt-3 > div > a'); + // Filter out the selected language. + $elements = $elements->reduce(function (Crawler $crawler) { + return $crawler->filter('svg')->count() === 0; + }); + $this->assertSameSize($expected, $elements); + + $actual = array_column(iterator_to_array($elements), 'nodeValue'); + $this->assertEquals($expected, $actual); + } + + /** + * Sets a request to a certain URI as the current in the request stack. + * + * @param string $uri + * The URI of the request. It needs to match a valid Drupal route. + */ + protected function setCurrentRequest(string $uri): void { + // Simulate a request to a node canonical route with a language prefix. + $request = Request::create($uri); + // Let the Drupal router populate all the request parameters. + $parameters = \Drupal::service('router.no_access_checks')->matchRequest($request); + $request->attributes->add($parameters); + // Set the prepared request as current. + \Drupal::requestStack()->push($request); + // Reset any discovered language. KernelTestBase creates a request to the + // root of the website for legacy purposes, so the language is set by + // default to the default one. + // @see \Drupal\KernelTests\KernelTestBase::bootKernel() + \Drupal::languageManager()->reset(); + } + +} diff --git a/tests/src/Kernel/MultilingualBlockTest.php b/tests/src/Kernel/MultilingualBlockTest.php index aa7053f842317df9abead6dd7a372151420c5707..8e21820ebb44726694206d574f27ef9cb2bf09a1 100644 --- a/tests/src/Kernel/MultilingualBlockTest.php +++ b/tests/src/Kernel/MultilingualBlockTest.php @@ -23,6 +23,7 @@ class MultilingualBlockTest extends KernelTestBase { 'locale', 'oe_bootstrap_theme_helper', 'oe_multilingual', + 'oe_whitelabel_multilingual', 'path', 'path_alias', 'pathauto',