Skip to content
Snippets Groups Projects
Commit 73d0110d authored by GitLab CI's avatar GitLab CI
Browse files

Merge branch 'develop' into 'main'

Merging develop into main

See merge request !382
parents 2557bdd7 01d2ac85
No related branches found
Tags v3.2.251
1 merge request!382Merging develop into main
Pipeline #1383950 passed
Showing
with 0 additions and 2592 deletions
{
"preferred-install": {
"*": "dist"
},
"sort-packages": true,
"discard-changes": true,
"gitlab-domains": [
"gitlab.lakedrops.com"
],
"allow-plugins": {
"composer/installers": true,
"cweagans/composer-patches": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"drupal/core-composer-scaffold": true,
"drupal/core-vendor-hardening": true,
"endroid/installer": true,
"lakedrops/*": true,
"mxr576/ddqg-composer-audit": true,
"oomphinc/composer-installers-extender": true,
"php-http/discovery": true,
"phpstan/extension-installer": true,
"zodiacmedia/drupal-libraries-installer": true
}
}
[
"DDQG-deprecated-drupal-variationcache-1.5.0.0",
"DDQG-unsupported-drupal-activitypub-1.0.0.0-alpha19",
"DDQG-unsupported-drupal-advanced_cors-1.5.0.0",
"DDQG-unsupported-drupal-analog_digital_clock-10.1.2.0",
"DDQG-unsupported-drupal-apitools-2.0.0.0-alpha3",
"DDQG-unsupported-drupal-blazy-2.16.0.0",
"DDQG-unsupported-drupal-blazy-2.27.0.0",
"DDQG-unsupported-drupal-block_field-1.0.0.0-RC5",
"DDQG-unsupported-drupal-book-2.0.0.0-alpha5",
"DDQG-unsupported-drupal-commerce_xquantity-2.0.0.0-beta1",
"DDQG-unsupported-drupal-conditional_fields-4.0.0.0-alpha6",
"DDQG-unsupported-drupal-config_update-2.0.0.0-alpha4",
"DDQG-unsupported-drupal-content_access-2.0.0.0",
"DDQG-unsupported-drupal-core-10.4.9999999.9999999-dev",
"DDQG-unsupported-drupal-default_content-2.0.0.0-alpha2",
"DDQG-unsupported-drupal-eca-2.1.0.0-RC1",
"DDQG-unsupported-drupal-elasticsearch_connector-8.0.0.0-alpha2",
"DDQG-unsupported-drupal-entitygroupfield-1.0.0.0-beta1",
"DDQG-unsupported-drupal-entity_import-0.0.0.0-dev",
"DDQG-unsupported-drupal-facets-3.0.0.0-beta4",
"DDQG-unsupported-drupal-feeds-3.0.0.0-beta5",
"DDQG-unsupported-drupal-flag-4.0.0.0-beta4",
"DDQG-unsupported-drupal-hacked-2.0.0.0-beta5",
"DDQG-unsupported-drupal-hide_submit_d8-0.0.0.0-dev",
"DDQG-unsupported-drupal-ief_popup-2.2.2.0",
"DDQG-unsupported-drupal-inline_entity_form-3.0.0.0-RC20",
"DDQG-unsupported-drupal-invoice_ninja-1.0.0.0-beta7",
"DDQG-unsupported-drupal-layout_library-1.0.0.0-beta4",
"DDQG-unsupported-drupal-matomo-2.0.0.0-alpha1",
"DDQG-unsupported-drupal-media_entity_link-2.0.1.0",
"DDQG-unsupported-drupal-menu_breadcrumb-2.0.0.0-alpha0",
"DDQG-unsupported-drupal-name-1.0.0.0-RC6",
"DDQG-unsupported-drupal-navigation_extra_tools-1.0.0.0-beta4",
"DDQG-unsupported-drupal-office_hours-0.0.0.0-dev",
"DDQG-unsupported-drupal-openai-1.0.0.0-beta6",
"DDQG-unsupported-drupal-openid_connect-3.0.0.0-alpha4",
"DDQG-unsupported-drupal-peertube-2.0.0.0-beta2",
"DDQG-unsupported-drupal-phone_number-2.0.0.0-alpha7",
"DDQG-unsupported-drupal-project_browser-2.0.0.0-alpha5",
"DDQG-unsupported-drupal-reader-1.0.0.0-beta2",
"DDQG-unsupported-drupal-readmehelp-2.0.0.0-beta1",
"DDQG-unsupported-drupal-schema_diff-1.0.0.0-alpha2",
"DDQG-unsupported-drupal-services-5.0.0.0-beta10",
"DDQG-unsupported-drupal-shs-2.0.0.0-RC12",
"DDQG-unsupported-drupal-simple_oauth-6.0.0.0-beta8",
"DDQG-unsupported-drupal-slick-2.9.0.0",
"DDQG-unsupported-drupal-slick-2.11.0.0",
"DDQG-unsupported-drupal-slick_views-2.7.0.0",
"DDQG-unsupported-drupal-slick_views-2.8.0.0",
"DDQG-unsupported-drupal-tamper-1.0.0.0-alpha5",
"DDQG-unsupported-drupal-term_merge-2.0.0.0-beta6",
"DDQG-unsupported-drupal-term_reference_change-2.0.0.0-beta5",
"DDQG-unsupported-drupal-toolbar_language_switcher-2.0.0.0-alpha2",
"DDQG-unsupported-drupal-viewfield-3.0.0.0-beta11",
"DDQG-unsupported-drupal-viewsreference-2.0.0.0-beta10",
"DDQG-unsupported-drupal-views_base_url-2.1.0.0-beta1",
"DDQG-unsupported-drupal-views_field_view-1.0.0.0-beta5",
"DDQG-unsupported-drupal-views_menu_children_filter-3.0.0.0-RC4",
"DDQG-unsupported-drupal-views_tree-2.0.0.0-RC1",
"DDQG-unsupported-drupal-xls_serialization-0.0.0.0-dev",
"DDQG-unsupported-drupal-xnumber-2.0.0.0-beta2",
"GHSA-mg8j-w93w-xjgc"
]
{
"blazy": "https://github.com/dinbror/blazy/archive/1.8.2.zip",
"codemirror": "https://github.com/components/codemirror/archive/refs/tags/5.65.12.zip",
"colorbox": "https://github.com/jackmoore/colorbox/archive/refs/tags/1.6.4.zip",
"dompurify": "https://github.com/cure53/DOMPurify/archive/refs/tags/3.0.9.zip",
"dropzone": "https://github.com/dropzone/dropzone/releases/download/v5.9.3/dist.zip",
"imagesloaded": "https://api.github.com/repos/desandro/imagesloaded/zipball/67c4e57453120935180c45c6820e7d3fbd2ea1f9",
"fontawesome": "https://use.fontawesome.com/releases/v6.5.1/fontawesome-free-6.5.1-web.zip",
"friendly-challenge": "https://registry.npmjs.org/friendly-challenge/-/friendly-challenge-0.9.16.tgz",
"fullcalendar": "https://github.com/fullcalendar/fullcalendar-workspace/releases/download/v6.1.11/fullcalendar-scheduler-6.1.11.zip",
"jquery.chosen": "https://github.com/harvesthq/chosen/releases/download/v1.8.7/chosen_v1.8.7.zip",
"jquery.geocomplete": "https://github.com/ubilabs/geocomplete/archive/refs/tags/1.7.0.zip",
"jquery.hotkeys": "https://github.com/jeresig/jquery.hotkeys/archive/refs/tags/0.2.0.zip",
"jquery.icheck": "https://github.com/drgullin/icheck/archive/refs/heads/1.0.3.zip",
"jquery.image-picker": "https://github.com/rvera/image-picker/archive/refs/tags/0.3.1.zip",
"jquery.inputmask": "https://github.com/RobinHerbots/jquery.inputmask/archive/refs/tags/5.0.8.zip",
"jquery.intl-tel-input": "https://github.com/jackocnr/intl-tel-input/archive/refs/tags/v17.0.19.zip",
"jquery.rateit": "https://github.com/gjunge/rateit.js/archive/refs/tags/1.1.5.zip",
"jquery.select2": "https://github.com/select2/select2/archive/refs/tags/4.0.13.zip",
"jquery-simple-color": "https://github.com/recurser/jquery-simple-color/archive/refs/tags/v1.2.3.tar.gz",
"jquery.textcounter": "https://github.com/ractoon/jQuery-Text-Counter/archive/refs/tags/0.9.1.zip",
"jquery.timepicker": "https://github.com/jonthornton/jquery-timepicker/archive/refs/tags/1.14.0.zip",
"jquery.toggles": "https://github.com/simontabor/jquery-toggles/archive/refs/tags/v4.0.0.zip",
"masonry": "https://api.github.com/repos/desandro/masonry/zipball/3b0883cf4a4a046896719b9cf282ea74be7ffecd",
"popperjs": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"progress-tracker": "https://github.com/NigelOToole/progress-tracker/archive/refs/tags/2.0.7.zip",
"select2": "https://github.com/select2/select2/archive/4.0.13.zip",
"signature_pad": "https://github.com/szimek/signature_pad/archive/refs/tags/v2.3.0.zip",
"slick": "https://github.com/kenwheeler/slick/archive/1.8.0.zip",
"slide-element": "https://github.com/alexmacarthur/slide-element/archive/refs/tags/v2.3.1.zip",
"spectrum": "https://github.com/bgrins/spectrum/archive/refs/tags/1.8.0.tar.gz",
"svg-pan-zoom": "https://github.com/ariutta/svg-pan-zoom/archive/refs/tags/3.6.1.zip",
"tabby": "https://github.com/cferdinandi/tabby/archive/refs/tags/v12.0.3.zip",
"tippyjs": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz"
}
{
"locations": {
"web-root": "./web"
},
"file-mapping": {
"[project-root]/.editorconfig": false,
"[project-root]/.gitattributes": false,
"[web-root]/example.gitignore": false,
"[web-root]/INSTALL.txt": false,
"[web-root]/README.txt": false,
"[web-root]/sites/README.txt": false,
"[web-root]/sites/development.services.yml": false,
"[web-root]/sites/example.settings.local.php": false,
"[web-root]/sites/example.sites.php": false,
"[web-root]/sites/default/default.services.yml": false,
"[web-root]/sites/default/default.settings.php": false,
"[web-root]/modules/README.txt": false,
"[web-root]/profiles/README.txt": false,
"[web-root]/themes/README.txt": false
}
}
{
"tests/{$name}": [
"type:lakedrops-tests"
]
}
[
"lakedrops-tests"
]
diff --git a/architect.info.yml b/architect.info.yml
index 58e1fc9..0c0b8ce 100644
--- a/architect.info.yml
+++ b/architect.info.yml
@@ -1,8 +1,7 @@
name: Architect
type: theme
description: the ARCHITECT Theme - A DESIGN SAVVY THEME USING UIKITTY.
-# core: 8.x
-core_version_requirement: ^8.8 || ^9
+core_version_requirement: ^10 || ^11
base theme: uikitty
libraries:
- architect/default
diff --git a/scss/components/sidebar.scss b/scss/components/sidebar.scss
index c5ab44c..61121c4 100644
--- a/scss/components/sidebar.scss
+++ b/scss/components/sidebar.scss
@@ -28,6 +28,6 @@
border-bottom: $border-width solid $border-color;
}
nav ul.nav {
- margin: 0 -($spacer);
+ margin: 0 (-($spacer));
}
}
\ No newline at end of file
diff --git a/css/components/form.css b/css/components/form.css
index 199631a57515d8781757760a508f8a7eb2044b1c..01c4b99980d6d7ebf414136099b79a8e366100b8 100644
--- a/css/components/form.css
+++ b/css/components/form.css
@@ -15,8 +15,8 @@
margin: 0 0.3em;
}
-.form-row>fieldset,
-.form-row>div {
+form .form-row>fieldset,
+form .form-row>div {
padding-right: 5px;
padding-left: 5px;
flex: 0 1 auto;
diff --git a/scss/components/form.scss b/scss/components/form.scss
index 61031d9dbf043267d631ed5c3afe2e02994dfbc7..a0be78538cd56f489d79ceadf520b6b147542131 100644
--- a/scss/components/form.scss
+++ b/scss/components/form.scss
@@ -7,7 +7,7 @@
content: '';
vertical-align: super;
display: inline-block;
- background-image: url(../images/required.svg);
+ background-image: url(#{$barrio_path_images}required.svg);
background-repeat: no-repeat;
background-size: ($input-height / 2) ($input-height / 2);
width: ($input-height / 2);
@@ -15,13 +15,15 @@
margin: 0 0.3em;
}
-.form-row>fieldset,
-.form-row>div {
- padding-right: 5px;
- padding-left: 5px;
- flex: 0 1 auto;
- width: auto;
- max-width: none;
+form {
+ .form-row>fieldset,
+ .form-row>div {
+ padding-right: 5px;
+ padding-left: 5px;
+ flex: 0 1 auto;
+ width: auto;
+ max-width: none;
+ }
}
.row .form-actions {
@@ -37,4 +39,4 @@ form .filter-wrapper {
form .form-type-textarea {
margin-bottom: 0;
-}
\ No newline at end of file
+}
diff --git a/scss/barrio.scss b/scss/barrio.scss
index 1d2ea1ac16e7d255c3095df33961ae249de77d64..3d02566aeceb4ca8555de674d039a8cc0ba86cef 100644
--- a/scss/barrio.scss
+++ b/scss/barrio.scss
@@ -1,3 +1,5 @@
+$barrio_path_images: "../../images/" !default;
+
@import "./components/mixins";
@import "./components/affix";
@import "./components/alerts";
@@ -43,4 +45,4 @@
@import "./components/vertical-tabs.component";
@import "./components/vertical-tabs";
@import "./components/views";
-@import "./components/webform";
\ No newline at end of file
+@import "./components/webform";
diff --git a/scss/components/file.scss b/scss/components/file.scss
index fe3500d53450aa0d7576901b12e8c2c346e8208b..ae14d9613953706d719cd865d181a892f35af11b 100644
--- a/scss/components/file.scss
+++ b/scss/components/file.scss
@@ -24,57 +24,57 @@
.file--general,
.file--application-octet-stream {
- background-image: url(../images/icons/application-octet-stream.png);
+ background-image: url(#{$barrio_path_images}icons/application-octet-stream.png);
}
.file--package-x-generic {
- background-image: url(../images/icons/package-x-generic.png);
+ background-image: url(#{$barrio_path_images}icons/package-x-generic.png);
}
.file--x-office-spreadsheet {
- background-image: url(../images/icons/x-office-spreadsheet.png);
+ background-image: url(#{$barrio_path_images}icons/x-office-spreadsheet.png);
}
.file--x-office-document {
- background-image: url(../images/icons/x-office-document.png);
+ background-image: url(#{$barrio_path_images}icons/x-office-document.png);
}
.file--x-office-presentation {
- background-image: url(../images/icons/x-office-presentation.png);
+ background-image: url(#{$barrio_path_images}icons/x-office-presentation.png);
}
.file--text-x-script {
- background-image: url(../images/icons/text-x-script.png);
+ background-image: url(#{$barrio_path_images}icons/text-x-script.png);
}
.file--text-html {
- background-image: url(../images/icons/text-html.png);
+ background-image: url(#{$barrio_path_images}icons/text-html.png);
}
.file--text-plain {
- background-image: url(../images/icons/text-plain.png);
+ background-image: url(#{$barrio_path_images}icons/text-plain.png);
}
.file--application-pdf {
- background-image: url(../images/icons/application-pdf.png);
+ background-image: url(#{$barrio_path_images}icons/application-pdf.png);
}
.file--application-x-executable {
- background-image: url(../images/icons/application-x-executable.png);
+ background-image: url(#{$barrio_path_images}icons/application-x-executable.png);
}
.file--audio {
- background-image: url(../images/icons/audio-x-generic.png);
+ background-image: url(#{$barrio_path_images}icons/audio-x-generic.png);
}
.file--video {
- background-image: url(../images/icons/video-x-generic.png);
+ background-image: url(#{$barrio_path_images}icons/video-x-generic.png);
}
.file--text {
- background-image: url(../images/icons/text-x-generic.png);
+ background-image: url(#{$barrio_path_images}icons/text-x-generic.png);
}
.file--image {
- background-image: url(../images/icons/image-x-generic.png);
-}
\ No newline at end of file
+ background-image: url(#{$barrio_path_images}icons/image-x-generic.png);
+}
diff --git a/scss/components/webform.scss b/scss/components/webform.scss
index 8d5c308e43fba1d0771d6ccc91da836fb3b3a9c5..905c5f2458cb761a0334bfdea5d1068ae181b645 100644
--- a/scss/components/webform.scss
+++ b/scss/components/webform.scss
@@ -9,7 +9,7 @@
content: '';
vertical-align: super;
display: inline-block;
- background-image: url(../../../contrib/bootstrap_barrio/images/required.svg);
+ background-image: url(#{$barrio_path_images}required.svg);
background-repeat: no-repeat;
background-size: 7px 7px;
width: 7px;
@@ -50,4 +50,4 @@
padding: 0;
}
}
-}
\ No newline at end of file
+}
Index: src/PhpSpreadsheet/Writer/Csv.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/PhpSpreadsheet/Writer/Csv.php (date 1563359827000)
+++ src/PhpSpreadsheet/Writer/Csv.php (date 1563359827000)
@@ -120,7 +120,7 @@
// Write rows to file
for ($row = 1; $row <= $maxRow; ++$row) {
// Convert the row to an array...
- $cellsArray = $sheet->rangeToArray('A' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas);
+ $cellsArray = $sheet->rangeToArray('D' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas);
// ... and write to the file
$this->writeLine($fileHandle, $cellsArray[0]);
}
This diff is collapsed.
This diff is collapsed.
{
"patches": {
"drupal/architect": {
"#3137889 Drupal 9": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3137889.diff",
"#local Drupal 10": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/architect-d10.patch"
},
"drupal/background_image": {
"#3161262 Pre render fix": "https://www.drupal.org/files/issues/2020-07-24/implement_trustedcallbackinterface.patch",
"#3170843 Dom Ready": "https://www.drupal.org/files/issues/2020-09-14/3170843-2.background_image.Library-drupaldomready-does-not-exist-in-Drupal-9.patch",
"#3173283 Cache": "https://www.drupal.org/files/issues/2020-09-26/3173283-2.background_image.Cache-context-also-requires-URL.patch",
"#3173340 Exception": "https://www.drupal.org/files/issues/2020-09-26/3173340-2.background_image.Error-Call-to-a-member-function-hasEntityToken-on-bool-in-DrupalbackgroundimageCacheContextBackgroundImageSettingsTextCacheContextgetContext.patch",
"#3128542 FileScan": "https://www.drupal.org/files/issues/2020-09-11/background_image-missing_folder-3128542-8.patch"
},
"drupal/bootstrap_clean_blog": {
"#3146287 Drupal 9": "https://www.drupal.org/files/issues/2021-10-23/3146287_3.patch"
},
"drupal/book": {
"#2918537 Save unpublished versions of published content without manage book privileges": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/2918537.diff",
"#3090234 Broken node theming for book export": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3090234.patch"
},
"drupal/ckeditor_find": {
"#3252081 Library location": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3252081.diff"
},
"drupal/codesnippet": {
"#3021431 Add Yaml as code format": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3021431.diff"
},
"drupal/comment_notify": {
"#2926228 Always notify admin": "https://www.drupal.org/files/issues/2019-09-11/2926228-11.comment_notify.Optionally-notify-site-admin-of-all-comments.patch"
},
"drupal/commerce_xquantity": {
"#3404050 Exceptions in actions of xquantity_stock": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3404050-2.diff"
},
"drupal/config_devel": {
"#3219083 Export raw data": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3219083.diff",
"#3227881 Support config_rewrite": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3227881.diff?v=2"
},
"drupal/config_sync": {
"#3176955 Drupal 9 test compatibility": "https://www.drupal.org/files/issues/2021-03-19/config_sync-config-sync-test-core-3176955-4.patch"
},
"drupal/config_update": {
"#3436790 Module weight": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3436790.diff?v=2",
"#3056249 Core hash for localisation": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3056249.diff"
},
"drupal/content_lock": {
"#2951652 No content lock für CLI commands": "https://www.drupal.org/files/issues/2022-04-05/2951652-13.patch",
"#3160781 Release lock when browsing away from locked form": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3160781-2.diff"
},
"drupal/core_for_review": {
"#3227732 Book hierarchy migration": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3227732.diff"
},
"drupal/core": {
"#local Hot fix timezoone": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/timezone.patch",
"#2647292 Date/time Views filter tries strotime() relative to Unix epoch": "https://www.drupal.org/files/issues/2022-02-10/with-dependency-injection-2647292-67.patch",
"#2884879 Ignore empty fields for REST export": "https://www.drupal.org/files/issues/2884879-11.patch",
"#2966735 Workaround for DateTime exposed filter": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/2966735.diff",
"#3043879 Layout Builder Config": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3043879.diff",
"#3195171 Fix view header group rendering": "https://www.drupal.org/files/issues/2022-01-05/3195171-7-fix-view-header-group-rendering.patch",
"#3180227 Missing options for entity refernces in views": "https://www.drupal.org/files/issues/2020-11-02/3180227-2.patch",
"#local Json API and entity reference warnings": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/jsonapi-entityref-warning.patch?v=3",
"#3228298 Empty path alias exception": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3228298.diff?v=2",
"#3227816 Hide password reset link": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3227816.diff",
"#3249628 Comments and paragraphs": "https://www.drupal.org/files/issues/2022-12-11/1415-11.diff",
"#2840283 Views action path with EVA": "https://www.drupal.org/files/issues/problem_with_action-2840283-25.patch",
"#2816447 RSS feed titles wrong language": "https://www.drupal.org/files/issues/2023-08-03/2816447-58.patch",
"#2915705 TypedData any": "https://www.drupal.org/files/issues/2022-12-11/2915705-82.patch",
"#3302450 Views field default type": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3302450.diff",
"#3311849 Views exposed filter, empty sections": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3311849.diff",
"#2797583 Actions for content moderation": "https://www.drupal.org/files/issues/2022-09-20/core-provide-moderation-states-as-actions-2797583-207.patch",
"#2918537 Save unpublished versions of published content without manage book privileges": "https://www.drupal.org/files/issues/2022-12-14/2918537-92.patch",
"#3047110 Taxonomy moderation": "https://www.drupal.org/files/issues/2021-07-23/3047110-32.patch",
"#3194462 Big pipe explode issue": "https://www.drupal.org/files/issues/2023-02-28/3194462-30.patch",
"#3090234 Broken node theming for book export": "https://www.drupal.org/files/issues/2020-10-06/3090234-9.patch",
"#3346430 DoPreSave load revision": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3346430.diff",
"#3340973 Media Lib type error on array_filter": "https://www.drupal.org/files/issues/2023-02-10/fix_media_library_php_error-3340973-2.patch",
"#3073822 Error: Call to a member function access() on null in Drupal\\comment\\CommentAccessControlHandler->checkAccess()": "https://www.drupal.org/files/issues/2023-01-12/3073822-12.patch",
"#2761273 Exposed filter values as token": "https://www.drupal.org/files/issues/2022-10-30/2761273-50.patch",
"#2955321 Non-translatable fields": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/2955321.diff",
"#3420862 Empty comment body": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3420862.diff",
"#3413508 Admin page access": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3413508.diff",
"#3053757 Filter for allowed moderation transitions": "https://www.drupal.org/files/issues/2024-03-12/content-moderation-user-filter-3053757-24.patch",
"#944582 File System Permissions": "https://www.drupal.org/files/issues/2024-01-16/944582-10.2.x-192.patch"
},
"drupal/dashboards": {
"#3366586 Shortcut error": "https://git.drupalcode.org/project/dashboards/-/merge_requests/26.diff"
},
"drupal/diff": {
"#3311234 Link to diff with prev rev": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3311234.diff?v=3",
"#3311372 Configure date format": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3311372.diff?v=2",
"#3360589 Form validation": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3360589.diff?v=4"
},
"drupal/dynamic_entity_reference": {
"#3099176 Errors when new entity types are added": "https://www.drupal.org/files/issues/2023-09-08/3099176-3.x-16.diff"
},
"drupal/eca": {
"#3352393 Condition list contains": "https://git.drupalcode.org/project/eca/-/merge_requests/349.diff",
"#3368530 eca_log tokens": "https://git.drupalcode.org/project/eca/-/merge_requests/370.diff",
"#3373537 Plain token replacement": "https://git.drupalcode.org/project/eca/-/merge_requests/375.diff",
"#3351738 Views argument default plugin": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/eca_views_argument.patch",
"#3396915 Improve #3368530 to cleanup context": "https://www.drupal.org/files/issues/2023-10-26/3396915-2.diff"
},
"drupal/elasticsearch_connector": {
"#2952301 Flatten keys": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/elasticsearch_connector.patch"
},
"drupal/entity_import": {
"#3061935 Make it work without content_translation": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3061935.diff"
},
"drupal/entity_share": {
"#3306745 File Share overrides the name of media entity": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3306745.diff",
"#3347453 VBO Dependency": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3347453.diff"
},
"drupal/entitygroupfield": {
"#3228312 Group load fails": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3228312.diff"
},
"drupal/fakeobjects": {
"#3208959 Library path": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3208959.diff"
},
"drupal/field_group": {
"#2858336 Token support": "https://www.drupal.org/files/issues/2019-01-15/field_group-tokens_in_classes-2858336-16.patch"
},
"drupal/flag": {
"#3238783 Fix flag action": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3238783.diff",
"#2500091 Activate token support": "https://www.drupal.org/files/issues/2022-12-30/flag_hook-tokens_2500091-43.patch"
},
"drupal/fullcalendar_view": {
"#3392567 Fix href": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3392567.diff",
"#3084395 Daterange basefield": "https://www.drupal.org/files/issues/2022-03-25/3084395-11.patch"
},
"drupal/gin_toolbar": {
"#3319445 Permission check": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3319445.diff"
},
"drupal/glossify": {
"#3360633 HTML entities": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3360633.diff"
},
"drupal/http_client_manager": {
"#3385117 Code generator": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3385117.diff"
},
"drupal/inline_entity_form": {
"#3204051 Check access": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3204051.diff?v=4"
},
"drupal/layout_library": {
"#3041543 Layout per display mode": "https://www.drupal.org/files/issues/2020-08-17/3041543-4.layout_library.Allow-created-layouts-to-be-limited-to-and-set-for-specific-view-modes.patch"
},
"drupal/ldap": {
"#3227813 Hide password field": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3227813.diff"
},
"drupal/linkchecker": {
"#3376854 Base path": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3376854.diff",
"#3313343 Disable cron": "https://www.drupal.org/files/issues/2022-10-03/support_disabling_cron-3313343-2.patch"
},
"drupal/menu_block": {
"#3082445 Add option to always render parent menu item": "https://www.drupal.org/files/issues/2020-10-12/menu_block-render-parent-3082445-26.patch"
},
"drupal/pluginreference": {
"#2979414 Allow no selection": "https://www.drupal.org/files/issues/2018-07-18/pluginreference-allow_no_plugin_to_be_selected-2979414-2.patch"
},
"drupal/profile": {
"#2899744 Multi-lingual": "https://www.drupal.org/files/issues/2022-04-17/2899744-54.patch"
},
"drupal/recaptcha": {
"#3113837 Downgrade unknown error": "https://www.drupal.org/files/issues/2020-02-15/3113837-2.recaptcha.Downgrade-unknown-error-info.patch"
},
"drupal/role_theme_switcher": {
"#3414975 Missing keys": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3414975.diff"
},
"drupal/select2": {
"#3211796 Z-Index in modal dialog": "https://www.drupal.org/files/issues/2023-04-18/select2-modal-zindex-mult-form-elem-fix-3211796-17.patch"
},
"drupal/simple_menu_icons": {
"#3379128 Do not delete all": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3379128.diff",
"#3404501 Set version and license": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3404501.diff"
},
"drupal/smart_login": {
"#2831386 Error 403 redirect": "https://www.drupal.org/files/issues/this_is_silently-2831386-2.patch",
"#2709529 Redirect after login": "https://www.drupal.org/files/issues/redirect_to_page_of-2709529-2.patch",
"#2901154 Properly handle destination": "https://www.drupal.org/files/issues/setting_form_redirect-2901154-2.patch"
},
"drupal/smtp": {
"#3252427 Add tokens": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3252427.diff"
},
"drupal/social_link_field": {
"#3241310 Add more channels": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3241310.diff"
},
"drupal/social_profile_field": {
"#3242595 Drupal 9": "https://www.drupal.org/files/issues/2021-10-11/3242595-3.patch",
"#2724653 Langparam": "https://www.drupal.org/files/issues/social_profile_field-fix-warnings-in-formatter-1.patch",
"#2799907 Alter icon path": "https://www.drupal.org/files/issues/allow_for_different-2799907-2.patch"
},
"drupal/svg_image_field": {
"#3090673 URL field formatter": "https://www.drupal.org/files/issues/2019-10-29/3090673-2.svg_image_field.Add-support-for-a-URL-image-formatter.patch"
},
"drupal/tamper": {
"#3279973 WordCount plugin": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3279973.diff",
"#3268276 Timezone plugin": "https://www.drupal.org/files/issues/2023-04-06/0001-Issue-3268276-Reworking-timezones.patch"
},
"drupal/taxonomy_machine_name": {
"#3193233 Filter doesn't work": "https://www.drupal.org/files/issues/2021-01-17/taxonomy_machine_name-view-save-error-3193233.patch",
"#3128397 View can not be saved": "https://www.drupal.org/files/issues/2020-04-16/config_schema-3128397-3.patch",
"#3352586 Parameter to disable machine name in terms overview ": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3352586-2.diff"
},
"drupal/title": {
"#3172331 D9 compatibility": "https://www.drupal.org/files/issues/2021-08-24/D9-compatibility_3172331.patch"
},
"drupal/token": {
"#3437013 Referrer tokens": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3437013.diff"
},
"drupal/uikitty": {
"#3149175 Drupal 9": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3149175.diff",
"#local Drupal 10": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/uikitty-d10.patch"
},
"drupal/views_data_export": {
"#3046184 Optional CSV Header (fix missing row on batch run)": "https://www.drupal.org/files/issues/2023-02-09/views_data_export-optional_csv_header-3046184-9.patch"
},
"drupal/video_embed_field": {
"#3238136 Vimeo hash parameter on private video url": "https://www.drupal.org/files/issues/2022-08-23/video_embed_field-vimeo_hash_parameters_private_video-3238136-8.patch"
},
"drupal/views_fieldsets": {
"#3395642 Fieldsets with only images don't display": "https://www.drupal.org/files/issues/2023-10-20/views_fieldset-allow_img.patch"
},
"drupal/views_tree": {
"#3344199 Add event just once": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3344199.diff"
},
"drupal/workflow": {
"#2948377 Do not hide widget when having only one option": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/show-widget-2948377-2.patch"
},
"drupal/wysiwyg_template": {
"#3354588 Drupal 10 compatible": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/d10/3354588.diff"
},
"grahl/ldap": {
"#Local Remove deprecation warnings": "https://gitlab.lakedrops.com/composer/plugin/drupal-environment/-/raw/main/patches/grahl-ldap.patch"
},
"henrywhitaker3/healthchecks-io": {
"#76 Double slashes in URL": "https://patch-diff.githubusercontent.com/raw/henrywhitaker3/PHP-healthchecks.io/pull/77.diff"
},
"phpcollection/phpcollection": {
"#31 PHP 8.1 deprecation": "https://patch-diff.githubusercontent.com/raw/schmittjoh/php-collection/pull/32.diff"
}
}
}
This diff is collapsed.
diff --git a/src/FieldGroupFormatterBase.php b/src/FieldGroupFormatterBase.php
index 5dc4e213e4a8b74379afe871e8f5f03ef2a38104..1f54d0edf7d23bd9fae250540ec541651b16fee3 100644
--- a/src/FieldGroupFormatterBase.php
+++ b/src/FieldGroupFormatterBase.php
@@ -126,6 +126,14 @@ abstract class FieldGroupFormatterBase extends PluginSettingsBase implements Fie
'#element_validate' => [[$class, 'validateCssClass']],
];
+ if (\Drupal::moduleHandler()->moduleExists('token')) {
+ $form['token_help'] = [
+ '#theme' => 'token_tree_link',
+ '#token_types' => [$this->group->entity_type],
+ '#weight' => 12
+ ];
+ $form['classes']['#element_validate'] = [[$class, 'validateCssClassToken']];
+ }
return $form;
}
@@ -222,6 +230,22 @@ abstract class FieldGroupFormatterBase extends PluginSettingsBase implements Fie
return $this->preRender($element, $processed_object);
}
+ /**
+ * Validate the entered css class with token from the submitted format settings.
+ *
+ * @param array $element
+ * The validated element.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ * The state of the form.
+ */
+ public static function validateCssClassToken(array $element, FormStateInterface $form_state) {
+ $form_state_values = $form_state->getValues();
+ $plugin_name = $form_state->get('plugin_settings_edit');
+ if (!empty($form_state_values['fields'][$plugin_name]['settings_edit_form']['settings']['classes']) && !preg_match('![A-Za-z0-9-_ ]*(\[[\w]+:([\w]+:)*[\w]+\])*!', $form_state_values['fields'][$plugin_name]['settings_edit_form']['settings']['classes'])) {
+ $form_state->setError($element, t('The css class must include only letters, numbers, underscores, dashes and token fields.'));
+ }
+ }
+
/**
* Validate the entered css class from the submitted format settings.
*
diff --git a/src/Plugin/field_group/FieldGroupFormatter/HtmlElement.php b/src/Plugin/field_group/FieldGroupFormatter/HtmlElement.php
index 66a11048f5ee2f9fb55a377dabd52b3b9a71d2de..e5a163f82ee066175cd000ef7d16056960c694cc 100644
--- a/src/Plugin/field_group/FieldGroupFormatter/HtmlElement.php
+++ b/src/Plugin/field_group/FieldGroupFormatter/HtmlElement.php
@@ -4,6 +4,7 @@ namespace Drupal\field_group\Plugin\field_group\FieldGroupFormatter;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Xss;
+use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Render\Markup;
use Drupal\Core\Template\Attribute;
@@ -55,6 +56,12 @@ class HtmlElement extends FieldGroupFormatterBase {
// Add the classes to the attributes array.
$classes = $this->getClasses();
+ if (\Drupal::moduleHandler()->moduleExists('token')) {
+ if (isset($processed_object["#{$this->group->entity_type}"])) {
+ $entity = $processed_object["#{$this->group->entity_type}"];
+ $classes = $this->tokenizeClasses($entity, $classes);
+ }
+ }
if (!empty($classes)) {
if (!isset($element_attributes['class'])) {
$element_attributes['class'] = [];
@@ -259,5 +266,21 @@ class HtmlElement extends FieldGroupFormatterBase {
return $defaults;
}
+
+ /**
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ * @param array $classes
+ * @return array
+ */
+ private function tokenizeClasses(EntityInterface $entity, array $classes) {
+ $token = \Drupal::token();
+ $variables = [
+ $entity->getEntityTypeId() => $entity
+ ];
+
+ $classString = implode(' ', $classes);
+ $tokenizedClasses = $token->replace($classString, $variables, ['clear' => TRUE]);
+ return explode(' ', $tokenizedClasses);
+ }
}
diff --git a/core/core.services.yml b/core/core.services.yml
index da5011df77..106db6a337 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -895,7 +895,8 @@ services:
arguments: ['@request_stack']
Drupal\Core\Routing\RouteMatchInterface: '@current_route_match'
event_dispatcher:
- class: Symfony\Component\EventDispatcher\EventDispatcher
+ class: Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
+ arguments: ['@service_container']
Psr\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
Symfony\Contracts\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
controller_resolver:
diff --git a/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php
index fd99e0335e..41afec903e 100644
--- a/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php
+++ b/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php
@@ -2,8 +2,6 @@
namespace Drupal\Component\EventDispatcher;
-@trigger_error('The ' . __NAMESPACE__ . '\ContainerAwareEventDispatcher is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use Symfony\Component\EventDispatcher\EventDispatcher instead. See https://www.drupal.org/node/3376090', E_USER_DEPRECATED);
-
use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -32,11 +30,6 @@
* runtime is not affected by this change though.
* </dd>
* </dl>
- *
- * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use
- * \Symfony\Component\EventDispatcher\EventDispatcher instead.
- *
- * @see https://www.drupal.org/node/3376090
*/
class ContainerAwareEventDispatcher implements EventDispatcherInterface {
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index 20fd28594a..368692ba7b 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -30,7 +30,6 @@
use Psr\Log\LoggerAwareInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
@@ -86,7 +85,7 @@ public function register(ContainerBuilder $container) {
$container->addCompilerPass(new TwigExtensionPass());
// Add a compiler pass for registering event subscribers.
- $container->addCompilerPass(new RegisterEventSubscribersPass(new RegisterListenersPass()), PassConfig::TYPE_AFTER_REMOVING);
+ $container->addCompilerPass(new RegisterEventSubscribersPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new LoggerAwarePass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new RegisterAccessChecksPass());
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php
index 82d1f1614d..0cae61c39f 100644
--- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php
@@ -4,50 +4,59 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
- * Wraps the Symfony event subscriber pass to use different tag names.
+ * Registers all event subscribers to the event dispatcher.
*/
class RegisterEventSubscribersPass implements CompilerPassInterface {
- /**
- * Constructs a RegisterEventSubscribersPass object.
- *
- * @param \Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass $pass
- * The Symfony compiler pass that registers event subscribers.
- */
- public function __construct(
- protected RegisterListenersPass $pass,
- ) {}
-
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container) {
- $this->renameTag($container, 'event_subscriber', 'kernel.event_subscriber');
- $this->pass->process($container);
- $this->renameTag($container, 'kernel.event_subscriber', 'event_subscriber');
- }
+ if (!$container->hasDefinition('event_dispatcher')) {
+ return;
+ }
- /**
- * Renames tags in the container.
- *
- * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
- * The container.
- * @param string $source_tag
- * The tag to be renamed.
- * @param string $target_tag
- * The tag to rename with.
- */
- protected function renameTag(ContainerBuilder $container, string $source_tag, string $target_tag): void {
- foreach ($container->getDefinitions() as $definition) {
- if ($definition->hasTag($source_tag)) {
- $attributes = $definition->getTag($source_tag)[0];
- $definition->addTag($target_tag, $attributes);
- $definition->clearTag($source_tag);
+ $definition = $container->getDefinition('event_dispatcher');
+
+ $event_subscriber_info = [];
+ foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) {
+
+ // We must assume that the class value has been correctly filled, even if
+ // the service is created by a factory.
+ $class = $container->getDefinition($id)->getClass();
+
+ $interface = EventSubscriberInterface::class;
+ if (!is_subclass_of($class, $interface)) {
+ throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
+ }
+
+ // Get all subscribed events.
+ foreach ($class::getSubscribedEvents() as $event_name => $params) {
+ if (is_string($params)) {
+ $priority = 0;
+ $event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $params]];
+ }
+ elseif (is_string($params[0])) {
+ $priority = $params[1] ?? 0;
+ $event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $params[0]]];
+ }
+ else {
+ foreach ($params as $listener) {
+ $priority = $listener[1] ?? 0;
+ $event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $listener[0]]];
+ }
+ }
}
}
+
+ foreach (array_keys($event_subscriber_info) as $event_name) {
+ krsort($event_subscriber_info[$event_name]);
+ }
+
+ $definition->addArgument($event_subscriber_info);
}
}
diff --git a/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php b/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php
index 63c52f408c..de8ecb220f 100644
--- a/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php
+++ b/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php
@@ -4,6 +4,7 @@
namespace Drupal\Tests\layout_builder\Unit;
+use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockManagerInterface;
@@ -23,7 +24,6 @@
use Drupal\layout_builder\SectionComponent;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
-use Symfony\Component\EventDispatcher\EventDispatcher;
/**
* @coversDefaultClass \Drupal\layout_builder\Section
@@ -62,7 +62,7 @@ class SectionRenderTest extends UnitTestCase {
/**
* The event dispatcher.
*
- * @var \Symfony\Component\EventDispatcher\EventDispatcher
+ * @var \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
*/
protected $eventDispatcher;
@@ -77,7 +77,7 @@ protected function setUp(): void {
$this->contextHandler = $this->prophesize(ContextHandlerInterface::class);
$this->contextRepository = $this->prophesize(ContextRepositoryInterface::class);
// @todo Refactor this into some better tests in https://www.drupal.org/node/2942605.
- $this->eventDispatcher = (new \ReflectionClass(EventDispatcher::class))->newInstanceWithoutConstructor();
+ $this->eventDispatcher = (new \ReflectionClass(ContainerAwareEventDispatcher::class))->newInstanceWithoutConstructor();
$this->account = $this->prophesize(AccountInterface::class);
$subscriber = new BlockComponentRenderArray($this->account->reveal());
diff --git a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
index 9ee42e3f70..a8fd9e87d6 100644
--- a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
+++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
@@ -25,7 +25,6 @@
* synchronizations.
*
* @group EventDispatcher
- * @group legacy
*/
class ContainerAwareEventDispatcherTest extends TestCase {
diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php
index c567bc0398..94ced461bc 100644
--- a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php
+++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php
@@ -4,13 +4,13 @@
namespace Drupal\Tests\Core\EventSubscriber;
+use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher as EventDispatcher;
use Drupal\Core\EventSubscriber\RedirectResponseSubscriber;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
use Drupal\Tests\UnitTestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Container;
-use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
@@ -87,7 +87,7 @@ protected function setUp(): void {
* @dataProvider providerTestDestinationRedirect
*/
public function testDestinationRedirect(Request $request, $expected) {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://example.com/drupal');
$request->headers->set('HOST', 'example.com');
@@ -128,7 +128,7 @@ public static function providerTestDestinationRedirect() {
* @dataProvider providerTestDestinationRedirectToExternalUrl
*/
public function testDestinationRedirectToExternalUrl($request, $expected) {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://other-example.com');
@@ -143,7 +143,7 @@ public function testDestinationRedirectToExternalUrl($request, $expected) {
* @covers ::checkRedirectUrl
*/
public function testRedirectWithOptInExternalUrl() {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new TrustedRedirectResponse('http://external-url.com');
$request = Request::create('');
@@ -176,7 +176,7 @@ public static function providerTestDestinationRedirectToExternalUrl() {
* @dataProvider providerTestDestinationRedirectWithInvalidUrl
*/
public function testDestinationRedirectWithInvalidUrl(Request $request) {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://example.com/drupal');
Subject: [PATCH] Issue #2909185 by longwave, donquixote, andypost, andregp, pounard, jibran, martin107, kostyashupenko, catch, znerol: Replace ContainerAwareEventDispatcher with Symfony EventDispatcher
---
Index: core/core.services.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/core.services.yml b/core/core.services.yml
--- a/core/core.services.yml (revision 6e733866fe414d0521be3d781c631c9368b818b1)
+++ b/core/core.services.yml (revision ed13e942030535430a4a8861cbf49808a0934a72)
@@ -873,7 +873,8 @@
arguments: ['@request_stack']
Drupal\Core\Routing\RouteMatchInterface: '@current_route_match'
event_dispatcher:
- class: Symfony\Component\EventDispatcher\EventDispatcher
+ class: Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
+ arguments: ['@service_container']
Psr\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
Symfony\Contracts\EventDispatcher\EventDispatcherInterface: '@event_dispatcher'
controller_resolver:
Index: core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php
--- a/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php (revision 6e733866fe414d0521be3d781c631c9368b818b1)
+++ b/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php (revision ed13e942030535430a4a8861cbf49808a0934a72)
@@ -2,8 +2,6 @@
namespace Drupal\Component\EventDispatcher;
-@trigger_error('The ' . __NAMESPACE__ . '\ContainerAwareEventDispatcher is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use Symfony\Component\EventDispatcher\EventDispatcher instead. See https://www.drupal.org/node/3376090', E_USER_DEPRECATED);
-
use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -32,11 +30,6 @@
* runtime is not affected by this change though.
* </dd>
* </dl>
- *
- * @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use
- * \Symfony\Component\EventDispatcher\EventDispatcher instead.
- *
- * @see https://www.drupal.org/node/3376090
*/
class ContainerAwareEventDispatcher implements EventDispatcherInterface {
Index: core/lib/Drupal/Core/CoreServiceProvider.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
--- a/core/lib/Drupal/Core/CoreServiceProvider.php (revision 6e733866fe414d0521be3d781c631c9368b818b1)
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php (revision ed13e942030535430a4a8861cbf49808a0934a72)
@@ -29,7 +29,6 @@
use Psr\Log\LoggerAwareInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
@@ -83,7 +82,7 @@
$container->addCompilerPass(new TwigExtensionPass());
// Add a compiler pass for registering event subscribers.
- $container->addCompilerPass(new RegisterEventSubscribersPass(new RegisterListenersPass()), PassConfig::TYPE_AFTER_REMOVING);
+ $container->addCompilerPass(new RegisterEventSubscribersPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new LoggerAwarePass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new RegisterAccessChecksPass());
Index: core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php
--- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php (revision 6e733866fe414d0521be3d781c631c9368b818b1)
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventSubscribersPass.php (revision ed13e942030535430a4a8861cbf49808a0934a72)
@@ -4,50 +4,59 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
- * Wraps the Symfony event subscriber pass to use different tag names.
+ * Registers all event subscribers to the event dispatcher.
*/
class RegisterEventSubscribersPass implements CompilerPassInterface {
- /**
- * Constructs a RegisterEventSubscribersPass object.
- *
- * @param \Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass $pass
- * The Symfony compiler pass that registers event subscribers.
- */
- public function __construct(
- protected RegisterListenersPass $pass
- ) {}
-
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container) {
- $this->renameTag($container, 'event_subscriber', 'kernel.event_subscriber');
- $this->pass->process($container);
- $this->renameTag($container, 'kernel.event_subscriber', 'event_subscriber');
- }
+ if (!$container->hasDefinition('event_dispatcher')) {
+ return;
+ }
+
+ $definition = $container->getDefinition('event_dispatcher');
+
+ $event_subscriber_info = [];
+ foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) {
+
+ // We must assume that the class value has been correctly filled, even if
+ // the service is created by a factory.
+ $class = $container->getDefinition($id)->getClass();
+
+ $interface = EventSubscriberInterface::class;
+ if (!is_subclass_of($class, $interface)) {
+ throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
+ }
- /**
- * Renames tags in the container.
- *
- * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
- * The container.
- * @param string $source_tag
- * The tag to be renamed.
- * @param string $target_tag
- * The tag to rename with.
- */
- protected function renameTag(ContainerBuilder $container, string $source_tag, string $target_tag): void {
- foreach ($container->getDefinitions() as $definition) {
- if ($definition->hasTag($source_tag)) {
- $attributes = $definition->getTag($source_tag)[0];
- $definition->addTag($target_tag, $attributes);
- $definition->clearTag($source_tag);
+ // Get all subscribed events.
+ foreach ($class::getSubscribedEvents() as $event_name => $params) {
+ if (is_string($params)) {
+ $priority = 0;
+ $event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $params]];
+ }
+ elseif (is_string($params[0])) {
+ $priority = $params[1] ?? 0;
+ $event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $params[0]]];
+ }
+ else {
+ foreach ($params as $listener) {
+ $priority = $listener[1] ?? 0;
+ $event_subscriber_info[$event_name][$priority][] = ['service' => [$id, $listener[0]]];
+ }
+ }
}
}
+
+ foreach (array_keys($event_subscriber_info) as $event_name) {
+ krsort($event_subscriber_info[$event_name]);
+ }
+
+ $definition->addArgument($event_subscriber_info);
}
}
Index: core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php b/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php
--- a/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php (revision 6e733866fe414d0521be3d781c631c9368b818b1)
+++ b/core/modules/layout_builder/tests/src/Unit/SectionRenderTest.php (revision ed13e942030535430a4a8861cbf49808a0934a72)
@@ -4,6 +4,7 @@
namespace Drupal\Tests\layout_builder\Unit;
+use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockManagerInterface;
@@ -23,7 +24,6 @@
use Drupal\layout_builder\SectionComponent;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
-use Symfony\Component\EventDispatcher\EventDispatcher;
/**
* @coversDefaultClass \Drupal\layout_builder\Section
@@ -62,7 +62,7 @@
/**
* The event dispatcher.
*
- * @var \Symfony\Component\EventDispatcher\EventDispatcher
+ * @var \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher
*/
protected $eventDispatcher;
@@ -77,7 +77,7 @@
$this->contextHandler = $this->prophesize(ContextHandlerInterface::class);
$this->contextRepository = $this->prophesize(ContextRepositoryInterface::class);
// @todo Refactor this into some better tests in https://www.drupal.org/node/2942605.
- $this->eventDispatcher = (new \ReflectionClass(EventDispatcher::class))->newInstanceWithoutConstructor();
+ $this->eventDispatcher = (new \ReflectionClass(ContainerAwareEventDispatcher::class))->newInstanceWithoutConstructor();
$this->account = $this->prophesize(AccountInterface::class);
$subscriber = new BlockComponentRenderArray($this->account->reveal());
Index: core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
--- a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php (revision 6e733866fe414d0521be3d781c631c9368b818b1)
+++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php (revision ed13e942030535430a4a8861cbf49808a0934a72)
@@ -25,7 +25,6 @@
* synchronizations.
*
* @group EventDispatcher
- * @group legacy
*/
class ContainerAwareEventDispatcherTest extends TestCase {
Index: core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php
--- a/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php (revision 6e733866fe414d0521be3d781c631c9368b818b1)
+++ b/core/tests/Drupal/Tests/Core/EventSubscriber/RedirectResponseSubscriberTest.php (revision ed13e942030535430a4a8861cbf49808a0934a72)
@@ -4,13 +4,13 @@
namespace Drupal\Tests\Core\EventSubscriber;
+use Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher as EventDispatcher;
use Drupal\Core\EventSubscriber\RedirectResponseSubscriber;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Utility\UnroutedUrlAssemblerInterface;
use Drupal\Tests\UnitTestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Container;
-use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
@@ -87,7 +87,7 @@
* @dataProvider providerTestDestinationRedirect
*/
public function testDestinationRedirect(Request $request, $expected) {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://example.com/drupal');
$request->headers->set('HOST', 'example.com');
@@ -128,7 +128,7 @@
* @dataProvider providerTestDestinationRedirectToExternalUrl
*/
public function testDestinationRedirectToExternalUrl($request, $expected) {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://other-example.com');
@@ -143,7 +143,7 @@
* @covers ::checkRedirectUrl
*/
public function testRedirectWithOptInExternalUrl() {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new TrustedRedirectResponse('http://external-url.com');
$request = Request::create('');
@@ -176,7 +176,7 @@
* @dataProvider providerTestDestinationRedirectWithInvalidUrl
*/
public function testDestinationRedirectWithInvalidUrl(Request $request) {
- $dispatcher = new EventDispatcher();
+ $dispatcher = new EventDispatcher(\Drupal::getContainer());
$kernel = $this->createMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$response = new RedirectResponse('http://example.com/drupal');
diff --git a/book.module b/book.module
index 1760113fe4188101391792b45cfa93e2399089b8..cc02b76fef5e9f44a9fa594292f3bc66f9d2c5ba 100644
--- a/book.module
+++ b/book.module
@@ -136,6 +136,9 @@ function book_node_links_alter(array &$links, NodeInterface $node, array &$conte
*/
function book_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$node = $form_state->getFormObject()->getEntity();
+ if (!book_type_is_allowed($node->getType())) {
+ return;
+ }
$account = \Drupal::currentUser();
$access = $account->hasPermission('administer book outlines');
if (!$access) {
@@ -290,6 +293,9 @@ function book_node_predelete(EntityInterface $node) {
* Implements hook_ENTITY_TYPE_prepare_form() for node entities.
*/
function book_node_prepare_form(NodeInterface $node, $operation, FormStateInterface $form_state) {
+ if (!book_type_is_allowed($node->getType())) {
+ return;
+ }
/** @var \Drupal\book\BookManagerInterface $book_manager */
$book_manager = \Drupal::service('book.manager');
diff --git a/src/Plugin/Validation/Constraint/BookOutlineConstraintValidator.php b/src/Plugin/Validation/Constraint/BookOutlineConstraintValidator.php
index ca8114dad4a661417bed20d375d33f06127b86b8..fc7b4ef7a0ae09b7268472e7f664c23490383862 100644
--- a/src/Plugin/Validation/Constraint/BookOutlineConstraintValidator.php
+++ b/src/Plugin/Validation/Constraint/BookOutlineConstraintValidator.php
@@ -43,7 +43,12 @@ public static function create(ContainerInterface $container) {
* {@inheritdoc}
*/
public function validate($entity, Constraint $constraint) {
- if (isset($entity) && !$entity->isNew() && !$entity->isDefaultRevision()) {
+ // Validate the book structure when the user has access to manage book
+ // outlines. When the user can manage book outlines, the book variable will
+ // be populated even if the node is not part of the book. If the user cannot
+ // manage book outlines, the book variable will be empty and we can safely
+ // ignore the constraints as the outline cannot be changed by this user.
+ if (isset($entity) && !empty($entity->book) && !$entity->isNew() && !$entity->isDefaultRevision()) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $original */
$original = $this->bookManager->loadBookLink($entity->id(), FALSE) ?: [
'bid' => 0,
diff --git a/tests/src/Functional/BookContentModerationTest.php b/tests/src/Functional/BookContentModerationTest.php
index 14898777d91ea52aa2630f6775a2251dc08b1530..3fc60cde1129430488bea2a258596637893bca38 100644
--- a/tests/src/Functional/BookContentModerationTest.php
+++ b/tests/src/Functional/BookContentModerationTest.php
@@ -4,6 +4,7 @@
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
+use Drupal\user\Entity\Role;
/**
* Tests Book and Content Moderation integration.
@@ -15,6 +16,13 @@ class BookContentModerationTest extends BrowserTestBase {
use BookTestTrait;
use ContentModerationTestTrait;
+ /**
+ * A user with permission to make workflow transitions but not manage books.
+ *
+ * @var \Drupal\user\UserInterface
+ */
+ protected $nonBookAdminUser;
+
/**
* Modules to install.
*
@@ -56,6 +64,19 @@ protected function setUp(): void {
'use editorial transition create_new_draft',
'use editorial transition publish',
]);
+
+ // Another user without manage book permissions to test updates to nodes
+ // that are
+ // 1. Not part of a book outline.
+ // 2. Part of a book outline.
+ $this->nonBookAdminUser = $this->drupalCreateUser([
+ 'create book content',
+ 'edit own book content',
+ 'use editorial transition create_new_draft',
+ 'use editorial transition publish',
+ 'access printer-friendly version',
+ 'view any unpublished content',
+ ]);
}
/**
@@ -163,4 +184,112 @@ public function testBookWithPendingRevisions() {
$this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
}
+ /**
+ * Tests that users who cannot manage books can still make node updates.
+ */
+ public function testNonBookAdminNodeUpdates() {
+ // 1. First test that users who cannot manage books can make updates to
+ // nodes that are not part of a book outline.
+ $this->drupalLogin($this->nonBookAdminUser);
+ // Create a new book page without actually attaching it to a book and create
+ // a draft.
+ $this->drupalGet('node/add/book');
+ $this->assertSession()->statusCodeEquals(200);
+ $edit = [
+ 'title[0][value]' => 'Some moderated content',
+ 'moderation_state[0][state]' => 'draft',
+ ];
+ $this->submitForm($edit, 'Save');
+ $this->assertSession()->pageTextContains('Some moderated content has been created.');
+ $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
+ $this->assertNotEmpty($node);
+
+ $this->drupalGet('node/' . $node->id() . '/edit');
+ $this->assertSession()->statusCodeEquals(200);
+ // Publish the content.
+ $edit = [
+ 'body[0][value]' => 'Second change non book admin user',
+ 'moderation_state[0][state]' => 'published',
+ ];
+ $this->submitForm($edit, 'Save');
+ $this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
+ $this->assertSession()->pageTextContains('Some moderated content has been updated');
+
+ // Now update content again, it should be successfully updated and not throw
+ // any errors.
+ $this->drupalGet('node/' . $node->id() . '/edit');
+ $this->assertSession()->statusCodeEquals(200);
+ $edit = [
+ 'moderation_state[0][state]' => 'draft',
+ ];
+ $this->submitForm($edit, 'Save');
+ $this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
+ $this->assertSession()->pageTextContains('Some moderated content has been updated');
+
+ // 2. Now test that users who cannot manage books can make updates to nodes
+ // that are part of a book outline. As the non admin book user, publish the
+ // content created above in order to be added to a book.
+ $this->drupalGet('node/' . $node->id() . '/edit');
+ $this->assertSession()->statusCodeEquals(200);
+ $edit = [
+ 'moderation_state[0][state]' => 'published',
+ ];
+ $this->submitForm($edit, 'Save');
+
+ // Create a book (as a book admin user).
+ $book_1_nodes = $this->createBook(['moderation_state[0][state]' => 'published']);
+ $book_1 = $this->book;
+
+ // Now add the node created previously by the non book admin user to the
+ // book created above. We need to grant additional permission for bookAuthor
+ // to be able to edit the node owned by nonBookAdminUser.
+ $role_ids = $this->bookAuthor->getRoles(TRUE);
+ $role_id = reset($role_ids);
+ $role = Role::load($role_id);
+ $role->grantPermission('edit any book content');
+ $role->save();
+ $this->drupalLogin($this->bookAuthor);
+ $this->drupalGet('node/' . $node->id() . '/edit');
+ $this->assertSession()->statusCodeEquals(200);
+ $edit = [
+ 'book[bid]' => $this->book->id(),
+ 'moderation_state[0][state]' => 'published',
+ ];
+ $this->submitForm($edit, 'Save');
+
+ // Assert that the node has been added to the book.
+ $this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
+ $this->assertSession()->pageTextContains('Some moderated content has been updated');
+ $this->checkBookNode($book_1, [
+ $book_1_nodes[0],
+ $book_1_nodes[3],
+ $book_1_nodes[4],
+ $node,
+ ], FALSE, FALSE, $book_1_nodes[0], []);
+
+ // Try to update the non book admin's node in the book as the user
+ // that cannot manage books, it should be successfully updated and not
+ // throw any errors.
+ $this->drupalLogin($this->nonBookAdminUser);
+ $this->drupalGet('node/' . $node->id() . '/edit');
+ $this->assertSession()->statusCodeEquals(200);
+ $edit = [
+ 'body[0][value]' => 'Change by non book admin user again',
+ 'moderation_state[0][state]' => 'draft',
+ ];
+ $this->submitForm($edit, 'Save');
+ $this->assertSession()->pageTextNotContains('You can only change the book outline for the published version of this content.');
+ $this->assertSession()->pageTextContains('Some moderated content has been updated');
+
+ // Check that the book outline did not change.
+ $this->book = $book_1;
+ $this->checkBookNode($book_1, [
+ $book_1_nodes[0],
+ $book_1_nodes[3],
+ $book_1_nodes[4],
+ $node,
+ ], FALSE, FALSE, $book_1_nodes[0], []);
+ $this->checkBookNode($book_1_nodes[0], [$book_1_nodes[1], $book_1_nodes[2]], $book_1, $book_1, $book_1_nodes[1], [$book_1]);
+ }
+
}
diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityUntranslatableFieldsConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityUntranslatableFieldsConstraintValidator.php
index 56f0da64fe8c6c0b2c7fd1a56b48ddad3ec69186..57e3903d5d7b17c37cd66790dd148e99fc1b6ce8 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityUntranslatableFieldsConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/EntityUntranslatableFieldsConstraintValidator.php
@@ -71,8 +71,11 @@ public function validate($entity, Constraint $constraint) {
// in default revisions.
if ($this->hasUntranslatableFieldsChanges($entity)) {
if ($entity->isDefaultTranslationAffectedOnly()) {
+ $moderationInformation = \Drupal::hasService('content_moderation.moderation_information') ?
+ \Drupal::service('content_moderation.moderation_information') :
+ NULL;
foreach ($entity->getTranslationLanguages(FALSE) as $langcode => $language) {
- if ($entity->getTranslation($langcode)->hasTranslationChanges()) {
+ if ($entity->getTranslation($langcode)->hasTranslationChanges() && ($moderationInformation === NULL || !$moderationInformation->isModeratedEntity($entity->getTranslation($langcode)))) {
$this->context->addViolation($constraint->defaultTranslationMessage);
break;
}
diff --git a/core/modules/content_translation/src/Plugin/Validation/Constraint/ContentTranslationSynchronizedFieldsConstraintValidator.php b/core/modules/content_translation/src/Plugin/Validation/Constraint/ContentTranslationSynchronizedFieldsConstraintValidator.php
index e52a18081064ddcdcd48777a401801253f183803..51eb95e420a63e3f64b0ea3dc6be8732b3213af0 100644
--- a/core/modules/content_translation/src/Plugin/Validation/Constraint/ContentTranslationSynchronizedFieldsConstraintValidator.php
+++ b/core/modules/content_translation/src/Plugin/Validation/Constraint/ContentTranslationSynchronizedFieldsConstraintValidator.php
@@ -111,8 +111,11 @@ public function validate($value, Constraint $constraint) {
$original_translation = $this->getOriginalTranslation($entity, $original);
if ($this->hasSynchronizedPropertyChanges($entity, $original_translation, $synchronized_properties)) {
if ($entity->isDefaultTranslationAffectedOnly()) {
+ $moderationInformation = \Drupal::hasService('content_moderation.moderation_information') ?
+ \Drupal::service('content_moderation.moderation_information') :
+ NULL;
foreach ($entity->getTranslationLanguages(FALSE) as $langcode => $language) {
- if ($entity->getTranslation($langcode)->hasTranslationChanges()) {
+ if ($entity->getTranslation($langcode)->hasTranslationChanges() && ($moderationInformation === NULL || !$moderationInformation->isModeratedEntity($entity->getTranslation($langcode)))) {
$this->context->addViolation($constraint->defaultTranslationMessage);
break;
}
diff --git a/core/modules/datetime/src/Plugin/views/filter/Date.php b/core/modules/datetime/src/Plugin/views/filter/Date.php
index f73a675fef0c72f3de88af21cdd759216713cdac..b4152bf730260e619814204140f5e18e15cd0f23 100644
--- a/core/modules/datetime/src/Plugin/views/filter/Date.php
+++ b/core/modules/datetime/src/Plugin/views/filter/Date.php
@@ -4,6 +4,8 @@
use Drupal\Component\Datetime\DateTimePlus;
use Drupal\Core\Datetime\DateFormatterInterface;
+use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
@@ -98,6 +100,54 @@ public static function create(ContainerInterface $container, array $configuratio
);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function validateExposed(&$form, FormStateInterface $form_state) {
+ // Do not validate value if filter is not exposed or grouped.
+ if (empty($this->options['exposed']) || $this->options['is_grouped']) {
+ return;
+ }
+
+ $identifier = $this->options['expose']['identifier'];
+ $input = $form_state->getValue($identifier);
+
+ $values = [];
+ if (is_array($input)) {
+ if (!empty($input['value'])) {
+ $values[] = $input['value'];
+ }
+ else {
+ if (!empty($input['min'])) {
+ $values[] = $input['min'];
+ }
+ if (!empty($input['max'])) {
+ $values[] = $input['max'];
+ }
+ }
+ }
+ elseif (!empty($input)) {
+ $values[] = $input;
+ }
+
+ foreach ($values as $value) {
+ try {
+ (new DrupalDateTime($value))->getTimestamp();
+ }
+ catch (\Exception $e) {
+ if (isset($form[$identifier])) {
+ $field = &$form[$identifier];
+ }
+ elseif (isset($form[$identifier . '_wrapper'])) {
+ $field = &$form[$identifier . '_wrapper'];
+ }
+ // Set the form error message.
+ $form_state->setError($field, $this->t('Invalid date format.'));
+ break;
+ }
+ }
+ }
+
/**
* Override parent method, which deals with dates as integers.
*/
diff --git a/src/Plugin/CKEditorPlugin/CodeSnippet.php b/src/Plugin/CKEditorPlugin/CodeSnippet.php
index 4cf9ab096ebdc001aaaeb918875e4af525cd001f..d5693bb409ecdec6aab495c88fc6fb799bbb0844 100644
--- a/src/Plugin/CKEditorPlugin/CodeSnippet.php
+++ b/src/Plugin/CKEditorPlugin/CodeSnippet.php
@@ -182,6 +182,7 @@ class CodeSnippet extends CKEditorPluginBase implements CKEditorPluginConfigurab
'vbscript' => 'VBScript',
'xhtml' => 'XHTML',
'xml' => 'XML',
+ 'yaml' => 'Yaml',
];
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment