diff --git a/.drone.yml b/.drone.yml index 2bda6c2dc..d51638434 100644 --- a/.drone.yml +++ b/.drone.yml @@ -34,6 +34,11 @@ services: environment: - DISPLAY=:99 - SE_OPTS=-debug + - DISPLAY=:99 + - SCREEN_WIDTH=1280 + - SCREEN_HEIGHT=800 + - NODE_MAX_INSTANCES=5 + - NODE_MAX_SESSION=5 pipeline: npm-build: diff --git a/CHANGELOG.md b/CHANGELOG.md index 24ebe08d1..73885d7fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,94 @@ # Changelog +## [2.20.0](https://github.com/openeuropa/oe_theme/tree/2.20.0) (2021-06-17) + +[Full Changelog](https://github.com/openeuropa/oe_theme/compare/2.19.0...2.20.0) + +**Merged pull requests:** + +- EWPP-1170: Remove dev branch from dependencies. [\#849](https://github.com/openeuropa/oe_theme/pull/849) ([imanoleguskiza](https://github.com/imanoleguskiza)) +- EWPP-1112: Style the iframe paragraph. [\#809](https://github.com/openeuropa/oe_theme/pull/809) ([yenyasinn](https://github.com/yenyasinn)) +- EWPP-1049: Address field should have only Country as mandatory. [\#792](https://github.com/openeuropa/oe_theme/pull/792) ([yenyasinn](https://github.com/yenyasinn)) + +## [2.19.0](https://github.com/openeuropa/oe_theme/tree/2.19.0) (2021-06-15) + +[Full Changelog](https://github.com/openeuropa/oe_theme/compare/2.18.0...2.19.0) + +**Merged pull requests:** + +- Prepare release 2.19.0. [\#848](https://github.com/openeuropa/oe_theme/pull/848) ([imanoleguskiza](https://github.com/imanoleguskiza)) +- EWPP-851: Update EPIC branch. [\#846](https://github.com/openeuropa/oe_theme/pull/846) ([sergepavle](https://github.com/sergepavle)) +- EWPP-953: Organisation version 2 epic [\#845](https://github.com/openeuropa/oe_theme/pull/845) ([ademarco](https://github.com/ademarco)) +- EWPP-953: Update epic. [\#844](https://github.com/openeuropa/oe_theme/pull/844) ([nagyad](https://github.com/nagyad)) +- EWPP-851: Update EPIC branch. [\#843](https://github.com/openeuropa/oe_theme/pull/843) ([sergepavle](https://github.com/sergepavle)) +- Update epic org v2 [\#842](https://github.com/openeuropa/oe_theme/pull/842) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-993: Add string translations for 'Leadership and organisation'. [\#841](https://github.com/openeuropa/oe_theme/pull/841) ([22Alexandra](https://github.com/22Alexandra)) +- Update org v2 epic [\#840](https://github.com/openeuropa/oe_theme/pull/840) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-851: Update EPIC branch. [\#838](https://github.com/openeuropa/oe_theme/pull/838) ([sergepavle](https://github.com/sergepavle)) +- EPIC EWPP-1041: Contact entity link field. [\#835](https://github.com/openeuropa/oe_theme/pull/835) ([upchuk](https://github.com/upchuk)) +- Updating epic EWPP-1041 [\#834](https://github.com/openeuropa/oe_theme/pull/834) ([upchuk](https://github.com/upchuk)) +- EWPP-851: Update EPIC branch of EWPP-851 in-page navigation. [\#833](https://github.com/openeuropa/oe_theme/pull/833) ([sergepavle](https://github.com/sergepavle)) +- EWPP-1153: Fix breadcrumb page title cache. [\#831](https://github.com/openeuropa/oe_theme/pull/831) ([nagyad](https://github.com/nagyad)) +- EWPP-953: Update organisation v2 epic. [\#826](https://github.com/openeuropa/oe_theme/pull/826) ([nagyad](https://github.com/nagyad)) +- EWPP-1169: Realign with release branch. [\#825](https://github.com/openeuropa/oe_theme/pull/825) ([hernani](https://github.com/hernani)) +- EWPP-851: Update EPIC branch. [\#823](https://github.com/openeuropa/oe_theme/pull/823) ([sergepavle](https://github.com/sergepavle)) +- Merge 2.x into EWPP-1041 Contacts. [\#822](https://github.com/openeuropa/oe_theme/pull/822) ([yenyasinn](https://github.com/yenyasinn)) +- EWPP-1101: Implement overridable js for adjusting layout on disappeared in-page navigation block. [\#821](https://github.com/openeuropa/oe_theme/pull/821) ([sergepavle](https://github.com/sergepavle)) +- EWPP-1143: Apply access checks for media render. [\#820](https://github.com/openeuropa/oe_theme/pull/820) ([nagyad](https://github.com/nagyad)) +- EWPP-900: Using master branch of oe\_media. [\#819](https://github.com/openeuropa/oe_theme/pull/819) ([upchuk](https://github.com/upchuk)) +- EWPP-1129: Use short title with fallback logic for rendering title on teaser view modes. [\#818](https://github.com/openeuropa/oe_theme/pull/818) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-000: Fix theme installation instructions. [\#816](https://github.com/openeuropa/oe_theme/pull/816) ([ademarco](https://github.com/ademarco)) +- EWPP-0000: Use latest dev version of oe\_media to fix test failures. [\#815](https://github.com/openeuropa/oe_theme/pull/815) ([brummbar](https://github.com/brummbar)) +- Updating the EWPP-1041 epic [\#814](https://github.com/openeuropa/oe_theme/pull/814) ([upchuk](https://github.com/upchuk)) +- EWPP-963: Add navigation block in template. [\#813](https://github.com/openeuropa/oe_theme/pull/813) ([sergepavle](https://github.com/sergepavle)) +- EWPP-851 Update epic branch. [\#812](https://github.com/openeuropa/oe_theme/pull/812) ([sergepavle](https://github.com/sergepavle)) +- EWPP-0000: Fixing oe\_multilingual\_install\(\) call. [\#810](https://github.com/openeuropa/oe_theme/pull/810) ([hernani](https://github.com/hernani)) +- Epic-EWPP-851 in page nav [\#807](https://github.com/openeuropa/oe_theme/pull/807) ([hernani](https://github.com/hernani)) +- EWPP-1087: Make tables created via WYSIWYG behave correctly when disp… [\#804](https://github.com/openeuropa/oe_theme/pull/804) ([yenyasinn](https://github.com/yenyasinn)) +- EWPP-1015: Update to ECL 2.38. [\#803](https://github.com/openeuropa/oe_theme/pull/803) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-1105: Add link to person node entity in OpenEuropa Compact Teaser view mode. [\#801](https://github.com/openeuropa/oe_theme/pull/801) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-1104: Update drupal-driver to 2.1.0. [\#798](https://github.com/openeuropa/oe_theme/pull/798) ([nagyad](https://github.com/nagyad)) +- EWPP-902: Gallery item to use icons for images as well. [\#797](https://github.com/openeuropa/oe_theme/pull/797) ([upchuk](https://github.com/upchuk)) +- Merging 2.x into EPIC-EWPP-1041-Contacts [\#796](https://github.com/openeuropa/oe_theme/pull/796) ([yenyasinn](https://github.com/yenyasinn)) +- Update organisation epic branch. [\#793](https://github.com/openeuropa/oe_theme/pull/793) ([22Alexandra](https://github.com/22Alexandra)) +- Updates Epic EWPP-953-Organisation [\#791](https://github.com/openeuropa/oe_theme/pull/791) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-1044: Include the Link field in the Contact rendering [\#789](https://github.com/openeuropa/oe_theme/pull/789) ([yenyasinn](https://github.com/yenyasinn)) +- EWPP-851: Update EPIC branch. [\#788](https://github.com/openeuropa/oe_theme/pull/788) ([sergepavle](https://github.com/sergepavle)) +- EWPP-989: Theme "Leadership and organisation" section. [\#787](https://github.com/openeuropa/oe_theme/pull/787) ([22Alexandra](https://github.com/22Alexandra)) +- Release 2.17.x into 2.x [\#786](https://github.com/openeuropa/oe_theme/pull/786) ([imanoleguskiza](https://github.com/imanoleguskiza)) +- EWPP-1047: Parallelize tests on oe\_theme [\#784](https://github.com/openeuropa/oe_theme/pull/784) ([ademarco](https://github.com/ademarco)) +- EWPP-1039: Fix organisation\_teaser and text\_featured\_media pattern preview [\#783](https://github.com/openeuropa/oe_theme/pull/783) ([ademarco](https://github.com/ademarco)) +- EWPP-992: Update contacts rendering on full and teaser view displays. [\#782](https://github.com/openeuropa/oe_theme/pull/782) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-990: Remove body field label from full view display. [\#781](https://github.com/openeuropa/oe_theme/pull/781) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-987: Adds overview field group to full view display. [\#779](https://github.com/openeuropa/oe_theme/pull/779) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-978: Update IEF to RC9 with the patch. [\#778](https://github.com/openeuropa/oe_theme/pull/778) ([nagyad](https://github.com/nagyad)) +- EWPP-865: Trim spaces in field--bare.html.twig. [\#777](https://github.com/openeuropa/oe_theme/pull/777) ([sergepavle](https://github.com/sergepavle)) +- EWPP-942: Order of languages in language switcher. [\#773](https://github.com/openeuropa/oe_theme/pull/773) ([yenyasinn](https://github.com/yenyasinn)) +- EWPP-856: Create inpage navigation block. [\#772](https://github.com/openeuropa/oe_theme/pull/772) ([sergepavle](https://github.com/sergepavle)) +- EWPP 855: Create in-page visibility plugin for the block. [\#766](https://github.com/openeuropa/oe_theme/pull/766) ([sergepavle](https://github.com/sergepavle)) +- EWPP-854: Create new in-page navigation entity meta. [\#763](https://github.com/openeuropa/oe_theme/pull/763) ([sergepavle](https://github.com/sergepavle)) +- EWPP-832: Print description in highlight variant of list item pattern. [\#761](https://github.com/openeuropa/oe_theme/pull/761) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-765: Allowing the navigation list to have optional URLs. [\#750](https://github.com/openeuropa/oe_theme/pull/750) ([upchuk](https://github.com/upchuk)) +- EWPP-721: Update xdebug configuration. [\#722](https://github.com/openeuropa/oe_theme/pull/722) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-722: Add theme suggestions for text fields to replace multiple field templates. [\#721](https://github.com/openeuropa/oe_theme/pull/721) ([22Alexandra](https://github.com/22Alexandra)) +- EWPP-402: Rework theme content type tests to use pattern assertion and drop behat [\#629](https://github.com/openeuropa/oe_theme/pull/629) ([yenyasinn](https://github.com/yenyasinn)) + +## [2.18.0](https://github.com/openeuropa/oe_theme/tree/2.18.0) (2021-05-10) + +[Full Changelog](https://github.com/openeuropa/oe_theme/compare/2.17.1...2.18.0) + +**Merged pull requests:** + +- EWPP-1059: Add translation for arabic, catalan and turhish languages. [\#800](https://github.com/openeuropa/oe_theme/pull/800) ([imanoleguskiza](https://github.com/imanoleguskiza)) +- Release 2.17.x into 2.x. [\#786](https://github.com/openeuropa/oe_theme/pull/786) ([nagyad](https://github.com/nagyad)) + ## [2.17.1](https://github.com/openeuropa/oe_theme/tree/2.17.1) (2021-04-20) + [Full Changelog](https://github.com/openeuropa/oe_theme/compare/2.17.0...2.17.1) **Merged pull requests:** +- Update CHANGELOG.md for release 2.17.1. [\#785](https://github.com/openeuropa/oe_theme/pull/785) ([ademarco](https://github.com/ademarco)) - EWPP-1031: Fix tests that use role reference field. [\#780](https://github.com/openeuropa/oe_theme/pull/780) ([imanoleguskiza](https://github.com/imanoleguskiza)) - EWPP-969: Move Social media links outside Media fieldgroup on Person full view display. [\#776](https://github.com/openeuropa/oe_theme/pull/776) ([22Alexandra](https://github.com/22Alexandra)) @@ -14,6 +98,7 @@ **Merged pull requests:** +- Release 2.17.0: Update changelog. [\#775](https://github.com/openeuropa/oe_theme/pull/775) ([nagyad](https://github.com/nagyad)) - EWPP-649: Person epic. [\#774](https://github.com/openeuropa/oe_theme/pull/774) ([nagyad](https://github.com/nagyad)) - Update person content type epic with latest 2.x [\#771](https://github.com/openeuropa/oe_theme/pull/771) ([ademarco](https://github.com/ademarco)) - EWPP-945: Drop legacy ECL presets and update version [\#770](https://github.com/openeuropa/oe_theme/pull/770) ([ademarco](https://github.com/ademarco)) diff --git a/README.md b/README.md index b6aef8467..ace17c763 100644 --- a/README.md +++ b/README.md @@ -36,22 +36,54 @@ This depends on the following software: The recommended way of installing the OpenEuropa theme is via [Composer][2]. +Before proceeding, please note that theme releases are built by a continuous integration system, and include code coming +from third-party libraries, such as [ECL][1] templates and other assets. Simply Running `composer require openeuropa/oe_theme` +will download the raw theme source code, which misses required third-party code. + +In order to instruct Composer to download the actual built artifact, you need to require and configure the +[Composer Artifacts][19] project. To do so run: + +``` +composer require openeuropa/composer-artifacts +``` + +Then add the following section, in your project's `composer.json`: + +``` + "extra": { + "artifacts": { + "openeuropa/oe_theme": { + "dist": { + "url": "https://github.com/{name}/releases/download/{pretty-version}/{project-name}-{pretty-version}.tar.gz", + "type": "tar" + } + } + }, + } +``` + +Once you are done, run: + ```bash composer require openeuropa/oe_theme ``` -If you are not using Composer then download the [release package][3] and install it as described [here][10]. +This will download the fully built artifact, as opposed to the raw theme source code. -**Note:** Release archives are built by the continuous integration system and include code coming from third-party -libraries, such as [ECL][1] templates and other assets. Make sure you use an actual release and not the source code -archives. +If you are not using Composer, then simply download a release artifact [here][3] (i.e. a `oe_theme-[x.y.z].tar.gz` file) +and install it as described [here][10]. ### Enable the theme In order to enable the theme in your project perform the following steps: 1. Enable the OpenEuropa Theme Helper module ```./vendor/bin/drush en oe_theme_helper``` -2. Enable the OpenEuropa Theme and set it as default ```./vendor/bin/drush config-set system.theme default oe_theme``` +2. Enable the OpenEuropa Theme and set it as default + +``` +./vendor/bin/drush theme:enable oe_theme +./vendor/bin/drush config-set system.theme default oe_theme +``` Step 1. is necessary until the following [Drupal core issue][8] is resolved. Alternatively you can patch Drupal core with [this patch][9] and enable the theme: the patched core will then enable the required OpenEuropa Theme Helper @@ -467,3 +499,4 @@ We use [SemVer](http://semver.org/) for versioning. For the available versions, [16]: https://github.com/openeuropa/ecl-twig-loader [17]: https://drone.io [18]: https://www.npmjs.com/package/patch-package +[19]: https://github.com/openeuropa/composer-artifacts diff --git a/composer.json b/composer.json index 407b91572..373757ad2 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,9 @@ "drupal/config_devel": "~1.2", "drupal/datetime_testing": "1.x-dev", "drupal/description_list_field": "1.0.x-dev", - "drupal/drupal-driver": "~2.0.0-alpha6", + "drupal/drupal-driver": "^2.1.1", "drupal/drupal-extension": "~4.0", + "drupal/emr": "~1.0-beta9", "drupal/entity_reference_revisions": "~1.3", "drupal/entity_browser": "^2.5", "drupal/extra_field": "^1.1", @@ -80,7 +81,7 @@ "psr-4": { "Drupal\\Tests\\oe_theme\\": "./tests/", "Drupal\\Tests\\oe_content\\": "./build/modules/contrib/oe_content/tests/", - "Drupal\\Tests\\oe_media\\": "./build/modules/contrib/oe_media/tests/src" + "Drupal\\Tests\\oe_media\\": "./build/modules/contrib/oe_media/tests/src/" } }, "repositories": { @@ -100,7 +101,7 @@ }, "patches": { "drupal/drupal-driver": { - "allow-date-only-date-fields": "https://patch-diff.githubusercontent.com/raw/jhedstrom/DrupalDriver/pull/201.patch" + "allow-date-only-date-fields": "https://patch-diff.githubusercontent.com/raw/jhedstrom/DrupalDriver/pull/235.patch" }, "drupal/address": { "https://www.drupal.org/project/address/issues/3144823": "https://www.drupal.org/files/issues/2020-11-05/3144823-6.patch" diff --git a/js/inpage_navigation.js b/js/inpage_navigation.js new file mode 100644 index 000000000..4417346f8 --- /dev/null +++ b/js/inpage_navigation.js @@ -0,0 +1,162 @@ +/** + * @file + * ECL inpage navigation initialisation code. + */ +(function (ECL, Drupal, $) { + /** + * Creates ECL inpage navigation items with elements gathered from defined source areas. + * + * To mark an element as source area, set the attribute `data-inpage-navigation-source-area`, where the value is a + * valid CSS selector. The elements targeted by all the selectors in the page will be used to generate an item in the + * navigation list. If the element is missing the ID attribute, one will be generated automatically. + * + * @type {Drupal~behavior} + * + * @prop {Drupal~behaviorAttach} attach + * Attaches the inpage navigation behaviors. + */ + Drupal.behaviors.eclInPageNavigation = { + attach: function attach(context, settings) { + // Loop through all the elements marked as source areas. + Array.prototype.forEach.call(document.querySelectorAll('[data-inpage-navigation-source-area]'), function (area) { + var selectors = area.getAttribute('data-inpage-navigation-source-area'); + + // Loop through all the elements that are referenced by the specified selector(s), and mark them as source + // elements. We cannot collect the elements at this stage, as multiple nested areas can be present in the page. + // This could lead to scenarios where elements are collected multiple times, or not collected following the + // order of appearance in the page. + // The :scope pseudo-class is needed to make sure that the selectors are applied inside the parent. + // @see https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll#user_notes + Array.prototype.forEach.call(area.querySelectorAll(':scope ' + selectors), function (element) { + element.setAttribute('data-inpage-navigation-source-element', ''); + }); + }); + + var items_markup = ''; + // Collect all the elements marked as source. Now the elements will be unique and ordered correctly. + Array.prototype.forEach.call(document.querySelectorAll('[data-inpage-navigation-source-element]'), function (element) { + var title = element.textContent.trim(); + + // Skip elements with empty content. + if (title.length === 0) { + return; + } + + // Generate an unique ID if not present. + if (!element.hasAttribute('id')) { + var id = Drupal.eclInPageNavigation.slug(title); + // If an empty ID is generated, skip this element. + if (id === false) { + return; + } + + element.setAttribute('id', id); + } + + // Cleanup the markup from the helper attribute added above. + element.removeAttribute('data-inpage-navigation-source-element'); + + items_markup += Drupal.theme('oe_theme_inpage_navigation_item', element.getAttribute('id'), title); + }); + + Array.prototype.forEach.call(document.querySelectorAll('[data-ecl-inpage-navigation]'), function (block) { + if (items_markup.length === 0) { + // When there are no items, execute the callback to handle the block. + Drupal.eclInPageNavigation.handleEmptyInpageNavigation(block); + return; + } + block.querySelector('ul').innerHTML = items_markup; + }) + } + }; + + /** + * Holds inpage navigation related functionality. + * + * @namespace + */ + Drupal.eclInPageNavigation = { + + /** + * A list of IDs already used by the slug generator. + * + * @type {object} + */ + seenIds: {}, + + /** + * Generates a unique slug from a text string. + * + * The following code is an adaptation from https://github.com/markedjs/marked/blob/master/src/Slugger.js. + * Since the above file is part of a bigger library, we extracted its code and adapted to account for already existing + * IDs on the page. + * + * @param {string} value + * The string to process. + * + * @returns {string|boolean} + * A unique slug, safe to use as ID for an element. False when the generated slug is empty. + */ + slug: function(value) { + var originalSlug = value + .toLowerCase() + .trim() + // Remove html tags. + .replace(/<[!\/a-z].*?>/ig, '') + // Remove unwanted chars. + .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '') + .replace(/\s/g, '-'); + + var slug = originalSlug; + var occurrenceAccumulator = 0; + + // If the slug string is empty, quit. + if (slug.length === 0) { + return false; + } + + // If an element with the generated slug as ID already exists, mark the slug as seen. + if (!this.seenIds.hasOwnProperty(slug) && document.querySelector('#' + slug)) { + this.seenIds[slug] = 0; + } + + // If the slug has been returned already, increase the counter, making sure that the ID is not present in the page. + if (this.seenIds.hasOwnProperty(slug)) { + occurrenceAccumulator = this.seenIds[slug]; + do { + occurrenceAccumulator++; + slug = originalSlug + '-' + occurrenceAccumulator; + } while (this.seenIds.hasOwnProperty(slug) || document.querySelector('#' + slug)); + } + this.seenIds[originalSlug] = occurrenceAccumulator; + this.seenIds[slug] = 0; + + return slug; + }, + + /** + * Handles an inpage navigation block with no items. + * + * @param {Element} block + * The inpage navigation block element. + */ + handleEmptyInpageNavigation: function(block) { + block.remove(); + } + }; + + /** + * Theme function for a single inpage navigation item. + * + * @param {string} id + * The ID of the element this item points to. + * @param {string} text + * The text of the link. + * + * @return {string} + * The HTML of the item. + */ + Drupal.theme.oe_theme_inpage_navigation_item = function (id, text) { + return '
  • ' + text + '
  • '; + } +})(ECL, Drupal, jQuery); diff --git a/modules/oe_theme_content_call_proposals/config/install/core.entity_view_display.node.oe_call_proposals.teaser.yml b/modules/oe_theme_content_call_proposals/config/install/core.entity_view_display.node.oe_call_proposals.teaser.yml index e57e9f7ce..061b79abd 100644 --- a/modules/oe_theme_content_call_proposals/config/install/core.entity_view_display.node.oe_call_proposals.teaser.yml +++ b/modules/oe_theme_content_call_proposals/config/install/core.entity_view_display.node.oe_call_proposals.teaser.yml @@ -35,7 +35,7 @@ third_party_settings: - oe_call_proposals_deadline - oe_call_proposals_funding parent_name: '' - weight: 1 + weight: 3 format_type: oe_theme_helper_field_list_pattern region: content format_settings: @@ -49,6 +49,11 @@ bundle: oe_call_proposals mode: teaser content: extra_field_oe_call_proposals_label_status: + weight: 1 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: weight: 0 region: content settings: { } @@ -98,7 +103,6 @@ hidden: body: true extra_field_oe_call_proposals_publication_details: true extra_field_oe_call_proposals_status: true - extra_field_oe_theme_helper_short_title_with_fallback: true langcode: true links: true oe_call_proposals_contact: true diff --git a/modules/oe_theme_content_call_proposals/config/post_updates/00001_update_teaser_view_display/core.entity_view_display.node.oe_call_proposals.teaser.yml b/modules/oe_theme_content_call_proposals/config/post_updates/00001_update_teaser_view_display/core.entity_view_display.node.oe_call_proposals.teaser.yml new file mode 100644 index 000000000..061b79abd --- /dev/null +++ b/modules/oe_theme_content_call_proposals/config/post_updates/00001_update_teaser_view_display/core.entity_view_display.node.oe_call_proposals.teaser.yml @@ -0,0 +1,120 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_call_proposals.body + - field.field.node.oe_call_proposals.oe_call_proposals_contact + - field.field.node.oe_call_proposals.oe_call_proposals_deadline + - field.field.node.oe_call_proposals.oe_call_proposals_funding + - field.field.node.oe_call_proposals.oe_call_proposals_grants + - field.field.node.oe_call_proposals.oe_call_proposals_journal + - field.field.node.oe_call_proposals.oe_call_proposals_model + - field.field.node.oe_call_proposals.oe_call_proposals_opening_date + - field.field.node.oe_call_proposals.oe_departments + - field.field.node.oe_call_proposals.oe_documents + - field.field.node.oe_call_proposals.oe_publication_date + - field.field.node.oe_call_proposals.oe_reference_code + - field.field.node.oe_call_proposals.oe_subject + - field.field.node.oe_call_proposals.oe_summary + - field.field.node.oe_call_proposals.oe_teaser + - node.type.oe_call_proposals + module: + - datetime + - field_group + - options + - rdf_skos + - user +third_party_settings: + field_group: + group_details: + children: + - oe_reference_code + - oe_call_proposals_opening_date + - oe_call_proposals_model + - oe_call_proposals_deadline + - oe_call_proposals_funding + parent_name: '' + weight: 3 + format_type: oe_theme_helper_field_list_pattern + region: content + format_settings: + variant: horizontal + classes: '' + id: '' + label: Details +id: node.oe_call_proposals.teaser +targetEntityType: node +bundle: oe_call_proposals +mode: teaser +content: + extra_field_oe_call_proposals_label_status: + weight: 1 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_call_proposals_deadline: + weight: 4 + label: above + settings: + timezone_override: '' + format_type: oe_call_proposals_teaser_date + third_party_settings: { } + type: datetime_default + region: content + oe_call_proposals_funding: + type: skos_concept_entity_reference_label + weight: 5 + region: content + label: above + settings: + link: false + third_party_settings: { } + oe_call_proposals_model: + weight: 3 + label: above + settings: { } + third_party_settings: { } + type: list_default + region: content + oe_call_proposals_opening_date: + weight: 2 + label: above + settings: + timezone_override: '' + format_type: oe_call_proposals_teaser_date + third_party_settings: { } + type: datetime_default + region: content + oe_reference_code: + weight: 1 + label: above + settings: + link_to_entity: false + third_party_settings: { } + type: string + region: content +hidden: + body: true + extra_field_oe_call_proposals_publication_details: true + extra_field_oe_call_proposals_status: true + langcode: true + links: true + oe_call_proposals_contact: true + oe_call_proposals_grants: true + oe_call_proposals_journal: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_departments: true + oe_documents: true + oe_publication_date: true + oe_subject: true + oe_summary: true + oe_teaser: true diff --git a/modules/oe_theme_content_call_proposals/oe_theme_content_call_proposals.post_update.php b/modules/oe_theme_content_call_proposals/oe_theme_content_call_proposals.post_update.php new file mode 100644 index 000000000..d657ca7a4 --- /dev/null +++ b/modules/oe_theme_content_call_proposals/oe_theme_content_call_proposals.post_update.php @@ -0,0 +1,31 @@ +read('core.entity_view_display.node.oe_call_proposals.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_call_tenders/config/install/core.entity_view_display.node.oe_call_tenders.teaser.yml b/modules/oe_theme_content_call_tenders/config/install/core.entity_view_display.node.oe_call_tenders.teaser.yml index c483c2c08..779bcea77 100644 --- a/modules/oe_theme_content_call_tenders/config/install/core.entity_view_display.node.oe_call_tenders.teaser.yml +++ b/modules/oe_theme_content_call_tenders/config/install/core.entity_view_display.node.oe_call_tenders.teaser.yml @@ -4,6 +4,8 @@ dependencies: config: - core.entity_view_mode.node.teaser - field.field.node.oe_call_tenders.body + - field.field.node.oe_call_tenders.oe_call_tenders_deadline + - field.field.node.oe_call_tenders.oe_call_tenders_opening_date - field.field.node.oe_call_tenders.oe_departments - field.field.node.oe_call_tenders.oe_documents - field.field.node.oe_call_tenders.oe_publication_date @@ -11,8 +13,6 @@ dependencies: - field.field.node.oe_call_tenders.oe_subject - field.field.node.oe_call_tenders.oe_summary - field.field.node.oe_call_tenders.oe_teaser - - field.field.node.oe_call_tenders.oe_call_tenders_deadline - - field.field.node.oe_call_tenders.oe_call_tenders_opening_date - node.type.oe_call_tenders module: - datetime @@ -46,6 +46,29 @@ content: region: content settings: { } third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 2 + region: content + settings: { } + third_party_settings: { } + oe_call_tenders_deadline: + type: datetime_default + weight: 4 + region: content + label: above + settings: + timezone_override: '' + format_type: oe_call_tenders_date_full_timezone + third_party_settings: { } + oe_call_tenders_opening_date: + type: datetime_default + weight: 3 + region: content + label: above + settings: + timezone_override: '' + format_type: oe_call_tenders_date_long + third_party_settings: { } oe_departments: type: skos_concept_entity_reference_label weight: 5 @@ -70,28 +93,9 @@ content: settings: link_to_entity: false third_party_settings: { } - oe_call_tenders_deadline: - type: datetime_default - weight: 4 - region: content - label: above - settings: - timezone_override: '' - format_type: oe_call_tenders_date_full_timezone - third_party_settings: { } - oe_call_tenders_opening_date: - type: datetime_default - weight: 3 - region: content - label: above - settings: - timezone_override: '' - format_type: oe_call_tenders_date_long - third_party_settings: { } hidden: body: true extra_field_oe_call_tenders_status: true - extra_field_oe_theme_helper_short_title_with_fallback: true langcode: true links: true oe_content_content_owner: true diff --git a/modules/oe_theme_content_call_tenders/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_call_tenders.teaser.yml b/modules/oe_theme_content_call_tenders/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_call_tenders.teaser.yml new file mode 100644 index 000000000..779bcea77 --- /dev/null +++ b/modules/oe_theme_content_call_tenders/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_call_tenders.teaser.yml @@ -0,0 +1,109 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_call_tenders.body + - field.field.node.oe_call_tenders.oe_call_tenders_deadline + - field.field.node.oe_call_tenders.oe_call_tenders_opening_date + - field.field.node.oe_call_tenders.oe_departments + - field.field.node.oe_call_tenders.oe_documents + - field.field.node.oe_call_tenders.oe_publication_date + - field.field.node.oe_call_tenders.oe_reference_code + - field.field.node.oe_call_tenders.oe_subject + - field.field.node.oe_call_tenders.oe_summary + - field.field.node.oe_call_tenders.oe_teaser + - node.type.oe_call_tenders + module: + - datetime + - field_group + - rdf_skos + - user +third_party_settings: + field_group: + group_details: + children: + - oe_reference_code + - oe_call_tenders_opening_date + - oe_call_tenders_deadline + - oe_departments + parent_name: '' + weight: 1 + format_type: oe_theme_helper_field_list_pattern + region: content + format_settings: + variant: horizontal + classes: '' + id: '' + label: Details +id: node.oe_call_tenders.teaser +targetEntityType: node +bundle: oe_call_tenders +mode: teaser +content: + extra_field_oe_call_tenders_label_status: + weight: 0 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 2 + region: content + settings: { } + third_party_settings: { } + oe_call_tenders_deadline: + type: datetime_default + weight: 4 + region: content + label: above + settings: + timezone_override: '' + format_type: oe_call_tenders_date_full_timezone + third_party_settings: { } + oe_call_tenders_opening_date: + type: datetime_default + weight: 3 + region: content + label: above + settings: + timezone_override: '' + format_type: oe_call_tenders_date_long + third_party_settings: { } + oe_departments: + type: skos_concept_entity_reference_label + weight: 5 + region: content + label: above + settings: + link: false + third_party_settings: { } + oe_reference: + weight: 1 + label: above + settings: + link_to_entity: false + third_party_settings: { } + type: string + region: content + oe_reference_code: + type: string + weight: 2 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } +hidden: + body: true + extra_field_oe_call_tenders_status: true + langcode: true + links: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_documents: true + oe_publication_date: true + oe_subject: true + oe_summary: true + oe_teaser: true diff --git a/modules/oe_theme_content_call_tenders/oe_theme_content_call_tenders.post_update.php b/modules/oe_theme_content_call_tenders/oe_theme_content_call_tenders.post_update.php index 64f631a0a..d068a815c 100644 --- a/modules/oe_theme_content_call_tenders/oe_theme_content_call_tenders.post_update.php +++ b/modules/oe_theme_content_call_tenders/oe_theme_content_call_tenders.post_update.php @@ -34,3 +34,23 @@ function oe_theme_content_call_tenders_post_update_00001() { $entity = $entity_storage->createFromStorageRecord($config); $entity->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_call_tenders_post_update_00002(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_call_tenders') . '/config/post_updates/00002_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_call_tenders.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_consultation/config/install/core.entity_view_display.node.oe_consultation.teaser.yml b/modules/oe_theme_content_consultation/config/install/core.entity_view_display.node.oe_consultation.teaser.yml index 5a719379f..cd57cddb5 100644 --- a/modules/oe_theme_content_consultation/config/install/core.entity_view_display.node.oe_consultation.teaser.yml +++ b/modules/oe_theme_content_consultation/config/install/core.entity_view_display.node.oe_consultation.teaser.yml @@ -32,7 +32,7 @@ third_party_settings: - oe_consultation_opening_date - oe_consultation_deadline parent_name: '' - weight: 1 + weight: 2 format_type: oe_theme_helper_field_list_pattern region: content format_settings: @@ -44,6 +44,11 @@ bundle: oe_consultation mode: teaser content: extra_field_oe_consultation_label_status: + weight: 1 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: weight: 0 region: content settings: { } @@ -67,9 +72,8 @@ content: type: datetime_default region: content hidden: - extra_field_oe_consultation_status: true - extra_field_oe_theme_helper_short_title_with_fallback: true extra_field_oe_consultation_closed_status_text: true + extra_field_oe_consultation_status: true langcode: true links: true oe_consultation_additional_info: true diff --git a/modules/oe_theme_content_consultation/config/post_updates/00001_update_teaser_view_display/core.entity_view_display.node.oe_consultation.teaser.yml b/modules/oe_theme_content_consultation/config/post_updates/00001_update_teaser_view_display/core.entity_view_display.node.oe_consultation.teaser.yml new file mode 100644 index 000000000..cd57cddb5 --- /dev/null +++ b/modules/oe_theme_content_consultation/config/post_updates/00001_update_teaser_view_display/core.entity_view_display.node.oe_consultation.teaser.yml @@ -0,0 +1,97 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_consultation.oe_consultation_additional_info + - field.field.node.oe_consultation.oe_consultation_aim + - field.field.node.oe_consultation.oe_consultation_closed_text + - field.field.node.oe_consultation.oe_consultation_contacts + - field.field.node.oe_consultation.oe_consultation_deadline + - field.field.node.oe_consultation.oe_consultation_documents + - field.field.node.oe_consultation.oe_consultation_guidelines + - field.field.node.oe_consultation.oe_consultation_legal_info + - field.field.node.oe_consultation.oe_consultation_opening_date + - field.field.node.oe_consultation.oe_consultation_outcome + - field.field.node.oe_consultation.oe_consultation_outcome_files + - field.field.node.oe_consultation.oe_consultation_response_button + - field.field.node.oe_consultation.oe_consultation_target_audience + - field.field.node.oe_consultation.oe_departments + - field.field.node.oe_consultation.oe_subject + - field.field.node.oe_consultation.oe_summary + - field.field.node.oe_consultation.oe_teaser + - node.type.oe_consultation + module: + - datetime + - field_group + - user +third_party_settings: + field_group: + group_details: + children: + - oe_consultation_opening_date + - oe_consultation_deadline + parent_name: '' + weight: 2 + format_type: oe_theme_helper_field_list_pattern + region: content + format_settings: + variant: horizontal + label: Details +id: node.oe_consultation.teaser +targetEntityType: node +bundle: oe_consultation +mode: teaser +content: + extra_field_oe_consultation_label_status: + weight: 1 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_consultation_deadline: + weight: 5 + label: hidden + settings: + timezone_override: '' + format_type: oe_consultation_date_with_time_and_timezone + third_party_settings: { } + type: datetime_default + region: content + oe_consultation_opening_date: + weight: 4 + label: hidden + settings: + timezone_override: '' + format_type: oe_consultation_date + third_party_settings: { } + type: datetime_default + region: content +hidden: + extra_field_oe_consultation_closed_status_text: true + extra_field_oe_consultation_status: true + langcode: true + links: true + oe_consultation_additional_info: true + oe_consultation_aim: true + oe_consultation_closed_text: true + oe_consultation_contacts: true + oe_consultation_documents: true + oe_consultation_guidelines: true + oe_consultation_legal_info: true + oe_consultation_outcome: true + oe_consultation_outcome_files: true + oe_consultation_response_button: true + oe_consultation_target_audience: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_departments: true + oe_subject: true + oe_summary: true + oe_teaser: true diff --git a/modules/oe_theme_content_consultation/oe_theme_content_consultation.post_update.php b/modules/oe_theme_content_consultation/oe_theme_content_consultation.post_update.php new file mode 100644 index 000000000..cda1f199e --- /dev/null +++ b/modules/oe_theme_content_consultation/oe_theme_content_consultation.post_update.php @@ -0,0 +1,31 @@ +read('core.entity_view_display.node.oe_consultation.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.full.yml b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.full.yml index afea75558..ee614d106 100644 --- a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.full.yml +++ b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.full.yml @@ -8,6 +8,7 @@ dependencies: - field.field.oe_contact.oe_general.oe_email - field.field.oe_contact.oe_general.oe_fax - field.field.oe_contact.oe_general.oe_image + - field.field.oe_contact.oe_general.oe_link - field.field.oe_contact.oe_general.oe_mobile - field.field.oe_contact.oe_general.oe_office - field.field.oe_contact.oe_general.oe_organisation @@ -88,12 +89,24 @@ content: third_party_settings: { } oe_image: type: oe_theme_helper_featured_media_formatter - weight: 4 + weight: 5 region: content label: hidden settings: image_style: '' third_party_settings: { } + oe_link: + type: link + weight: 4 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } oe_mobile: type: string weight: 15 diff --git a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.oe_details.yml b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.oe_details.yml index 6c69df986..4df9e20b8 100644 --- a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.oe_details.yml +++ b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_general.oe_details.yml @@ -8,6 +8,7 @@ dependencies: - field.field.oe_contact.oe_general.oe_email - field.field.oe_contact.oe_general.oe_fax - field.field.oe_contact.oe_general.oe_image + - field.field.oe_contact.oe_general.oe_link - field.field.oe_contact.oe_general.oe_mobile - field.field.oe_contact.oe_general.oe_office - field.field.oe_contact.oe_general.oe_organisation @@ -92,6 +93,7 @@ hidden: oe_body: true oe_fax: true oe_image: true + oe_link: true oe_mobile: true oe_office: true oe_organisation: true diff --git a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.full.yml b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.full.yml index cf902e05b..fb054efca 100644 --- a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.full.yml +++ b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.full.yml @@ -2,11 +2,13 @@ langcode: en status: true dependencies: config: + - core.entity_view_mode.oe_contact.full - field.field.oe_contact.oe_press.oe_address - field.field.oe_contact.oe_press.oe_body - field.field.oe_contact.oe_press.oe_email - field.field.oe_contact.oe_press.oe_fax - field.field.oe_contact.oe_press.oe_image + - field.field.oe_contact.oe_press.oe_link - field.field.oe_contact.oe_press.oe_mobile - field.field.oe_contact.oe_press.oe_office - field.field.oe_contact.oe_press.oe_organisation @@ -87,12 +89,24 @@ content: third_party_settings: { } oe_image: type: oe_theme_helper_featured_media_formatter - weight: 4 + weight: 5 region: content label: hidden settings: image_style: '' third_party_settings: { } + oe_link: + type: link + weight: 4 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } oe_mobile: type: string weight: 5 diff --git a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.oe_details.yml b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.oe_details.yml index 18261a31b..fc5c5e352 100644 --- a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.oe_details.yml +++ b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_display.oe_contact.oe_press.oe_details.yml @@ -8,6 +8,7 @@ dependencies: - field.field.oe_contact.oe_press.oe_email - field.field.oe_contact.oe_press.oe_fax - field.field.oe_contact.oe_press.oe_image + - field.field.oe_contact.oe_press.oe_link - field.field.oe_contact.oe_press.oe_mobile - field.field.oe_contact.oe_press.oe_office - field.field.oe_contact.oe_press.oe_organisation @@ -92,6 +93,7 @@ hidden: oe_body: true oe_fax: true oe_image: true + oe_link: true oe_mobile: true oe_office: true oe_organisation: true diff --git a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_mode.oe_contact.full.yml b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_mode.oe_contact.full.yml index 50cb14ccd..366484d3c 100644 --- a/modules/oe_theme_content_entity_contact/config/install/core.entity_view_mode.oe_contact.full.yml +++ b/modules/oe_theme_content_entity_contact/config/install/core.entity_view_mode.oe_contact.full.yml @@ -2,7 +2,7 @@ langcode: en status: true dependencies: module: - - oe_theme_content_entity_contact + - oe_content_entity_contact id: oe_contact.full label: Full targetEntityType: oe_contact diff --git a/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_general.full.yml b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_general.full.yml new file mode 100644 index 000000000..ee614d106 --- /dev/null +++ b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_general.full.yml @@ -0,0 +1,181 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.oe_contact.full + - field.field.oe_contact.oe_general.oe_address + - field.field.oe_contact.oe_general.oe_body + - field.field.oe_contact.oe_general.oe_email + - field.field.oe_contact.oe_general.oe_fax + - field.field.oe_contact.oe_general.oe_image + - field.field.oe_contact.oe_general.oe_link + - field.field.oe_contact.oe_general.oe_mobile + - field.field.oe_contact.oe_general.oe_office + - field.field.oe_contact.oe_general.oe_organisation + - field.field.oe_contact.oe_general.oe_phone + - field.field.oe_contact.oe_general.oe_press_contact_url + - field.field.oe_contact.oe_general.oe_social_media + - field.field.oe_contact.oe_general.oe_website + - oe_content_entity_contact.oe_contact_type.oe_general + module: + - field_group + - link + - oe_theme_helper + - text +third_party_settings: + field_group: + group_contact_information: + children: + - oe_organisation + - oe_website + - oe_email + - oe_phone + - oe_mobile + - oe_fax + - oe_address + - oe_office + - oe_social_media + parent_name: '' + weight: 2 + format_type: oe_theme_helper_field_list_pattern + format_settings: + variant: horizontal + classes: '' + id: '' + label: 'Contact information' + region: content +id: oe_contact.oe_general.full +targetEntityType: oe_contact +bundle: oe_general +mode: full +content: + name: + type: string + weight: 0 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_address: + weight: 17 + label: hidden + settings: + delimiter: ', ' + third_party_settings: { } + type: oe_theme_helper_address_inline + region: content + oe_body: + type: text_default + weight: 1 + region: content + label: hidden + settings: { } + third_party_settings: { } + oe_email: + weight: 13 + label: hidden + settings: { } + third_party_settings: { } + type: email_mailto + region: content + oe_fax: + type: string + weight: 16 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_image: + type: oe_theme_helper_featured_media_formatter + weight: 5 + region: content + label: hidden + settings: + image_style: '' + third_party_settings: { } + oe_link: + type: link + weight: 4 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + oe_mobile: + type: string + weight: 15 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_office: + type: string + weight: 18 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_organisation: + type: string + weight: 11 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_phone: + weight: 14 + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + type: string + region: content + oe_press_contact_url: + type: link + weight: 3 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + oe_social_media: + type: oe_theme_helper_social_media_icons_list_formatter + weight: 19 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: nofollow + target: _blank + third_party_settings: { } + oe_website: + type: link + weight: 12 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } +hidden: + created: true + langcode: true + status: true diff --git a/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_general.oe_details.yml b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_general.oe_details.yml new file mode 100644 index 000000000..4df9e20b8 --- /dev/null +++ b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_general.oe_details.yml @@ -0,0 +1,102 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.oe_contact.oe_details + - field.field.oe_contact.oe_general.oe_address + - field.field.oe_contact.oe_general.oe_body + - field.field.oe_contact.oe_general.oe_email + - field.field.oe_contact.oe_general.oe_fax + - field.field.oe_contact.oe_general.oe_image + - field.field.oe_contact.oe_general.oe_link + - field.field.oe_contact.oe_general.oe_mobile + - field.field.oe_contact.oe_general.oe_office + - field.field.oe_contact.oe_general.oe_organisation + - field.field.oe_contact.oe_general.oe_phone + - field.field.oe_contact.oe_general.oe_press_contact_url + - field.field.oe_contact.oe_general.oe_social_media + - field.field.oe_contact.oe_general.oe_website + - oe_content_entity_contact.oe_contact_type.oe_general + module: + - field_group + - oe_theme_helper +third_party_settings: + field_group: + group_contact_information: + children: + - name + - oe_email + - oe_phone + - oe_address + parent_name: '' + weight: 0 + format_type: oe_theme_helper_field_list_pattern + format_settings: + variant: horizontal + classes: '' + id: '' + label: 'Contact information' + region: content +id: oe_contact.oe_general.oe_details +targetEntityType: oe_contact +bundle: oe_general +mode: oe_details +content: + name: + type: string + weight: 0 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } + oe_address: + weight: 3 + label: above + settings: + delimiter: ', ' + third_party_settings: { } + type: oe_theme_helper_address_inline + region: content + oe_email: + weight: 1 + label: above + settings: { } + third_party_settings: { } + type: basic_string + region: content + oe_phone: + weight: 2 + label: above + settings: + link_to_entity: false + third_party_settings: { } + type: string + region: content + oe_social_media: + type: oe_theme_helper_social_media_links_formatter + weight: 5 + region: content + label: hidden + settings: + trim_length: 80 + rel: nofollow + target: _blank + title: 'Social media' + variant: horizontal + url_only: false + url_plain: false + third_party_settings: { } +hidden: + created: true + langcode: true + oe_body: true + oe_fax: true + oe_image: true + oe_link: true + oe_mobile: true + oe_office: true + oe_organisation: true + oe_press_contact_url: true + oe_website: true + status: true diff --git a/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_press.full.yml b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_press.full.yml new file mode 100644 index 000000000..fb054efca --- /dev/null +++ b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_press.full.yml @@ -0,0 +1,181 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.oe_contact.full + - field.field.oe_contact.oe_press.oe_address + - field.field.oe_contact.oe_press.oe_body + - field.field.oe_contact.oe_press.oe_email + - field.field.oe_contact.oe_press.oe_fax + - field.field.oe_contact.oe_press.oe_image + - field.field.oe_contact.oe_press.oe_link + - field.field.oe_contact.oe_press.oe_mobile + - field.field.oe_contact.oe_press.oe_office + - field.field.oe_contact.oe_press.oe_organisation + - field.field.oe_contact.oe_press.oe_phone + - field.field.oe_contact.oe_press.oe_press_contact_url + - field.field.oe_contact.oe_press.oe_social_media + - field.field.oe_contact.oe_press.oe_website + - oe_content_entity_contact.oe_contact_type.oe_press + module: + - field_group + - link + - oe_theme_helper + - text +third_party_settings: + field_group: + group_contact_information: + children: + - oe_organisation + - oe_website + - oe_email + - oe_phone + - oe_mobile + - oe_fax + - oe_address + - oe_office + - oe_social_media + parent_name: '' + weight: 2 + format_type: oe_theme_helper_field_list_pattern + format_settings: + variant: horizontal + classes: '' + id: '' + label: 'Contact information' + region: content +id: oe_contact.oe_press.full +targetEntityType: oe_contact +bundle: oe_press +mode: full +content: + name: + type: string + weight: 0 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_address: + weight: 7 + label: hidden + settings: + delimiter: ', ' + third_party_settings: { } + type: oe_theme_helper_address_inline + region: content + oe_body: + type: text_default + weight: 1 + region: content + label: hidden + settings: { } + third_party_settings: { } + oe_email: + weight: 3 + label: hidden + settings: { } + third_party_settings: { } + type: basic_string + region: content + oe_fax: + type: string + weight: 6 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_image: + type: oe_theme_helper_featured_media_formatter + weight: 5 + region: content + label: hidden + settings: + image_style: '' + third_party_settings: { } + oe_link: + type: link + weight: 4 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + oe_mobile: + type: string + weight: 5 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_office: + type: string + weight: 8 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_organisation: + type: string + weight: 1 + region: content + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + oe_phone: + weight: 4 + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + type: string + region: content + oe_press_contact_url: + type: link + weight: 3 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + oe_social_media: + type: oe_theme_helper_social_media_icons_list_formatter + weight: 9 + region: content + label: hidden + settings: + trim_length: 80 + rel: nofollow + target: _blank + url_only: false + url_plain: false + third_party_settings: { } + oe_website: + type: link + weight: 2 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } +hidden: + created: true + langcode: true + status: true diff --git a/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_press.oe_details.yml b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_press.oe_details.yml new file mode 100644 index 000000000..fc5c5e352 --- /dev/null +++ b/modules/oe_theme_content_entity_contact/config/post_updates/00003_full_view_display_link_field/core.entity_view_display.oe_contact.oe_press.oe_details.yml @@ -0,0 +1,102 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.oe_contact.oe_details + - field.field.oe_contact.oe_press.oe_address + - field.field.oe_contact.oe_press.oe_body + - field.field.oe_contact.oe_press.oe_email + - field.field.oe_contact.oe_press.oe_fax + - field.field.oe_contact.oe_press.oe_image + - field.field.oe_contact.oe_press.oe_link + - field.field.oe_contact.oe_press.oe_mobile + - field.field.oe_contact.oe_press.oe_office + - field.field.oe_contact.oe_press.oe_organisation + - field.field.oe_contact.oe_press.oe_phone + - field.field.oe_contact.oe_press.oe_press_contact_url + - field.field.oe_contact.oe_press.oe_social_media + - field.field.oe_contact.oe_press.oe_website + - oe_content_entity_contact.oe_contact_type.oe_press + module: + - field_group + - oe_theme_helper +third_party_settings: + field_group: + group_contact_information: + children: + - name + - oe_email + - oe_phone + - oe_address + parent_name: '' + weight: 0 + format_type: oe_theme_helper_field_list_pattern + format_settings: + variant: horizontal + classes: '' + id: '' + label: 'Contact information' + region: content +id: oe_contact.oe_press.oe_details +targetEntityType: oe_contact +bundle: oe_press +mode: oe_details +content: + name: + label: above + type: string + weight: 1 + region: content + settings: + link_to_entity: false + third_party_settings: { } + oe_address: + weight: 4 + label: above + settings: + delimiter: ', ' + third_party_settings: { } + type: oe_theme_helper_address_inline + region: content + oe_email: + weight: 2 + label: above + settings: { } + third_party_settings: { } + type: basic_string + region: content + oe_phone: + weight: 3 + label: above + settings: + link_to_entity: false + third_party_settings: { } + type: string + region: content + oe_social_media: + type: oe_theme_helper_social_media_links_formatter + weight: 4 + region: content + label: hidden + settings: + trim_length: 80 + rel: nofollow + target: _blank + title: 'Social media' + variant: horizontal + url_only: false + url_plain: false + third_party_settings: { } +hidden: + created: true + langcode: true + oe_body: true + oe_fax: true + oe_image: true + oe_link: true + oe_mobile: true + oe_office: true + oe_organisation: true + oe_press_contact_url: true + oe_website: true + status: true diff --git a/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.info.yml b/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.info.yml index 30afe3cbf..e68732134 100755 --- a/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.info.yml +++ b/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.info.yml @@ -7,3 +7,11 @@ core: 8.x dependencies: - oe_theme:oe_theme_helper - oe_content:oe_content_entity_contact + +config_devel: + install: + - core.entity_view_display.oe_contact.oe_general.full + - core.entity_view_display.oe_contact.oe_general.oe_details + - core.entity_view_display.oe_contact.oe_press.full + - core.entity_view_display.oe_contact.oe_press.oe_details + - core.entity_view_mode.oe_contact.full diff --git a/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.post_update.php b/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.post_update.php index f59f1f108..5da14eba3 100644 --- a/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.post_update.php +++ b/modules/oe_theme_content_entity_contact/oe_theme_content_entity_contact.post_update.php @@ -65,3 +65,28 @@ function oe_theme_content_entity_contact_post_update_00002(): void { $entity->save(); } } + +/** + * Add Link field to the "Full" and "Details" Contact entity view displays. + */ +function oe_theme_content_entity_contact_post_update_00003(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_entity_contact') . '/config/post_updates/00003_full_view_display_link_field'); + + // View display configurations to update. + $displays = [ + 'core.entity_view_display.oe_contact.oe_general.full', + 'core.entity_view_display.oe_contact.oe_general.oe_details', + 'core.entity_view_display.oe_contact.oe_press.full', + 'core.entity_view_display.oe_contact.oe_press.oe_details', + ]; + foreach ($displays as $display) { + $display_values = $storage->read($display); + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $updated_display = \Drupal::entityTypeManager() + ->getStorage($view_display->getEntityTypeId()) + ->updateFromStorageRecord($view_display, $display_values); + $updated_display->save(); + } + } +} diff --git a/modules/oe_theme_content_entity_organisation/oe_theme_content_entity_organisation.module b/modules/oe_theme_content_entity_organisation/oe_theme_content_entity_organisation.module index 1869d10f0..985469ba1 100644 --- a/modules/oe_theme_content_entity_organisation/oe_theme_content_entity_organisation.module +++ b/modules/oe_theme_content_entity_organisation/oe_theme_content_entity_organisation.module @@ -31,15 +31,19 @@ function oe_theme_content_entity_organisation_preprocess_oe_organisation(&$varia $media_image = \Drupal::service('entity.repository')->getTranslationFromContext($media_image); $cacheability = CacheableMetadata::createFromRenderArray($variables); $cacheability->addCacheableDependency($media_image); - - // Get the media source. - $source = $media_image->getSource(); - if ($source instanceof MediaAvPortalPhotoSource || $source instanceof Image) { - $thumbnail = $media_image->get('thumbnail')->first(); - $variables['logo'] = ImageValueObject::fromStyledImageItem($thumbnail, 'oe_theme_medium_no_crop'); - $cacheability->addCacheableDependency($thumbnail->entity); + // Run access checks on the media entity. + $access = $media_image->access('view', NULL, TRUE); + $cacheability->addCacheableDependency($access); + if ($access->isAllowed()) { + // Get the media source. + $source = $media_image->getSource(); + if ($source instanceof MediaAvPortalPhotoSource || $source instanceof Image) { + $thumbnail = $media_image->get('thumbnail')->first(); + $variables['logo'] = ImageValueObject::fromStyledImageItem($thumbnail, 'oe_theme_medium_no_crop'); + $cacheability->addCacheableDependency($thumbnail->entity); + } + $cacheability->applyTo($variables); } - $cacheability->applyTo($variables); } // Set contact page url. diff --git a/modules/oe_theme_content_event/config/install/core.entity_view_display.node.oe_event.teaser.yml b/modules/oe_theme_content_event/config/install/core.entity_view_display.node.oe_event.teaser.yml index 44748e6b3..3c38b08c0 100644 --- a/modules/oe_theme_content_event/config/install/core.entity_view_display.node.oe_event.teaser.yml +++ b/modules/oe_theme_content_event/config/install/core.entity_view_display.node.oe_event.teaser.yml @@ -41,17 +41,22 @@ bundle: oe_event mode: teaser content: extra_field_oe_theme_content_event_date_aware_status: - weight: 2 + weight: 3 region: content settings: { } third_party_settings: { } extra_field_oe_theme_content_event_teaser_details: - weight: 0 + weight: 1 region: content settings: { } third_party_settings: { } extra_field_oe_theme_content_event_teaser_meta: - weight: 1 + weight: 2 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 region: content settings: { } third_party_settings: { } diff --git a/modules/oe_theme_content_event/config/post_updates/00003_update_teaser_view_display/core.entity_view_display.node.oe_event.teaser.yml b/modules/oe_theme_content_event/config/post_updates/00003_update_teaser_view_display/core.entity_view_display.node.oe_event.teaser.yml new file mode 100644 index 000000000..3c38b08c0 --- /dev/null +++ b/modules/oe_theme_content_event/config/post_updates/00003_update_teaser_view_display/core.entity_view_display.node.oe_event.teaser.yml @@ -0,0 +1,105 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_event.body + - field.field.node.oe_event.oe_author + - field.field.node.oe_event.oe_event_contact + - field.field.node.oe_event.oe_event_dates + - field.field.node.oe_event.oe_event_description_summary + - field.field.node.oe_event.oe_event_entrance_fee + - field.field.node.oe_event.oe_event_featured_media + - field.field.node.oe_event.oe_event_featured_media_legend + - field.field.node.oe_event.oe_event_languages + - field.field.node.oe_event.oe_event_online_dates + - field.field.node.oe_event.oe_event_online_description + - field.field.node.oe_event.oe_event_online_link + - field.field.node.oe_event.oe_event_online_type + - field.field.node.oe_event.oe_event_organiser_internal + - field.field.node.oe_event.oe_event_organiser_is_internal + - field.field.node.oe_event.oe_event_organiser_name + - field.field.node.oe_event.oe_event_registration_capacity + - field.field.node.oe_event.oe_event_registration_dates + - field.field.node.oe_event.oe_event_registration_url + - field.field.node.oe_event.oe_event_report_summary + - field.field.node.oe_event.oe_event_report_text + - field.field.node.oe_event.oe_event_status + - field.field.node.oe_event.oe_event_type + - field.field.node.oe_event.oe_event_venue + - field.field.node.oe_event.oe_event_website + - field.field.node.oe_event.oe_social_media_links + - field.field.node.oe_event.oe_subject + - field.field.node.oe_event.oe_summary + - field.field.node.oe_event.oe_teaser + - node.type.oe_event + module: + - user +id: node.oe_event.teaser +targetEntityType: node +bundle: oe_event +mode: teaser +content: + extra_field_oe_theme_content_event_date_aware_status: + weight: 3 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_content_event_teaser_details: + weight: 1 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_content_event_teaser_meta: + weight: 2 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } +hidden: + body: true + extra_field_oe_theme_content_event_contacts: true + extra_field_oe_theme_content_event_description: true + extra_field_oe_theme_content_event_details: true + extra_field_oe_theme_content_event_organiser: true + extra_field_oe_theme_content_event_registration_button: true + extra_field_oe_theme_content_event_summary: true + langcode: true + links: true + oe_author: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_event_contact: true + oe_event_dates: true + oe_event_description_summary: true + oe_event_entrance_fee: true + oe_event_featured_media: true + oe_event_featured_media_legend: true + oe_event_languages: true + oe_event_online_dates: true + oe_event_online_description: true + oe_event_online_link: true + oe_event_online_type: true + oe_event_organiser_internal: true + oe_event_organiser_is_internal: true + oe_event_organiser_name: true + oe_event_registration_capacity: true + oe_event_registration_dates: true + oe_event_registration_status: true + oe_event_registration_url: true + oe_event_report_summary: true + oe_event_report_text: true + oe_event_status: true + oe_event_type: true + oe_event_venue: true + oe_event_website: true + oe_social_media_links: true + oe_subject: true + oe_summary: true + oe_teaser: true diff --git a/modules/oe_theme_content_event/oe_theme_content_event.post_update.php b/modules/oe_theme_content_event/oe_theme_content_event.post_update.php index 32bb04711..4ba5625d7 100644 --- a/modules/oe_theme_content_event/oe_theme_content_event.post_update.php +++ b/modules/oe_theme_content_event/oe_theme_content_event.post_update.php @@ -54,3 +54,23 @@ function oe_theme_content_event_post_update_00002() { $entity = $entity_storage->createFromStorageRecord($config); $entity->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_event_post_update_00003(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_event') . '/config/post_updates/00003_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_event.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DescriptionExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DescriptionExtraField.php index b3bf74649..546a50471 100755 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DescriptionExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DescriptionExtraField.php @@ -193,6 +193,15 @@ protected function addFeaturedMediaThumbnail(array &$build, ContentEntityInterfa $cache = new CacheableMetadata(); $cache->addCacheableDependency($media); + + // Run access checks on the media entity. + $access = $media->access('view', NULL, TRUE); + $cache->addCacheableDependency($access); + if (!$access->isAllowed()) { + $cache->applyTo($build); + return; + } + $thumbnail = !$media->get('thumbnail')->isEmpty() ? $media->get('thumbnail')->first() : NULL; if (!$thumbnail instanceof ImageItem || !$thumbnail->entity instanceof FileInterface) { $cache->applyTo($build); diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DetailsExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DetailsExtraField.php index 10e63a8c7..acff6bdbb 100755 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DetailsExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/DetailsExtraField.php @@ -4,11 +4,10 @@ namespace Drupal\oe_theme_content_event\Plugin\ExtraField\Display; -use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Render\RendererInterface; use Drupal\oe_content_entity_venue\Entity\VenueInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -24,7 +23,7 @@ * visible = true * ) */ -class DetailsExtraField extends EventExtraFieldBase implements ContainerFactoryPluginInterface { +class DetailsExtraField extends EventExtraFieldBase { /** * The entity repository. @@ -33,6 +32,13 @@ class DetailsExtraField extends EventExtraFieldBase implements ContainerFactoryP */ protected $entityRepository; + /** + * The renderer service. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + /** * EventExtraFieldBase constructor. * @@ -46,10 +52,17 @@ class DetailsExtraField extends EventExtraFieldBase implements ContainerFactoryP * The entity type manager. * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository * The entity repository service. + * @param \Drupal\Core\Render\RendererInterface|null $renderer + * The renderer service. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository, RendererInterface $renderer = NULL) { parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager); $this->entityRepository = $entity_repository; + // Load service statically to provide backward compatibility. + if (!$renderer instanceof RendererInterface) { + $renderer = \Drupal::service('renderer'); + } + $this->renderer = $renderer; } /** @@ -61,7 +74,8 @@ public static function create(ContainerInterface $container, array $configuratio $plugin_id, $plugin_definition, $container->get('entity_type.manager'), - $container->get('entity.repository') + $container->get('entity.repository'), + $container->get('renderer') ); } @@ -95,12 +109,7 @@ public function viewElements(ContentEntityInterface $entity) { ]; $this->addRenderableLocation($build, $entity); - if (!$entity->get('oe_event_online_type')->isEmpty()) { - $build['#fields']['items'][] = [ - 'icon' => 'livestreaming', - 'text' => $this->t('Live streaming available'), - ]; - } + $this->addRenderableOnlineType($build, $entity); return $build; } @@ -144,7 +153,7 @@ protected function getRenderableDates(ContentEntityInterface $entity): array { } /** - * Add event location to event details, if any. + * Add event locality and country to event details. * * @param array $build * Render array. @@ -152,41 +161,70 @@ protected function getRenderableDates(ContentEntityInterface $entity): array { * Content entity. */ protected function addRenderableLocation(array &$build, ContentEntityInterface $entity): void { - if ($entity->get('oe_event_venue')->isEmpty()) { - return; - } - - $venue = $entity->get('oe_event_venue')->entity; - if (!$venue instanceof VenueInterface) { - return; + if (!$entity->get('oe_event_venue')->isEmpty() && $entity->get('oe_event_venue')->entity instanceof VenueInterface) { + $address = $this->getVenueInlineAddress($entity->get('oe_event_venue')->entity); + if (!empty($address)) { + $build['#fields']['items'][] = [ + 'icon' => 'location', + 'text' => [ + '#markup' => $address, + ], + ]; + } } + } + /** + * Gets rendered address field from Venue entity. + * + * @param \Drupal\oe_content_entity_venue\Entity\VenueInterface $venue + * Venue entity. + * + * @return string|null + * Rendered address field. + */ + protected function getVenueInlineAddress(VenueInterface $venue): ?string { $venue = $this->entityRepository->getTranslationFromContext($venue); - $cacheability = CacheableMetadata::createFromRenderArray($build); - $access = $venue->access('view', NULL, TRUE); - $cacheability->addCacheableDependency($access); - if (!$access->isAllowed()) { - return; + return NULL; } - $cacheability->addCacheableDependency($venue); - $cacheability->applyTo($build); + // Bubble cacheability metadata of the entity into the current render + // context. + $build = $this->entityTypeManager->getViewBuilder('oe_venue')->view($venue); + $this->renderer->render($build); - // If address is empty only return cache metadata, so it can bubble up. if ($venue->get('oe_address')->isEmpty()) { - return; + return NULL; } - // Only display locality and country, inline. + $location = []; $renderable = $this->entityTypeManager->getViewBuilder('oe_venue')->viewField($venue->get('oe_address')); - $build['#fields']['items'][] = [ - 'icon' => 'location', - 'text' => [ - '#markup' => $renderable[0]['locality']['#value'] . ', ' . $renderable[0]['country']['#value'], - ], - ]; + foreach (['locality', 'country'] as $field) { + if (!empty($renderable[0][$field]['#value'])) { + $location[] = $renderable[0][$field]['#value']; + } + } + + return implode(', ', $location); + } + + /** + * Add event online type to event details. + * + * @param array $build + * Render array. + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * Content entity. + */ + protected function addRenderableOnlineType(array &$build, ContentEntityInterface $entity): void { + if (!$entity->get('oe_event_online_type')->isEmpty()) { + $build['#fields']['items'][] = [ + 'icon' => 'livestreaming', + 'text' => $this->t('Live streaming available'), + ]; + } } } diff --git a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php index 1ce0edddc..c87e1114e 100644 --- a/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php +++ b/modules/oe_theme_content_event/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php @@ -4,12 +4,7 @@ namespace Drupal\oe_theme_content_event\Plugin\ExtraField\Display; -use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\ContentEntityInterface; -use Drupal\Core\Entity\EntityRepositoryInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\oe_content_entity_venue\Entity\VenueInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Extra field displaying event details on teasers. @@ -23,46 +18,7 @@ * visible = false * ) */ -class TeaserDetailsExtraField extends EventExtraFieldBase { - - /** - * The entity repository. - * - * @var \Drupal\Core\Entity\EntityRepositoryInterface - */ - protected $entityRepository; - - /** - * TeaserDetailsExtraField constructor. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager - * The entity type manager. - * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository - * The entity repository service. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityRepositoryInterface $entity_repository) { - parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager); - $this->entityRepository = $entity_repository; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('entity_type.manager'), - $container->get('entity.repository') - ); - } +class TeaserDetailsExtraField extends DetailsExtraField { /** * {@inheritdoc} @@ -84,31 +40,9 @@ public function viewElements(ContentEntityInterface $entity) { ], ]; - $cache = CacheableMetadata::createFromRenderArray($build); - if (!$entity->get('oe_event_venue')->isEmpty() && $entity->get('oe_event_venue')->entity instanceof VenueInterface) { - /** @var \Drupal\oe_content_entity_venue\Entity\VenueInterface $venue */ - $venue = $this->entityRepository->getTranslationFromContext($entity->get('oe_event_venue')->entity); - $venue_access = $venue->access('view', NULL, TRUE); - - $cache->addCacheableDependency($venue); - $cache->addCacheableDependency($venue_access); - if ($venue_access->isAllowed() && !$venue->get('oe_address')->isEmpty()) { - $renderable = $this->entityTypeManager->getViewBuilder('oe_venue')->viewField($venue->get('oe_address')); - $build['#fields']['items'][] = [ - 'icon' => 'location', - 'text' => $renderable[0]['locality']['#value'] . ', ' . $renderable[0]['country']['#value'], - ]; - } - } - - if (!$entity->get('oe_event_online_type')->isEmpty()) { - $build['#fields']['items'][] = [ - 'icon' => 'livestreaming', - 'text' => $this->t('Live streaming available'), - ]; - } + $this->addRenderableLocation($build, $entity); + $this->addRenderableOnlineType($build, $entity); - $cache->applyTo($build); return $build; } diff --git a/modules/oe_theme_content_news/config/post_updates/00008_update_teaser_view_display/core.entity_view_display.node.oe_news.teaser.yml b/modules/oe_theme_content_news/config/post_updates/00008_update_teaser_view_display/core.entity_view_display.node.oe_news.teaser.yml new file mode 100644 index 000000000..6d935aed6 --- /dev/null +++ b/modules/oe_theme_content_news/config/post_updates/00008_update_teaser_view_display/core.entity_view_display.node.oe_news.teaser.yml @@ -0,0 +1,78 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_news.body + - field.field.node.oe_news.oe_author + - field.field.node.oe_news.oe_news_featured_media + - field.field.node.oe_news.oe_news_location + - field.field.node.oe_news.oe_news_types + - field.field.node.oe_news.oe_publication_date + - field.field.node.oe_news.oe_related_links + - field.field.node.oe_news.oe_subject + - field.field.node.oe_news.oe_summary + - field.field.node.oe_news.oe_teaser + - image.style.oe_theme_ratio_3_2_medium + - node.type.oe_news + module: + - datetime + - oe_theme_helper + - rdf_skos + - text + - user +id: node.oe_news.teaser +targetEntityType: node +bundle: oe_news +mode: teaser +content: + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_news_featured_media: + type: oe_theme_helper_media_thumbnail_url + weight: 3 + region: content + label: hidden + settings: + image_style: oe_theme_ratio_3_2_medium + third_party_settings: { } + oe_news_types: + type: skos_concept_entity_reference_label + weight: 1 + region: content + label: hidden + settings: + link: false + third_party_settings: { } + oe_publication_date: + type: datetime_default + weight: 2 + region: content + label: hidden + settings: + timezone_override: '' + format_type: oe_theme_news_date + third_party_settings: { } + oe_teaser: + type: text_default + weight: 4 + region: content + label: hidden + settings: { } + third_party_settings: { } +hidden: + body: true + langcode: true + links: true + oe_author: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_news_location: true + oe_related_links: true + oe_subject: true + oe_summary: true diff --git a/modules/oe_theme_content_news/oe_theme_content_news.module b/modules/oe_theme_content_news/oe_theme_content_news.module index 93e31f084..35bc55296 100644 --- a/modules/oe_theme_content_news/oe_theme_content_news.module +++ b/modules/oe_theme_content_news/oe_theme_content_news.module @@ -7,6 +7,7 @@ declare(strict_types = 1); +use Drupal\Core\Cache\CacheableMetadata; use Drupal\media\MediaInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; @@ -24,6 +25,17 @@ function oe_theme_content_news_preprocess_node__oe_news(&$variables) { $media = $node->get('oe_news_featured_media')->entity; if ($media instanceof MediaInterface) { + $cacheability = CacheableMetadata::createFromRenderArray($variables); + $cacheability->addCacheableDependency($media); + + // Run access checks on the media entity. + $access = $media->access('view', $variables['user'], TRUE); + $cacheability->addCacheableDependency($access); + $cacheability->applyTo($variables); + if (!$access->isAllowed()) { + return; + } + $builder = \Drupal::entityTypeManager()->getViewBuilder('media'); $variables['content']['featured_image'] = $builder->view($media, 'oe_theme_main_content'); // Show the image always at the top. diff --git a/modules/oe_theme_content_news/oe_theme_content_news.post_update.php b/modules/oe_theme_content_news/oe_theme_content_news.post_update.php index 311568449..5dfd07af5 100644 --- a/modules/oe_theme_content_news/oe_theme_content_news.post_update.php +++ b/modules/oe_theme_content_news/oe_theme_content_news.post_update.php @@ -108,3 +108,23 @@ function oe_theme_content_news_post_update_00007() { $entity = $entity_storage->createFromStorageRecord($config); $entity->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_news_post_update_00008(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_news') . '/config/post_updates/00008_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_news.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.full.yml b/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.full.yml index bafa0ffbb..606064a2d 100644 --- a/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.full.yml +++ b/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.full.yml @@ -2,20 +2,27 @@ langcode: en status: true dependencies: config: + - core.entity_view_mode.node.full - field.field.node.oe_organisation.body + - field.field.node.oe_organisation.oe_organisation_staff_link - field.field.node.oe_organisation.oe_organisation_acronym - field.field.node.oe_organisation.oe_organisation_contact - field.field.node.oe_organisation.oe_organisation_eu_org - field.field.node.oe_organisation.oe_organisation_eu_org_type - field.field.node.oe_organisation.oe_organisation_logo - field.field.node.oe_organisation.oe_organisation_non_eu_org_type + - field.field.node.oe_organisation.oe_organisation_chart - field.field.node.oe_organisation.oe_organisation_org_type + - field.field.node.oe_organisation.oe_organisation_overview + - field.field.node.oe_organisation.oe_organisation_persons - field.field.node.oe_organisation.oe_summary - field.field.node.oe_organisation.oe_teaser - node.type.oe_organisation module: + - description_list_field - entity_reference_revisions - field_group + - link - text - user third_party_settings: @@ -23,7 +30,9 @@ third_party_settings: group_in_page_navigation: children: - oe_organisation_logo + - group_overview - group_description + - group_leadership_and_organisation - group_contact parent_name: '' weight: 0 @@ -37,24 +46,48 @@ third_party_settings: children: - body parent_name: group_in_page_navigation - weight: 1 + weight: 2 format_type: oe_theme_helper_in_page_navigation_item region: content format_settings: id: '' classes: '' - label: Description + label: '' group_contact: children: - oe_organisation_contact parent_name: group_in_page_navigation - weight: 2 + weight: 4 format_type: oe_theme_helper_in_page_navigation_item region: content format_settings: id: '' classes: '' label: Contact + group_overview: + children: + - oe_organisation_overview + parent_name: group_in_page_navigation + weight: 1 + format_type: oe_theme_helper_in_page_navigation_item + region: content + format_settings: + id: '' + classes: '' + label: Overview + group_leadership_and_organisation: + children: + - oe_organisation_persons + - oe_organisation_chart + - oe_organisation_staff_link + parent_name: group_in_page_navigation + weight: 3 + format_type: oe_theme_helper_in_page_navigation_item + region: content + format_settings: + id: '' + classes: '' + label: 'Leadership and organisation' id: node.oe_organisation.full targetEntityType: node bundle: oe_organisation @@ -72,6 +105,18 @@ content: region: content settings: { } third_party_settings: { } + oe_organisation_staff_link: + type: link + weight: 2 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } oe_organisation_contact: weight: 6 label: hidden @@ -89,6 +134,31 @@ content: settings: link: true third_party_settings: { } + oe_organisation_chart: + type: entity_reference_entity_view + weight: 1 + region: content + label: hidden + settings: + view_mode: default + link: false + third_party_settings: { } + oe_organisation_overview: + type: description_list_formatter + weight: 0 + region: content + label: hidden + settings: { } + third_party_settings: { } + oe_organisation_persons: + type: entity_reference_entity_view + weight: 0 + region: content + label: hidden + settings: + view_mode: oe_compact_teaser + link: false + third_party_settings: { } hidden: extra_field_oe_theme_content_organisation_teaser_details: true extra_field_oe_theme_helper_short_title_with_fallback: true diff --git a/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.teaser.yml b/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.teaser.yml index 9cd0494dc..4b86dc03b 100644 --- a/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.teaser.yml +++ b/modules/oe_theme_content_organisation/config/install/core.entity_view_display.node.oe_organisation.teaser.yml @@ -26,7 +26,12 @@ bundle: oe_organisation mode: teaser content: extra_field_oe_theme_content_organisation_teaser_details: - weight: 2 + weight: 4 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 3 region: content settings: { } third_party_settings: { } @@ -48,7 +53,7 @@ content: third_party_settings: { } oe_organisation_logo: type: oe_theme_helper_media_thumbnail_url - weight: 4 + weight: 6 region: content label: above settings: @@ -64,14 +69,13 @@ content: third_party_settings: { } oe_teaser: type: text_default - weight: 3 + weight: 5 region: content label: above settings: { } third_party_settings: { } hidden: body: true - extra_field_oe_theme_helper_short_title_with_fallback: true langcode: true links: true oe_content_content_owner: true diff --git a/modules/oe_theme_content_organisation/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_organisation.teaser.yml b/modules/oe_theme_content_organisation/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_organisation.teaser.yml new file mode 100644 index 000000000..4b86dc03b --- /dev/null +++ b/modules/oe_theme_content_organisation/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_organisation.teaser.yml @@ -0,0 +1,88 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_organisation.body + - field.field.node.oe_organisation.oe_organisation_acronym + - field.field.node.oe_organisation.oe_organisation_contact + - field.field.node.oe_organisation.oe_organisation_eu_org + - field.field.node.oe_organisation.oe_organisation_eu_org_type + - field.field.node.oe_organisation.oe_organisation_logo + - field.field.node.oe_organisation.oe_organisation_non_eu_org_type + - field.field.node.oe_organisation.oe_organisation_org_type + - field.field.node.oe_organisation.oe_summary + - field.field.node.oe_organisation.oe_teaser + - image.style.oe_theme_medium_no_crop + - node.type.oe_organisation + module: + - oe_theme_helper + - rdf_skos + - text + - user +id: node.oe_organisation.teaser +targetEntityType: node +bundle: oe_organisation +mode: teaser +content: + extra_field_oe_theme_content_organisation_teaser_details: + weight: 4 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 3 + region: content + settings: { } + third_party_settings: { } + oe_organisation_acronym: + type: string + weight: 2 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } + oe_organisation_eu_org_type: + type: skos_concept_entity_reference_label + weight: 0 + region: content + label: above + settings: + link: false + third_party_settings: { } + oe_organisation_logo: + type: oe_theme_helper_media_thumbnail_url + weight: 6 + region: content + label: above + settings: + image_style: oe_theme_medium_no_crop + third_party_settings: { } + oe_organisation_non_eu_org_type: + type: skos_concept_entity_reference_label + weight: 1 + region: content + label: above + settings: + link: false + third_party_settings: { } + oe_teaser: + type: text_default + weight: 5 + region: content + label: above + settings: { } + third_party_settings: { } +hidden: + body: true + langcode: true + links: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_organisation_contact: true + oe_organisation_eu_org: true + oe_organisation_org_type: true + oe_summary: true diff --git a/modules/oe_theme_content_organisation/config/post_updates/00003_update_full_view_display/core.entity_view_display.node.oe_organisation.full.yml b/modules/oe_theme_content_organisation/config/post_updates/00003_update_full_view_display/core.entity_view_display.node.oe_organisation.full.yml new file mode 100644 index 000000000..606064a2d --- /dev/null +++ b/modules/oe_theme_content_organisation/config/post_updates/00003_update_full_view_display/core.entity_view_display.node.oe_organisation.full.yml @@ -0,0 +1,176 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.full + - field.field.node.oe_organisation.body + - field.field.node.oe_organisation.oe_organisation_staff_link + - field.field.node.oe_organisation.oe_organisation_acronym + - field.field.node.oe_organisation.oe_organisation_contact + - field.field.node.oe_organisation.oe_organisation_eu_org + - field.field.node.oe_organisation.oe_organisation_eu_org_type + - field.field.node.oe_organisation.oe_organisation_logo + - field.field.node.oe_organisation.oe_organisation_non_eu_org_type + - field.field.node.oe_organisation.oe_organisation_chart + - field.field.node.oe_organisation.oe_organisation_org_type + - field.field.node.oe_organisation.oe_organisation_overview + - field.field.node.oe_organisation.oe_organisation_persons + - field.field.node.oe_organisation.oe_summary + - field.field.node.oe_organisation.oe_teaser + - node.type.oe_organisation + module: + - description_list_field + - entity_reference_revisions + - field_group + - link + - text + - user +third_party_settings: + field_group: + group_in_page_navigation: + children: + - oe_organisation_logo + - group_overview + - group_description + - group_leadership_and_organisation + - group_contact + parent_name: '' + weight: 0 + format_type: oe_theme_helper_in_page_navigation + region: content + format_settings: + id: '' + classes: '' + label: 'Page contents' + group_description: + children: + - body + parent_name: group_in_page_navigation + weight: 2 + format_type: oe_theme_helper_in_page_navigation_item + region: content + format_settings: + id: '' + classes: '' + label: '' + group_contact: + children: + - oe_organisation_contact + parent_name: group_in_page_navigation + weight: 4 + format_type: oe_theme_helper_in_page_navigation_item + region: content + format_settings: + id: '' + classes: '' + label: Contact + group_overview: + children: + - oe_organisation_overview + parent_name: group_in_page_navigation + weight: 1 + format_type: oe_theme_helper_in_page_navigation_item + region: content + format_settings: + id: '' + classes: '' + label: Overview + group_leadership_and_organisation: + children: + - oe_organisation_persons + - oe_organisation_chart + - oe_organisation_staff_link + parent_name: group_in_page_navigation + weight: 3 + format_type: oe_theme_helper_in_page_navigation_item + region: content + format_settings: + id: '' + classes: '' + label: 'Leadership and organisation' +id: node.oe_organisation.full +targetEntityType: node +bundle: oe_organisation +mode: full +content: + body: + label: hidden + type: text_default + weight: 4 + settings: { } + third_party_settings: { } + region: content + links: + weight: 1 + region: content + settings: { } + third_party_settings: { } + oe_organisation_staff_link: + type: link + weight: 2 + region: content + label: hidden + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + oe_organisation_contact: + weight: 6 + label: hidden + settings: + view_mode: full + link: '' + third_party_settings: { } + type: entity_reference_revisions_entity_view + region: content + oe_organisation_logo: + type: entity_reference_label + weight: 0 + region: content + label: above + settings: + link: true + third_party_settings: { } + oe_organisation_chart: + type: entity_reference_entity_view + weight: 1 + region: content + label: hidden + settings: + view_mode: default + link: false + third_party_settings: { } + oe_organisation_overview: + type: description_list_formatter + weight: 0 + region: content + label: hidden + settings: { } + third_party_settings: { } + oe_organisation_persons: + type: entity_reference_entity_view + weight: 0 + region: content + label: hidden + settings: + view_mode: oe_compact_teaser + link: false + third_party_settings: { } +hidden: + extra_field_oe_theme_content_organisation_teaser_details: true + extra_field_oe_theme_helper_short_title_with_fallback: true + langcode: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_organisation_acronym: true + oe_organisation_eu_org: true + oe_organisation_eu_org_type: true + oe_organisation_non_eu_org_type: true + oe_organisation_org_type: true + oe_summary: true + oe_teaser: true diff --git a/modules/oe_theme_content_organisation/oe_theme_content_organisation.info.yml b/modules/oe_theme_content_organisation/oe_theme_content_organisation.info.yml index 09eeea65c..5e84d35f9 100644 --- a/modules/oe_theme_content_organisation/oe_theme_content_organisation.info.yml +++ b/modules/oe_theme_content_organisation/oe_theme_content_organisation.info.yml @@ -5,6 +5,7 @@ package: OpenEuropa core: 8.x dependencies: - oe_content:oe_content_organisation + - oe_content:oe_content_organisation_person_reference - oe_theme:oe_theme_helper - oe_theme:oe_theme_content_entity_contact - rdf_skos:rdf_skos diff --git a/modules/oe_theme_content_organisation/oe_theme_content_organisation.post_update.php b/modules/oe_theme_content_organisation/oe_theme_content_organisation.post_update.php index 202c049f3..e97d0bc70 100644 --- a/modules/oe_theme_content_organisation/oe_theme_content_organisation.post_update.php +++ b/modules/oe_theme_content_organisation/oe_theme_content_organisation.post_update.php @@ -9,6 +9,7 @@ use Drupal\Component\Utility\Crypt; use Drupal\Core\Config\FileStorage; +use Drupal\Core\Entity\Entity\EntityViewDisplay; /** * Create the 'full' entity view display on the organisation CT. @@ -33,3 +34,41 @@ function oe_theme_content_organisation_post_update_00001() { $entity = $entity_storage->createFromStorageRecord($config); $entity->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_organisation_post_update_00002(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_organisation') . '/config/post_updates/00002_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_organisation.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} + +/** + * Update the 'full' entity view display on the organisation CT. + */ +function oe_theme_content_organisation_post_update_00003() { + // Enable new dependency. + \Drupal::service('module_installer')->install(['oe_content_organisation_person_reference']); + + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_organisation') . '/config/post_updates/00003_update_full_view_display'); + $view_display_values = $storage->read('core.entity_view_display.node.oe_organisation.full'); + $view_display = EntityViewDisplay::load($view_display_values['id']); + if ($view_display) { + $updated_view_display = \Drupal::entityTypeManager() + ->getStorage($view_display->getEntityTypeId()) + ->updateFromStorageRecord($view_display, $view_display_values); + $updated_view_display->save(); + } +} diff --git a/modules/oe_theme_content_organisation/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php b/modules/oe_theme_content_organisation/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php index 1d320de0b..ee05d00b7 100644 --- a/modules/oe_theme_content_organisation/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php +++ b/modules/oe_theme_content_organisation/src/Plugin/ExtraField/Display/TeaserDetailsExtraField.php @@ -9,7 +9,6 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\extra_field\Plugin\ExtraFieldDisplayFormattedBase; -use Drupal\oe_content_entity_contact\Entity\ContactInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -71,46 +70,46 @@ public function viewElements(ContentEntityInterface $entity) { return []; } - $contact = $entity->get('oe_organisation_contact')->entity; - if (!$contact instanceof ContactInterface) { - return []; - } - - $build = [ - '#type' => 'pattern', - '#id' => 'field_list', - '#variant' => 'horizontal', - '#fields' => [ - 'items' => [], - ], - ]; + $build = []; $cache = CacheableMetadata::createFromRenderArray($build); - $contact_access = $contact->access('view', NULL, TRUE); - $cache->addCacheableDependency($contact); - $cache->addCacheableDependency($contact_access); - - if (!$contact_access->isAllowed()) { - $cache->applyTo($build); - return $build; - } + /** @var \Drupal\oe_content_entity_contact\Entity\ContactInterface $contact */ + foreach ($entity->get('oe_organisation_contact')->referencedEntities() as $delta => $contact) { + if (!$contact) { + continue; + } + $contact_access = $contact->access('view', NULL, TRUE); + $cache->addCacheableDependency($contact); + $cache->addCacheableDependency($contact_access); + if (!$contact_access->isAllowed()) { + continue; + } - $items = []; - $fields = [ - 'oe_website' => [], - 'oe_email' => ['type' => 'email_mailto'], - 'oe_phone' => [], - 'oe_address' => [ - 'type' => 'oe_theme_helper_address_inline', - 'settings' => ['delimiter' => ', '], - ], - ]; - foreach ($fields as $field_name => $display_options) { - if (!$contact->get($field_name)->isEmpty()) { - $items[] = $this->getRenderableFieldListItem($contact, $field_name, $display_options); + $build[$delta] = [ + '#type' => 'pattern', + '#id' => 'field_list', + '#variant' => 'horizontal', + '#fields' => [ + 'items' => [], + ], + ]; + $items = []; + $fields = [ + 'oe_website' => [], + 'oe_email' => ['type' => 'email_mailto'], + 'oe_phone' => [], + 'oe_address' => [ + 'type' => 'oe_theme_helper_address_inline', + 'settings' => ['delimiter' => ', '], + ], + ]; + foreach ($fields as $field_name => $display_options) { + if (!$contact->get($field_name)->isEmpty()) { + $items[] = $this->getRenderableFieldListItem($contact, $field_name, $display_options); + } } + $build[$delta]['#fields']['items'] = $items; } - $build['#fields']['items'] = $items; $cache->applyTo($build); return $build; diff --git a/modules/oe_theme_content_page/config/install/core.entity_view_display.node.oe_page.teaser.yml b/modules/oe_theme_content_page/config/install/core.entity_view_display.node.oe_page.teaser.yml new file mode 100644 index 000000000..d65d5011a --- /dev/null +++ b/modules/oe_theme_content_page/config/install/core.entity_view_display.node.oe_page.teaser.yml @@ -0,0 +1,44 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_page.body + - field.field.node.oe_page.oe_author + - field.field.node.oe_page.oe_related_links + - field.field.node.oe_page.oe_subject + - field.field.node.oe_page.oe_summary + - field.field.node.oe_page.oe_teaser + - node.type.oe_page + module: + - text + - user +id: node.oe_page.teaser +targetEntityType: node +bundle: oe_page +mode: teaser +content: + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_teaser: + type: text_default + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } +hidden: + body: true + langcode: true + links: true + oe_author: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_related_links: true + oe_subject: true + oe_summary: true diff --git a/modules/oe_theme_content_page/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_page.teaser.yml b/modules/oe_theme_content_page/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_page.teaser.yml new file mode 100644 index 000000000..d65d5011a --- /dev/null +++ b/modules/oe_theme_content_page/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_page.teaser.yml @@ -0,0 +1,44 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_page.body + - field.field.node.oe_page.oe_author + - field.field.node.oe_page.oe_related_links + - field.field.node.oe_page.oe_subject + - field.field.node.oe_page.oe_summary + - field.field.node.oe_page.oe_teaser + - node.type.oe_page + module: + - text + - user +id: node.oe_page.teaser +targetEntityType: node +bundle: oe_page +mode: teaser +content: + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_teaser: + type: text_default + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } +hidden: + body: true + langcode: true + links: true + oe_author: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_related_links: true + oe_subject: true + oe_summary: true diff --git a/modules/oe_theme_content_page/oe_theme_content_page.post_update.php b/modules/oe_theme_content_page/oe_theme_content_page.post_update.php index 248cd77f6..400e7d219 100644 --- a/modules/oe_theme_content_page/oe_theme_content_page.post_update.php +++ b/modules/oe_theme_content_page/oe_theme_content_page.post_update.php @@ -34,3 +34,23 @@ function oe_theme_content_page_post_update_00001() { $entity = $entity_storage->createFromStorageRecord($config); $entity->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_page_post_update_00002(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_page') . '/config/post_updates/00002_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_page.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_person/config/install/core.entity_view_display.node.oe_person.oe_compact_teaser.yml b/modules/oe_theme_content_person/config/install/core.entity_view_display.node.oe_person.oe_compact_teaser.yml new file mode 100644 index 000000000..3b97409d8 --- /dev/null +++ b/modules/oe_theme_content_person/config/install/core.entity_view_display.node.oe_person.oe_compact_teaser.yml @@ -0,0 +1,85 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.oe_compact_teaser + - field.field.node.oe_person.oe_departments + - field.field.node.oe_person.oe_person_biography_intro + - field.field.node.oe_person.oe_person_biography_timeline + - field.field.node.oe_person.oe_person_contacts + - field.field.node.oe_person.oe_person_cv + - field.field.node.oe_person.oe_person_displayed_name + - field.field.node.oe_person.oe_person_documents + - field.field.node.oe_person.oe_person_first_name + - field.field.node.oe_person.oe_person_gender + - field.field.node.oe_person.oe_person_interests_file + - field.field.node.oe_person.oe_person_interests_intro + - field.field.node.oe_person.oe_person_jobs + - field.field.node.oe_person.oe_person_last_name + - field.field.node.oe_person.oe_person_media + - field.field.node.oe_person.oe_person_organisation + - field.field.node.oe_person.oe_person_photo + - field.field.node.oe_person.oe_person_transparency_intro + - field.field.node.oe_person.oe_person_transparency_links + - field.field.node.oe_person.oe_person_type + - field.field.node.oe_person.oe_social_media_links + - field.field.node.oe_person.oe_subject + - field.field.node.oe_person.oe_summary + - field.field.node.oe_person.oe_teaser + - image.style.oe_theme_small_no_crop + - node.type.oe_person + module: + - entity_reference_revisions + - oe_theme_helper + - user +id: node.oe_person.oe_compact_teaser +targetEntityType: node +bundle: oe_person +mode: oe_compact_teaser +content: + oe_person_jobs: + type: entity_reference_revisions_label + weight: 0 + region: content + label: hidden + settings: + link: false + third_party_settings: { } + oe_person_photo: + type: oe_theme_helper_media_thumbnail_url + weight: 1 + region: content + label: hidden + settings: + image_style: oe_theme_small_no_crop + third_party_settings: { } +hidden: + extra_field_oe_theme_content_person_job_list: true + extra_field_oe_theme_helper_short_title_with_fallback: true + langcode: true + links: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_departments: true + oe_person_biography_intro: true + oe_person_biography_timeline: true + oe_person_contacts: true + oe_person_cv: true + oe_person_displayed_name: true + oe_person_documents: true + oe_person_first_name: true + oe_person_gender: true + oe_person_interests_file: true + oe_person_interests_intro: true + oe_person_last_name: true + oe_person_media: true + oe_person_organisation: true + oe_person_transparency_intro: true + oe_person_transparency_links: true + oe_person_type: true + oe_social_media_links: true + oe_subject: true + oe_summary: true + oe_teaser: true diff --git a/modules/oe_theme_content_person/config/post_updates/20002_create_oe_compact_teaser_view_display/core.entity_view_display.node.oe_person.oe_compact_teaser.yml b/modules/oe_theme_content_person/config/post_updates/20002_create_oe_compact_teaser_view_display/core.entity_view_display.node.oe_person.oe_compact_teaser.yml new file mode 100644 index 000000000..3b97409d8 --- /dev/null +++ b/modules/oe_theme_content_person/config/post_updates/20002_create_oe_compact_teaser_view_display/core.entity_view_display.node.oe_person.oe_compact_teaser.yml @@ -0,0 +1,85 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.oe_compact_teaser + - field.field.node.oe_person.oe_departments + - field.field.node.oe_person.oe_person_biography_intro + - field.field.node.oe_person.oe_person_biography_timeline + - field.field.node.oe_person.oe_person_contacts + - field.field.node.oe_person.oe_person_cv + - field.field.node.oe_person.oe_person_displayed_name + - field.field.node.oe_person.oe_person_documents + - field.field.node.oe_person.oe_person_first_name + - field.field.node.oe_person.oe_person_gender + - field.field.node.oe_person.oe_person_interests_file + - field.field.node.oe_person.oe_person_interests_intro + - field.field.node.oe_person.oe_person_jobs + - field.field.node.oe_person.oe_person_last_name + - field.field.node.oe_person.oe_person_media + - field.field.node.oe_person.oe_person_organisation + - field.field.node.oe_person.oe_person_photo + - field.field.node.oe_person.oe_person_transparency_intro + - field.field.node.oe_person.oe_person_transparency_links + - field.field.node.oe_person.oe_person_type + - field.field.node.oe_person.oe_social_media_links + - field.field.node.oe_person.oe_subject + - field.field.node.oe_person.oe_summary + - field.field.node.oe_person.oe_teaser + - image.style.oe_theme_small_no_crop + - node.type.oe_person + module: + - entity_reference_revisions + - oe_theme_helper + - user +id: node.oe_person.oe_compact_teaser +targetEntityType: node +bundle: oe_person +mode: oe_compact_teaser +content: + oe_person_jobs: + type: entity_reference_revisions_label + weight: 0 + region: content + label: hidden + settings: + link: false + third_party_settings: { } + oe_person_photo: + type: oe_theme_helper_media_thumbnail_url + weight: 1 + region: content + label: hidden + settings: + image_style: oe_theme_small_no_crop + third_party_settings: { } +hidden: + extra_field_oe_theme_content_person_job_list: true + extra_field_oe_theme_helper_short_title_with_fallback: true + langcode: true + links: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_departments: true + oe_person_biography_intro: true + oe_person_biography_timeline: true + oe_person_contacts: true + oe_person_cv: true + oe_person_displayed_name: true + oe_person_documents: true + oe_person_first_name: true + oe_person_gender: true + oe_person_interests_file: true + oe_person_interests_intro: true + oe_person_last_name: true + oe_person_media: true + oe_person_organisation: true + oe_person_transparency_intro: true + oe_person_transparency_links: true + oe_person_type: true + oe_social_media_links: true + oe_subject: true + oe_summary: true + oe_teaser: true diff --git a/modules/oe_theme_content_person/oe_theme_content_person.module b/modules/oe_theme_content_person/oe_theme_content_person.module index 1ff8bac2c..d4832a88b 100644 --- a/modules/oe_theme_content_person/oe_theme_content_person.module +++ b/modules/oe_theme_content_person/oe_theme_content_person.module @@ -41,7 +41,7 @@ function oe_theme_content_person_node_view_alter(array &$build, EntityInterface } } - if ($build['#view_mode'] === 'teaser') { + if ($build['#view_mode'] === 'teaser' || $build['#view_mode'] === 'oe_compact_teaser') { // Set default image for Portrait. $build['portrait_image']['#markup'] = base_path() . drupal_get_path('theme', 'oe_theme') . '/images/user_icon.svg'; if (!empty($build['oe_person_photo'][0]['#markup'])) { diff --git a/modules/oe_theme_content_person/oe_theme_content_person.post_update.php b/modules/oe_theme_content_person/oe_theme_content_person.post_update.php index 4f49502da..251dd7eec 100644 --- a/modules/oe_theme_content_person/oe_theme_content_person.post_update.php +++ b/modules/oe_theme_content_person/oe_theme_content_person.post_update.php @@ -9,6 +9,8 @@ use Drupal\Core\Config\FileStorage; use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\Component\Utility\Crypt; +use Drupal\Core\Entity\Entity\EntityViewMode; /** * Moves social media links on a separated fieldgroup. @@ -26,3 +28,32 @@ function oe_theme_content_person_post_update_20001(): void { $updated_display->save(); } } + +/** + * Create the 'oe_compact_teaser' entity view display on the person CT. + */ +function oe_theme_content_person_post_update_20002() { + // Create the OpenEuropa: Compact teaser if it doesn't exist yet. + if (!EntityViewMode::load('node.oe_compact_teaser')) { + EntityViewMode::create([ + 'id' => 'node.oe_compact_teaser', + 'targetEntityType' => 'node', + 'status' => TRUE, + 'enabled' => TRUE, + 'label' => 'OpenEuropa: Compact teaser', + ])->save(); + } + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_person') . '/config/post_updates/20002_create_oe_compact_teaser_view_display'); + + $entity_type_manager = \Drupal::entityTypeManager(); + $config = $storage->read('core.entity_view_display.node.oe_person.oe_compact_teaser'); + // We are creating the config which means that we are also shipping + // it in the config/install folder so we want to make sure it gets the hash + // so Drupal treats it as a shipped config. This means that it gets exposed + // to be translated via the locale system as well. + $config['_core']['default_config_hash'] = Crypt::hashBase64(serialize($config)); + /** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $entity_storage */ + $entity_storage = $entity_type_manager->getStorage('entity_view_display'); + $entity = $entity_storage->createFromStorageRecord($config); + $entity->save(); +} diff --git a/modules/oe_theme_content_policy/config/install/core.entity_view_display.node.oe_policy.teaser.yml b/modules/oe_theme_content_policy/config/install/core.entity_view_display.node.oe_policy.teaser.yml new file mode 100644 index 000000000..837083c54 --- /dev/null +++ b/modules/oe_theme_content_policy/config/install/core.entity_view_display.node.oe_policy.teaser.yml @@ -0,0 +1,44 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_policy.body + - field.field.node.oe_policy.oe_author + - field.field.node.oe_policy.oe_subject + - field.field.node.oe_policy.oe_summary + - field.field.node.oe_policy.oe_teaser + - field.field.node.oe_policy.oe_timeline + - node.type.oe_policy + module: + - text + - user +id: node.oe_policy.teaser +targetEntityType: node +bundle: oe_policy +mode: teaser +content: + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_teaser: + type: text_default + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } +hidden: + body: true + langcode: true + links: true + oe_author: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_subject: true + oe_summary: true + oe_timeline: true diff --git a/modules/oe_theme_content_policy/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_policy.teaser.yml b/modules/oe_theme_content_policy/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_policy.teaser.yml new file mode 100644 index 000000000..837083c54 --- /dev/null +++ b/modules/oe_theme_content_policy/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_policy.teaser.yml @@ -0,0 +1,44 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_policy.body + - field.field.node.oe_policy.oe_author + - field.field.node.oe_policy.oe_subject + - field.field.node.oe_policy.oe_summary + - field.field.node.oe_policy.oe_teaser + - field.field.node.oe_policy.oe_timeline + - node.type.oe_policy + module: + - text + - user +id: node.oe_policy.teaser +targetEntityType: node +bundle: oe_policy +mode: teaser +content: + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_teaser: + type: text_default + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } +hidden: + body: true + langcode: true + links: true + oe_author: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_subject: true + oe_summary: true + oe_timeline: true diff --git a/modules/oe_theme_content_policy/oe_theme_content_policy.post_update.php b/modules/oe_theme_content_policy/oe_theme_content_policy.post_update.php index f996da936..b9295ef91 100644 --- a/modules/oe_theme_content_policy/oe_theme_content_policy.post_update.php +++ b/modules/oe_theme_content_policy/oe_theme_content_policy.post_update.php @@ -34,3 +34,23 @@ function oe_theme_content_policy_post_update_00001() { $entity = $entity_storage->createFromStorageRecord($config); $entity->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_policy_post_update_00002(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_policy') . '/config/post_updates/00002_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_policy.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_project/config/install/core.entity_view_display.node.oe_project.teaser.yml b/modules/oe_theme_content_project/config/install/core.entity_view_display.node.oe_project.teaser.yml index f444e9d03..3768a6625 100644 --- a/modules/oe_theme_content_project/config/install/core.entity_view_display.node.oe_project.teaser.yml +++ b/modules/oe_theme_content_project/config/install/core.entity_view_display.node.oe_project.teaser.yml @@ -49,6 +49,11 @@ targetEntityType: node bundle: oe_project mode: teaser content: + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } oe_featured_media: type: oe_theme_helper_featured_media_thumbnail_url_formatter weight: 2 @@ -67,7 +72,7 @@ content: third_party_settings: { } oe_teaser: type: text_default - weight: 0 + weight: 1 region: content label: above settings: { } @@ -75,7 +80,6 @@ content: hidden: body: true extra_field_oe_theme_content_project_percentage: true - extra_field_oe_theme_helper_short_title_with_fallback: true langcode: true links: true oe_content_content_owner: true diff --git a/modules/oe_theme_content_project/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_project.teaser.yml b/modules/oe_theme_content_project/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_project.teaser.yml new file mode 100644 index 000000000..3768a6625 --- /dev/null +++ b/modules/oe_theme_content_project/config/post_updates/00002_update_teaser_view_display/core.entity_view_display.node.oe_project.teaser.yml @@ -0,0 +1,104 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_project.body + - field.field.node.oe_project.oe_departments + - field.field.node.oe_project.oe_documents + - field.field.node.oe_project.oe_featured_media + - field.field.node.oe_project.oe_project_budget + - field.field.node.oe_project.oe_project_budget_eu + - field.field.node.oe_project.oe_project_calls + - field.field.node.oe_project.oe_project_contact + - field.field.node.oe_project.oe_project_coordinators + - field.field.node.oe_project.oe_project_dates + - field.field.node.oe_project.oe_project_funding_programme + - field.field.node.oe_project.oe_project_locations + - field.field.node.oe_project.oe_project_participants + - field.field.node.oe_project.oe_project_result_files + - field.field.node.oe_project.oe_project_results + - field.field.node.oe_project.oe_project_website + - field.field.node.oe_project.oe_reference_code + - field.field.node.oe_project.oe_subject + - field.field.node.oe_project.oe_summary + - field.field.node.oe_project.oe_teaser + - image.style.oe_theme_ratio_3_2_medium + - node.type.oe_project + module: + - field_group + - oe_theme_helper + - text + - user +third_party_settings: + field_group: + group_details: + children: + - oe_project_locations + parent_name: '' + weight: 3 + format_type: oe_theme_helper_field_list_pattern + region: content + format_settings: + variant: horizontal + classes: '' + id: '' + label: Details +id: node.oe_project.teaser +targetEntityType: node +bundle: oe_project +mode: teaser +content: + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 0 + region: content + settings: { } + third_party_settings: { } + oe_featured_media: + type: oe_theme_helper_featured_media_thumbnail_url_formatter + weight: 2 + region: content + label: above + settings: + image_style: oe_theme_ratio_3_2_medium + third_party_settings: { } + oe_project_locations: + type: oe_theme_helper_address_inline + weight: 1 + region: content + label: above + settings: + delimiter: ', ' + third_party_settings: { } + oe_teaser: + type: text_default + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } +hidden: + body: true + extra_field_oe_theme_content_project_percentage: true + langcode: true + links: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_departments: true + oe_documents: true + oe_project_budget: true + oe_project_budget_eu: true + oe_project_calls: true + oe_project_contact: true + oe_project_coordinators: true + oe_project_dates: true + oe_project_funding_programme: true + oe_project_participants: true + oe_project_result_files: true + oe_project_results: true + oe_project_website: true + oe_reference_code: true + oe_subject: true + oe_summary: true diff --git a/modules/oe_theme_content_project/oe_theme_content_project.post_update.php b/modules/oe_theme_content_project/oe_theme_content_project.post_update.php index 23af5f6fa..b4cda621e 100644 --- a/modules/oe_theme_content_project/oe_theme_content_project.post_update.php +++ b/modules/oe_theme_content_project/oe_theme_content_project.post_update.php @@ -34,3 +34,23 @@ function oe_theme_content_project_post_update_00001() { $entity = $entity_storage->createFromStorageRecord($config); $entity->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_project_post_update_00002(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_project') . '/config/post_updates/00002_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_project.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_publication/config/post_updates/00010_update_teaser_view_display/core.entity_view_display.node.oe_publication.teaser.yml b/modules/oe_theme_content_publication/config/post_updates/00010_update_teaser_view_display/core.entity_view_display.node.oe_publication.teaser.yml new file mode 100644 index 000000000..9476a0c92 --- /dev/null +++ b/modules/oe_theme_content_publication/config/post_updates/00010_update_teaser_view_display/core.entity_view_display.node.oe_publication.teaser.yml @@ -0,0 +1,99 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.oe_publication.body + - field.field.node.oe_publication.oe_author + - field.field.node.oe_publication.oe_departments + - field.field.node.oe_publication.oe_documents + - field.field.node.oe_publication.oe_publication_contacts + - field.field.node.oe_publication.oe_publication_countries + - field.field.node.oe_publication.oe_publication_date + - field.field.node.oe_publication.oe_publication_last_updated + - field.field.node.oe_publication.oe_publication_thumbnail + - field.field.node.oe_publication.oe_publication_type + - field.field.node.oe_publication.oe_reference_codes + - field.field.node.oe_publication.oe_subject + - field.field.node.oe_publication.oe_summary + - field.field.node.oe_publication.oe_teaser + - image.style.oe_theme_publication_thumbnail + - node.type.oe_publication + module: + - datetime + - oe_theme_helper + - rdf_skos + - text + - user +id: node.oe_publication.teaser +targetEntityType: node +bundle: oe_publication +mode: teaser +content: + extra_field_oe_theme_content_publication_description: + weight: 0 + region: content + settings: { } + third_party_settings: { } + extra_field_oe_theme_helper_short_title_with_fallback: + weight: 3 + region: content + settings: { } + third_party_settings: { } + oe_author: + type: skos_concept_entity_reference_label + weight: 6 + region: content + label: hidden + settings: + link: false + third_party_settings: { } + oe_publication_date: + type: datetime_default + weight: 1 + region: content + label: hidden + settings: + timezone_override: '' + format_type: oe_theme_publication_date + third_party_settings: { } + oe_publication_thumbnail: + type: oe_theme_helper_media_thumbnail_url + weight: 4 + region: content + label: hidden + settings: + image_style: oe_theme_publication_thumbnail + third_party_settings: { } + oe_publication_type: + type: skos_concept_entity_reference_label + weight: 5 + region: content + label: hidden + settings: + link: false + third_party_settings: { } + oe_teaser: + type: text_default + weight: 2 + region: content + label: hidden + settings: { } + third_party_settings: { } +hidden: + body: true + extra_field_oe_theme_content_publication_date: true + langcode: true + links: true + oe_content_content_owner: true + oe_content_legacy_link: true + oe_content_navigation_title: true + oe_content_short_title: true + oe_departments: true + oe_documents: true + oe_publication_contacts: true + oe_publication_countries: true + oe_publication_last_updated: true + oe_reference_codes: true + oe_subject: true + oe_summary: true diff --git a/modules/oe_theme_content_publication/oe_theme_content_publication.post_update.php b/modules/oe_theme_content_publication/oe_theme_content_publication.post_update.php index ae446d668..e770f6372 100644 --- a/modules/oe_theme_content_publication/oe_theme_content_publication.post_update.php +++ b/modules/oe_theme_content_publication/oe_theme_content_publication.post_update.php @@ -183,3 +183,23 @@ function oe_theme_content_publication_post_update_00009() { } $display->save(); } + +/** + * Updates the teaser view display. + */ +function oe_theme_content_publication_post_update_00010(): void { + $storage = new FileStorage(drupal_get_path('module', 'oe_theme_content_publication') . '/config/post_updates/00010_update_teaser_view_display'); + + $display_values = $storage->read('core.entity_view_display.node.oe_publication.teaser'); + $storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + + $view_display = EntityViewDisplay::load($display_values['id']); + if ($view_display) { + $display = $storage->updateFromStorageRecord($view_display, $display_values); + $display->save(); + return; + } + + $display = $storage->createFromStorageRecord($display_values); + $display->save(); +} diff --git a/modules/oe_theme_content_publication/src/Plugin/ExtraField/Display/PublicationDescription.php b/modules/oe_theme_content_publication/src/Plugin/ExtraField/Display/PublicationDescription.php index 9ff34c865..cbbce9a22 100644 --- a/modules/oe_theme_content_publication/src/Plugin/ExtraField/Display/PublicationDescription.php +++ b/modules/oe_theme_content_publication/src/Plugin/ExtraField/Display/PublicationDescription.php @@ -92,6 +92,15 @@ public function viewElements(ContentEntityInterface $entity) { $cacheability = CacheableMetadata::createFromRenderArray($build); $cacheability->addCacheableDependency($media); + + // Run access checks on the media entity. + $access = $media->access('view', NULL, TRUE); + $cacheability->addCacheableDependency($access); + if (!$access->isAllowed()) { + $cacheability->applyTo($build); + return $build; + } + $thumbnail = !$media->get('thumbnail')->isEmpty() ? $media->get('thumbnail')->first() : NULL; if (!$thumbnail instanceof ImageItem || !$thumbnail->entity instanceof FileInterface) { diff --git a/modules/oe_theme_helper/config/install/core.entity_view_mode.node.oe_compact_teaser.yml b/modules/oe_theme_helper/config/install/core.entity_view_mode.node.oe_compact_teaser.yml new file mode 100644 index 000000000..59448815b --- /dev/null +++ b/modules/oe_theme_helper/config/install/core.entity_view_mode.node.oe_compact_teaser.yml @@ -0,0 +1,9 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.oe_compact_teaser +label: 'OpenEuropa: Compact teaser' +targetEntityType: node +cache: true diff --git a/modules/oe_theme_helper/oe_theme_helper.info.yml b/modules/oe_theme_helper/oe_theme_helper.info.yml index 91f594614..94b414f65 100644 --- a/modules/oe_theme_helper/oe_theme_helper.info.yml +++ b/modules/oe_theme_helper/oe_theme_helper.info.yml @@ -4,6 +4,7 @@ description: OpenEuropa theme helpers and tools. package: OpenEuropa core: 8.x dependencies: + - drupal:node - ui_patterns:ui_patterns_library - drupal:responsive_image - smart_trim:smart_trim diff --git a/modules/oe_theme_helper/oe_theme_helper.module b/modules/oe_theme_helper/oe_theme_helper.module index 127cf3e1f..2884e49d6 100644 --- a/modules/oe_theme_helper/oe_theme_helper.module +++ b/modules/oe_theme_helper/oe_theme_helper.module @@ -11,6 +11,7 @@ use Drupal\Component\Utility\Html; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Form\FormStateInterface; use Drupal\image\Plugin\Field\FieldType\ImageItem; use Drupal\media\MediaInterface; use Drupal\oe_theme\ValueObject\ImageValueObject; @@ -102,6 +103,11 @@ function oe_theme_helper_theme($existing, $type, $theme, $path) { 'name' => '', ], ], + 'oe_theme_helper_inpage_navigation_block' => [ + 'variables' => [ + 'title' => NULL, + ], + ], ]; } @@ -236,6 +242,18 @@ function _oe_theme_helper_inpage_nav_prepare_image(array &$variables, EntityInte // The media entity is not available anymore, bail out. return; } + + $cacheability = CacheableMetadata::createFromRenderArray($variables); + $cacheability->addCacheableDependency($media); + + // Run access checks on the media entity. + $access = $media->access('view', $variables['user'], TRUE); + $cacheability->addCacheableDependency($access); + if (!$access->isAllowed()) { + $cacheability->applyTo($variables); + return; + } + $thumbnail = !$media->get('thumbnail')->isEmpty() ? $media->get('thumbnail')->first() : NULL; $alt = ''; if ($thumbnail instanceof ImageItem) { @@ -249,8 +267,7 @@ function _oe_theme_helper_inpage_nav_prepare_image(array &$variables, EntityInte ], ]); - CacheableMetadata::createFromRenderArray($variables) - ->merge(CacheableMetadata::createFromRenderArray($renderable[0])) + $cacheability->merge(CacheableMetadata::createFromRenderArray($renderable[0])) ->applyTo($variables); $variables['image'] = ImageValueObject::fromArray([ @@ -279,3 +296,14 @@ function oe_theme_helper_entity_bundle_info_alter(&$bundles) { : 'thumbnail'; } } + +/** + * Implements hook_form_FORM_ID_alter() for the entity view display form. + */ +function oe_theme_helper_form_entity_view_display_edit_form_alter(&$form, FormStateInterface $form_state) { + foreach ($form['#fieldgroups'] as $name) { + if ($form['fields'][$name]['human_name']['#markup'] === "") { + $form['fields'][$name]['human_name']['#markup'] = t('- No label -'); + } + } +} diff --git a/modules/oe_theme_helper/oe_theme_helper.post_update.php b/modules/oe_theme_helper/oe_theme_helper.post_update.php index 4f44d1aee..1ba8f0f92 100644 --- a/modules/oe_theme_helper/oe_theme_helper.post_update.php +++ b/modules/oe_theme_helper/oe_theme_helper.post_update.php @@ -10,6 +10,7 @@ use Drupal\block\Entity\Block; use Drupal\Core\Config\FileStorage; use Drupal\Component\Utility\Crypt; +use Drupal\Core\Entity\Entity\EntityViewMode; use Drupal\image\Entity\ImageStyle; /** @@ -278,3 +279,20 @@ function oe_theme_helper_post_update_20015() { $entity_view_display_storage->create($view_display_values)->save(); } } + +/** + * Create the OpenEuropa: Compact teaser view mode for node entities. + */ +function oe_theme_helper_post_update_20016() { + if (EntityViewMode::load('node.oe_compact_teaser')) { + // We bail out if it already exists. + return t('Skipping since the view mode node.oe_compact_teaser already exists.'); + } + EntityViewMode::create([ + 'id' => 'node.oe_compact_teaser', + 'targetEntityType' => 'node', + 'status' => TRUE, + 'enabled' => TRUE, + 'label' => 'OpenEuropa: Compact teaser', + ])->save(); +} diff --git a/modules/oe_theme_helper/src/Plugin/Block/InpageNavigationBlock.php b/modules/oe_theme_helper/src/Plugin/Block/InpageNavigationBlock.php new file mode 100644 index 000000000..ddd9aec5f --- /dev/null +++ b/modules/oe_theme_helper/src/Plugin/Block/InpageNavigationBlock.php @@ -0,0 +1,36 @@ + 'oe_theme_helper_inpage_navigation_block', + '#title' => $this->t('Page contents'), + '#attached' => [ + 'library' => [ + 'oe_theme/inpage_navigation', + ], + ], + ]; + return $build; + } + +} diff --git a/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/AddressInlineFormatter.php b/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/AddressInlineFormatter.php index f103a9495..576a04cbf 100644 --- a/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/AddressInlineFormatter.php +++ b/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/AddressInlineFormatter.php @@ -100,6 +100,7 @@ protected function viewElement(AddressInterface $address, $langcode) { else { $format_string = $address_format->getFormat() . "\n" . '%country'; } + $format_string = str_replace([',', ' - '], "\n", $format_string); $items = $this->extractAddressItems($format_string, $address_elements); diff --git a/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/FeaturedMediaFormatter.php b/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/FeaturedMediaFormatter.php index 12789a808..37b7efe4e 100644 --- a/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/FeaturedMediaFormatter.php +++ b/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/FeaturedMediaFormatter.php @@ -152,9 +152,11 @@ public function viewElements(FieldItemListInterface $items, $langcode) { * * @return array * The ECL media-container parameters. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function viewElement(FieldItemInterface $item, string $langcode): array { - $build = ['#theme' => 'oe_theme_helper_featured_media']; + $build = []; $params = ['description' => $item->caption]; $media = $item->entity; $cacheability = CacheableMetadata::createFromRenderArray($build); @@ -165,12 +167,18 @@ protected function viewElement(FieldItemInterface $item, string $langcode): arra // Retrieve the correct media translation. $media = $this->entityRepository->getTranslationFromContext($media, $langcode); - - // Caches are handled by the formatter usually. Since we are not rendering - // the original render arrays, we need to propagate our caches to the - // oe_theme_helper_featured_media template. $cacheability->addCacheableDependency($media); + // Run access checks on the media entity. + $access = $media->access('view', NULL, TRUE); + $cacheability->addCacheableDependency($access); + if (!$access->isAllowed()) { + $cacheability->applyTo($build); + return $build; + } + + $build['#theme'] = 'oe_theme_helper_featured_media'; + // Get the media source. $source = $media->getSource(); diff --git a/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatter.php b/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatter.php index 65be3c2b2..04a173060 100644 --- a/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatter.php +++ b/modules/oe_theme_helper/src/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatter.php @@ -74,12 +74,15 @@ public function viewElements(FieldItemListInterface $items, $langcode) { // to each element. $cache = new CacheableMetadata(); $cache->addCacheableDependency($media); - $cache->addCacheableDependency($items->get($delta)->_accessCacheability); + + // Run access checks on the media entity. + $access = $media->access('view', NULL, TRUE); + $cache->addCacheableDependency($access); + if (!$access->isAllowed()) { + continue; + } if ($media->get('thumbnail')->isEmpty()) { - // In case the thumbnail is missing from the media entity, we should - // apply the cache metadata of the media to the render array. - $cache->applyTo($elements[$delta]); continue; } diff --git a/modules/oe_theme_helper/src/Plugin/Filter/FilterEclTable.php b/modules/oe_theme_helper/src/Plugin/Filter/FilterEclTable.php new file mode 100644 index 000000000..472dbe9aa --- /dev/null +++ b/modules/oe_theme_helper/src/Plugin/Filter/FilterEclTable.php @@ -0,0 +1,84 @@ +query('//table[.//th]') as $table) { + // Skip the table if any cell spans over multiple columns or rows. + $span_cells = $xpath->query('.//*[self::th or self::td][(@colspan and @colspan > 1) or (@rowspan and @rowspan > 1)]', $table); + if ($span_cells->count() !== 0) { + continue; + } + + // Do not process tables that use th cells anywhere but in the first + // column. + $ths_in_body = $xpath->query('.//tr[not(parent::thead)]/*[position()>1 and self::th]', $table); + if ($ths_in_body->count() !== 0) { + continue; + } + + $headers = []; + // Collect the first header row, validating that is composed only of + // th elements. + $has_header_row = $xpath->query('(./thead/tr[1])[count(./*[not(self::th)]) = 0]', $table); + if ($has_header_row->count()) { + $header_row = $has_header_row[0]; + foreach ($xpath->query('./th', $header_row) as $cell) { + $headers[] = $cell->nodeValue; + } + } + + // Loop through all the table rows, aside from header ones. + foreach ($xpath->query('.//tr[not(parent::thead)]', $table) as $row) { + // Fetch all the cells inside the row. + foreach ($xpath->query('./*[self::th or self::td]', $row) as $cell_index => $cell) { + $existing_class = $cell->getAttribute('class'); + $new_class = $existing_class ? "$existing_class ecl-table__cell" : 'ecl-table__cell'; + $cell->setAttribute('class', $new_class); + + if (array_key_exists($cell_index, $headers)) { + $cell->setAttribute('data-ecl-table-header', $headers[$cell_index]); + } + } + } + } + + $result->setProcessedText(Html::serialize($dom)); + + return $result; + } + +} diff --git a/modules/oe_theme_helper/templates/oe-theme-helper-inpage-navigation-block.html.twig b/modules/oe_theme_helper/templates/oe-theme-helper-inpage-navigation-block.html.twig new file mode 100644 index 000000000..879032bb5 --- /dev/null +++ b/modules/oe_theme_helper/templates/oe-theme-helper-inpage-navigation-block.html.twig @@ -0,0 +1,12 @@ +{# +/** + * @file + * Template to display an inpage navigation block. + */ +#} +{% block navigation %} + {% include '@ecl-twig/inpage-navigation' with { + 'title': title, + 'icon_path': ecl_icon_path, + } %} +{% endblock %} diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/js/inpage_navigation_test.js b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/js/inpage_navigation_test.js new file mode 100644 index 000000000..8d0e40b8c --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/js/inpage_navigation_test.js @@ -0,0 +1,14 @@ +/** + * @file + * Overriding of ECL inpage navigation for empty navigation list. + */ +(function (Drupal) { + /** + * Override behaviour for empty navigation list. + */ + Drupal.eclInPageNavigation.handleEmptyInpageNavigation = function(element) { + document.querySelector('h1.ecl-page-header-core__title').classList.add('empty-inpage-nav-test'); + element.remove(); + } + +})(Drupal); diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.info.yml b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.info.yml new file mode 100644 index 000000000..42e562e0d --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.info.yml @@ -0,0 +1,7 @@ +name: 'OpenEuropa Theme In-page Navigation Test' +type: module +description: 'Module for testing in-page navigation functionality' +package: OpenEuropa +core: 8.x +dependencies: + - oe_theme:oe_theme_helper diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.libraries.yml b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.libraries.yml new file mode 100644 index 000000000..f937bf0c9 --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.libraries.yml @@ -0,0 +1,6 @@ +inpage_navigation_test: + js: + js/inpage_navigation_test.js: {} + dependencies: + - core/drupal + - oe_theme/inpage_navigation diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.module b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.module new file mode 100644 index 000000000..0a6e85425 --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.module @@ -0,0 +1,22 @@ + [ + 'render element' => 'element', + ], + 'oe_theme_inpage_navigation_test_no_elements' => [ + 'render element' => 'element', + ], + ]; +} diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.routing.yml b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.routing.yml new file mode 100644 index 000000000..79410deea --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/oe_theme_inpage_navigation_test.routing.yml @@ -0,0 +1,15 @@ +oe_theme_inpage_navigation_test.content: + path: '/oe-theme-inpage-navigation-test/content' + defaults: + _title: 'In-page navigation content page' + _controller: '\Drupal\oe_theme_inpage_navigation_test\Controller\InpageNavigationTestController::contentPage' + requirements: + _access: 'TRUE' + +oe_theme_inpage_navigation_test.no_entries: + path: '/oe-theme-inpage-navigation-test/no-entries' + defaults: + _title: 'In-page navigation no entries page' + _controller: '\Drupal\oe_theme_inpage_navigation_test\Controller\InpageNavigationTestController::noEntriesPage' + requirements: + _access: 'TRUE' diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/src/Controller/InpageNavigationTestController.php b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/src/Controller/InpageNavigationTestController.php new file mode 100644 index 000000000..e17502715 --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/src/Controller/InpageNavigationTestController.php @@ -0,0 +1,38 @@ + 'oe_theme_inpage_navigation_test_content', + ]; + } + + /** + * Returns content that doesn't generate any entries for inpage navigation. + * + * @return array + * The response render array. + */ + public function noEntriesPage(): array { + return [ + '#theme' => 'oe_theme_inpage_navigation_test_no_elements', + ]; + } + +} diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/templates/oe-theme-inpage-navigation-test-content.html.twig b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/templates/oe-theme-inpage-navigation-test-content.html.twig new file mode 100644 index 000000000..fcb85edc3 --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/templates/oe-theme-inpage-navigation-test-content.html.twig @@ -0,0 +1,48 @@ +{# +/** + * @file + * Test template with content for in-page navigation. + */ +#} +{# A source area with a complex selector, including encoded characters. #} +
    + + {# A nested source area, with a selector that overlaps partially the one above. #} +
    + {# An element that will be picked by both selectors. First occurrence of an heading with "Details" as text. #} +

    Details

    +

    Multiple words with spaces

    +

    Lorem ipsum dolor sit.

    +

    Small heading

    + + {# Placed inside the nested source area to verify that outer selectors search inside nested areas. #} + Test on attribute selector. +

    Lorem ipsum dolor sit amet.

    +
    + + {# Second occurrence of an heading with "Details" as text. #} +

    Details

    + + {# An element with an already specified ID. #} +

    More details

    + +

    Not targeted

    + +

    Title with HTML tags

    + +

    + +

    ~

    + +

    Not targeted

    + +

    Strip ‿\'!"#$%&()*+,./:;<=>?@[]^`{|}~ unwanted characters

    + + {# Scenarios to test the correct handling of object properties with Object.hasOwnProperty(). #} + {# An element with an existing ID that can represent a property of the Object prototype. #} +

    Reserved keyword

    + + {# An element that will generate an ID that can represent a property of the Object prototype. #} +

    Length

    + +
    diff --git a/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/templates/oe-theme-inpage-navigation-test-no-elements.html.twig b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/templates/oe-theme-inpage-navigation-test-no-elements.html.twig new file mode 100644 index 000000000..3aeb1f341 --- /dev/null +++ b/modules/oe_theme_helper/tests/modules/oe_theme_inpage_navigation_test/templates/oe-theme-inpage-navigation-test-no-elements.html.twig @@ -0,0 +1,14 @@ +{# +/** + * @file + * Test template with content that generates no entries for the inpage navigation. + */ +#} +{{ attach_library('oe_theme_inpage_navigation_test/inpage_navigation_test') }} +
    + +

    Lorem ipsum dolor sit.

    +

    Lorem ipsum dolor sit amet, consectetur.

    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deleniti, eius!

    + +
    diff --git a/modules/oe_theme_helper/tests/src/FunctionalJavascript/InPageNavigationBlockTest.php b/modules/oe_theme_helper/tests/src/FunctionalJavascript/InPageNavigationBlockTest.php new file mode 100644 index 000000000..29f3c4a7e --- /dev/null +++ b/modules/oe_theme_helper/tests/src/FunctionalJavascript/InPageNavigationBlockTest.php @@ -0,0 +1,127 @@ +container->get('theme_installer')->install(['oe_theme']); + $this->container->get('theme_handler')->setDefault('oe_theme'); + $this->container->set('theme.registry', NULL); + + // Rebuild the ui_pattern definitions to collect the ones provided by + // oe_theme itself. + \Drupal::service('plugin.manager.ui_patterns')->clearCachedDefinitions(); + + // Enable inpage_navigation block. + $this->drupalPlaceBlock('oe_theme_helper_inpage_navigation', [ + 'region' => 'content', + 'weight' => -10, + 'label_display' => FALSE, + 'id' => 'inpage_navigation', + ]); + + FilterFormat::create([ + 'format' => 'full_html', + 'name' => 'Full HTML', + ])->save(); + } + + /** + * Tests that blocks are configured to use h2 in inpage navigation generation. + */ + public function testContentWithoutInPageNav(): void { + // Create a Page node with required fields only. + /** @var \Drupal\node\Entity\Node $node */ + $node = $this->container->get('entity_type.manager') + ->getStorage('node') + ->create([ + 'type' => 'oe_page', + 'title' => 'Test Page node', + 'body' => 'Body text', + 'oe_teaser' => 'Teaser text', + 'oe_content_content_owner' => 'http://publications.europa.eu/resource/authority/corporate-body/COMMU', + 'uid' => 0, + 'status' => 1, + ]); + + // Add related links. + $node->set('oe_related_links', [ + [ + 'uri' => 'internal:/node', + 'title' => 'Node listing', + ], + [ + 'uri' => 'https://example.com', + 'title' => 'External link', + ], + ]); + $node->save(); + $this->drupalGet($node->toUrl()); + // Assert that the “Related link” entry is generated. + $navigation = $this->assertSession()->elementExists('css', '#block-inpage-navigation nav[data-ecl-inpage-navigation]'); + $inpage_nav_assert = new InPageNavigationAssert(); + $inpage_nav_expected_values = [ + 'title' => 'Page contents', + 'list' => [ + ['label' => 'Related links', 'href' => '#related-links'], + ], + ]; + $inpage_nav_assert->assertPattern($inpage_nav_expected_values, $navigation->getOuterHtml()); + + // Add some h2 headers in the body field. + $node->set('body', [ + [ + 'value' => '

    Heading from body field

    ', + 'format' => 'full_html', + ], + ]); + $node->save(); + $this->drupalGet($node->toUrl()); + // Assert h2 are also considered in the in-page navigation. + $navigation = $this->assertSession()->elementExists('css', '#block-inpage-navigation nav[data-ecl-inpage-navigation]'); + $inpage_nav_assert = new InPageNavigationAssert(); + $inpage_nav_expected_values = [ + 'title' => 'Page contents', + 'list' => [ + ['label' => 'Heading from body field', 'href' => '#heading-from-body-field'], + ['label' => 'Related links', 'href' => '#related-links'], + ], + ]; + $inpage_nav_assert->assertPattern($inpage_nav_expected_values, $navigation->getOuterHtml()); + + // Assert that the in-page navigation block is removed + // when there are no more h2 in the content area. + $node->set('oe_related_links', NULL); + $node->set('body', NULL); + $node->save(); + $this->drupalGet($node->toUrl()); + $this->assertSession()->elementNotExists('css', '#main-content h2'); + $this->assertSession()->elementNotExists('css', '#block-inpage-navigation nav[data-ecl-inpage-navigation]'); + } + +} diff --git a/modules/oe_theme_helper/tests/src/FunctionalJavascript/InPageNavigationLibraryTest.php b/modules/oe_theme_helper/tests/src/FunctionalJavascript/InPageNavigationLibraryTest.php new file mode 100644 index 000000000..705ff2edb --- /dev/null +++ b/modules/oe_theme_helper/tests/src/FunctionalJavascript/InPageNavigationLibraryTest.php @@ -0,0 +1,151 @@ +container->get('theme_installer')->install(['oe_theme']); + $this->container->get('theme_handler')->setDefault('oe_theme'); + $this->container->set('theme.registry', NULL); + + // Rebuild the ui_pattern definitions to collect the ones provided by + // oe_theme itself. + \Drupal::service('plugin.manager.ui_patterns')->clearCachedDefinitions(); + } + + /** + * Test the inpage navigation JS library functionality. + */ + public function testLibrary(): void { + // Place the block so there's an element that will host the generated items. + $this->drupalPlaceBlock('oe_theme_helper_inpage_navigation', [ + 'region' => 'content', + 'weight' => -10, + 'label_display' => FALSE, + 'id' => 'inpage_navigation', + ]); + + $this->drupalGet('/oe-theme-inpage-navigation-test/content'); + $assert_session = $this->assertSession(); + $container = $assert_session->elementExists('css', '#inpage-navigation-test-container'); + + // Verify that IDs are added to the correct elements inside the test + // container. + // CSS selector uses "descendent-or-self" as prefix, so we need to use + // XPath to exclude the container from the selection. + $this->assertCount(10, $container->findAll('xpath', '//*[@id]')); + + $inner = $container->find('xpath', '/div[@data-inpage-navigation-source-area="h3"]'); + // Since an element with ID "details" already exists in the page, the + // counter will start from 1 for this element. + $this->assertEquals('details-1', $inner->find('xpath', '/h3[@class="heading"][text()="Details"]')->getAttribute('id')); + $this->assertEquals('multiple-words-with-spaces', $inner->find('xpath', '/h3[text()="Multiple words with spaces "]')->getAttribute('id')); + // This line covers two cases: + // - escaped selectors are applied correctly; + // - selectors from "outside" source areas are applied also in inner areas. + $this->assertEquals('test-on-attribute-selector', $inner->find('xpath', '/strong[@data-test-attribute="heading"]')->getAttribute('id')); + + // The counter keeps increasing for instances with same slug. + $this->assertEquals( + 'details-2', + $container->find('xpath', '/div[@data-inpage-navigation-source-area="h3"]/following-sibling::h3[position() = 1][text()="Details"]')->getAttribute('id') + ); + + // The element where the ID was specified retained it correctly. + $this->assertEquals('More details', $container->find('xpath', '/h3[@id="details"]')->getText()); + + // Test that markup is removed from generated IDs. We search by ID as it's + // easier to assert the content. + $this->assertEquals('Title with HTML tags', $container->find('xpath', '/h3[@id="title-with-html-tags"]')->getHtml()); + + // Last 3 assertions for the ID generation. + $this->assertEquals('strip--unwanted-characters', $container->find('css', '.strip')->getAttribute('id')); + $this->assertEquals('constructor', $container->find('xpath', '/h3[@class="heading"][text()="Reserved keyword"]')->getAttribute('id')); + $this->assertEquals('length', $container->find('xpath', '/h3[@class="heading"][text()="Length"]')->getAttribute('id')); + + $navigation = $assert_session->elementExists('css', '#block-inpage-navigation nav[data-ecl-inpage-navigation]'); + $assert = new InPageNavigationAssert(); + $expected = [ + 'title' => 'Page contents', + 'list' => [ + [ + 'label' => 'Details', + 'href' => '#details-1', + ], + [ + 'label' => 'Multiple words with spaces', + 'href' => '#multiple-words-with-spaces', + ], + [ + 'label' => 'Test on attribute selector.', + 'href' => '#test-on-attribute-selector', + ], + [ + 'label' => 'Details', + 'href' => '#details-2', + ], + [ + 'label' => 'More details', + 'href' => '#details', + ], + [ + 'label' => 'Title with HTML tags', + 'href' => '#title-with-html-tags', + ], + [ + 'label' => "Strip \u{203F}\'!\"#\$%&()*+,./:;<=>?@[]^`{|}~ unwanted characters", + 'href' => '#strip--unwanted-characters', + ], + [ + 'label' => 'Reserved keyword', + 'href' => '#constructor', + ], + [ + 'label' => 'Length', + 'href' => '#length', + ], + ], + ]; + $assert->assertPattern($expected, $navigation->getOuterHtml()); + + $this->drupalGet('/oe-theme-inpage-navigation-test/no-entries'); + // Give time for the javascript code to remove the block from the page. + $assert_session->waitForElementRemoved('css', '#block-inpage-navigation'); + // Ensure that overridden callback is triggered for empty navigation list. + $assert_session->elementExists('css', 'h1.ecl-page-header-core__title.empty-inpage-nav-test'); + } + +} diff --git a/modules/oe_theme_helper/tests/src/Kernel/InPageNavigationBlockTest.php b/modules/oe_theme_helper/tests/src/Kernel/InPageNavigationBlockTest.php new file mode 100644 index 000000000..590d1fbf6 --- /dev/null +++ b/modules/oe_theme_helper/tests/src/Kernel/InPageNavigationBlockTest.php @@ -0,0 +1,34 @@ +buildBlock('oe_theme_helper_inpage_navigation', []); + + $assert = new InPageNavigationAssert(); + $assert->assertPattern([ + 'title' => 'Page contents', + 'list' => [], + ], $this->renderRoot($build)); + + $this->assertEquals([ + 'library' => ['oe_theme/inpage_navigation'], + ], $build['#attached']); + } + +} diff --git a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/AddressInlineFormatterTest.php b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/AddressInlineFormatterTest.php index bdc2de596..7374097eb 100644 --- a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/AddressInlineFormatterTest.php +++ b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/AddressInlineFormatterTest.php @@ -32,19 +32,91 @@ protected function setUp(): void { /** * Tests formatting of address. */ - public function testInlineFormatterAddress() { + public function testInlineFormatterAddress(): void { $entity = EntityTestMul::create([]); - $entity->{$this->fieldName} = [ - 'country_code' => 'BE', - 'locality' => 'Brussels ', - 'postal_code' => '1000', - 'address_line1' => 'Rue de la Loi, 56 <123>', - 'address_line2' => 'or \'Wetstraat\' (Dutch), meaning "Law Street"', - ]; + foreach ($this->addressFieldTestData() as $data) { + $cloned_entity = clone $entity; + $cloned_entity->{$this->fieldName} = $data['address']; + $this->renderEntityFields($cloned_entity, $this->display); + $this->assertRaw($data['expected']); + unset($cloned_entity); + } + } - $this->renderEntityFields($entity, $this->display); - $expected = 'Rue de la Loi, 56 <123>, or 'Wetstraat' (Dutch), meaning "Law Street", 1000 Brussels <Bruxelles>, Belgium'; - $this->assertRaw($expected); + /** + * Test data for testInlineFormatterAddress. + * + * @return array[] + * An array of test data arrays with expected result. + */ + public function addressFieldTestData(): array { + return [ + 'Brussels Belgium' => [ + 'address' => [ + 'country_code' => 'BE', + 'locality' => 'Brussels ', + 'postal_code' => '1000', + 'address_line1' => 'Rue de la Loi, 56 <123>', + 'address_line2' => 'or \'Wetstraat\' (Dutch), meaning "Law Street"', + ], + 'expected' => 'Rue de la Loi, 56 <123>, or 'Wetstraat' (Dutch), meaning "Law Street", 1000 Brussels <Bruxelles>, Belgium', + ], + 'Mexico' => [ + 'address' => [ + 'country_code' => 'MX', + ], + 'expected' => 'Mexico', + ], + 'Mexico Ciudad de Mexico' => [ + 'address' => [ + 'country_code' => 'MX', + 'administrative_area' => 'CDMX', + ], + 'expected' => 'CDMX, Mexico', + ], + 'Mexico Baja California Tijuana' => [ + 'address' => [ + 'country_code' => 'MX', + 'administrative_area' => 'B.C.', + 'locality' => 'Tijuana', + ], + 'expected' => 'Tijuana, B.C., Mexico', + ], + 'Mexico Baja California Tijuana 22000' => [ + 'address' => [ + 'country_code' => 'MX', + 'administrative_area' => 'B.C.', + 'locality' => 'Tijuana', + 'postal_code' => '22000', + ], + 'expected' => '22000 Tijuana, B.C., Mexico', + ], + 'Mexico Baja California Tijuana 22000 Street' => [ + 'address' => [ + 'country_code' => 'MX', + 'administrative_area' => 'B.C.', + 'locality' => 'Tijuana', + 'postal_code' => '22000', + 'address_line1' => 'Street', + ], + 'expected' => 'Street, 22000 Tijuana, B.C., Mexico', + ], + 'Bangladesh Dhaka' => [ + 'address' => [ + 'country_code' => 'BD', + 'locality' => 'Dhaka', + ], + 'expected' => 'Dhaka, Bangladesh', + ], + 'Bangladesh Dhaka 1100' => [ + 'address' => [ + 'country_code' => 'BD', + 'locality' => 'Dhaka', + 'postal_code' => '1100', + ], + 'expected' => 'Dhaka, 1100, Bangladesh', + ], + ]; } } diff --git a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaFormatterTest.php b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaFormatterTest.php index a64137c26..38bebb379 100644 --- a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaFormatterTest.php +++ b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaFormatterTest.php @@ -68,6 +68,10 @@ protected function setUp(): void { 'oe_content_featured_media_field', ]); + // Call the install hook of the Media module. + module_load_include('install', 'media'); + media_install(); + // Create a content type. $type = NodeType::create(['name' => 'Test content type', 'type' => 'test_ct']); $type->save(); diff --git a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaThumbnailUrlFormatterTest.php b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaThumbnailUrlFormatterTest.php index 1cb74a7b8..618ac8e49 100644 --- a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaThumbnailUrlFormatterTest.php +++ b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/FeaturedMediaThumbnailUrlFormatterTest.php @@ -21,6 +21,7 @@ class FeaturedMediaThumbnailUrlFormatterTest extends MediaThumbnailUrlFormatterT */ protected static $modules = [ 'oe_content_featured_media_field', + 'node', ]; /** diff --git a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaGalleryFormatterTest.php b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaGalleryFormatterTest.php index f0d15221c..e2d643291 100644 --- a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaGalleryFormatterTest.php +++ b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaGalleryFormatterTest.php @@ -40,6 +40,7 @@ class MediaGalleryFormatterTest extends AbstractKernelTestBase { 'oe_media_iframe', 'oe_media_oembed_mock', 'options', + 'node', ]; /** @@ -60,6 +61,10 @@ protected function setUp() { 'oe_media_iframe', ]); + // Call the install hook of the Media module. + module_load_include('install', 'media'); + media_install(); + // Add a copyright field to some of the media bundles used in the test. Use // different names to make sure that the correct settings are used in the // formatter. diff --git a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatterTestBase.php b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatterTestBase.php index 0d0d47f0d..471ffd9a0 100644 --- a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatterTestBase.php +++ b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/MediaThumbnailUrlFormatterTestBase.php @@ -26,6 +26,7 @@ class MediaThumbnailUrlFormatterTestBase extends AbstractKernelTestBase { 'field', 'file', 'media', + 'node', ]; /** @@ -44,6 +45,10 @@ protected function setUp() { 'entity_reference', 'media', ]); + + // Call the install hook of the Media module. + module_load_include('install', 'media'); + media_install(); } /** diff --git a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/SocialMediaLinksFormatterTestBase.php b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/SocialMediaLinksFormatterTestBase.php index 4ccad01f2..79d362c6f 100644 --- a/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/SocialMediaLinksFormatterTestBase.php +++ b/modules/oe_theme_helper/tests/src/Kernel/Plugin/Field/FieldFormatter/SocialMediaLinksFormatterTestBase.php @@ -25,6 +25,7 @@ class SocialMediaLinksFormatterTestBase extends AbstractKernelTestBase { 'link', 'typed_link', 'entity_test', + 'node', ]; /** diff --git a/modules/oe_theme_helper/tests/src/Kernel/TwigExtensionTest.php b/modules/oe_theme_helper/tests/src/Kernel/TwigExtensionTest.php index aefefaab6..1a094ef11 100644 --- a/modules/oe_theme_helper/tests/src/Kernel/TwigExtensionTest.php +++ b/modules/oe_theme_helper/tests/src/Kernel/TwigExtensionTest.php @@ -16,6 +16,13 @@ */ class TwigExtensionTest extends AbstractKernelTestBase { + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'node', + ]; + /** * Test smart_trim filter. * diff --git a/modules/oe_theme_helper/tests/src/Unit/FilterEclTableTest.php b/modules/oe_theme_helper/tests/src/Unit/FilterEclTableTest.php new file mode 100644 index 000000000..9e7bbf434 --- /dev/null +++ b/modules/oe_theme_helper/tests/src/Unit/FilterEclTableTest.php @@ -0,0 +1,109 @@ + 'test']); + $filter->setStringTranslation($this->getStringTranslationStub()); + + $processed_text = $filter->process($html, NULL)->getProcessedText(); + $this->assertEquals($expected, $processed_text); + } + + /** + * Data provider for testProcess(). + * + * @return array + * The test data. + */ + public function processDataProvider(): array { + return [ + 'Full table with thead and tfoot' => [ + '

    Some text before table

    Caption
    Column 1Column 2
    1-11-2
    2-12-2
    Footer 1Footer 2

    Some text after table

    ', + '

    Some text before table

    Caption
    Column 1Column 2
    1-11-2
    2-12-2
    Footer 1Footer 2

    Some text after table

    ', + ], + 'Table with vertical header - only class is added' => [ + '
    Row 11-11-2
    Row 22-12-2
    Row 33-13-2
    ', + '
    Row 11-11-2
    Row 22-12-2
    Row 33-13-2
    ', + ], + 'Table with horizontal and vertical headers' => [ + '
    Column 1Column 2Column 3
    Row 11-21-3
    Row 22-22-3
    ', + '
    Column 1Column 2Column 3
    Row 11-21-3
    Row 22-22-3
    ', + ], + 'Table without tbody' => [ + '
    Caption
    Column 1Column 2
    1-11-2
    2-12-2
    ', + '
    Caption
    Column 1Column 2
    1-11-2
    2-12-2
    ', + ], + 'Multiple tables' => [ + '
    Column A1Column A2
    A1-1A1-2
    A2-1A2-2
    B1-1B1-2
    B2-1B2-2
    Column C1Column C2Column C3
    C1-1C1-2C1-3
    C2-1C2-2C2-3
    ', + '
    Column A1Column A2
    A1-1A1-2
    A2-1A2-2
    B1-1B1-2
    B2-1B2-2
    Column C1Column C2Column C3
    C1-1C1-2C1-3
    C2-1C2-2C2-3
    ', + ], + 'Table without any th - not processed' => [ + '
    1-11-2
    2-12-2
    3-13-2
    ', + '
    1-11-2
    2-12-2
    3-13-2
    ', + ], + 'Table with cells spanning multiple rows - not processed' => [ + '
    Column 1Column 2Column 3
    1-11-21-3
    2-22-3
    ', + '
    Column 1Column 2Column 3
    1-11-21-3
    2-22-3
    ', + ], + 'Table with cells spanning multiple columns - not processed' => [ + '
    Column 1Column 3
    1-11-21-
    2-12-22-3
    ', + '
    Column 1Column 3
    1-11-21-
    2-12-22-3
    ', + ], + 'Table with header cells spanning multiple rows - not processed' => [ + '
    Column 1Column 2
    Column 4
    1-11-2
    2-12-2
    ', + '
    Column 1Column 2
    Column 4
    1-11-2
    2-12-2
    ', + ], + 'Table with header cells spanning multiple columns - not processed' => [ + '
    Column 1Column 2Column 3
    1-11-3
    2-12-22-3
    ', + '
    Column 1Column 2Column 3
    1-11-3
    2-12-22-3
    ', + ], + 'Table with th cell in body - not processed' => [ + '
    Column 1Column 2
    1-11-2
    2-12-2
    ', + '
    Column 1Column 2
    1-11-2
    2-12-2
    ', + ], + 'Table with multiple header rows - first row is used' => [ + '
    Column 1Column 2Column 3
    Column 4Column 5Column 6
    1-11-21-3
    ', + '
    Column 1Column 2Column 3
    Column 4Column 5Column 6
    1-11-21-3
    ', + ], + 'Table header with invalid header - only class is added' => [ + '
    Column 1Column 2
    1-11-2
    ', + '
    Column 1Column 2
    1-11-2
    ', + ], + 'Table wrapped in HTML comment - not processed' => [ + '', + '', + ], + 'No table' => [ + '

    Some random text with no tables around.

    ', + '

    Some random text with no tables around.

    ', + ], + ]; + } + +} diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-ar.po b/modules/oe_theme_helper/translations/oe_theme_helper-ar.po new file mode 100644 index 000000000..d8f1a12cd --- /dev/null +++ b/modules/oe_theme_helper/translations/oe_theme_helper-ar.po @@ -0,0 +1,309 @@ + +msgid "" +msgstr "" + +msgid "Organisation type" +msgstr "نوع المنظمة" + +msgid "Show @numb more items" +msgstr "إظهار @numb المزيد من العناصر" + +msgid "When" +msgstr "الموعد" + +msgid "Where" +msgstr "المكان" + +msgid "Organiser" +msgstr "المنظم" + +msgid "Website" +msgstr "الموقع الإلكتروني" + +msgid "Social media" +msgstr "وسائل التواصل الاجتماعي" + +msgid "Number of seats" +msgstr "عدد المقاعد" + +msgid "Entrance fee" +msgstr "رسوم الدخول" + +msgid "Book your seat, @time_left left to register, registration will end on @end_date" +msgstr "احجز مقعدك، @time_left بقي للتسجيل، وسوف ينتهي التسجيل في @end_date." + +msgid "Registration will open in @time_left. You can register from @start_date, until @end_date." +msgstr "سيتم فتح التسجيل في @time_left. يمكنكم التسجيل من @start_date ، حتى @end_date." + +msgid "Registration period ended on @end_date." +msgstr "انتهت فترة التسجيل في @end_date." + +msgid "Postal address" +msgstr "العنوان البريدي" + +msgid "Authors" +msgstr "الكتّاب" + +msgid "Department" +msgstr "القسم" + +msgid "Project duration" +msgstr "مدة المشروع" + +msgid "Project website" +msgstr "موقع المشروع الإلكتروني" + +msgid "Contact organisation" +msgstr "جهة الاتصال" + +msgid "Call status: @label" +msgstr "حالة الدعوة: @label" + +msgid "Press contacts" +msgstr "معلومات الاتصال للصحافة" + +msgid "Call for tenders" +msgstr "دعوة لتقديم عطاءات" + +msgid "Related links" +msgstr "روابط ذات صلة" + +msgid "Practical information" +msgstr "معلومات عملية" + +msgid "Phone number" +msgstr "رقم الهاتف" + +msgid "Opening date" +msgstr "موعد بدء استقبال الطلبات" + +msgid "Deadline date" +msgstr "الموعد النهائي" + +msgid "Deadline dates" +msgstr "المواعيد النهائية" + +msgid "Publication date" +msgstr "تاريخ النشر" + +msgid "Author" +msgstr "الكاتب" + +msgid "Location" +msgstr "الموقع" + +msgid "News type" +msgstr "نوع الخبر" + +msgid "Project locations" +msgstr "مواقع المشروع" + +msgid "Overall budget" +msgstr "الميزانية الإجمالية" + +msgid "EU contribution" +msgstr "مساهمة الاتحاد الأوروبي" + +msgid "Departments" +msgstr "الأقسام" + +msgid "Results" +msgstr "النتائج" + +msgid "Stakeholders" +msgstr "أصحاب المصلحة" + +msgid "Coordinators" +msgstr "المنسقون" + +msgid "Participants" +msgstr "المشاركون" + +msgid "Country" +msgstr "البلد" + +msgid "Countries" +msgstr "البلدان" + +msgid "EU Organisation" +msgstr "منظمة تابعة للاتحاد الأوروبي" + +msgid "Non-EU organisation" +msgstr "منظمة غير تابعة للاتحاد الأوروبي" + +msgid "Reference" +msgstr "رقم المرجع" + +msgid "Upcoming" +msgstr "لم يفتح بعد" + +msgid "Open" +msgstr "مفتوح" + +msgid "Closed" +msgstr "مغلق" + +msgid "Details" +msgstr "التفاصيل" + +msgid "Status" +msgstr "حالة الدعوة" + +msgid "Publication" +msgstr "منشور" + +msgid "Description" +msgstr "الوصف" + +msgid "Email" +msgstr "البريد الإلكتروني" + +msgid "Contact" +msgstr "اتصل بنا" + +msgid "Contacts" +msgstr "جهات الاتصال" + +msgid "Organisation" +msgstr "اسم المنظمة" + +msgid "Fax number" +msgstr "رقم الفاكس" + +msgid "Mobile number" +msgstr "رقم الهاتف المحمول" + +msgid "Office" +msgstr "مكتب" + +msgid "Documents" +msgstr "الوثائق والمستندات" + +msgid "Funding" +msgstr "التمويل" + +msgid "As planned" +msgstr "كما هو مخطط" + +msgid "Cancelled" +msgstr "ملغى" + +msgid "Rescheduled" +msgstr "معاد جدولته" + +msgid "Postponed" +msgstr "مؤجل" + +msgid "Address" +msgstr "العنوان" + +msgid "Live stream" +msgstr "البث المباشر" + +msgid "Live streaming available" +msgstr "البث المباشر متاح" + +msgid "Project" +msgstr "مشروع" + +msgid "Publication type" +msgstr "نوع المنشور" + +msgid "Call for proposals" +msgstr "دعوة لتقديم مقترحات" + +msgid "Funding programme" +msgstr "برنامج التمويل" + +msgid "Deadline model" +msgstr "نموذج الموعد النهائي" + +msgid "Single-stage" +msgstr "على مرحلة واحدة" + +msgid "Two-stage" +msgstr "على مرحلتين" + +msgid "Multiple cut-off" +msgstr "عدة مراحل متقطعة" + +msgid "Permanent" +msgstr "دائم" + +msgid "Last updated on: @date" +msgstr "آخر تحديث في: @date" + +msgid "File" +msgstr "ملف" + +msgid "Files" +msgstr "ملفات" + +msgid "Identification" +msgstr "تعريف" + +msgid "Identifications" +msgstr "تعريفات" + +msgid "Related department" +msgstr "القسم ذو الصلة" + +msgid "Related departments" +msgstr "الأقسام ذوي الصلة" + +msgid "Consultation" +msgstr "استشارة" + +msgid "Deadline" +msgstr "الموعد نهائي" + +msgid "Respond to the questionnaire" +msgstr "الرد على الاستبيان" + +msgid "Respond to the consultation" +msgstr "الرد على الاستشارة" + +msgid "Target audience" +msgstr "الجمهور المستهدف" + +msgid "Why we are consulting" +msgstr "لماذا نطلب الاستشارة" + +msgid "Consultation outcome" +msgstr "نتائج الاستشارة" + +msgid "Additional information" +msgstr "معلومات إضافية" + +msgid "Reference documents" +msgstr "المستندات المرجعية" + +msgid "The response period for this consultation has ended. Thank you for your input." +msgstr "انتهت فترة الاستجابة لهذه الاستشارة. شكراً على مساهمتكم." + +msgid "Responsibilities" +msgstr "المسؤوليات" + +msgid "Media" +msgstr "الإعلام" + +msgid "Latest" +msgstr "آخر الأحداث" + +msgid "Transparency" +msgstr "الشفافية" + +msgid "Articles and presentations" +msgstr "مقالات وعروض تقديمية" + +msgid "Biography" +msgstr "السيرة الذاتية" + +msgid "Declaration of interests" +msgstr "إعلان المصالح " + +msgid "Show contact details" +msgstr "إظهار تفاصيل الاتصال" + +msgid "Hide contact details" +msgstr "إخفاء تفاصيل الاتصال" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-bg.po b/modules/oe_theme_helper/translations/oe_theme_helper-bg.po index c9a90caa5..fb742a448 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-bg.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-bg.po @@ -336,3 +336,6 @@ msgstr "Показване на координати за връзка" msgid "Hide contact details" msgstr "Скриване на координатите за връзка" + +msgid "Leadership and organisation" +msgstr "Ръководство и организация" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-ca.po b/modules/oe_theme_helper/translations/oe_theme_helper-ca.po new file mode 100644 index 000000000..4bcb30397 --- /dev/null +++ b/modules/oe_theme_helper/translations/oe_theme_helper-ca.po @@ -0,0 +1,309 @@ + +msgid "" +msgstr "" + +msgid "Organisation type" +msgstr "Tipus d'organització" + +msgid "Show @numb more items" +msgstr "Mostra @numb elements més" + +msgid "When" +msgstr "Quan" + +msgid "Where" +msgstr "On" + +msgid "Organiser" +msgstr "Organitzador" + +msgid "Website" +msgstr "Lloc web" + +msgid "Social media" +msgstr "Xarxes socials" + +msgid "Number of seats" +msgstr "Nombre de localitats" + +msgid "Entrance fee" +msgstr "Preu de l'entrada" + +msgid "Book your seat, @time_left left to register, registration will end on @end_date" +msgstr "Reserveu la vostra plaça. Queden @time_left per inscriure's-hi. El termini acaba el @end_date." + +msgid "Registration will open in @time_left. You can register from @start_date, until @end_date." +msgstr "El termini d'inscripció comença el @time_left. Podeu inscriure-us del @start_date al @end_date." + +msgid "Registration period ended on @date." +msgstr "El termini d'inscripció va finalitzar el @end_date." + +msgid "Postal address" +msgstr "Adreça postal" + +msgid "Authors" +msgstr "Autors" + +msgid "Department" +msgstr "Servei" + +msgid "Project duration" +msgstr "Durada del projecte" + +msgid "Project website" +msgstr "Lloc web del projecte" + +msgid "Contact organisation" +msgstr "Organització de contacte" + +msgid "Call status: @label" +msgstr "Estat de la convocatòria: @label" + +msgid "Press contacts" +msgstr "Contactes de premsa" + +msgid "Call for tenders" +msgstr "Convocatòria de licitacions" + +msgid "Related links" +msgstr "Enllaços relacionats" + +msgid "Practical information" +msgstr "Informació pràctica" + +msgid "Phone number" +msgstr "Número de telèfon" + +msgid "Opening date" +msgstr "Data d'obertura" + +msgid "Deadline date" +msgstr "Data límit" + +msgid "Deadline dates" +msgstr "Dates límit" + +msgid "Publication date" +msgstr "Data de publicació" + +msgid "Author" +msgstr "Autor" + +msgid "Location" +msgstr "Lloc" + +msgid "News type" +msgstr "Tipus de notícia" + +msgid "Project locations" +msgstr "Llocs del projecte" + +msgid "Overall budget" +msgstr "Pressupost total" + +msgid "EU contribution" +msgstr "Contribució de la UE" + +msgid "Departments" +msgstr "Serveis" + +msgid "Results" +msgstr "Resultats" + +msgid "Stakeholders" +msgstr "Parts interessades" + +msgid "Coordinators" +msgstr "Coordinadors" + +msgid "Participants" +msgstr "Participants" + +msgid "Country" +msgstr "País" + +msgid "Countries" +msgstr "Països" + +msgid "EU Organisation" +msgstr "Organització de la UE" + +msgid "Non-EU organisation" +msgstr "Organització no pertanyent a la UE" + +msgid "Reference" +msgstr "Referència" + +msgid "Upcoming" +msgstr "Properament" + +msgid "Open" +msgstr "Obert" + +msgid "Closed" +msgstr "Tancat" + +msgid "Details" +msgstr "Detalls" + +msgid "Status" +msgstr "Estat" + +msgid "Publication" +msgstr "Publicació" + +msgid "Description" +msgstr "Descripció" + +msgid "Email" +msgstr "Correu electrònic" + +msgid "Contact" +msgstr "Contacte" + +msgid "Contacts" +msgstr "Contactes" + +msgid "Organisation" +msgstr "Organització" + +msgid "Fax number" +msgstr "Número de fax" + +msgid "Mobile number" +msgstr "Número de mòbil" + +msgid "Office" +msgstr "Oficina" + +msgid "Documents" +msgstr "Documents" + +msgid "Funding" +msgstr "Finançament" + +msgid "As planned" +msgstr "Com estava previst" + +msgid "Cancelled" +msgstr "Cancel·lat" + +msgid "Rescheduled" +msgstr "Reprogramat" + +msgid "Postponed" +msgstr "Ajornat" + +msgid "Address" +msgstr "Adreça" + +msgid "Live stream" +msgstr "Retransmissió en directe" + +msgid "Live streaming available" +msgstr "Retransmissió en directe disponible" + +msgid "Project" +msgstr "Projecte" + +msgid "Publication type" +msgstr "Tipus de publicació" + +msgid "Call for proposals" +msgstr "Convocatòria de propostes" + +msgid "Funding programme" +msgstr "Programa de finançament" + +msgid "Deadline model" +msgstr "Model de termini" + +msgid "Single-stage" +msgstr "D'una fase" + +msgid "Two-stage" +msgstr "De dues fases" + +msgid "Multiple cut-off" +msgstr "Vàries dates límit" + +msgid "Permanent" +msgstr "Permanent" + +msgid "Last updated on: @date" +msgstr "Darrera actualització: @date " + +msgid "File" +msgstr "Arxiu" + +msgid "Files" +msgstr "Arxius" + +msgid "Identification" +msgstr "Identificació" + +msgid "Identifications" +msgstr "Identificacions" + +msgid "Related department" +msgstr "Servei relacionat" + +msgid "Related departments" +msgstr "Serveis relacionats" + +msgid "Consultation" +msgstr "Consulta" + +msgid "Deadline" +msgstr "Data límit" + +msgid "Respond to the questionnaire" +msgstr "Responeu el qüestionari" + +msgid "Respond to the consultation" +msgstr "Responeu a la consulta" + +msgid "Target audience" +msgstr "Destinatari" + +msgid "Why we are consulting" +msgstr "Per què fem aquesta consulta" + +msgid "Consultation outcome" +msgstr "Resultat de la consulta" + +msgid "Additional information" +msgstr "Informació addicional" + +msgid "Reference documents" +msgstr "Documents de referència" + +msgid "Responsibilities" +msgstr "Responsabilitats" + +msgid "Media" +msgstr "Mitjans de comunicació" + +msgid "Latest" +msgstr "Actualitat" + +msgid "Transparency" +msgstr "Transparència" + +msgid "Articles and presentations" +msgstr "Articles i presentacions" + +msgid "Biography" +msgstr "Biografia" + +msgid "Declaration of interests" +msgstr "Declaració d'interessos" + +msgid "Show contact details" +msgstr "Mostra les dades de contacte" + +msgid "Hide contact details" +msgstr "Amagueu les dades de contacte" + +msgid "Leadership and organisation" +msgstr "Direcció i organització" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-cs.po b/modules/oe_theme_helper/translations/oe_theme_helper-cs.po index 412a68f06..5f85d7d32 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-cs.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-cs.po @@ -336,3 +336,6 @@ msgstr "Zobrazit kontaktní údaje" msgid "Hide contact details" msgstr "Skrýt kontaktní údaje" + +msgid "Leadership and organisation" +msgstr "Vedení a organizace" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-da.po b/modules/oe_theme_helper/translations/oe_theme_helper-da.po index 6ebf6a55a..16cda2851 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-da.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-da.po @@ -336,3 +336,6 @@ msgstr "Vis kontaktoplysninger" msgid "Hide contact details" msgstr "Skjul kontaktoplysninger" + +msgid "Leadership and organisation" +msgstr "Ledelse og organisation" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-de.po b/modules/oe_theme_helper/translations/oe_theme_helper-de.po index 689d59aa4..a60084aec 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-de.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-de.po @@ -336,3 +336,6 @@ msgstr "Kontaktdaten anzeigen" msgid "Hide contact details" msgstr "Kontaktdaten verbergen" + +msgid "Leadership and organisation" +msgstr "Leitung und Organisation" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-el.po b/modules/oe_theme_helper/translations/oe_theme_helper-el.po index 1bda39b7c..0bb6262b4 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-el.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-el.po @@ -336,3 +336,6 @@ msgstr "Εμφάνιση στοιχείων επικοινωνίας" msgid "Hide contact details" msgstr "Απόκρυψη στοιχείων επικοινωνίας" + +msgid "Leadership and organisation" +msgstr "Διοίκηση και οργάνωση" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-es.po b/modules/oe_theme_helper/translations/oe_theme_helper-es.po index bfe23e5de..721fbfedb 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-es.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-es.po @@ -336,3 +336,6 @@ msgstr "Mostrar datos del contacto" msgid "Hide contact details" msgstr "Ocultar datos de contacto" + +msgid "Leadership and organisation" +msgstr "Dirección y organización" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-et.po b/modules/oe_theme_helper/translations/oe_theme_helper-et.po index e60066c3c..af5c9ba19 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-et.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-et.po @@ -336,3 +336,6 @@ msgstr "Näita kontaktandmeid" msgid "Hide contact details" msgstr "Peida kontaktandmed" + +msgid "Leadership and organisation" +msgstr "Juhtkond ja struktuur" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-fi.po b/modules/oe_theme_helper/translations/oe_theme_helper-fi.po index 0739c7b69..bf1b51bd5 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-fi.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-fi.po @@ -336,3 +336,6 @@ msgstr "Näytä yhteystiedot" msgid "Hide contact details" msgstr "Piilota yhteystiedot" + +msgid "Leadership and organisation" +msgstr "Johto ja organisaatio" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-fr.po b/modules/oe_theme_helper/translations/oe_theme_helper-fr.po index dbeb04a78..60b1e0607 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-fr.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-fr.po @@ -336,3 +336,6 @@ msgstr "Afficher les coordonnées" msgid "Hide contact details" msgstr "Masquer les coordonnées" + +msgid "Leadership and organisation" +msgstr "Direction et organisation" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-ga.po b/modules/oe_theme_helper/translations/oe_theme_helper-ga.po index 3a29ac65a..7ffb18190 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-ga.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-ga.po @@ -336,3 +336,6 @@ msgstr "Taispeáin de shonraí teagmhála" msgid "Hide contact details" msgstr "Cuir na sonraí teagmhála i bhfolach" + +msgid "Leadership and organisation" +msgstr "Ceannaireacht agus eagrúchán" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-hr.po b/modules/oe_theme_helper/translations/oe_theme_helper-hr.po index becc6b5ce..9fc0aa703 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-hr.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-hr.po @@ -336,3 +336,6 @@ msgstr "Prikaži podatke za kontakt" msgid "Hide contact details" msgstr "Sakrij podatke za kontakt" + +msgid "Leadership and organisation" +msgstr "Vodstvo i ustroj" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-hu.po b/modules/oe_theme_helper/translations/oe_theme_helper-hu.po index 65ed20db1..4dfd07511 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-hu.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-hu.po @@ -336,3 +336,6 @@ msgstr "Elérhetőségi adatok megjelenítése" msgid "Hide contact details" msgstr "Elérhetőségi adatok elrejtése" + +msgid "Leadership and organisation" +msgstr "Vezetés és szervezeti felépítés" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-it.po b/modules/oe_theme_helper/translations/oe_theme_helper-it.po index 71026c4b8..dd8cf5230 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-it.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-it.po @@ -336,3 +336,6 @@ msgstr "Mostra contatti" msgid "Hide contact details" msgstr "Nascondi i contatti" + +msgid "Leadership and organisation" +msgstr "Direzione e organizzazione" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-lt.po b/modules/oe_theme_helper/translations/oe_theme_helper-lt.po index 57cbcd6dd..a2e64b579 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-lt.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-lt.po @@ -336,3 +336,6 @@ msgstr "Rodyti kontaktinius duomenis" msgid "Hide contact details" msgstr "Slėpti kontaktinius duomenis" + +msgid "Leadership and organisation" +msgstr "Vadovybė ir organizacinė struktūra" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-lv.po b/modules/oe_theme_helper/translations/oe_theme_helper-lv.po index a4045b769..d9b0adec3 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-lv.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-lv.po @@ -336,3 +336,6 @@ msgstr "Parādīt kontaktinformāciju" msgid "Hide contact details" msgstr "Paslēpt kontaktinformāciju" + +msgid "Leadership and organisation" +msgstr "Vadība un organizācija" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-mt.po b/modules/oe_theme_helper/translations/oe_theme_helper-mt.po index cf5d67a85..8217638f1 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-mt.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-mt.po @@ -336,3 +336,6 @@ msgstr "Uri d-dettalji ta' kuntatt" msgid "Hide contact details" msgstr "Aħbi d-dettalji ta' kuntatt" + +msgid "Leadership and organisation" +msgstr "Tmexxija u organizzazzjoni" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-nl.po b/modules/oe_theme_helper/translations/oe_theme_helper-nl.po index 8cf38098a..abe28feee 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-nl.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-nl.po @@ -336,3 +336,6 @@ msgstr "Contactinformatie" msgid "Hide contact details" msgstr "Contactinformatie verbergen" + +msgid "Leadership and organisation" +msgstr "Leiding en organisatie" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-pl.po b/modules/oe_theme_helper/translations/oe_theme_helper-pl.po index 1941afa5e..861cebefb 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-pl.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-pl.po @@ -336,3 +336,6 @@ msgstr "Pokaż dane kontaktowe" msgid "Hide contact details" msgstr "Ukryj dane kontaktowe" + +msgid "Leadership and organisation" +msgstr "Kierownictwo i organizacja" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-pt-pt.po b/modules/oe_theme_helper/translations/oe_theme_helper-pt-pt.po index 65503a919..6aa59fc8c 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-pt-pt.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-pt-pt.po @@ -336,3 +336,6 @@ msgstr "Ver contactos" msgid "Hide contact details" msgstr "Ocultar contactos" + +msgid "Leadership and organisation" +msgstr "Direção e organização" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-ro.po b/modules/oe_theme_helper/translations/oe_theme_helper-ro.po index 830537045..8831fbcff 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-ro.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-ro.po @@ -336,3 +336,6 @@ msgstr "Afișați datele de contact" msgid "Hide contact details" msgstr "Ascundeți datele de contact" + +msgid "Leadership and organisation" +msgstr "Conducere și organizare" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-sk.po b/modules/oe_theme_helper/translations/oe_theme_helper-sk.po index 315dca476..fb087dc67 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-sk.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-sk.po @@ -336,3 +336,6 @@ msgstr "Zobraziť kontaktné informácie" msgid "Hide contact details" msgstr "Skryť kontaktné informácie" + +msgid "Leadership and organisation" +msgstr "Vedenie a organizácia" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-sl.po b/modules/oe_theme_helper/translations/oe_theme_helper-sl.po index 7916026d9..526a3fd3d 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-sl.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-sl.po @@ -336,3 +336,6 @@ msgstr "Prikaži kontaktne podatke" msgid "Hide contact details" msgstr "Skrij kontaktne podatke" + +msgid "Leadership and organisation" +msgstr "Vodstvo in organiziranost" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-sv.po b/modules/oe_theme_helper/translations/oe_theme_helper-sv.po index d23fae659..6acc83c13 100644 --- a/modules/oe_theme_helper/translations/oe_theme_helper-sv.po +++ b/modules/oe_theme_helper/translations/oe_theme_helper-sv.po @@ -336,3 +336,6 @@ msgstr "Visa kontaktuppgifter" msgid "Hide contact details" msgstr "Dölj kontaktuppgifter" + +msgid "Leadership and organisation" +msgstr "Ledning och organisation" diff --git a/modules/oe_theme_helper/translations/oe_theme_helper-tr.po b/modules/oe_theme_helper/translations/oe_theme_helper-tr.po new file mode 100644 index 000000000..b66ffd880 --- /dev/null +++ b/modules/oe_theme_helper/translations/oe_theme_helper-tr.po @@ -0,0 +1,309 @@ + +msgid "" +msgstr "" + +msgid "Organisation type" +msgstr "Organizasyon türü" + +msgid "Show @numb more items" +msgstr "Daha fazla öğe göster @numb" + +msgid "When" +msgstr "Tarih" + +msgid "Where" +msgstr "Yer" + +msgid "Organiser" +msgstr "Organizatör" + +msgid "Website" +msgstr "İnternet sitesi" + +msgid "Social media" +msgstr "Sosyal medya" + +msgid "Number of seats" +msgstr "Yer sayısı" + +msgid "Entrance fee" +msgstr "Giriş ücreti" + +msgid "Book your seat, @time_left left to register, registration will end on @end_date" +msgstr "Yerinizi ayırmak için rezervasyon yapın, Kayıt için kalan süre: @time_left, Kayıtlar @end_date tarihinde sona erecek." + +msgid "Registration will open in @time_left. You can register from @start_date, until @end_date." +msgstr "Kayıtlar @time_left içinde açılacaktır. @start_date tarihinden @end_date tarihine kadar kayıt yaptırabilirsiniz.yaptırabilirsiniz." + +msgid "Registration period ended on @date." +msgstr "Kayıt dönemi @end_date tarihinde sona erdi." + +msgid "Postal address" +msgstr "Posta adresi" + +msgid "Authors" +msgstr "Yazarlar" + +msgid "Department" +msgstr "Bölüm" + +msgid "Project duration" +msgstr "Proje süresi" + +msgid "Project website" +msgstr "Proje web sitesi" + +msgid "Contact organisation" +msgstr "İletişime geçilecek kurum" + +msgid "Call status: @label" +msgstr "Çağrı durumu: @label" + +msgid "Press contacts" +msgstr "İletişime geçilecek basın görevlileri" + +msgid "Call for tenders" +msgstr "İhale çağrısı" + +msgid "Related links" +msgstr "İlgili linkler (bağlantılar)" + +msgid "Practical information" +msgstr "Pratik bilgiler" + +msgid "Phone number" +msgstr "Telefon numarası" + +msgid "Opening date" +msgstr "Açılış tarihi" + +msgid "Deadline date" +msgstr "Son teslim tarihi" + +msgid "Deadline dates" +msgstr "Son teslim tarihleri" + +msgid "Publication date" +msgstr "Yayın tarihi" + +msgid "Author" +msgstr "Yazar" + +msgid "Location" +msgstr "Konum " + +msgid "News type" +msgstr "Haber türü" + +msgid "Project locations" +msgstr "Proje yerleri" + +msgid "Overall budget" +msgstr "Genel bütçe" + +msgid "EU contribution" +msgstr "AB katkısı" + +msgid "Departments" +msgstr "Bölümler" + +msgid "Results" +msgstr "Sonuçlar" + +msgid "Stakeholders" +msgstr "Paydaşlar" + +msgid "Coordinators" +msgstr "Koordinatörler" + +msgid "Participants" +msgstr "Katılımcılar" + +msgid "Country" +msgstr "Ülke" + +msgid "Countries" +msgstr "Ülkeler" + +msgid "EU Organisation" +msgstr "AB Organizasyonu" + +msgid "Non-EU organisation" +msgstr "AB Dışı Kuruluş" + +msgid "Reference" +msgstr "Referans" + +msgid "Upcoming" +msgstr "Önümüzdeki" + +msgid "Open" +msgstr "Açık" + +msgid "Closed" +msgstr "Kapalı" + +msgid "Details" +msgstr "Detaylar" + +msgid "Status" +msgstr "Durum" + +msgid "Publication" +msgstr "Yayın" + +msgid "Description" +msgstr "Açıklama" + +msgid "Email" +msgstr "E-posta adresi" + +msgid "Contact" +msgstr "İletişim" + +msgid "Contacts" +msgstr "İletişime geçilecek kişiler" + +msgid "Organisation" +msgstr "Organizasyon " + +msgid "Fax number" +msgstr "Faks numarası" + +msgid "Mobile number" +msgstr "Mobil telefon numarası" + +msgid "Office" +msgstr "Ofis" + +msgid "Documents" +msgstr "Belgeler" + +msgid "Funding" +msgstr "Finansman" + +msgid "As planned" +msgstr "Planlandığı üzere" + +msgid "Cancelled" +msgstr "İptal edildi" + +msgid "Rescheduled" +msgstr "Yeni bir tarihe ertelendi" + +msgid "Postponed" +msgstr "Ertelendi" + +msgid "Address" +msgstr "Adres" + +msgid "Live stream" +msgstr "Canlı yayın" + +msgid "Live streaming available" +msgstr "Canlı yayın mevcut" + +msgid "Project" +msgstr "Proje" + +msgid "Publication type" +msgstr "Yayın türü" + +msgid "Call for proposals" +msgstr "Teklif çağrısı" + +msgid "Funding programme" +msgstr "Finansman programı" + +msgid "Deadline model" +msgstr "Son teslim tarihi modeli" + +msgid "Single-stage" +msgstr "Tek aşamalı" + +msgid "Two-stage" +msgstr "İki aşamalı" + +msgid "Multiple cut-off" +msgstr "Çoklu aşamalı ihale düzeni" + +msgid "Permanent" +msgstr "Kalıcı" + +msgid "File" +msgstr "Dosya" + +msgid "Files" +msgstr "Dosyalar" + +msgid "Identification" +msgstr "Kimlik" + +msgid "Identifications" +msgstr "Kimlikler" + +msgid "Related department" +msgstr "İlgili bölüm" + +msgid "Related departments" +msgstr "İlgili bölümler" + +msgid "Consultation" +msgstr "İstişare " + +msgid "Deadline" +msgstr "Son teslim tarihi" + +msgid "Respond to the questionnaire" +msgstr "Ankete katılın" + +msgid "Respond to the consultation" +msgstr "Halka açık istişare toplantısına katılın" + +msgid "Target audience" +msgstr "Hedef kitle" + +msgid "Why we are consulting" +msgstr "Neden istişare toplantısı düzenliyoruz" + +msgid "Consultation outcome" +msgstr "İstişare toplantısı sonucu" + +msgid "Additional information" +msgstr "Ek Bilgiler" + +msgid "Reference documents" +msgstr "Referans dökümanlar" + +msgid "The response period for this consultation has ended. Thank you for your input." +msgstr "Bu istişare toplantısı için yanıt süresi sona ermiştir. Katkılarınız için teşekkürler." + +msgid "Responsibilities" +msgstr "Sorumluluklar" + +msgid "Media" +msgstr "Medya" + +msgid "Latest" +msgstr "Son" + +msgid "Transparency" +msgstr "Şeffaflık" + +msgid "Articles and presentations" +msgstr "Makaleler ve sunumlar" + +msgid "Biography" +msgstr "Biyografi" + +msgid "Declaration of interests" +msgstr "İlgi alanları beyanı" + +msgid "Show contact details" +msgstr "İletişim bilgilerinizi gösteriniz" + +msgid "Hide contact details" +msgstr "İletişim bilgilerinizi gizle" + +msgid "Leadership and organisation" +msgstr "Liderlik ve organizasyon" diff --git a/oe_theme.libraries.yml b/oe_theme.libraries.yml index be19fce27..2c1d1c9f4 100644 --- a/oe_theme.libraries.yml +++ b/oe_theme.libraries.yml @@ -46,3 +46,10 @@ print: css: theme: css/print.css: { media: print } + +inpage_navigation: + js: + js/inpage_navigation.js: {} + dependencies: + - core/drupal + - core/jquery diff --git a/oe_theme.theme b/oe_theme.theme index d9c65da4c..33d352b53 100644 --- a/oe_theme.theme +++ b/oe_theme.theme @@ -82,10 +82,15 @@ function oe_theme_preprocess(&$variables) { * Implements hook_preprocess_breadcrumb(). */ function oe_theme_preprocess_breadcrumb(array &$variables): void { - $request = \Drupal::request(); + $cacheability = CacheableMetadata::createFromRenderArray($variables); + $cacheability->addCacheContexts(['route']); + $cacheability->applyTo($variables); + + $request = \Drupal::request(); $route_match = \Drupal::routeMatch(); - $title = \Drupal::service('title_resolver') - ->getTitle($request, $route_match->getRouteObject()); + + $route = $route_match->getRouteObject(); + $title = \Drupal::service('title_resolver')->getTitle($request, $route); unset($variables['links']); $variables['links'] = array_map(function ($item) { @@ -401,10 +406,6 @@ function oe_theme_preprocess_form_element(array &$variables): void { * Add paragraph formatting to body. */ function oe_theme_preprocess_field(&$variables, $hook): void { - if ($variables['field_name'] === 'body') { - $variables['attributes']['class'][] = 'ecl-editor'; - } - // Add the ECL image class to the image fields. $field_name = $variables['field_name']; if (in_array($field_name, ['oe_media_avportal_photo'])) { @@ -928,6 +929,14 @@ function oe_theme_preprocess_paragraph__oe_text_feature_media(array &$variables) // paragraph template. $cacheability->addCacheableDependency($media); + // Run access checks on the media entity. + $access = $media->access('view', $variables['user'], TRUE); + $cacheability->addCacheableDependency($access); + if (!$access->isAllowed()) { + $cacheability->applyTo($variables); + return; + } + // Get the media source. $source = $media->getSource(); @@ -978,6 +987,52 @@ function oe_theme_preprocess_paragraph__oe_text_feature_media(array &$variables) $cacheability->applyTo($variables); } +/** + * Implements hook_preprocess_HOOK(). + */ +function oe_theme_preprocess_paragraph__oe_iframe_media(&$variables) { + /** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */ + $paragraph = $variables['paragraph']; + + /** @var \Drupal\media\Entity\Media $media */ + $media = $paragraph->get('field_oe_media')->entity; + if (!$media instanceof MediaInterface) { + // The media entity is not available anymore, bail out. + return; + } + + // Caches are handled by the formatter usually. Since we are not rendering + // the original render arrays, we need to propagate our caches to the + // paragraph template. + $cacheability = CacheableMetadata::createFromRenderArray($variables); + $cacheability->addCacheableDependency($media); + $media_type = \Drupal::entityTypeManager()->getStorage('media_type')->load($media->bundle()); + $cacheability->addCacheableDependency($media_type); + + $access = $media->access('view', $variables['user'], TRUE); + $cacheability->addCacheableDependency($access); + $cacheability->applyTo($variables); + + if (!$access->isAllowed()) { + return; + } + + // Get the full width value. + $variables['full_width'] = (bool) $paragraph->get('field_oe_iframe_media_full_width')->value; + + // Retrieve the correct media translation. + $media = \Drupal::service('entity.repository')->getTranslationFromContext($media, $paragraph->language()->getId()); + + // Get the ratio value. + $variables['ratio'] = _oe_theme_get_oe_media_iframe_ratio($media); + + // Get the Iframe content to render. + $variables['iframe'] = $media->get('oe_media_iframe')->view([ + 'label' => 'hidden', + 'type' => 'oe_media_iframe', + ]); +} + /** * Implements hook_preprocess_pattern(). */ @@ -1434,6 +1489,14 @@ function oe_theme_preprocess_paragraph__oe_banner(array &$variables): void { // paragraph template. $cacheability->addCacheableDependency($media); + // Run access checks on the media entity. + $access = $media->access('view', $variables['user'], TRUE); + $cacheability->addCacheableDependency($access); + if (!$access->isAllowed()) { + $cacheability->applyTo($variables); + return; + } + $source = $media->getSource(); // We only support images and AV Portal photos for now. if (!$source instanceof MediaAvPortalSourceInterface && !$source instanceof Image) { @@ -1525,13 +1588,27 @@ function oe_theme_preprocess_field__media__oe_media_iframe__video_iframe__oe_the $variables['ratio'] = $variables['element']['#object']->get('oe_media_iframe_ratio')->value; } +/** + * Gets the value from oe_media_iframe_ratio field. + * + * @param \Drupal\media\MediaInterface $media + * Media with oe_media_iframe_ratio field. + * + * @return string + * Prepared ratio to be used in templates. + */ +function _oe_theme_get_oe_media_iframe_ratio(MediaInterface $media): string { + $ratio = $media->get('oe_media_iframe_ratio')->value ?? 'custom'; + return str_replace('_', '-', $ratio); +} + /** * Implements hook_preprocess_HOOK(). */ function oe_theme_preprocess_field__media__oe_media_iframe__iframe__oe_theme_main_content(array &$variables): void { // Set iframe aspect ratio when rendering the "oe_theme_main_content" // display mode. - $variables['ratio'] = $variables['element']['#object']->get('oe_media_iframe_ratio')->value ?? 'custom'; + $variables['ratio'] = _oe_theme_get_oe_media_iframe_ratio($variables['element']['#object']); } /** diff --git a/src/ValueObject/GalleryItemValueObject.php b/src/ValueObject/GalleryItemValueObject.php index d3bb19fdf..1d0395690 100644 --- a/src/ValueObject/GalleryItemValueObject.php +++ b/src/ValueObject/GalleryItemValueObject.php @@ -170,7 +170,7 @@ public function getArray(): array { 'image' => $this->getThumbnail()->getArray(), 'description' => $this->getCaption(), 'meta' => $this->getMeta(), - 'icon' => '', + 'icon' => 'image', ]; // If video, then set the required source URL format and icon. diff --git a/templates/blocks/block--oe-theme-inpage-navigation-menu.html.twig b/templates/blocks/block--oe-theme-inpage-navigation-menu.html.twig new file mode 100644 index 000000000..bb484fe47 --- /dev/null +++ b/templates/blocks/block--oe-theme-inpage-navigation-menu.html.twig @@ -0,0 +1,9 @@ +{# +/** + * @file + * Theme override for the breadcrumb block wrapper. + * + * @see ./core/themes/stable/templates/block/block.html.twig + */ +#} +{% include '@oe_theme/blocks/block--bare.html.twig' %} diff --git a/templates/blocks/block--region-content--oe-theme-main-page-content.html.twig b/templates/blocks/block--region-content--oe-theme-main-page-content.html.twig new file mode 100644 index 000000000..69ec9fbff --- /dev/null +++ b/templates/blocks/block--region-content--oe-theme-main-page-content.html.twig @@ -0,0 +1,10 @@ +{# +/** + * @file + * Theme override for blocks in the content region for page content block. + * + * @see ./block--region-content.html.twig + */ +#} +{% extends 'block--region-content.html.twig' %} +{% set attributes = attributes.setAttribute('data-inpage-navigation-source-area', 'h2') %} diff --git a/templates/content/node--oe-call-proposals--teaser.html.twig b/templates/content/node--oe-call-proposals--teaser.html.twig index 3e9cd2334..cafe57937 100644 --- a/templates/content/node--oe-call-proposals--teaser.html.twig +++ b/templates/content/node--oe-call-proposals--teaser.html.twig @@ -14,7 +14,7 @@ {{ pattern('list_item', { 'variant': 'default', 'url': url, - 'title': label, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, 'meta': meta, 'additional_information': additional_information, }) }} diff --git a/templates/content/node--oe-call-tenders--teaser.html.twig b/templates/content/node--oe-call-tenders--teaser.html.twig index 5001664a3..b138d1858 100644 --- a/templates/content/node--oe-call-tenders--teaser.html.twig +++ b/templates/content/node--oe-call-tenders--teaser.html.twig @@ -14,7 +14,7 @@ {{ pattern('list_item', { 'variant': 'default', 'url': url, - 'title': label, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, 'meta': meta, 'additional_information': additional_information, }) }} diff --git a/templates/content/node--oe-consultation--teaser.html.twig b/templates/content/node--oe-consultation--teaser.html.twig index 024fa5862..71800eb58 100644 --- a/templates/content/node--oe-consultation--teaser.html.twig +++ b/templates/content/node--oe-consultation--teaser.html.twig @@ -11,7 +11,7 @@ {{ pattern('list_item', { 'variant': 'default', 'url': url, - 'title': label, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, 'meta': [ content.extra_field_oe_consultation_label_status|field_value, ], diff --git a/templates/content/node--oe-event--teaser.html.twig b/templates/content/node--oe-event--teaser.html.twig index fca5c5118..70f5766e7 100644 --- a/templates/content/node--oe-event--teaser.html.twig +++ b/templates/content/node--oe-event--teaser.html.twig @@ -16,7 +16,7 @@ {{ pattern('list_item', { 'variant': variant|default('date'), 'url': url, - 'title': label, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, 'date': pattern_date, 'meta': meta, 'detail': detail, diff --git a/templates/content/node--oe-organisation--teaser.html.twig b/templates/content/node--oe-organisation--teaser.html.twig index 5109f88ac..a921d98f0 100644 --- a/templates/content/node--oe-organisation--teaser.html.twig +++ b/templates/content/node--oe-organisation--teaser.html.twig @@ -16,7 +16,7 @@ not node.oe_organisation_eu_org_type.isEmpty() ? content.oe_organisation_eu_org_type|field_value : content.oe_organisation_non_eu_org_type|field_value, not node.oe_organisation_acronym.isEmpty() ? content.oe_organisation_acronym|field_value, ], - 'title': label, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, 'detail': content.oe_teaser|field_value, 'additional_information': additional_information, 'image': image_url ? { 'src': image_url } diff --git a/templates/content/node--oe-page--teaser.html.twig b/templates/content/node--oe-page--teaser.html.twig new file mode 100644 index 000000000..64023b076 --- /dev/null +++ b/templates/content/node--oe-page--teaser.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Teaser template implementation for "Page" content type. + */ +#} +{% block content %} + {{ pattern('list_item', { + 'variant': 'default', + 'url': url, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, + 'detail': content.oe_teaser|field_value, + 'additional_information': additional_information|default([]) + }) }} +{% endblock %} diff --git a/templates/content/node--oe-person--oe-compact-teaser.html.twig b/templates/content/node--oe-person--oe-compact-teaser.html.twig new file mode 100644 index 000000000..bce166b8a --- /dev/null +++ b/templates/content/node--oe-person--oe-compact-teaser.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Theme override to display a Person node in the Openeuropa Compact Teaser view mode. + */ +#} +
    + +
    + {% if not node.oe_person_jobs.isEmpty() %} +
    {{ content.oe_person_jobs }}
    + {% endif %} + {{ label }} +
    +
    diff --git a/templates/content/node--oe-policy--teaser.html.twig b/templates/content/node--oe-policy--teaser.html.twig new file mode 100644 index 000000000..5c2a956d1 --- /dev/null +++ b/templates/content/node--oe-policy--teaser.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Teaser template implementation for "Policy" content type. + */ +#} +{% block content %} + {{ pattern('list_item', { + 'variant': 'default', + 'url': url, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, + 'detail': content.oe_teaser|field_value, + 'additional_information': additional_information|default([]) + }) }} +{% endblock %} diff --git a/templates/content/node--oe-project--teaser.html.twig b/templates/content/node--oe-project--teaser.html.twig index 4575642ca..32229e2ae 100644 --- a/templates/content/node--oe-project--teaser.html.twig +++ b/templates/content/node--oe-project--teaser.html.twig @@ -12,7 +12,7 @@ {{ pattern('list_item', { 'variant': 'thumbnail_secondary', 'url': url, - 'title': label, + 'title': content.extra_field_oe_theme_helper_short_title_with_fallback|field_value, 'detail': content.oe_teaser|field_value, 'additional_information': additional_information, 'image': image_url ? { 'src': image_url } diff --git a/templates/field/field--bare.html.twig b/templates/field/field--bare.html.twig index bd89575e0..049f43afd 100644 --- a/templates/field/field--bare.html.twig +++ b/templates/field/field--bare.html.twig @@ -7,5 +7,5 @@ */ #} {% for item in items %} - {{ item.content }} + {{- item.content -}} {% endfor %} diff --git a/templates/field/field--media--oe-media-iframe--iframe--oe-theme-main-content.html.twig b/templates/field/field--media--oe-media-iframe--iframe--oe-theme-main-content.html.twig index c983ad351..6a94ddee8 100644 --- a/templates/field/field--media--oe-media-iframe--iframe--oe-theme-main-content.html.twig +++ b/templates/field/field--media--oe-media-iframe--iframe--oe-theme-main-content.html.twig @@ -7,7 +7,7 @@ {% for item in items %} {% include '@ecl-twig/media-container' with { 'embedded_media': item.content, - 'ratio': ratio|replace({'_': '-'}), + 'ratio': ratio, 'extra_classes': (ratio == 'custom') ? 'ecl-media-container--custom-ratio' : '', } %} {% endfor %} diff --git a/templates/field/field--media--oe-media-iframe--iframe.html.twig b/templates/field/field--media--oe-media-iframe--iframe.html.twig new file mode 100644 index 000000000..f346ef668 --- /dev/null +++ b/templates/field/field--media--oe-media-iframe--iframe.html.twig @@ -0,0 +1,9 @@ +{# +/** + * @file + * Theme override for the Iframe field on Iframe media. + * + * @see ./templates/field/field--bare.html.twig + */ +#} +{%- include 'field--bare.html.twig' -%} diff --git a/templates/field/field--node--extra-field-oe-theme-content-organisation-teaser-details.html.twig b/templates/field/field--node--extra-field-oe-theme-content-organisation-teaser-details.html.twig new file mode 100644 index 000000000..c2ede84d3 --- /dev/null +++ b/templates/field/field--node--extra-field-oe-theme-content-organisation-teaser-details.html.twig @@ -0,0 +1,11 @@ +{# +/** + * @file + * Field template for oe_theme_content_organisation_teaser_details extra field. + */ +#} +{% for item in items %} + {% if item.content|render|striptags|trim is not empty %} + {{ item.content }} + {% endif %} +{% endfor %} diff --git a/templates/field/field--node--oe-consultation-aim--oe-consultation--full.html.twig b/templates/field/field--node--oe-consultation-aim--oe-consultation--full.html.twig deleted file mode 100644 index dbdf1828f..000000000 --- a/templates/field/field--node--oe-consultation-aim--oe-consultation--full.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{# -/** - * @file - * OE Consultation Why we are consulting field template. - * - * @see ./core/themes/stable/templates/field/field.html.twig - */ -#} -{% for item in items %} -
    - {{ item.content }} -
    -{% endfor %} diff --git a/templates/field/field--node--oe-consultation-guidelines--oe-consultation--full.html.twig b/templates/field/field--node--oe-consultation-guidelines--oe-consultation--full.html.twig deleted file mode 100644 index dc01cb836..000000000 --- a/templates/field/field--node--oe-consultation-guidelines--oe-consultation--full.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{# -/** - * @file - * OE Consultation Respond to the consultation field template. - * - * @see ./core/themes/stable/templates/field/field.html.twig - */ -#} -{% for item in items %} -
    - {{ item.content }} -
    -{% endfor %} diff --git a/templates/field/field--node--oe-consultation-legal-info--oe-consultation--full.html.twig b/templates/field/field--node--oe-consultation-legal-info--oe-consultation--full.html.twig deleted file mode 100644 index 9b9efd30c..000000000 --- a/templates/field/field--node--oe-consultation-legal-info--oe-consultation--full.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{# -/** - * @file - * OE Consultation legal notice field template. - * - * @see ./core/themes/stable/templates/field/field.html.twig - */ -#} -{% for item in items %} -
    - {{ item.content }} -
    -{% endfor %} diff --git a/templates/field/field--node--oe-consultation-outcome--oe-consultation--full.html.twig b/templates/field/field--node--oe-consultation-outcome--oe-consultation--full.html.twig deleted file mode 100644 index 0857e29a4..000000000 --- a/templates/field/field--node--oe-consultation-outcome--oe-consultation--full.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{# -/** - * @file - * OE Consultation Consultation outcome field template. - * - * @see ./core/themes/stable/templates/field/field.html.twig - */ -#} -{% for item in items %} -
    - {{ item.content }} -
    -{% endfor %} diff --git a/templates/field/field--node--oe-consultation-target-audience--oe-consultation--full.html.twig b/templates/field/field--node--oe-consultation-target-audience--oe-consultation--full.html.twig deleted file mode 100644 index 011f28389..000000000 --- a/templates/field/field--node--oe-consultation-target-audience--oe-consultation--full.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{# -/** - * @file - * OE Consultation Target audience field template. - * - * @see ./core/themes/stable/templates/field/field.html.twig - */ -#} -{% for item in items %} -
    - {{ item.content }} -
    -{% endfor %} diff --git a/templates/field/field--node--oe-consultation-additional-info--oe-consultation--full.html.twig b/templates/field/field--node--oe-organisation-chart--oe-organisation--full.html.twig similarity index 53% rename from templates/field/field--node--oe-consultation-additional-info--oe-consultation--full.html.twig rename to templates/field/field--node--oe-organisation-chart--oe-organisation--full.html.twig index 39c4ecace..1feeaca8f 100644 --- a/templates/field/field--node--oe-consultation-additional-info--oe-consultation--full.html.twig +++ b/templates/field/field--node--oe-organisation-chart--oe-organisation--full.html.twig @@ -1,13 +1,13 @@ {# /** * @file - * OE Consultation Additional information field template. + * Theme override for Organisation chart field template in the Organisation CT full view mode. * * @see ./core/themes/stable/templates/field/field.html.twig */ #} {% for item in items %} -
    +
    {{ item.content }}
    {% endfor %} diff --git a/templates/field/field--node--oe-organisation-contact--oe-organisation--full.html.twig b/templates/field/field--node--oe-organisation-contact--oe-organisation--full.html.twig new file mode 100644 index 000000000..594e3f2c9 --- /dev/null +++ b/templates/field/field--node--oe-organisation-contact--oe-organisation--full.html.twig @@ -0,0 +1,26 @@ +{# +/** + * @file + * Organisation contacts field template. + * + * @see ./core/themes/stable/templates/field/field.html.twig + */ +#} +{% set contacts %}{% for item in items %}{{ item.content }}{% endfor %}{% endset %} + +{% if contacts is not empty %} + {% if items|length == 1 %} + {{ contacts }} + {% else %} + {% include '@ecl-twig/expandable' with { + 'label_expanded': 'Hide contact details'|t, + 'label_collapsed': 'Show contact details'|t, + 'button': { + 'icon': { + 'path': ecl_icon_path, + }, + }, + content: contacts + } only %} + {% endif %} +{% endif %} diff --git a/templates/field/field--node--oe-organisation-staff-link--oe-organisation--full.html.twig b/templates/field/field--node--oe-organisation-staff-link--oe-organisation--full.html.twig new file mode 100644 index 000000000..78838ce08 --- /dev/null +++ b/templates/field/field--node--oe-organisation-staff-link--oe-organisation--full.html.twig @@ -0,0 +1,22 @@ +{# +/** + * @file + * Theme override for Organisation staff search link field template in the Organisation CT full view mode. + * + * @see ./core/themes/stable/templates/field/field.html.twig + */ +#} +{% for item in items %} + {% set bubble_cache = item.content|render %} +
    + {% include '@ecl-twig/link' with { + link: { + type: 'standalone', + label: item.content['#title'], + path: item.content['#url'], + icon_position: 'after' + }, + icon: get_link_icon(item.content['#url'].toString()) + } %} +
    +{% endfor %} diff --git a/templates/field/field--node--oe-person-jobs--oe-person--oe-compact-teaser.html.twig b/templates/field/field--node--oe-person-jobs--oe-person--oe-compact-teaser.html.twig new file mode 100644 index 000000000..43cb02b94 --- /dev/null +++ b/templates/field/field--node--oe-person-jobs--oe-person--oe-compact-teaser.html.twig @@ -0,0 +1,9 @@ +{# +/** + * @file + * Theme override for the Jobs field template of the Person CT in the Openeuropa Compact Teaser view mode. + * + * @see ./core/themes/stable/templates/field/field.html.twig + */ +#} +{%- include 'field--multiple-values--comma-separated.html.twig' -%} diff --git a/templates/field/field--node--oe-project-results--oe-project--full.html.twig b/templates/field/field--node--oe-project-results--oe-project--full.html.twig deleted file mode 100644 index aadfee7a3..000000000 --- a/templates/field/field--node--oe-project-results--oe-project--full.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{# -/** - * @file - * Project results field template. - * - * @see ./core/themes/stable/templates/field/field.html.twig - */ -#} -{% for item in items %} -
    - {{ item.content }} -
    -{% endfor %} diff --git a/templates/field/field--oe-contact--oe-body.html.twig b/templates/field/field--oe-contact--oe-body.html.twig deleted file mode 100644 index 03168651e..000000000 --- a/templates/field/field--oe-contact--oe-body.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{# -/** - * @file - * Theme override for the field template. - * - * @see ./core/themes/stable/templates/field/field.html.twig - */ -#} -
    - {% for item in items %} - {{- item.content -}} - {% endfor %} -
    diff --git a/templates/field/field--oe-contact--oe-link--full.html.twig b/templates/field/field--oe-contact--oe-link--full.html.twig new file mode 100644 index 000000000..5d66dbe47 --- /dev/null +++ b/templates/field/field--oe-contact--oe-link--full.html.twig @@ -0,0 +1,22 @@ +{# +/** + * @file + * Link field in the Contact entity default view mode. + * + * @see ./core/themes/stable/templates/field/field.html.twig + */ +#} +{% for item in items %} + {% set bubble_cache = item.content|render %} +
    + {% include '@ecl-twig/link' with { + link: { + type: 'standalone', + label: item.content['#title'], + path: item.content['#url'], + icon_position: 'after' + }, + icon: get_link_icon(item.content['#url'].toString()) + } %} +
    +{% endfor %} diff --git a/templates/field/field--oe-contact--oe-press-contact-url--full.html.twig b/templates/field/field--oe-contact--oe-press-contact-url--full.html.twig index 329e4d753..b31ae97e0 100644 --- a/templates/field/field--oe-contact--oe-press-contact-url--full.html.twig +++ b/templates/field/field--oe-contact--oe-press-contact-url--full.html.twig @@ -7,15 +7,16 @@ */ #} {% for item in items %} -
    - {% include '@ecl-twig/link' with { - link: { - type: 'standalone', - label: 'Press contacts'|t, - path: item.content['#url'], - icon_position: 'after' - }, - icon: get_link_icon(item.content['#url'].toString()) - } %} -
    + {% set bubble_cache = item.content|render %} +
    + {% include '@ecl-twig/link' with { + link: { + type: 'standalone', + label: 'Press contacts'|t, + path: item.content['#url'], + icon_position: 'after' + }, + icon: get_link_icon(item.content['#url'].toString()) + } %} +
    {% endfor %} diff --git a/templates/field/field--paragraph--field-oe-text-long.html.twig b/templates/field/field--paragraph--field-oe-text-long.html.twig index 09164b2d4..98b31f765 100644 --- a/templates/field/field--paragraph--field-oe-text-long.html.twig +++ b/templates/field/field--paragraph--field-oe-text-long.html.twig @@ -6,6 +6,5 @@ * @see ./core/themes/stable/templates/field/field.html.twig */ #} -
    - {%- include 'field--bare.html.twig' -%} -
    +{% set label_hidden = true %} +{% include '@oe_theme/field/field--text-long.html.twig' %} diff --git a/templates/field/field--text-long.html.twig b/templates/field/field--text-long.html.twig new file mode 100644 index 000000000..875009c91 --- /dev/null +++ b/templates/field/field--text-long.html.twig @@ -0,0 +1,23 @@ +{# +/** + * @file + * Theme override for the text long fields. + * + * @see ./core/themes/stable/templates/field/field.html.twig + */ +#} +{% spaceless %} + {% if not label_hidden %} + {% + set title_classes = [ + 'ecl-u-type-bold', + 'ecl-u-mb-m', + label_display == 'visually_hidden' ? 'visually-hidden', + ] + %} + {{ label }}
    + {% endif %} +
    + {%- include 'field--bare.html.twig' -%} +
    +{% endspaceless %} diff --git a/templates/field/field--text-with-summary.html.twig b/templates/field/field--text-with-summary.html.twig new file mode 100644 index 000000000..07d615c7b --- /dev/null +++ b/templates/field/field--text-with-summary.html.twig @@ -0,0 +1,9 @@ +{# +/** + * @file + * Theme override for the text with summary fields. + * + * @see ./core/themes/stable/templates/field/field.html.twig + */ +#} +{% include '@oe_theme/field/field--text-long.html.twig' %} diff --git a/templates/oe_contact/oe-contact--full.html.twig b/templates/oe_contact/oe-contact--full.html.twig index 2f0c5da20..9dcccdcd8 100644 --- a/templates/oe_contact/oe-contact--full.html.twig +++ b/templates/oe_contact/oe-contact--full.html.twig @@ -16,7 +16,7 @@
    {% endif %} {% if entity.oe_body is not empty %} -
    +
    {{ content.oe_body }}
    {% endif %} diff --git a/templates/paragraphs/paragraph--oe-iframe-media.html.twig b/templates/paragraphs/paragraph--oe-iframe-media.html.twig new file mode 100644 index 000000000..0c2f2bff3 --- /dev/null +++ b/templates/paragraphs/paragraph--oe-iframe-media.html.twig @@ -0,0 +1,30 @@ +{# +/** + * @file + * Theme override to display the 'Iframe' paragraph. + * + * @see ./modules/contrib/paragraphs/templates/paragraph.html.twig + */ +#} + +{% set extra_classes = [] %} + +{% if full_width %} + {% set extra_classes = ['ecl-media-container--fullwidth'] %} +{% endif %} + +{% if ratio == 'custom' %} + {% set extra_classes = extra_classes|merge(['ecl-media-container--custom-ratio']) %} +{% endif %} + +{% if not paragraph.field_oe_title.isEmpty() %} +

    {{ content.field_oe_title }}

    +{% endif %} + +{% if iframe is not empty %} + {% include '@ecl-twig/media-container' with { + 'embedded_media': iframe|default(''), + 'ratio': ratio, + 'extra_classes': extra_classes|join(' '), + } %} +{% endif %} diff --git a/templates/patterns/gallery/gallery.ui_patterns.yml b/templates/patterns/gallery/gallery.ui_patterns.yml index 0dda6a7fc..b836aaa61 100644 --- a/templates/patterns/gallery/gallery.ui_patterns.yml +++ b/templates/patterns/gallery/gallery.ui_patterns.yml @@ -12,11 +12,11 @@ gallery: description: 'List of GalleryItemValueObject objects.' preview: - thumbnail: - src: 'http://i3.ytimg.com/vi/DSXipcdzfmM/maxresdefault.jpg' + src: 'https://inno-ecl.s3.amazonaws.com/media/examples/example-external-video.jpg' alt: 'Example alt text' caption: 'Bio-defence preparedness programme' meta: 'Copyright © 2021, Author and Licence' - source: 'https://www.youtube.com/embed/DSXipcdzfmM' + source: 'https://inno-ecl.s3.amazonaws.com/media/videos/big_buck_bunny.mp4' media_type: 'video' - thumbnail: src: 'https://loremflickr.com/800/600/cat' diff --git a/tests/Functional/BreadcrumbTest.php b/tests/Functional/BreadcrumbTest.php new file mode 100644 index 000000000..0a5ab9f2a --- /dev/null +++ b/tests/Functional/BreadcrumbTest.php @@ -0,0 +1,116 @@ +drupalPlaceBlock('system_breadcrumb_block', [ + 'region' => 'page_header', + ]); + + // Create a news node. + /** @var \Drupal\node\Entity\Node $node */ + $node_1 = $this->getStorage('node')->create([ + 'type' => 'oe_news', + 'title' => 'Test news node', + 'oe_news_types' => 'http://publications.europa.eu/resource/authority/resource-type/ARTICLE_NEWS', + 'oe_teaser' => 'News teaser', + 'oe_summary' => 'http://www.example.org is a web page', + 'body' => 'News body', + 'oe_reference_code' => 'News reference', + 'oe_publication_date' => [ + 'value' => '2020-09-18', + ], + 'oe_author' => 'http://publications.europa.eu/resource/authority/corporate-body/ACJHR', + 'oe_content_content_owner' => 'http://publications.europa.eu/resource/authority/corporate-body/COMMU', + 'uid' => 0, + 'status' => 1, + ]); + $node_1->save(); + + // Create another news node with different title. + $node_2 = $this->getStorage('node')->create([ + 'type' => 'oe_news', + 'title' => 'Test news article breadcrumb', + 'oe_news_types' => 'http://publications.europa.eu/resource/authority/resource-type/ARTICLE_NEWS', + 'oe_teaser' => 'News teaser', + 'oe_summary' => 'http://www.example.org is a web page', + 'body' => 'News body', + 'oe_reference_code' => 'News reference', + 'oe_publication_date' => [ + 'value' => '2020-09-18', + ], + 'oe_author' => 'http://publications.europa.eu/resource/authority/corporate-body/ACJHR', + 'oe_content_content_owner' => 'http://publications.europa.eu/resource/authority/corporate-body/COMMU', + 'uid' => 0, + 'status' => 1, + ]); + $node_2->save(); + + $expected = [ + 'Home', + 'Node', + 'Test news node', + ]; + $this->drupalGet($node_1->toUrl()); + $this->assertSystemBreadcrumbs($expected); + + $expected = [ + 'Home', + 'Node', + 'Test news article breadcrumb', + ]; + $this->drupalGet($node_2->toUrl()); + $this->assertSystemBreadcrumbs($expected); + } + + /** + * Helper to assert system breadcrumbs on the page. + * + * @param array $expected + * The expected breadcrumb titles in the expected order. + */ + protected function assertSystemBreadcrumbs(array $expected): void { + // Get the last segment title and the link titles. + $last_segment_title = array_pop($expected); + $page_breadcrumb = $this->assertSession()->elementExists('css', '[class="ecl-breadcrumb-core"]'); + + // Assert the link titles. + $links = $page_breadcrumb->findAll('css', 'a'); + $this->assertSameSize($expected, $links); + foreach ($expected as $index => $title) { + $this->assertEquals($title, trim($links[$index]->getText())); + } + + // Check the last segment title. + $current_page = $page_breadcrumb->findAll('css', 'li:last-child'); + $this->assertCount(1, $current_page); + $current_page = reset($current_page); + $this->assertEquals($last_segment_title, trim($current_page->getText())); + } + +} diff --git a/tests/Functional/ContentEventRenderTest.php b/tests/Functional/ContentEventRenderTest.php index 88e773a6e..f6dd9bd79 100644 --- a/tests/Functional/ContentEventRenderTest.php +++ b/tests/Functional/ContentEventRenderTest.php @@ -125,8 +125,8 @@ public function testEventFeaturedMediaTranslation(): void { $node->save(); $file_urls = [ - 'en' => $en_file->createFileUrl(), 'bg' => $bg_file->createFileUrl(), + 'en' => $en_file->createFileUrl(), ]; foreach ($node->getTranslationLanguages() as $node_langcode => $node_language) { @@ -134,6 +134,13 @@ public function testEventFeaturedMediaTranslation(): void { $this->drupalGet($node->toUrl()); $this->assertSession()->elementExists('css', 'figure[class="ecl-media-container"] img[src*="' . $file_urls[$node_langcode] . '"][alt="default ' . $node_langcode . ' alt"]'); } + + // Unpublish the media and assert it is not rendered anymore. + $media->set('status', 0); + $media->save(); + + $this->drupalGet($node->toUrl()); + $this->assertSession()->elementNotExists('css', 'figure[class="ecl-media-container"] img[src*="' . $file_urls['en'] . '"][alt="default en alt"]'); } /** @@ -270,7 +277,7 @@ public function testEventRendering(): void { 'items' => [ [ 'label' => 'Where', - 'body' => "event_venue\n Address event_venue, 1001 Brussels, Belgium", + 'body' => "event_venue\n Address event_venue, 1001 , Belgium", ], [ 'label' => 'When', 'body' => "Friday 28 February 2020, 01:00\n to Monday 9 March 2020, 01:00", @@ -284,10 +291,20 @@ public function testEventRendering(): void { $icons_text_expected_values['items'][2] = [ 'icon' => 'location', - 'text' => 'Brussels, Belgium', + 'text' => ', Belgium', ]; $icons_text_assert->assertPattern($icons_text_expected_values, $details_list_content->getOuterHtml()); + // Assert address in Venue using country only. + $venue_entity->set('oe_address', ['country_code' => 'MX'])->save(); + $this->drupalGet($node->toUrl()); + + $field_list_expected_values['items'][0]['body'] = "event_venue\n Mexico"; + $field_list_assert->assertPattern($field_list_expected_values, $practical_list_content->getOuterHtml()); + + $icons_text_expected_values['items'][2]['text'] = 'Mexico'; + $icons_text_assert->assertPattern($icons_text_expected_values, $details_list_content->getOuterHtml()); + // Assert "Internal organiser" field. $node->set('oe_event_organiser_is_internal', TRUE); $node->set('oe_event_organiser_internal', 'http://publications.europa.eu/resource/authority/corporate-body/AASM'); diff --git a/tests/Functional/ContentNewsRenderTest.php b/tests/Functional/ContentNewsRenderTest.php index 41d8716a2..c6cf5bc45 100644 --- a/tests/Functional/ContentNewsRenderTest.php +++ b/tests/Functional/ContentNewsRenderTest.php @@ -142,6 +142,15 @@ public function testNewsRendering(): void { $this->assertContentHeader($contacts_content, 'Contacts'); $this->assertContactDefaultRender($contacts_content, 'news_contact'); + // Add a different and unpublished media and assert it is not rendered + // in the contact. + $media = $this->getStorage('media')->loadByProperties(['name' => 'Test image news_contact']); + $media = reset($media); + $media->set('status', 0)->save(); + + $this->drupalGet($node->toUrl()); + $this->assertSession()->elementNotExists('css', 'div#news-contacts div figure.ecl-media-container img'); + // Assert Featured media field. $this->assertSession()->elementNotExists('css', 'article[role=article] article.ecl-u-type-paragraph.ecl-u-mb-l'); @@ -154,6 +163,17 @@ public function testNewsRendering(): void { $this->assertContains('placeholder_news_featured_media.png', $image->getAttribute('src')); $this->assertEquals('Alternative text news_featured_media', $image->getAttribute('alt')); + // Unpublish the media and assert it is not rendered anymore. + $media->set('status', 0); + $media->save(); + + $this->drupalGet($node->toUrl()); + $this->assertSession()->elementNotExists('css', 'article[role=article] article.ecl-u-type-paragraph.ecl-u-mb-l picture'); + + // Publish the media. + $media->set('status', 1); + $media->save(); + // Assert related links. $node->set('oe_related_links', [ [ diff --git a/tests/Functional/ContentOrganisationRenderTest.php b/tests/Functional/ContentOrganisationRenderTest.php index 314a59284..08629f4d5 100644 --- a/tests/Functional/ContentOrganisationRenderTest.php +++ b/tests/Functional/ContentOrganisationRenderTest.php @@ -4,6 +4,9 @@ namespace Drupal\Tests\oe_theme\Functional; +use Drupal\oe_content_entity\Entity\CorporateEntityInterface; +use Drupal\node\Entity\Node; +use Drupal\oe_content_person\Entity\PersonJob; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; use Drupal\Tests\oe_theme\PatternAssertions\PatternPageHeaderAssert; @@ -29,6 +32,7 @@ class ContentOrganisationRenderTest extends ContentRenderTestBase { 'oe_theme_helper', 'oe_theme_content_entity_contact', 'oe_theme_content_organisation', + 'oe_theme_content_person', 'page_header_metadata_test', 'media_avportal_mock', ]; @@ -55,7 +59,7 @@ public function testOrganisationRendering(): void { $file->setPermanent(); $file->save(); - $media = $this->getStorage('media')->create([ + $media = Media::create([ 'bundle' => 'image', 'name' => 'test image', 'oe_media_image' => [ @@ -67,8 +71,9 @@ public function testOrganisationRendering(): void { ]); $media->save(); - /** @var \Drupal\node\Entity\Node $node */ - $node = $this->getStorage('node')->create([ + $first_general_contact = $this->createContactEntity('first_general_contact', 'oe_general', CorporateEntityInterface::PUBLISHED); + + $node = Node::create([ 'type' => 'oe_organisation', 'title' => 'My node title', 'oe_summary' => 'My introduction', @@ -111,6 +116,7 @@ public function testOrganisationRendering(): void { // Add body text and contact values. $node->set('body', 'My body text'); + $node->set('oe_organisation_contact', [$first_general_contact]); $node->save(); $this->drupalGet($node->toUrl()); @@ -120,7 +126,7 @@ public function testOrganisationRendering(): void { $inpage_nav_expected_values = [ 'title' => 'Page contents', 'list' => [ - ['label' => 'Description', 'href' => '#description'], + ['label' => 'Contact', 'href' => '#contact'], ], ]; $inpage_nav_assert->assertPattern($inpage_nav_expected_values, $navigation->getOuterHtml()); @@ -146,33 +152,136 @@ public function testOrganisationRendering(): void { $logo = $this->assertSession()->elementExists('css', '.ecl-col-l-3 img.ecl-media-container__media'); $this->assertContains('files/styles/oe_theme_medium_no_crop/public/media_avportal_thumbnails/' . $file->getFilename(), $logo->getAttribute('src')); + // Add overview values. + $node->set('oe_organisation_overview', [ + [ + 'term' => 'Overview Term 1', + 'description' => 'Overview Description 1', + ], + [ + 'term' => 'Overview Term 2', + 'description' => 'Overview Description 2', + ], + ]); + $node->save(); + $this->drupalGet($node->toUrl()); + // Assert content part. $wrapper = $this->assertSession()->elementExists('css', '.ecl-row.ecl-u-mt-l'); $content = $this->assertSession()->elementExists('css', '.ecl-col-l-9', $wrapper); $this->assertSession()->elementsCount('css', '.ecl-col-l-9', 1); $content_items = $content->findAll('xpath', '/div'); - $this->assertCount(1, $content_items); - // Assert header of first field group. - $this->assertContentHeader($content_items[0], 'Description', 'description'); + // Assert header of the first field group. + $this->assertContentHeader($content_items[0], 'Overview', 'overview'); + + // Assert values of the first group. + $overview = $content_items[0]->findAll('css', 'dl.ecl-description-list.ecl-description-list--horizontal'); + $this->assertCount(1, $overview); + $overview_terms = $overview[0]->findAll('css', 'dt.ecl-description-list__term'); + $this->assertCount(2, $overview_terms); + $this->assertEquals('Overview Term 1', $overview_terms[0]->getText()); + $this->assertEquals('Overview Term 2', $overview_terms[1]->getText()); + $overview_descriptions = $overview[0]->findAll('css', 'dd.ecl-description-list__definition'); + $this->assertCount(2, $overview_descriptions); + $this->assertEquals('Overview Description 1', $overview_descriptions[0]->getText()); + $this->assertEquals('Overview Description 2', $overview_descriptions[1]->getText()); - // Assert values for first group. - $body = $content_items[0]->findAll('css', '.ecl-editor'); + // Assert values of the second group. + $body = $content_items[1]->findAll('css', '.ecl-editor'); $this->assertCount(1, $body); $this->assertEquals('My body text', $body[0]->getText()); - // Assert Organisation's contacts. - $contact = $this->createContactEntity('organisation_contact'); - $node->set('oe_organisation_contact', [$contact])->save(); + // Assert Organisation's contact is displayed expanded. + $contact_headers = $content_items[2]->findAll('css', 'h2'); + // Assert header of the third field group. + $this->assertEquals('Contact', $contact_headers[0]->getText()); + $this->assertSession()->pageTextNotContains('Show contact details'); + $this->assertContactDefaultRender($content_items[2], 'first_general_contact'); + + // Create another contact and add it to the node. + $second_general_contact = $this->createContactEntity('second_general_contact', 'oe_general'); + $node->set('oe_organisation_contact', [$first_general_contact, $second_general_contact]); + $node->save(); $this->drupalGet($node->toUrl()); + // Assert rendering is updated. + $this->assertSession()->pageTextContains('Show contact details'); + $contacts = $content->findAll('css', 'div#-content.ecl-expandable__content div.ecl-row.ecl-u-mv-xl'); + $this->assertCount(2, $contacts); + $this->assertContactDefaultRender($contacts[0], 'first_general_contact'); + $this->assertContactDefaultRender($contacts[1], 'second_general_contact'); + + // Set value for only the staff search link field and assert rendering is + // updated. + $node->set('oe_organisation_staff_link', [ + 'uri' => 'https://example.com', + 'title' => 'Search for staff', + ])->save(); + $this->drupalGet($node->toUrl()); + + // Assert Contact group was moved on the 4th position. $content_items = $content->findAll('xpath', '/div'); - $this->assertCount(2, $content_items); - $this->assertContentHeader($content_items[1], 'Contact', 'contact'); - $this->assertContactDefaultRender($content_items[1], 'organisation_contact'); + $contact_headers = $content_items[3]->findAll('css', 'h2'); + $this->assertEquals('Contact', $contact_headers[0]->getText()); + // Assert Leadership and organisation region is rendered. + $this->assertContentHeader($content_items[2], 'Leadership and organisation', 'leadership-and-organisation'); + // Assert staff search link values. + $staff_search_link = $content_items[2]->findAll('css', 'a.ecl-link.ecl-link--standalone.ecl-link--icon.ecl-link--icon-after'); + $this->assertCount(1, $staff_search_link); + $this->assertEquals('Search for staff', $staff_search_link[0]->find('css', '.ecl-link__label')->getText()); + $staff_search_link[0]->hasLink('https://example.com'); - $inpage_nav_expected_values['list'][] = ['label' => 'Contact', 'href' => '#contact']; - $inpage_nav_assert->assertPattern($inpage_nav_expected_values, $navigation->getOuterHtml()); + // Create jobs for person entity. + $person_job_1 = PersonJob::create([ + 'type' => 'oe_default', + 'oe_role_reference' => 'http://publications.europa.eu/resource/authority/role-qualifier/ADVIS', + ]); + $person_job_1->save(); + $person_job_2 = PersonJob::create([ + 'type' => 'oe_default', + 'oe_role_reference' => 'http://publications.europa.eu/resource/authority/role-qualifier/ADVIS_CHIEF', + ]); + $person_job_2->save(); + // Create a person node to be referenced by the organisation node. + $person = Node::create([ + 'type' => 'oe_person', + 'oe_person_first_name' => 'Jane', + 'oe_person_last_name' => 'Doe', + 'status' => 1, + ]); + $person->save(); + // Create document to be referenced as organisation chart. + $chart = $this->createMediaDocument('chart'); + + // Update the node values for person and organisation chart fields. + $node->set('oe_organisation_persons', $person) + ->set('oe_organisation_chart', $chart); + $node->save(); + $this->drupalGet($node->toUrl()); + + $content_items = $content->findAll('xpath', '/div'); + $person_content = $content_items[2]->findAll('css', 'article.ecl-u-d-flex.ecl-u-pv-m.ecl-u-border-bottom.ecl-u-border-color-grey-15'); + $this->assertCount(1, $person_content); + $this->assertContains('node/2', $person_content[0]->find('css', 'a.ecl-link.ecl-link--standalone')->getAttribute('href')); + // Assert person content. + $first_person_image = $person_content[0]->find('css', '.ecl-u-flex-shrink-0.ecl-u-mr-s.ecl-u-media-a-s.ecl-u-media-bg-size-contain.ecl-u-media-bg-repeat-none'); + // Assert default image. + $this->assertEquals('background-image:url(/build/themes/custom/oe_theme/images/user_icon.svg)', $first_person_image->getAttribute('style')); + // Assert role div is not printed when there are no jobs. + $this->assertCount(0, $person_content[0]->findAll('css', '.ecl-content-item__meta.ecl-u-type-s.ecl-u-type-color-grey-75.ecl-u-mb-xs')); + // Assert name. + $this->assertEquals('Jane Doe', $person_content[0]->find('css', 'a.ecl-link.ecl-link--standalone')->getText()); + // Assert organisation chart document. + $chart_document = $content_items[2]->findAll('css', '.ecl-u-mb-l.ecl-u-mt-l'); + $this->assertMediaDocumentDefaultRender($chart_document[0], 'chart', 'English', '2.96 KB - PDF', '', 'Download'); + + // Update person node with jobs and assert rendering is updated. + $person->set('oe_person_jobs', [$person_job_1, $person_job_2]); + $person->save(); + $this->getSession()->reload(); + $person_content = $content_items[2]->findAll('css', 'article.ecl-u-d-flex.ecl-u-pv-m.ecl-u-border-bottom.ecl-u-border-color-grey-15'); + $this->assertEquals('Advisor, Chief advisor', $person_content[0]->find('css', '.ecl-content-item__meta.ecl-u-type-s.ecl-u-type-color-grey-75.ecl-u-mb-xs')->getText()); } } diff --git a/tests/Functional/ContentPersonRenderTest.php b/tests/Functional/ContentPersonRenderTest.php index 209498c20..53c5984c5 100644 --- a/tests/Functional/ContentPersonRenderTest.php +++ b/tests/Functional/ContentPersonRenderTest.php @@ -114,6 +114,16 @@ public function testPersonRendering(): void { $this->assertContains('/files/styles/oe_theme_medium_no_crop/public/placeholder_portrait.png', $portrait->getAttribute('src')); $this->assertEquals('Alternative text portrait', $portrait->getAttribute('alt')); + // Unpublish the media and assert it is not rendered anymore. + $portrait_media->set('status', 0); + $portrait_media->save(); + $this->drupalGet($node->toUrl()); + $this->assertNotContains('/files/styles/oe_theme_medium_no_crop/public/placeholder_portrait.png', $portrait->getAttribute('src')); + + // Publish the media. + $portrait_media->set('status', 1); + $portrait_media->save(); + // Assert Department field with single value. $node->set('oe_departments', 'http://publications.europa.eu/resource/authority/corporate-body/ABEC')->save(); $this->drupalGet($node->toUrl()); diff --git a/tests/Functional/ContentProjectRenderTest.php b/tests/Functional/ContentProjectRenderTest.php index 6e6107410..52316fbf2 100644 --- a/tests/Functional/ContentProjectRenderTest.php +++ b/tests/Functional/ContentProjectRenderTest.php @@ -184,7 +184,7 @@ public function testProjectRendering(): void { 'body' => '€100', ], [ 'label' => 'EU contribution', - 'body' => "€100\n\n 100% of the overall budget", + 'body' => "€100100% of the overall budget", ], ], ]; @@ -210,7 +210,7 @@ public function testProjectRendering(): void { $field_list_assert->assertPattern($first_field_list_expected_values, $description_lists[0]->getHtml()); // Assert the second description list block's labels and values. - $second_field_list_expected_values['items'][1]['body'] = "€50\n\n 50% of the overall budget"; + $second_field_list_expected_values['items'][1]['body'] = "€5050% of the overall budget"; $field_list_assert->assertPattern($second_field_list_expected_values, $description_lists[1]->getHtml()); // Assert the third description list block's labels and values. @@ -265,6 +265,14 @@ public function testProjectRendering(): void { $this->assertEquals($stakeholder_sub_headers[0]->getText(), 'Coordinators'); $this->assertStakeholderOrganisationRendering($project_stakeholders, 'coordinator'); + // Load logo that is unpublished and assert that is not rendered. + $media = $this->getStorage('media')->loadByProperties(['name' => 'Test image coordinator']); + $media = reset($media); + $media->set('status', 0)->save(); + + $this->drupalGet($node->toUrl()); + $this->assertEmpty($project_stakeholders->findAll('css', 'div[role=img]')); + // Unpublish Coordinator and publish Participant organisations. $coordinator_organisation->set('status', CorporateEntityInterface::NOT_PUBLISHED); $coordinator_organisation->save(); diff --git a/tests/Functional/ContentPublicationRenderTest.php b/tests/Functional/ContentPublicationRenderTest.php index 8212087b6..7edcc6fa1 100644 --- a/tests/Functional/ContentPublicationRenderTest.php +++ b/tests/Functional/ContentPublicationRenderTest.php @@ -277,6 +277,17 @@ public function testPublicationRendering(): void { $this->assertContains("oe_theme_publication_thumbnail", $image_element->getAttribute('src')); $this->assertEquals("Alternative text publication_image", $image_element->getAttribute('alt')); + // Unpublish the media and assert it is not rendered anymore. + $media_image->set('status', 0); + $media_image->save(); + + $this->drupalGet($node->toUrl()); + $this->assertSession()->elementNotExists('css', $thumbnail_wrapper_selector); + + // Publish the media. + $media_image->set('status', 1); + $media_image->save(); + // Assert Contact field. $contact = $this->createContactEntity('publication_contact'); $node->set('oe_publication_contacts', $contact)->save(); diff --git a/tests/Functional/ContentRenderTestBase.php b/tests/Functional/ContentRenderTestBase.php index 3891742d4..22cb5ccda 100644 --- a/tests/Functional/ContentRenderTestBase.php +++ b/tests/Functional/ContentRenderTestBase.php @@ -207,6 +207,10 @@ protected function createContactEntity(string $name, string $bundle = 'oe_genera 'oe_organisation' => "Organisation $name", 'oe_phone' => "Phone number $name", 'oe_press_contact_url' => ['uri' => "http://www.example.com/press_contact_$name"], + 'oe_link' => [ + 'uri' => "http://www.example.com/link_$name", + 'title' => "Link title $name", + ], 'oe_social_media' => [ [ 'uri' => "http://www.example.com/social_media_$name", @@ -281,9 +285,13 @@ protected function assertContactDefaultRender(NodeElement $element, string $name $field_list_assert->assertPattern($contact_expected_values, $contacts_html); $field_list_assert->assertVariant('horizontal', $contacts_html); - // Assert Press contacts. - $press = $element->find('css', '.ecl-u-border-top.ecl-u-border-bottom.ecl-u-border-color-grey-15.ecl-u-mt-s.ecl-u-pt-l.ecl-u-pb-l'); - $this->assertLinkIcon($press, 'Press contacts', "http://www.example.com/press_contact_$name"); + // Assert Press contacts field. + $links_wrapper = $element->findAll('css', 'div.ecl-u-border-top.ecl-u-border-color-grey-15.ecl-u-mt-s div.ecl-u-border-bottom.ecl-u-border-color-grey-15.ecl-u-pt-l.ecl-u-pb-l'); + $this->assertCount(2, $links_wrapper); + $this->assertLinkIcon($links_wrapper[0], 'Press contacts', "http://www.example.com/press_contact_$name"); + + // Assert Link field. + $this->assertLinkIcon($links_wrapper[1], "Link title $name", "http://www.example.com/link_$name"); // Assert contacts Image. $this->assertFeaturedMediaField($element, $name); @@ -308,7 +316,7 @@ protected function createVenueEntity(string $name, string $bundle = 'oe_default' 'name' => $name, 'oe_address' => [ 'country_code' => 'BE', - 'locality' => 'Brussels', + 'locality' => '', 'address_line1' => "Address $name", 'postal_code' => '1001', ], diff --git a/tests/Kernel/AbstractKernelTestBase.php b/tests/Kernel/AbstractKernelTestBase.php index c7dd94471..8ff923c3e 100644 --- a/tests/Kernel/AbstractKernelTestBase.php +++ b/tests/Kernel/AbstractKernelTestBase.php @@ -31,6 +31,7 @@ abstract class AbstractKernelTestBase extends KernelTestBase { 'ui_patterns', 'ui_patterns_library', 'user', + 'node', ]; /** diff --git a/tests/Kernel/CallForProposalsRenderTest.php b/tests/Kernel/CallForProposalsRenderTest.php index 63bb11b23..d7173713d 100644 --- a/tests/Kernel/CallForProposalsRenderTest.php +++ b/tests/Kernel/CallForProposalsRenderTest.php @@ -137,6 +137,13 @@ public function testTeaser(): void { $actual = $crawler->filter('span.call-status.ecl-label.ecl-u-text-uppercase.ecl-label--high.ecl-u-type-color-black'); $this->assertCount(1, $actual); + // Test short title fallback. + $node->set('oe_content_short_title', 'CFP short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'CFP short title'; + $assert->assertPattern($expected_values, $html); + // Check label for multiple deadline values. $deadline_date2 = (clone $static_time)->modify('+ 4 days'); $deadline_date2->setTimeZone(new \DateTimeZone('Australia/Sydney')); diff --git a/tests/Kernel/CallForTendersRenderTest.php b/tests/Kernel/CallForTendersRenderTest.php index 420dd4539..3fb02bea7 100644 --- a/tests/Kernel/CallForTendersRenderTest.php +++ b/tests/Kernel/CallForTendersRenderTest.php @@ -137,6 +137,13 @@ public function testTeaser(): void { $actual = $crawler->filter('span.call-status.ecl-label.ecl-u-text-uppercase.ecl-label--high.ecl-u-type-color-black'); $this->assertCount(1, $actual); + // Test short title fallback. + $node->set('oe_content_short_title', 'CFT short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'CFT short title'; + $assert->assertPattern($expected_values, $html); + // Check Department/s label for multiple department values. $node->set('oe_departments', 'http://publications.europa.eu/resource/authority/corporate-body/ABEC')->save(); $build = $this->nodeViewBuilder->view($node, 'teaser'); diff --git a/tests/Kernel/ConsultationRenderTest.php b/tests/Kernel/ConsultationRenderTest.php index 5a014fb9d..8f9c4178e 100644 --- a/tests/Kernel/ConsultationRenderTest.php +++ b/tests/Kernel/ConsultationRenderTest.php @@ -121,6 +121,13 @@ public function testTeaser(): void { $actual = $crawler->filter('span.call-status.ecl-label.ecl-u-text-uppercase.ecl-label--high.ecl-u-type-color-black'); $this->assertCount(1, $actual); + // Test short title fallback. + $node->set('oe_content_short_title', 'Consultation short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'Consultation short title'; + $assert->assertPattern($expected_values, $html); + // Check status Closed label and background. $deadline_date->modify('- 4 days'); $node->set('oe_consultation_deadline', [ diff --git a/tests/Kernel/ContactRenderTest.php b/tests/Kernel/ContactRenderTest.php index 5fc69439b..0b19141be 100644 --- a/tests/Kernel/ContactRenderTest.php +++ b/tests/Kernel/ContactRenderTest.php @@ -194,17 +194,23 @@ public function testFullView(): void { $build = $this->contactViewBuilder->view($contact, 'full'); $html = $this->renderRoot($build); $crawler = new Crawler($html); - $press = $crawler->filter('.ecl-u-border-top.ecl-u-border-bottom.ecl-u-border-color-grey-15.ecl-u-mt-s.ecl-u-pt-l.ecl-u-pb-l'); - $press_link = $press->filter('a'); - $this->assertCount(1, $press_link); - $this->assertEquals("http://www.example.com/press_contact_$name", $press_link->attr('href')); - - $press_label = $press_link->filter('.ecl-link__label'); - $this->assertCount(1, $press_label); - $this->assertEquals('Press contacts', trim($press_label->text())); + $links_wrapper = $crawler->filter('div.ecl-u-border-top.ecl-u-border-color-grey-15.ecl-u-mt-s div.ecl-u-border-bottom.ecl-u-border-color-grey-15.ecl-u-pt-l.ecl-u-pb-l'); + $press_link = $links_wrapper->filter('a'); + $this->assertBottomLink($press_link, "http://www.example.com/press_contact_$name", 'Press contacts'); + + // Assert Link field. + $contact->set('oe_link', [ + 'uri' => "http://www.example.com/link_$name", + 'title' => "Link title $name", + ])->save(); + $build = $this->contactViewBuilder->view($contact, 'full'); + $html = $this->renderRoot($build); + $crawler = new Crawler($html); + $links_wrapper = $crawler->filter('div.ecl-u-border-top.ecl-u-border-color-grey-15.ecl-u-mt-s div.ecl-u-border-bottom.ecl-u-border-color-grey-15.ecl-u-pt-l.ecl-u-pb-l'); + $this->assertCount(2, $links_wrapper); - $press_icon = $press_link->filter('.ecl-icon.ecl-icon--s.ecl-icon--primary.ecl-link__icon'); - $this->assertCount(1, $press_icon); + $link = $links_wrapper->last()->filter('a'); + $this->assertBottomLink($link, "http://www.example.com/link_$name", "Link title $name"); } /** @@ -254,4 +260,26 @@ protected function assertFeaturedMediaField(string $html, string $name): void { $this->assertEquals("Caption $name", trim($caption->text())); } + /** + * Asserts links in the bottom of full view rendering. + * + * @param \Symfony\Component\DomCrawler\Crawler $element + * Link element. + * @param string $link + * Expected href attribute. + * @param string $title + * Expected link title. + */ + protected function assertBottomLink(Crawler $element, string $link, string $title): void { + $this->assertCount(1, $element); + $this->assertEquals($link, $element->attr('href')); + + $link_label = $element->filter('.ecl-link__label'); + $this->assertCount(1, $link_label); + $this->assertEquals($title, trim($link_label->text())); + + $link_icon = $element->filter('.ecl-icon.ecl-icon--s.ecl-icon--primary.ecl-link__icon'); + $this->assertCount(1, $link_icon); + } + } diff --git a/tests/Kernel/EventRenderTest.php b/tests/Kernel/EventRenderTest.php index 8c2102100..ebfeb5ee7 100644 --- a/tests/Kernel/EventRenderTest.php +++ b/tests/Kernel/EventRenderTest.php @@ -101,9 +101,6 @@ public function testEventTeaser(): void { $venue->set('oe_address', [ 'country_code' => 'BE', - 'locality' => 'Brussels', - 'postal_code' => 1000, - 'address_line1' => 'The street', ]); $venue->save(); @@ -162,7 +159,7 @@ public function testEventTeaser(): void { 'items' => [ [ 'icon' => 'location', - 'text' => 'Brussels, Belgium', + 'text' => 'Belgium', ], ], ]), @@ -178,6 +175,21 @@ public function testEventTeaser(): void { $assert->assertPattern($expected_values, $html); $assert->assertVariant('date', $html); + // Test short title fallback. + $node->set('oe_content_short_title', 'Event short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'Event short title'; + $assert->assertPattern($expected_values, $html); + + // Set full address in venue. + $venue->set('oe_address', [ + 'country_code' => 'BE', + 'locality' => '', + 'postal_code' => 1000, + 'address_line1' => 'The street', + ])->save(); + // Set the online type to be livestream and assert the details are updated. $node->set('oe_event_online_type', 'livestream')->save(); $this->nodeViewBuilder->resetCache(); @@ -187,7 +199,7 @@ public function testEventTeaser(): void { 'items' => [ [ 'icon' => 'location', - 'text' => 'Brussels, Belgium', + 'text' => ', Belgium', ], [ 'icon' => 'livestreaming', @@ -239,7 +251,7 @@ public function testEventTeaser(): void { 'items' => [ [ 'icon' => 'location', - 'text' => 'Brussels, Белгия', + 'text' => ', Белгия', ], [ 'icon' => 'livestreaming', diff --git a/tests/Kernel/LegacyContentRenderTest.php b/tests/Kernel/LegacyContentRenderTest.php index 366aaf49e..3e04e78ec 100644 --- a/tests/Kernel/LegacyContentRenderTest.php +++ b/tests/Kernel/LegacyContentRenderTest.php @@ -53,6 +53,9 @@ public function testPage(): void { $crawler = new Crawler($html); + $title = $crawler->filter('h2 a span'); + $this->assertEquals('Test page node', $title->text()); + // Body wrapper. $body_wrapper = $crawler->filter('.ecl-editor'); $this->assertCount(1, $body_wrapper); @@ -63,6 +66,14 @@ public function testPage(): void { $this->assertContains('Related links', $related_links_heading->text()); $related_links = $crawler->filter('.ecl-list .ecl-link.ecl-link--standalone'); $this->assertCount(2, $related_links); + + // Test short title fallback. + $node->set('oe_content_short_title', 'Page short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $crawler = new Crawler($html); + $title = $crawler->filter('.ecl-content-item__title.ecl-u-type-heading-5.ecl-u-mb-xs.ecl-u-mt-none'); + $this->assertEquals('Page short title', $title->text()); } /** @@ -84,10 +95,21 @@ public function testPolicy(): void { $crawler = new Crawler($html); + $title = $crawler->filter('h2 a span'); + $this->assertEquals('Test policy node', $title->text()); + // Body wrapper. $body_wrapper = $crawler->filter('.ecl-editor'); $this->assertCount(1, $body_wrapper); $this->assertContains('Body', $body_wrapper->text()); + + // Test short title fallback. + $node->set('oe_content_short_title', 'Policy short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $crawler = new Crawler($html); + $title = $crawler->filter('.ecl-content-item__title.ecl-u-type-heading-5.ecl-u-mb-xs.ecl-u-mt-none'); + $this->assertEquals('Policy short title', $title->text()); } /** diff --git a/tests/Kernel/MultilingualAbstractKernelTestBase.php b/tests/Kernel/MultilingualAbstractKernelTestBase.php index 8f0c1956c..577aec5f4 100644 --- a/tests/Kernel/MultilingualAbstractKernelTestBase.php +++ b/tests/Kernel/MultilingualAbstractKernelTestBase.php @@ -56,7 +56,7 @@ protected function setUp() { ]); $this->container->get('module_handler')->loadInclude('oe_multilingual', 'install'); - oe_multilingual_install(); + oe_multilingual_install(FALSE); // Rebuild the container in order to make sure tests pass. // @todo: fix test setup so that we can get rid of this line. diff --git a/tests/Kernel/NewsRenderTest.php b/tests/Kernel/NewsRenderTest.php index 078d973d3..629ca70d4 100644 --- a/tests/Kernel/NewsRenderTest.php +++ b/tests/Kernel/NewsRenderTest.php @@ -7,7 +7,6 @@ use Drupal\media\Entity\Media; use Drupal\Tests\oe_theme\PatternAssertions\ListItemAssert; use Drupal\Tests\user\Traits\UserCreationTrait; -use Drupal\user\Entity\User; /** * Tests the News content type rendering. @@ -28,10 +27,6 @@ protected function setUp(): void { module_load_include('install', 'oe_content'); oe_content_install(); - - // Set current user to UID 1, so that by default we can access everything. - $account = User::load(1); - $this->setCurrentUser($account); } /** @@ -88,6 +83,43 @@ public function testNewsTeaser(): void { $assert->assertPattern($expected_values, $html); $assert->assertVariant('thumbnail_primary', $html); + // Test short title fallback. + $node->set('oe_content_short_title', 'News short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'News short title'; + $assert->assertPattern($expected_values, $html); + + // Unpublish the media and assert it is not rendered anymore. + $media->set('status', 0); + $media->save(); + + // Since static cache is not cleared due to lack of requests in the test we + // need to reset manually. + $this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache(); + + $this->nodeViewBuilder->resetCache(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + + $expected_values = [ + 'title' => 'News short title', + 'url' => '/en/node/1', + 'description' => 'Teaser', + 'meta' => 'News article | 2 April 2019', + 'image' => NULL, + ]; + $assert->assertPattern($expected_values, $html); + $assert->assertVariant('default', $html); + + // Publish the media. + $media->set('status', 1); + $media->save(); + + // Since static cache is not cleared due to lack of requests in the test we + // need to reset manually. + $this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache(); + // Set news type. $node->set('oe_news_types', 'http://publications.europa.eu/resource/authority/resource-type/PRESS_REL')->save(); $this->nodeViewBuilder->resetCache(); @@ -95,7 +127,16 @@ public function testNewsTeaser(): void { $build = $this->nodeViewBuilder->view($node, 'teaser'); $html = $this->renderRoot($build); - $expected_values['meta'] = 'Press release | 2 April 2019'; + $expected_values = [ + 'title' => 'News short title', + 'url' => '/en/node/1', + 'description' => 'Teaser', + 'meta' => 'Press release | 2 April 2019', + 'image' => [ + 'src' => 'example_1.jpeg', + 'alt' => '', + ], + ]; $assert->assertPattern($expected_values, $html); $assert->assertVariant('thumbnail_primary', $html); diff --git a/tests/Kernel/OrganisationRenderTest.php b/tests/Kernel/OrganisationRenderTest.php index 7a11b19ce..c8a601d18 100644 --- a/tests/Kernel/OrganisationRenderTest.php +++ b/tests/Kernel/OrganisationRenderTest.php @@ -11,6 +11,7 @@ use Drupal\Tests\oe_theme\PatternAssertions\PatternAssertState; use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\user\Entity\User; +use Symfony\Component\DomCrawler\Crawler; /** * Tests the organisation rendering. @@ -40,6 +41,7 @@ class OrganisationRenderTest extends ContentRenderTestBase { 'composite_reference', 'oe_theme_content_entity_contact', 'oe_theme_content_organisation', + 'description_list_field', ]; /** @@ -73,7 +75,7 @@ protected function setUp(): void { */ public function testOrganisationTeaser(): void { $logo_media = $this->createMediaImage('organisation_logo'); - $contact = $this->createContactEntity('organisation_contact', 'oe_general'); + $first_contact = $this->createContactEntity('first_contact', 'oe_general'); $node = Node::create([ 'type' => 'oe_organisation', @@ -90,8 +92,8 @@ public function testOrganisationTeaser(): void { ], 'oe_organisation_contact' => [ [ - 'target_id' => $contact->id(), - 'target_revision_id' => $contact->getRevisionId(), + 'target_id' => $first_contact->id(), + 'target_revision_id' => $first_contact->getRevisionId(), ], ], 'status' => 1, @@ -117,19 +119,19 @@ public function testOrganisationTeaser(): void { 'items' => [ [ 'label' => 'Website', - 'body' => 'http://www.example.com/website_organisation_contact', + 'body' => 'http://www.example.com/website_first_contact', ], [ 'label' => 'Email', - 'body' => 'organisation_contact@example.com', + 'body' => 'first_contact@example.com', ], [ 'label' => 'Phone number', - 'body' => 'Phone number organisation_contact', + 'body' => 'Phone number first_contact', ], [ 'label' => 'Address', - 'body' => 'Address organisation_contact, 1001 Brussels, Belgium', + 'body' => 'Address first_contact, 1001 Brussels, Belgium', ], ], ]), @@ -138,7 +140,50 @@ public function testOrganisationTeaser(): void { $assert->assertPattern($expected_values, $html); $assert->assertVariant('thumbnail_secondary', $html); + // Test short title fallback. + $node->set('oe_content_short_title', 'Organisation short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'Organisation short title'; + $assert->assertPattern($expected_values, $html); + + // Create another contact and add it to the node. + $second_contact = $this->createContactEntity('second_contact', 'oe_general'); + $node->set('oe_organisation_contact', [$first_contact, $second_contact]); + $node->save(); + + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $crawler = new Crawler($html); + $first_contact_render = $crawler->filter('article .ecl-content-item__additional_information.ecl-u-mb-s div.ecl-u-border-bottom.ecl-u-border-color-grey-15.ecl-u-mb-m.ecl-u-pb-m'); + $this->assertCount(1, $first_contact_render); + + $field_assert = new FieldListAssert(); + $second_contact_expected_values = [ + 'items' => [ + [ + 'label' => 'Website', + 'body' => 'http://www.example.com/website_second_contact', + ], + [ + 'label' => 'Email', + 'body' => 'second_contact@example.com', + ], + [ + 'label' => 'Phone number', + 'body' => 'Phone number second_contact', + ], + [ + 'label' => 'Address', + 'body' => 'Address second_contact, 1001 Brussels, Belgium', + ], + ], + ]; + $second_contact_render = $crawler->filter('article div.ecl-content-item__additional_information.ecl-u-mb-s div:nth-child(2)'); + $field_assert->assertPattern($second_contact_expected_values, $second_contact_render->html()); + // Change organisation type to non eu. + $node->set('oe_organisation_contact', NULL); $node->set('oe_organisation_org_type', 'non_eu'); $node->set('oe_organisation_non_eu_org_type', 'http://data.europa.eu/uxp/5432'); $node->save(); @@ -146,6 +191,7 @@ public function testOrganisationTeaser(): void { $build = $this->nodeViewBuilder->view($node, 'teaser'); $html = $this->renderRoot($build); + $expected_values['additional_information'] = NULL; $expected_values['meta'] = 'embassy | Acronym'; $assert->assertPattern($expected_values, $html); $assert->assertVariant('thumbnail_secondary', $html); diff --git a/tests/Kernel/Paragraphs/MediaParagraphsTest.php b/tests/Kernel/Paragraphs/MediaParagraphsTest.php index ca27af6e8..c37a41ee5 100644 --- a/tests/Kernel/Paragraphs/MediaParagraphsTest.php +++ b/tests/Kernel/Paragraphs/MediaParagraphsTest.php @@ -25,6 +25,7 @@ class MediaParagraphsTest extends ParagraphsTestBase { 'oe_paragraphs_media', 'allowed_formats', 'oe_paragraphs_media_field_storage', + 'oe_paragraphs_iframe_media', 'oe_paragraphs_banner', 'views', 'entity_browser', @@ -52,9 +53,13 @@ protected function setUp() { 'media_avportal', 'oe_media_avportal', 'oe_paragraphs_banner', + 'oe_paragraphs_iframe_media', 'options', 'oe_media_iframe', ]); + // Call the install hook of the Media module. + module_load_include('install', 'media'); + media_install(); } /** @@ -153,6 +158,31 @@ public function testTextWithMedia(): void { $html = $this->renderParagraph($paragraph, 'bg'); $assert->assertPattern($expected_values, $html); + // Unpublish the media and assert it is not rendered anymore. + $media->set('status', 0); + $media->save(); + + // Since static cache is not cleared due to lack of requests in the test we + // need to reset manually. + $this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache(); + + $expected_values = [ + 'title' => 'Title', + 'caption' => NULL, + 'text' => 'Full text', + 'image' => NULL, + ]; + $html = $this->renderParagraph($paragraph); + $assert->assertPattern($expected_values, $html); + + // Publish the media. + $media->set('status', 1); + $media->save(); + + // Since static cache is not cleared due to lack of requests in the test we + // need to reset manually. + $this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache(); + // Remove the text and assert the element is no longer rendered. $paragraph->set('field_oe_text_long', ''); $paragraph->save(); @@ -348,6 +378,27 @@ public function testBanner(): void { // Variant - image / Modifier - hero_left / Full width - No. $paragraph->get('field_oe_banner_type')->setValue('hero_left'); $paragraph->save(); + + // Unpublish the media and assert it is not rendered anymore. + $media->set('status', 0); + $media->save(); + + // Since static cache is not cleared due to lack of requests in the test we + // need to reset manually. + $this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache(); + + $html = $this->renderParagraph($paragraph); + $crawler = new Crawler($html); + $this->assertCount(0, $crawler->filter('section.ecl-hero-banner.ecl-hero-banner--image div.ecl-hero-banner__image')); + + // Publish the media. + $media->set('status', 1); + $media->save(); + + // Since static cache is not cleared due to lack of requests in the test we + // need to reset manually. + $this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache(); + $html = $this->renderParagraph($paragraph); $crawler = new Crawler($html); @@ -688,4 +739,97 @@ public function testBanner(): void { ); } + /** + * Test 'Iframe' paragraph rendering. + */ + public function testIframe(): void { + // Set Iframe media translatable. + $this->container->get('content_translation.manager')->setEnabled('media', 'iframe', TRUE); + + // Make the Iframe field translatable. + $field_config = $this->container->get('entity_type.manager')->getStorage('field_config')->load('media.iframe.oe_media_iframe'); + $field_config->set('translatable', TRUE)->save(); + $this->container->get('router.builder')->rebuild(); + + // Create unpublished Iframe media with required fields to check access. + $media_storage = $this->container->get('entity_type.manager')->getStorage('media'); + $media = $media_storage->create([ + 'bundle' => 'iframe', + 'name' => 'Test Iframe', + 'oe_media_iframe' => '', + 'status' => 0, + ]); + $media->save(); + + // Create a paragraph with required fields only. + $paragraph = $this->container + ->get('entity_type.manager') + ->getStorage('paragraph')->create([ + 'type' => 'oe_iframe_media', + 'field_oe_media' => [ + 'target_id' => $media->id(), + ], + ]); + $paragraph->save(); + + // Assert unpublished media isn't shown. + $html = $this->renderParagraph($paragraph); + $this->assertNotContains('figure', $html); + $this->assertNotContains('http://example.com/iframe', $html); + $this->assertNotContains('ecl-u-type-heading-2', $html); + + // Publish media. + $media->setPublished()->save(); + // Since static cache is not cleared due to lack of requests in the test we + // need to reset manually. + $this->container->get('entity_type.manager')->getAccessControlHandler('media')->resetCache(); + $html = $this->renderParagraph($paragraph); + $crawler = new Crawler($html); + $iframe = $crawler->filter('figure.ecl-media-container.ecl-media-container--custom-ratio div.ecl-media-container__media.ecl-media-container__media--ratio-custom iframe'); + $this->assertContains('http://example.com/iframe', $iframe->attr('src')); + $this->assertNotContains('ecl-u-type-heading-2', $html); + + // Assert "Full width" field. + $paragraph->set('field_oe_iframe_media_full_width', TRUE)->save(); + $html = $this->renderParagraph($paragraph); + $crawler = new Crawler($html); + $iframe = $crawler->filter('figure.ecl-media-container.ecl-media-container--fullwidth.ecl-media-container--custom-ratio div.ecl-media-container__media.ecl-media-container__media--ratio-custom iframe'); + $this->assertContains('http://example.com/iframe', $iframe->attr('src')); + + // Assert ratio. + $media->set('oe_media_iframe_ratio', '1_1')->save(); + $html = $this->renderParagraph($paragraph); + $crawler = new Crawler($html); + $iframe = $crawler->filter('figure.ecl-media-container.ecl-media-container--fullwidth div.ecl-media-container__media.ecl-media-container__media--ratio-1-1 iframe'); + $this->assertContains('http://example.com/iframe', $iframe->attr('src')); + + // Assert title and full width. + $paragraph->set('field_oe_title', 'Iframe paragraph title'); + $paragraph->set('field_oe_iframe_media_full_width', FALSE)->save(); + $html = $this->renderParagraph($paragraph); + $crawler = new Crawler($html); + $title = $crawler->filter('h2.ecl-u-type-heading-2', $html); + $this->assertContains('Iframe paragraph title', $title->text()); + $iframe = $crawler->filter('figure.ecl-media-container div.ecl-media-container__media.ecl-media-container__media--ratio-1-1 iframe'); + $this->assertContains('http://example.com/iframe', $iframe->attr('src')); + + // Translate the media to Bulgarian. + $media_bg = $media->addTranslation('bg', [ + 'name' => 'Test Iframe bg', + 'oe_media_iframe' => '', + ]); + $media_bg->save(); + + // Add Bulgarian translation. + $paragraph->addTranslation('bg', ['field_oe_title' => 'Iframe paragraph title bg'])->save(); + + // Assert paragraph translation. + $html = $this->renderParagraph($paragraph, 'bg'); + $crawler = new Crawler($html); + $title = $crawler->filter('h2.ecl-u-type-heading-2', $html); + $this->assertContains('Iframe paragraph title bg', $title->text()); + $iframe = $crawler->filter('figure.ecl-media-container div.ecl-media-container__media.ecl-media-container__media--ratio-1-1 iframe'); + $this->assertContains('http://example.com/iframe_bg', $iframe->attr('src')); + } + } diff --git a/tests/Kernel/PersonRenderTest.php b/tests/Kernel/PersonRenderTest.php index 1b4a843ad..b5a4e5fa0 100644 --- a/tests/Kernel/PersonRenderTest.php +++ b/tests/Kernel/PersonRenderTest.php @@ -42,6 +42,7 @@ class PersonRenderTest extends ContentRenderTestBase { 'oe_theme_content_organisation', 'oe_theme_content_organisation_reference', 'oe_theme_content_person', + 'description_list_field', ]; /** diff --git a/tests/Kernel/ProjectRenderTest.php b/tests/Kernel/ProjectRenderTest.php index e245ca253..b082b712a 100644 --- a/tests/Kernel/ProjectRenderTest.php +++ b/tests/Kernel/ProjectRenderTest.php @@ -180,6 +180,13 @@ public function testProjectTeaser(): void { ]; $assert->assertPattern($expected_values, $html); $assert->assertVariant('thumbnail_secondary', $html); + + // Test short title fallback. + $node->set('oe_content_short_title', 'Project short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'Project short title'; + $assert->assertPattern($expected_values, $html); } } diff --git a/tests/Kernel/PublicationRenderTest.php b/tests/Kernel/PublicationRenderTest.php index 960e63f4b..ad4cbe882 100644 --- a/tests/Kernel/PublicationRenderTest.php +++ b/tests/Kernel/PublicationRenderTest.php @@ -60,6 +60,13 @@ public function testTeaser(): void { ]; $assert->assertPattern($expected_values, $html); + // Test short title fallback. + $node->set('oe_content_short_title', 'Publication short title')->save(); + $build = $this->nodeViewBuilder->view($node, 'teaser'); + $html = $this->renderRoot($build); + $expected_values['title'] = 'Publication short title'; + $assert->assertPattern($expected_values, $html); + // Add thumbnail. $media_image = $this->createMediaImage('publication_image'); $node->set('oe_publication_thumbnail', $media_image)->save(); diff --git a/tests/Kernel/fixtures/rendering.yml b/tests/Kernel/fixtures/rendering.yml index a1a442114..021863f99 100644 --- a/tests/Kernel/fixtures/rendering.yml +++ b/tests/Kernel/fixtures/rendering.yml @@ -736,9 +736,10 @@ '.ecl-gallery .ecl-gallery__list .ecl-gallery__item .ecl-gallery__image[alt="Example alt text"]': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item figcaption.ecl-gallery__description': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item .ecl-gallery__meta': 1 - '.ecl-gallery .ecl-gallery__list .ecl-gallery__item svg.ecl-icon': 0 + '.ecl-gallery .ecl-gallery__list .ecl-gallery__item figcaption.ecl-gallery__description svg.ecl-icon': 1 equals: '.ecl-gallery .ecl-gallery__list .ecl-gallery__item .ecl-gallery__meta': 'Copyright © 2021, Author and Licence' + '.ecl-gallery .ecl-gallery__list .ecl-gallery__item svg.ecl-icon': '' contains: - 'A picture of a cat' - array: @@ -769,7 +770,7 @@ '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(1) .ecl-gallery__image[alt="Example alt text cat"]': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(1) figcaption.ecl-gallery__description': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(1) .ecl-gallery__meta': 0 - '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(1) .ecl-gallery__image-container svg.ecl-icon': 0 + '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(1) .ecl-gallery__image-container figcaption.ecl-gallery__description svg.ecl-icon': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(2) a.ecl-gallery__item-link[href="https://www.youtube.com/watch?v=1-g73ty9v04"]': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(2) .ecl-gallery__image[src="https://loremflickr.com/320/240/dog"]': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(2) .ecl-gallery__image[alt="Example alt text dog"]': 1 @@ -777,6 +778,7 @@ '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(2) .ecl-gallery__meta': 1 '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(2) .ecl-gallery__image-container figcaption.ecl-gallery__description svg.ecl-icon': 1 equals: + '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(1) .ecl-gallery__image-container svg.ecl-icon': '' '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(2) .ecl-gallery__meta': 'Copyright © 2021 EC' '.ecl-gallery .ecl-gallery__list .ecl-gallery__item:nth-child(2) .ecl-gallery__image-container figcaption.ecl-gallery__description svg.ecl-icon': '' contains: diff --git a/tests/PatternAssertions/InPageNavigationAssert.php b/tests/PatternAssertions/InPageNavigationAssert.php index e4558aeb6..8cb73bd8d 100644 --- a/tests/PatternAssertions/InPageNavigationAssert.php +++ b/tests/PatternAssertions/InPageNavigationAssert.php @@ -47,16 +47,17 @@ protected function assertBaseElements(string $html, string $variant): void { * The DomCrawler where to check the element. */ protected function assertList($expected, string $variant, Crawler $crawler): void { - $list_selector = 'ul.ecl-inpage-navigation__list'; - $this->assertElementExists($list_selector, $crawler); - $items = $crawler->filter('.ecl-inpage-navigation__item a'); - self::assertCount(count($expected), $items); - - foreach ($expected as $index => $expected_value) { - $item = $items->eq($index); - self::assertEquals($expected_value['label'], $item->text()); - self::assertEquals($expected_value['href'], $item->attr('href')); - } + $this->assertElementExists('ul.ecl-inpage-navigation__list', $crawler); + + $actual = []; + $crawler->filter('ul.ecl-inpage-navigation__list .ecl-inpage-navigation__item a')->each(function (Crawler $node) use (&$actual) { + $actual[] = [ + 'label' => $node->text(), + 'href' => $node->attr('href'), + ]; + }); + + self::assertEquals($expected, $actual); } } diff --git a/tests/Unit/ValueObject/GalleryItemValueObjectTest.php b/tests/Unit/ValueObject/GalleryItemValueObjectTest.php index aef56d843..738aae2df 100644 --- a/tests/Unit/ValueObject/GalleryItemValueObjectTest.php +++ b/tests/Unit/ValueObject/GalleryItemValueObjectTest.php @@ -19,17 +19,18 @@ class GalleryItemValueObjectTest extends UnitTestCase { * Test constructing a gallery item value object from an array. */ public function testFromArray(): void { + $image_value_object = ImageValueObject::fromArray([ + 'src' => 'http://placehold.it/380x185', + 'name' => 'Test thumbnail', + 'alt' => 'Alt text', + 'responsive' => TRUE, + ]); $values = [ - 'thumbnail' => ImageValueObject::fromArray([ - 'src' => 'http://placehold.it/380x185', - 'name' => 'Test thumbnail', - 'alt' => 'Alt text', - 'responsive' => TRUE, - ]), + 'thumbnail' => $image_value_object, 'source' => 'http://placehold.it/600x400', 'type' => GalleryItemValueObject::TYPE_VIDEO, - 'caption' => 'Test caption.', - 'meta' => 'Test meta.', + 'caption' => 'Test video caption.', + 'meta' => 'Test video meta.', ]; /** @var \Drupal\oe_theme\ValueObject\GalleryItemValueObject $item */ @@ -41,6 +42,15 @@ public function testFromArray(): void { $this->assertEquals($values['caption'], $item->getCaption()); $this->assertEquals($values['meta'], $item->getMeta()); + $to_array = $item->getArray(); + $this->assertEquals($to_array['image'], $image_value_object->getArray()); + $this->assertEquals($to_array['embedded_video'], [ + 'src' => 'http://placehold.it/600x400', + ]); + $this->assertEquals($to_array['icon'], 'video'); + $this->assertEquals($to_array['description'], 'Test video caption.'); + $this->assertEquals($to_array['meta'], 'Test video meta.'); + // Verify that the thumbnail can be also passed as array. $item = GalleryItemValueObject::fromArray([ 'thumbnail' => $values['thumbnail']->getArray(), @@ -51,6 +61,23 @@ public function testFromArray(): void { $this->assertEquals($values['type'], $item->getType()); $this->assertEquals($values['caption'], $item->getCaption()); $this->assertEquals($values['meta'], $item->getMeta()); + + // Create an image-based Gallery item. + $values = [ + 'thumbnail' => $image_value_object, + 'source' => 'http://placehold.it/800x600', + 'type' => GalleryItemValueObject::TYPE_IMAGE, + 'caption' => 'Test image caption.', + 'meta' => 'Test image meta.', + ]; + + /** @var \Drupal\oe_theme\ValueObject\GalleryItemValueObject $item */ + $item = GalleryItemValueObject::fromArray($values); + $this->assertEquals($values['type'], $item->getType()); + $to_array = $item->getArray(); + $this->assertEquals($to_array['icon'], 'image'); + $this->assertEquals($to_array['description'], 'Test image caption.'); + $this->assertEquals($to_array['meta'], 'Test image meta.'); } /**