diff --git a/CHANGELOG.md b/CHANGELOG.md index 05f300bc8..0d72ab358 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +* [633](https://github.com/itk-dev/deltag.aarhus.dk/pull/633) + Added handling of orphaned timeline note paragraphs. * [PR-630](https://github.com/itk-dev/deltag.aarhus.dk/pull/630) * Updated accessibility * Added back to dialogue buttons. diff --git a/config/sync/block.block.claro_breadcrumbs.yml b/config/sync/block.block.claro_breadcrumbs.yml index 1b16931a3..fc09dc0a6 100644 --- a/config/sync/block.block.claro_breadcrumbs.yml +++ b/config/sync/block.block.claro_breadcrumbs.yml @@ -16,7 +16,7 @@ provider: null plugin: system_breadcrumb_block settings: id: system_breadcrumb_block - label: Breadcrumbs + label: Brødkrummer label_display: '0' provider: system visibility: { } diff --git a/config/sync/block.block.claro_content.yml b/config/sync/block.block.claro_content.yml index 5a239f909..11c2f3c7a 100644 --- a/config/sync/block.block.claro_content.yml +++ b/config/sync/block.block.claro_content.yml @@ -16,7 +16,7 @@ provider: null plugin: system_main_block settings: id: system_main_block - label: 'Main page content' + label: 'Primært sideindhold' label_display: '0' provider: system visibility: { } diff --git a/config/sync/core.entity_form_display.node.dialogue.default.yml b/config/sync/core.entity_form_display.node.dialogue.default.yml index 5c6b84ddc..79cccf842 100644 --- a/config/sync/core.entity_form_display.node.dialogue.default.yml +++ b/config/sync/core.entity_form_display.node.dialogue.default.yml @@ -66,7 +66,7 @@ third_party_settings: children: - field_project_reference - field_hide_in_timeline - label: 'Projektreference' + label: Projektreference region: hidden parent_name: group_information weight: 32 diff --git a/config/sync/core.entity_view_mode.comment.full.yml b/config/sync/core.entity_view_mode.comment.full.yml index 8e5eb1426..941e736b9 100644 --- a/config/sync/core.entity_view_mode.comment.full.yml +++ b/config/sync/core.entity_view_mode.comment.full.yml @@ -7,7 +7,7 @@ dependencies: _core: default_config_hash: N4mUjXpPckUkVRY1PbKw4GGoL1i2ECU7PL3EreiKStk id: comment.full -label: 'Full comment' +label: 'Fuld kommentar' description: '' targetEntityType: comment cache: true diff --git a/config/sync/field.field.node.course.field_project_reference.yml b/config/sync/field.field.node.course.field_project_reference.yml index ddbcbb1e5..29c977f20 100644 --- a/config/sync/field.field.node.course.field_project_reference.yml +++ b/config/sync/field.field.node.course.field_project_reference.yml @@ -10,7 +10,7 @@ id: node.course.field_project_reference field_name: field_project_reference entity_type: node bundle: course -label: 'Projektreference' +label: Projektreference description: '' required: false translatable: false diff --git a/config/sync/locale.settings.yml b/config/sync/locale.settings.yml index 053b4e5ff..ed2eac386 100644 --- a/config/sync/locale.settings.yml +++ b/config/sync/locale.settings.yml @@ -1,6 +1,6 @@ langcode: da translation: - use_source: local + use_source: remote_and_local overwrite_customized: false overwrite_not_customized: true update_interval_days: 0 diff --git a/config/sync/publishcontent.settings.yml b/config/sync/publishcontent.settings.yml index 59cc5fedf..6317442d4 100644 --- a/config/sync/publishcontent.settings.yml +++ b/config/sync/publishcontent.settings.yml @@ -5,5 +5,5 @@ ui_localtask: false ui_checkbox: true create_revision: false create_log_entry: false -publish_text_value: Publish -unpublish_text_value: Unpublish +publish_text_value: Udgiv +unpublish_text_value: 'Træk tilbage' diff --git a/config/sync/system.action.comment_save_action.yml b/config/sync/system.action.comment_save_action.yml index f9f556493..af173431f 100644 --- a/config/sync/system.action.comment_save_action.yml +++ b/config/sync/system.action.comment_save_action.yml @@ -7,7 +7,7 @@ dependencies: _core: default_config_hash: lfyE_snmvfg_EQ3VDyhUtGAXgmqtEiqa46I3bTMg8DU id: comment_save_action -label: 'Save comment' +label: 'Gem kommentar' type: comment plugin: 'entity:save_action:comment' configuration: { } diff --git a/config/sync/system.action.webform_delete_action.yml b/config/sync/system.action.webform_delete_action.yml index d1716a1fc..d9378db3c 100644 --- a/config/sync/system.action.webform_delete_action.yml +++ b/config/sync/system.action.webform_delete_action.yml @@ -7,7 +7,7 @@ dependencies: _core: default_config_hash: e1bCTp0ryXZZtnS9nlVAbtoWz3-8fmbNlqKY3GHzbsM id: webform_delete_action -label: 'Delete webform' +label: 'Slet webform' type: webform plugin: webform_delete_action configuration: { } diff --git a/config/sync/views.view.comment.yml b/config/sync/views.view.comment.yml index 7551acf22..d23118891 100644 --- a/config/sync/views.view.comment.yml +++ b/config/sync/views.view.comment.yml @@ -10,7 +10,7 @@ _core: id: comment label: Kommentarer module: comment -description: 'Find and manage comments.' +description: 'Find og administrér kommentarer.' tag: default base_table: comment_field_data base_field: cid @@ -282,7 +282,7 @@ display: entity_type: comment entity_field: entity_id plugin_id: commented_entity - label: 'Posted in' + label: 'Indsendt til' exclude: false alter: alter_text: false @@ -578,7 +578,7 @@ display: admin_label: '' plugin_id: text_custom empty: true - content: 'No comments available.' + content: 'Der er ingen kommentarer at vise.' tokenize: false sorts: changed: @@ -695,7 +695,7 @@ display: exposed: true expose: operator_id: combine_op - label: 'Author name' + label: Forfatternavn description: '' use_operator: false operator: combine_op @@ -877,11 +877,11 @@ display: cacheable: false page_published: id: page_published - display_title: 'Published comments' + display_title: 'Udgivne kommentarer' display_plugin: page position: 1 display_options: - display_description: 'The approved comments listing.' + display_description: 'Liste over godkendte kommentarer.' display_comment: '' exposed_block: false display_extenders: { } @@ -889,7 +889,7 @@ display: menu: type: tab title: Kommentarer - description: 'Comments published' + description: 'Publicerede kommentarer' weight: 0 menu_name: admin parent: '' @@ -906,7 +906,7 @@ display: cacheable: false page_unapproved: id: page_unapproved - display_title: 'Unapproved comments' + display_title: 'Ikke-godkendte kommentarer' display_plugin: page position: 2 display_options: @@ -1170,7 +1170,7 @@ display: entity_type: comment entity_field: entity_id plugin_id: commented_entity - label: 'Posted in' + label: 'Indsendt til' exclude: false alter: alter_text: false @@ -1514,7 +1514,7 @@ display: exposed: true expose: operator_id: combine_op - label: 'Author Name' + label: Forfatternavn description: '' use_operator: false operator: combine_op @@ -1594,13 +1594,13 @@ display: fields: false filters: false filter_groups: false - display_description: 'The unapproved comments listing.' + display_description: 'Listen af ikke-godkendte kommentarer.' display_extenders: { } path: admin/content/comment/approval menu: type: tab - title: 'Unapproved comments' - description: 'Comments unapproved' + title: 'Ikke-godkendte kommentarer' + description: 'Ikke-godkendte kommentarer' weight: 1 menu_name: admin parent: '' diff --git a/config/sync/views.view.comments_recent.yml b/config/sync/views.view.comments_recent.yml index a9cc4f270..34f43aeeb 100644 --- a/config/sync/views.view.comments_recent.yml +++ b/config/sync/views.view.comments_recent.yml @@ -9,9 +9,9 @@ dependencies: _core: default_config_hash: cFOucxH8PAXDQ2kViCcAHgK-JMCcxVkpIMzD56EfpZo id: comments_recent -label: 'Recent comments' +label: 'Seneste kommentarer' module: views -description: 'Recent comments.' +description: 'Seneste kommentarer.' tag: default base_table: comment_field_data base_field: cid @@ -22,7 +22,7 @@ display: display_plugin: default position: 0 display_options: - title: 'Recent comments' + title: 'Seneste kommentarer' fields: subject: id: subject @@ -131,8 +131,8 @@ display: hide_alter_empty: true type: timestamp_ago settings: - future_format: '@interval hence' - past_format: '@interval ago' + future_format: 'om @interval' + past_format: '@interval siden' granularity: 2 pager: type: some @@ -257,8 +257,8 @@ display: position: 1 display_options: display_extenders: { } - block_description: 'Recent comments' - block_category: 'Lists (Views)' + block_description: 'Seneste kommentarer' + block_category: 'Lister (Views)' allow: items_per_page: true cache_metadata: diff --git a/config/sync/views.view.webform_submissions.yml b/config/sync/views.view.webform_submissions.yml index e5f40cca3..0d58c39b9 100644 --- a/config/sync/views.view.webform_submissions.yml +++ b/config/sync/views.view.webform_submissions.yml @@ -11,7 +11,7 @@ dependencies: _core: default_config_hash: YPgxGC8TmLtfCOLGCCHJcdH2llA7QksUkdi1abhB7Ro id: webform_submissions -label: 'Webform submissions' +label: 'Indsendte webforms' module: views description: 'Default webform submissions views.' tag: '' @@ -24,7 +24,7 @@ display: display_plugin: default position: 0 display_options: - title: 'Webform submissions' + title: 'Indsendte webforms' fields: sid: id: sid @@ -102,7 +102,7 @@ display: entity_type: webform_submission entity_field: in_draft plugin_id: field - label: Draft + label: Kladde exclude: false alter: alter_text: false @@ -245,7 +245,7 @@ display: entity_type: webform_submission entity_field: remote_addr plugin_id: field - label: 'IP address' + label: IP-adresse exclude: false alter: alter_text: false @@ -350,7 +350,7 @@ display: hide_empty: false empty_zero: false hide_alter_empty: true - text: view + text: vis output_url_as_text: false absolute: false pager: @@ -592,7 +592,7 @@ display: admin_label: '' plugin_id: result empty: false - content: 'Displaying @start - @end of @total' + content: 'Viser @start - @end af @total' footer: { } display_extenders: { } cache_metadata: @@ -740,7 +740,7 @@ display: entity_type: webform_submission entity_field: in_draft plugin_id: field - label: Draft + label: Kladde exclude: false alter: alter_text: false @@ -807,7 +807,7 @@ display: entity_type: webform_submission entity_field: sticky plugin_id: field - label: Sticky + label: Klæbrig exclude: false alter: alter_text: false @@ -874,7 +874,7 @@ display: entity_type: webform_submission entity_field: locked plugin_id: field - label: Locked + label: Låst exclude: false alter: alter_text: false @@ -1017,7 +1017,7 @@ display: entity_type: webform_submission entity_field: completed plugin_id: field - label: Completed + label: Gennemført exclude: false alter: alter_text: false @@ -1093,7 +1093,7 @@ display: entity_type: webform_submission entity_field: remote_addr plugin_id: field - label: 'IP address' + label: IP-adresse exclude: false alter: alter_text: false @@ -1263,7 +1263,7 @@ display: exposed: true expose: operator_id: '' - label: Sticky + label: Klæbrig description: '' use_operator: false operator: sticky_op @@ -1305,7 +1305,7 @@ display: exposed: true expose: operator_id: '' - label: Locked + label: Låst description: '' use_operator: false operator: locked_op @@ -1680,7 +1680,7 @@ display: entity_type: webform_submission entity_field: in_draft plugin_id: field - label: Draft + label: Kladde exclude: false alter: alter_text: false @@ -1747,7 +1747,7 @@ display: entity_type: webform_submission entity_field: sticky plugin_id: field - label: Sticky + label: Klæbrig exclude: false alter: alter_text: false @@ -1814,7 +1814,7 @@ display: entity_type: webform_submission entity_field: locked plugin_id: field - label: Locked + label: Låst exclude: false alter: alter_text: false @@ -1957,7 +1957,7 @@ display: entity_type: webform_submission entity_field: completed plugin_id: field - label: Completed + label: Gennemført exclude: false alter: alter_text: false @@ -2033,7 +2033,7 @@ display: entity_type: webform_submission entity_field: remote_addr plugin_id: field - label: 'IP address' + label: IP-adresse exclude: false alter: alter_text: false @@ -2138,7 +2138,7 @@ display: hide_empty: false empty_zero: false hide_alter_empty: true - text: view + text: vis output_url_as_text: false absolute: false edit_webform_submission: @@ -2191,7 +2191,7 @@ display: hide_empty: false empty_zero: false hide_alter_empty: true - text: edit + text: redigér output_url_as_text: false absolute: false access: @@ -2257,7 +2257,7 @@ display: exposed: true expose: operator_id: '' - label: Sticky + label: Klæbrig description: '' use_operator: false operator: sticky_op @@ -2299,7 +2299,7 @@ display: exposed: true expose: operator_id: '' - label: Locked + label: Låst description: '' use_operator: false operator: locked_op @@ -2532,7 +2532,7 @@ display: entity_type: webform_submission entity_field: in_draft plugin_id: field - label: Draft + label: Kladde exclude: false alter: alter_text: false @@ -2599,7 +2599,7 @@ display: entity_type: webform_submission entity_field: sticky plugin_id: field - label: Sticky + label: Klæbrig exclude: false alter: alter_text: false @@ -2666,7 +2666,7 @@ display: entity_type: webform_submission entity_field: locked plugin_id: field - label: Locked + label: Låst exclude: false alter: alter_text: false @@ -2809,7 +2809,7 @@ display: entity_type: webform_submission entity_field: completed plugin_id: field - label: Completed + label: Gennemført exclude: false alter: alter_text: false @@ -2885,7 +2885,7 @@ display: entity_type: webform_submission entity_field: remote_addr plugin_id: field - label: 'IP address' + label: IP-adresse exclude: false alter: alter_text: false @@ -2990,7 +2990,7 @@ display: hide_empty: false empty_zero: false hide_alter_empty: true - text: view + text: vis output_url_as_text: false absolute: false access: @@ -3056,7 +3056,7 @@ display: exposed: true expose: operator_id: '' - label: Sticky + label: Klæbrig description: '' use_operator: false operator: sticky_op @@ -3098,7 +3098,7 @@ display: exposed: true expose: operator_id: '' - label: Locked + label: Låst description: '' use_operator: false operator: locked_op diff --git a/config/sync/webform.settings.yml b/config/sync/webform.settings.yml index d3281e7c0..0e037e1b7 100644 --- a/config/sync/webform.settings.yml +++ b/config/sync/webform.settings.yml @@ -10,7 +10,7 @@ settings: default_ajax_progress_type: throbber default_ajax_effect: fade default_ajax_speed: 500 - default_submit_button_label: Submit + default_submit_button_label: Indsend default_reset_button_label: Reset default_delete_button_label: Slet default_form_submit_once: false @@ -30,19 +30,19 @@ settings: default_form_details_toggle: true default_form_file_limit: '' default_form_file_limit_message: "This form's file upload quota of %quota has been exceeded. Please remove some files." - default_wizard_prev_button_label: '< Previous' - default_wizard_next_button_label: 'Next >' + default_wizard_prev_button_label: '< Tidligere' + default_wizard_next_button_label: 'Næste >' default_wizard_start_label: Start - default_wizard_confirmation_label: Complete - default_wizard_toggle_show_label: 'Show all' - default_wizard_toggle_hide_label: 'Hide all' + default_wizard_confirmation_label: Komplet + default_wizard_toggle_show_label: 'Vis alle' + default_wizard_toggle_hide_label: 'Skjul alle' default_preview_next_button_label: Gennemse - default_preview_prev_button_label: '< Previous' + default_preview_prev_button_label: '< Tidligere' default_preview_label: Gennemse default_preview_title: '[webform:title]: Preview' default_preview_message: 'Please review your submission. Your submission is not complete until you press the "Submit" button!' - default_draft_button_label: 'Save Draft' - default_draft_saved_message: 'Submission saved. You may return to this form later and it will restore the current values.' + default_draft_button_label: 'Gem kladde' + default_draft_saved_message: 'Formular gemt. Du kan vende tilbage senere og gendanne standardværdierne.' default_draft_loaded_message: 'A partially-completed form was found. Please complete the remaining portions.' default_draft_pending_single_message: 'You have a pending draft for this webform. Load your pending draft.' default_draft_pending_multiple_message: 'You have pending drafts for this webform. View your pending drafts.' @@ -70,8 +70,8 @@ settings: default_submission_access_denied_message: 'Please login to access this submission.' default_submission_exception_message: 'Unable to process this submission. Please contact the site administrator.' default_submission_locked_message: 'This submission has been locked.' - default_previous_submission_message: 'You have already submitted this webform. View your previous submission.' - default_previous_submissions_message: 'You have already submitted this webform. View your previous submissions.' + default_previous_submission_message: 'Du har allerede indsendt denne formular. Se din forrige indsendelse.' + default_previous_submissions_message: 'Du har allerede indsendt denne formular. Se dine forrige indsendelser.' default_autofill_message: 'This submission has been autofilled with your previous submission.' form_classes: | container-inline clearfix @@ -110,13 +110,13 @@ settings: dialog: false dialog_options: narrow: - title: Narrow + title: Smal width: 600 normal: title: Normal width: 800 wide: - title: Wide + title: Bred width: 1000 assets: css: '' diff --git a/config/sync/webform.webform_options.days.yml b/config/sync/webform.webform_options.days.yml index aff01af0a..2ae2c2d2a 100644 --- a/config/sync/webform.webform_options.days.yml +++ b/config/sync/webform.webform_options.days.yml @@ -8,8 +8,8 @@ dependencies: _core: default_config_hash: YNrKbYrWWjeubUUM8AsQ19KnX7cU1elACR14CZJHmdg id: days -label: Days -category: 'Date and time' +label: Dage +category: 'Dato og tid' likert: false options: | Sunday: Sunday diff --git a/config/sync/webform.webform_options.education.yml b/config/sync/webform.webform_options.education.yml index 138ed1a0f..53694f5b6 100644 --- a/config/sync/webform.webform_options.education.yml +++ b/config/sync/webform.webform_options.education.yml @@ -9,7 +9,7 @@ _core: default_config_hash: mII4acOv33s-j8PINywrCag4OITbeJGxdPO373dnHHw id: education label: Education -category: Demographic +category: Demografi likert: false options: | High School: High School diff --git a/config/sync/webform.webform_options.gender.yml b/config/sync/webform.webform_options.gender.yml index eddeaeada..8a4980512 100644 --- a/config/sync/webform.webform_options.gender.yml +++ b/config/sync/webform.webform_options.gender.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: yxhG0JmQs2HT-Ro6ZeDQboDc9ZWR4GglflTtyoqxK4A id: gender -label: Gender +label: Køn category: Demographic likert: false options: | diff --git a/config/sync/webform.webform_options.languages.yml b/config/sync/webform.webform_options.languages.yml index 67786ac6e..6de0a2210 100644 --- a/config/sync/webform.webform_options.languages.yml +++ b/config/sync/webform.webform_options.languages.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: mYH14Vi65Ixj10c_GFa7CipxU3D0Bt9wgo8zE8zjOfE id: languages -label: Languages +label: Sprog category: Language likert: false options: '' diff --git a/config/sync/webform.webform_options.months.yml b/config/sync/webform.webform_options.months.yml index 54e1a01ba..0fec4dcbe 100644 --- a/config/sync/webform.webform_options.months.yml +++ b/config/sync/webform.webform_options.months.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: pZJnuQkh9afNML5IcMuKTUC__vmHMFn66Qr5IWtedZ4 id: months -label: Months +label: Måneder category: 'Date and time' likert: false options: | diff --git a/config/sync/webform.webform_options.relationship.yml b/config/sync/webform.webform_options.relationship.yml index 9462a8a32..2474ca46c 100644 --- a/config/sync/webform.webform_options.relationship.yml +++ b/config/sync/webform.webform_options.relationship.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: 4J2RPG4JmsD4Fm1NlIQY0JHkrJ08UUl0qTF0_EjUxvw id: relationship -label: Relationship +label: Forbindelse category: Demographic likert: false options: | diff --git a/config/sync/webform.webform_options.sex.yml b/config/sync/webform.webform_options.sex.yml index a59ebe845..214640c72 100644 --- a/config/sync/webform.webform_options.sex.yml +++ b/config/sync/webform.webform_options.sex.yml @@ -8,9 +8,7 @@ dependencies: _core: default_config_hash: WRpxpwYpfcO_i0so7BV4QXxXlbPiSVppYmAV6DAz4c0 id: sex -label: Sex +label: Køn category: Demographic likert: false -options: | - Male: Male - Female: Female +options: "Mand: Mand\r\nKvinde: Kvinde\n" diff --git a/config/sync/webform.webform_options.time_zones.yml b/config/sync/webform.webform_options.time_zones.yml index ed8929a42..f1a0ac615 100644 --- a/config/sync/webform.webform_options.time_zones.yml +++ b/config/sync/webform.webform_options.time_zones.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: 8rVcRXLnTAEoWs7zl8du-7RIUnayqUcGYnvb3JT21-o id: time_zones -label: 'Time zones' +label: Tidszoner category: 'Date and time' likert: false options: '' diff --git a/config/sync/webform.webform_options.titles.yml b/config/sync/webform.webform_options.titles.yml index c51bc8bb6..d789bba4b 100644 --- a/config/sync/webform.webform_options.titles.yml +++ b/config/sync/webform.webform_options.titles.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: PEUoedWrfYEX7oZ8CcOukfBTVxar1cPSROX8534esuU id: titles -label: Titles +label: Titler category: Demographic likert: false options: | diff --git a/config/sync/webform.webform_options.translations.yml b/config/sync/webform.webform_options.translations.yml index 9cc071494..b45500bfd 100644 --- a/config/sync/webform.webform_options.translations.yml +++ b/config/sync/webform.webform_options.translations.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: Mb_L3vE-0IBZH5s2rjpk2LNn0QHClQP9AARQdCmVLt4 id: translations -label: Translations +label: Oversættelser category: Language likert: false options: '' diff --git a/config/sync/webform.webform_options.yes_no.yml b/config/sync/webform.webform_options.yes_no.yml index 5bbb5fb6b..810cb0ad0 100644 --- a/config/sync/webform.webform_options.yes_no.yml +++ b/config/sync/webform.webform_options.yes_no.yml @@ -8,7 +8,7 @@ dependencies: _core: default_config_hash: W88NYg31DbaVNQx1Uir_dwwXHVtF09QOq4VBGsH1Snk id: yes_no -label: Yes/No +label: Ja/nej category: General likert: false options: | diff --git a/web/modules/custom/hoeringsportal_project/hoeringsportal_project.install b/web/modules/custom/hoeringsportal_project/hoeringsportal_project.install new file mode 100644 index 000000000..5eec30ed1 --- /dev/null +++ b/web/modules/custom/hoeringsportal_project/hoeringsportal_project.install @@ -0,0 +1,61 @@ +getStorage('paragraph'); + $nodeStorage = \Drupal::entityTypeManager()->getStorage('node'); + + // Get all timeline_note paragraphs. + $query = $paragraphStorage->getQuery(); + $query->accessCheck(FALSE); + $query->condition('type', 'timeline_note'); + $paragraphIds = $query->execute(); + + if (empty($paragraphIds)) { + return t('No timeline_note paragraphs found.'); + } + + // Get all nodes with field_timeline. + $nodeQuery = $nodeStorage->getQuery(); + $nodeQuery->accessCheck(FALSE); + $nodeQuery->exists('field_timeline'); + $nodeIds = $nodeQuery->execute(); + + // Collect all referenced paragraph IDs. + $referencedParagraphIds = []; + if (!empty($nodeIds)) { + $nodes = $nodeStorage->loadMultiple($nodeIds); + foreach ($nodes as $node) { + if ($node->hasField('field_timeline') && !$node->get('field_timeline')->isEmpty()) { + foreach ($node->get('field_timeline') as $item) { + if ($item->target_id) { + $referencedParagraphIds[] = $item->target_id; + } + } + } + } + } + + // Find orphaned paragraphs. + $orphanedParagraphIds = array_diff($paragraphIds, $referencedParagraphIds); + + if (empty($orphanedParagraphIds)) { + return t('No orphaned timeline_note paragraphs found.'); + } + + // Delete orphaned paragraphs. + $paragraphs = $paragraphStorage->loadMultiple($orphanedParagraphIds); + foreach ($paragraphs as $paragraph) { + $paragraph->delete(); + } + + $count = count($orphanedParagraphIds); + return t('Deleted @count orphaned timeline_note paragraph(s).', ['@count' => $count]); +} diff --git a/web/modules/custom/hoeringsportal_project/src/Helper/ProjectHelper.php b/web/modules/custom/hoeringsportal_project/src/Helper/ProjectHelper.php index eecea112e..5ef4d8559 100644 --- a/web/modules/custom/hoeringsportal_project/src/Helper/ProjectHelper.php +++ b/web/modules/custom/hoeringsportal_project/src/Helper/ProjectHelper.php @@ -2,6 +2,7 @@ namespace Drupal\hoeringsportal_project\Helper; +use Drupal\Core\Cache\Cache; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -113,44 +114,112 @@ public function projectFormAlter(array &$form, FormStateInterface $form_state): #[Hook('entity_presave')] public function entityPresave(EntityInterface $entity): void { if ($entity instanceof NodeInterface) { + // When changing references, we must clear cache for nodes that was + // previously referenced as well as new referenced nodes. try { - if (!$entity->hasField('field_project_reference')) { - return; + if ($entity->hasField('field_project_reference')) { + $newTargetId = (int) ($entity->get('field_project_reference')->target_id ?? 0); + + $originalEntity = $entity->original ?? NULL; + $originalTargetId = 0; + if ($originalEntity?->hasField('field_project_reference')) { + $originalTargetId = (int) ($originalEntity->get('field_project_reference')->target_id ?? 0); + } + + // Only act if the reference actually changed. + if ($originalTargetId === $newTargetId) { + return; + } + + $idsToReset = []; + if ($originalTargetId > 0) { + $idsToReset[] = $originalTargetId; + } + if ($newTargetId > 0) { + $idsToReset[] = $newTargetId; + } + + if ($idsToReset === []) { + return; + } + + // Clear cache for project nodes when we change an entity pointing to + // it. + $idsToReset = array_values(array_unique($idsToReset)); + $nodes = $this->entityTypeManagerInterface->getStorage('node')->load($idsToReset); + foreach ($nodes as $node) { + Cache::invalidateTags($node->getCacheTags()); + } } + } + catch (\Exception $e) { + $this->logger->error('Error in node presave hook: @message', ['@message' => $e->getMessage()]); + } - $newTargetId = (int) ($entity->get('field_project_reference')->target_id ?? 0); + // Delete orphaned paragraphs when references are removed. + $this->deleteOrphanedParagraphs($entity); + } + } - $originalEntity = $entity->original ?? NULL; - $oldTargetId = 0; - if ($originalEntity?->hasField('field_project_reference')) { - $oldTargetId = (int) ($originalEntity->get('field_project_reference')->target_id ?? 0); - } + /** + * Delete orphaned paragraphs when they are removed from entity references. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity being saved. + */ + private function deleteOrphanedParagraphs(EntityInterface $entity): void { + if (!$entity instanceof NodeInterface) { + return; + } - // Only act if the reference actually changed. - if ($oldTargetId === $newTargetId) { - return; - } + $originalEntity = $entity->original ?? NULL; + if (!$originalEntity) { + return; + } - $idsToReset = []; - if ($oldTargetId > 0) { - $idsToReset[] = $oldTargetId; - } - if ($newTargetId > 0) { - $idsToReset[] = $newTargetId; + try { + // Get current paragraph IDs. + $currentParagraphIds = []; + if (!$entity->get('field_timeline')->isEmpty()) { + foreach ($entity->get('field_timeline') as $item) { + if ($item->target_id) { + $currentParagraphIds[] = $item->target_id; + } } + } - if ($idsToReset === []) { - return; + // Get original paragraph IDs. + $originalParagraphIds = []; + if (!$originalEntity->get('field_timeline')->isEmpty()) { + foreach ($originalEntity->get('field_timeline') as $item) { + if ($item->target_id) { + $originalParagraphIds[] = $item->target_id; + } } + } + + // Find removed paragraph IDs. + $removedParagraphIds = array_diff($originalParagraphIds, $currentParagraphIds); - $idsToReset = array_values(array_unique($idsToReset)); - $this->entityTypeManagerInterface->getStorage('node') - ->resetCache($idsToReset); + if (empty($removedParagraphIds)) { + return; } - catch (\Exception $e) { - $this->logger->error('Error in node presave hook: @message', ['@message' => $e->getMessage()]); + + // Delete the orphaned paragraphs. + $paragraphStorage = $this->entityTypeManagerInterface->getStorage('paragraph'); + $paragraphs = $paragraphStorage->loadMultiple($removedParagraphIds); + + foreach ($paragraphs as $paragraph) { + $paragraph->delete(); + $this->logger->info('Deleted orphaned paragraph @id of type @type', [ + '@id' => $paragraph->id(), + '@type' => $paragraph->bundle(), + ]); } } + catch (\Exception $e) { + $this->logger->error('Error deleting orphaned paragraphs: @message', ['@message' => $e->getMessage()]); + } } /** diff --git a/web/modules/custom/hoeringsportal_project/translations/hoeringsportal_project.da.po b/web/modules/custom/hoeringsportal_project/translations/hoeringsportal_project.da.po index ca885df38..20defacd3 100644 --- a/web/modules/custom/hoeringsportal_project/translations/hoeringsportal_project.da.po +++ b/web/modules/custom/hoeringsportal_project/translations/hoeringsportal_project.da.po @@ -3,8 +3,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2026-01-28 10:13+0100\n" -"PO-Revision-Date: 2026-01-28 10:13+0100\n" +"POT-Creation-Date: 2026-03-03 13:18+0100\n" +"PO-Revision-Date: 2026-03-03 13:18+0100\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" @@ -13,12 +13,21 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "Language: da\n" +msgid "Deleted @count orphaned timeline_note paragraph(s)." +msgstr "Slettede @count løse tidslinjenoteparagraf(fer)" + msgid "Finished" msgstr "Afsluttet" msgid "In progress" msgstr "I gang" +msgid "No orphaned timeline_note paragraphs found." +msgstr "Ingen løse tidslinjenoter fundet" + +msgid "No timeline_note paragraphs found." +msgstr "Ingen tidslinjenote fundet" + msgid "Note" msgstr "Note"