diff --git a/.DS_Store b/.DS_Store index 711a192aa..7be137e74 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/composer.json b/composer.json index 75d430f8a..990c0a414 100644 --- a/composer.json +++ b/composer.json @@ -120,7 +120,9 @@ "codemirror/codemirror": "5.65.12", "jquery/inputmask": "5.0.8", "jquery/intl-tel-input": "17.0.19", - "progress-tracker/progress-tracker": "2.0.7" + "progress-tracker/progress-tracker": "2.0.7", + "drupal/shield": "^1.8", + "drupal/media_alias_display": "^2.1" }, "repositories": { "drupal": { diff --git a/modules/tide_landing_page/config/install/core.entity_form_display.node.landing_page.default.yml b/modules/tide_landing_page/config/install/core.entity_form_display.node.landing_page.default.yml index 257d59f0c..a088b7375 100644 --- a/modules/tide_landing_page/config/install/core.entity_form_display.node.landing_page.default.yml +++ b/modules/tide_landing_page/config/install/core.entity_form_display.node.landing_page.default.yml @@ -223,8 +223,8 @@ third_party_settings: label: 'Customised Header' parent_name: group_section_header children: - - field_landing_page_hero_image - field_landing_page_hero_theme + - field_landing_page_hero_image - field_landing_page_hero_logo - field_graphical_image - field_bottom_graphical_image diff --git a/modules/tide_landing_page/config/install/field.field.node.landing_page.field_landing_page_hero_theme.yml b/modules/tide_landing_page/config/install/field.field.node.landing_page.field_landing_page_hero_theme.yml index 087e8ca17..e79189c12 100644 --- a/modules/tide_landing_page/config/install/field.field.node.landing_page.field_landing_page_hero_theme.yml +++ b/modules/tide_landing_page/config/install/field.field.node.landing_page.field_landing_page_hero_theme.yml @@ -10,11 +10,13 @@ id: node.landing_page.field_landing_page_hero_theme field_name: field_landing_page_hero_theme entity_type: node bundle: landing_page -label: Here image theme -description: 'If your hero image is mostly dark, apply the dark theme. This changes how the page title is displayed.' -required: false +label: Page title display style +description: 'By default the page title will display in the site’s primary colour. If you choose ‘Reverse blocked text’ the heading and introduction text will be white with a coloured block behind the text (the site’s ‘accent contrast’ and ‘accent alternate’ colours). See Ripple header page to understand the header component design.' +required: true translatable: false -default_value: { } +default_value: + - + value: light default_value_callback: '' settings: { } field_type: list_string diff --git a/modules/tide_landing_page/config/install/field.storage.node.field_landing_page_hero_theme.yml b/modules/tide_landing_page/config/install/field.storage.node.field_landing_page_hero_theme.yml index dca3701b4..4a0101329 100644 --- a/modules/tide_landing_page/config/install/field.storage.node.field_landing_page_hero_theme.yml +++ b/modules/tide_landing_page/config/install/field.storage.node.field_landing_page_hero_theme.yml @@ -12,10 +12,10 @@ settings: allowed_values: - value: dark - label: Dark + label: Reverse blocked text - value: light - label: Light + label: Default allowed_values_function: '' module: options locked: false diff --git a/modules/tide_landing_page/tests/behat/features/fields.feature b/modules/tide_landing_page/tests/behat/features/fields.feature index 53568ea26..0f8881237 100644 --- a/modules/tide_landing_page/tests/behat/features/fields.feature +++ b/modules/tide_landing_page/tests/behat/features/fields.feature @@ -35,6 +35,8 @@ Feature: Fields for Landing Page content type And the "#edit-field-bottom-graphical-image" element should contain "Bottom Corner Graphic" And I should see an "input#edit-field-bottom-graphical-image-entity-browser-target" element + And I should see a "select#edit-field-landing-page-hero-theme" element + And I click on the horizontal tab "Header extras" And I should see text matching "Header components" And I press the "edit-field-landing-page-header-add-more-add-modal-form-area-add-more" button @@ -164,6 +166,8 @@ Feature: Fields for Landing Page content type And the "#edit-field-bottom-graphical-image" element should contain "Bottom Corner Graphic" And I should see an "input#edit-field-bottom-graphical-image-entity-browser-target" element + And I should see a "select#edit-field-landing-page-hero-theme" element + And I click on the horizontal tab "Header extras" And I should see text matching "Header components" And I press the "edit-field-landing-page-header-add-more-add-modal-form-area-add-more" button @@ -300,3 +304,48 @@ Feature: Fields for Landing Page content type # This field can be "seen" but not visible. And I see field "field_landing_page_component[0][subform][field_customise][value]" And save screenshot + + +@api @javascript + Scenario: Selecting Corner graphics value from header style. + Given I am logged in as a user with the "editor" role + When I visit "node/add/landing_page" + And I click on the horizontal tab "Customised Header" + Then I should see an "#edit-header-style-options-corner" element + And I select "corner" from "edit-header-style-options-corner" + Then I should see an "#edit-field-landing-page-hero-theme" element + And I should see text matching "Default" + And save screenshot + + @api @javascript + Scenario: Selecting Default appearance value from header style. + Given I am logged in as a user with the "editor" role + When I visit "node/add/landing_page" + And I click on the horizontal tab "Customised Header" + Then I should see an "#edit-header-style-options-default" element + And I select "corner" from "edit-header-style-options-default" + Then I should see an "#edit-field-landing-page-hero-theme" element + And I should see text matching "Default" + And save screenshot + +@api @javascript + Scenario: Selecting Full-width background image value from header style. + Given I am logged in as a user with the "editor" role + When I visit "node/add/landing_page" + And I click on the horizontal tab "Customised Header" + Then I should see an "#edit-header-style-options-fullwidtht" element + And I select "corner" from "edit-header-style-options-fullwidth" + Then I should see an "#edit-field-landing-page-hero-theme" element + And I should see text matching "Reverse blocked text" + And save screenshot + +@api @javascript + Scenario: Selecting Call to action banner value from header style. + Given I am logged in as a user with the "editor" role + When I visit "node/add/landing_page" + And I click on the horizontal tab "Customised Header" + Then I should see an "#edit-header-style-options-cta" element + And I select "corner" from "edit-header-style-options-cta" + Then I should see an "#edit-field-landing-page-hero-theme" element + And I should see text matching "Default" + And save screenshot diff --git a/modules/tide_landing_page/tide_landing_page.install b/modules/tide_landing_page/tide_landing_page.install index de73d8b3d..eda33cafa 100644 --- a/modules/tide_landing_page/tide_landing_page.install +++ b/modules/tide_landing_page/tide_landing_page.install @@ -203,3 +203,43 @@ function tide_landing_page_update_10107() { $tide_update_helper = \Drupal::service('tide_core.entity_update_helper'); $tide_update_helper->revert('field_config', 'paragraph.key_journeys.field_paragraph_title'); } + +/** + * Set field `field_landing_page_hero_theme` to mandatory, description, label. + */ +function tide_landing_page_update_10108() { + $bundles = [ + 'landing_page', + 'publication', + 'publication_page', + ]; + + foreach ($bundles as $bundle) { + $field = FieldConfig::loadByName('node', $bundle, 'field_landing_page_hero_theme'); + if (!empty($field)) { + $field->setLabel('Page title display style'); + $field->setRequired(TRUE); + $field->setDefaultValue('light'); + $field->setDescription('By default the page title will display in the site’s primary colour. If you choose ‘Reverse blocked text’ the heading and introduction text will be white with a coloured block behind the text (the site’s ‘accent contrast’ and ‘accent alternate’ colours). See Ripple header page to understand the header component design.'); + $field->save(); + } + } +} + +/** + * Set label options for `field_landing_page_hero_theme`. + */ +function tide_landing_page_update_10109() { + $config = \Drupal::configFactory()->getEditable('field.storage.node.field_landing_page_hero_theme'); + $allowed_values = $config->get('settings.allowed_values'); + foreach ($allowed_values as $key => $allowed_value) { + if ($allowed_value['label'] === 'Dark') { + $allowed_values[$key]['label'] = 'Reverse blocked text'; + } + elseif ($allowed_value['label'] === 'Light') { + $allowed_values[$key]['label'] = 'Default'; + } + } + $config->set('settings.allowed_values', $allowed_values); + $config->save(); +} diff --git a/modules/tide_landing_page/tide_landing_page.module b/modules/tide_landing_page/tide_landing_page.module index fe1d0196b..2d59732ae 100644 --- a/modules/tide_landing_page/tide_landing_page.module +++ b/modules/tide_landing_page/tide_landing_page.module @@ -5,6 +5,8 @@ * Tide Landing Page module functionality. */ +use Drupal\Core\Ajax\AjaxResponse; +use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Cache\Cache; use Drupal\Core\Field\WidgetBase; use Drupal\Core\Form\FormStateInterface; @@ -117,11 +119,6 @@ function tide_landing_page_form_node_form_alter(&$form, FormStateInterface $form $form['field_landing_page_hero_image']['widget']['field_show_hero_image_caption'] = $form['field_show_hero_image_caption']; unset($form['field_show_hero_image_caption']); } - // Move Hero Image theme to Hero Image field group. - if (isset($form['field_landing_page_hero_theme']) && isset($form['field_landing_page_hero_image']['widget'])) { - $form['field_landing_page_hero_image']['widget']['field_landing_page_hero_theme'] = $form['field_landing_page_hero_theme']; - unset($form['field_landing_page_hero_theme']); - } // @todo the below block needs to be in a proper widget alter. if (isset($form['field_landing_page_component']['widget'][0])) { @@ -371,6 +368,34 @@ function tide_landing_page_field_widget_single_element_paragraphs_form_alter(&$e } } +/** + * Function to set value to Hero image theme. + * + * @param array $form + * The form. + * @param Drupal\Core\Form\FormStateInterface $form_state + * The form state. + * + * @return Drupal\Core\Ajax\AjaxResponse + * The response. + */ +function tide_landing_page_set_value_hero_image_theme(array $form, FormStateInterface $form_state): AjaxResponse { + $response = new AjaxResponse(); + $value = $form_state->getValue('_header_style_options'); + if ($value === 'fullwidth') { + return $response->addCommand(new InvokeCommand( + '#edit-field-landing-page-hero-theme', + 'val', + ['dark'] + )); + } + return $response->addCommand(new InvokeCommand( + '#edit-field-landing-page-hero-theme', + 'val', + ['light'] + )); +} + /** * Node form #process callback. * @@ -405,6 +430,16 @@ function _tide_landing_page_form_node_form_process(array $form, FormStateInterfa 'corner' => t('Corner graphics'), 'cta' => t('Call to action banner'), ], + '#ajax' => [ + 'callback' => 'tide_landing_page_set_value_hero_image_theme', + ], + ]; + + $form['field_landing_page_hero_theme']['#states']['disabled'] = [ + ':input[name="_header_style_options"]' => [ + ['value' => 'fullwidth'], + ['value' => 'cta'], + ], ]; $form['field_landing_page_hero_image']['#states']['visible'] = [ @@ -413,6 +448,7 @@ function _tide_landing_page_form_node_form_process(array $form, FormStateInterfa ['value' => 'cta'], ], ]; + $form['field_graphical_image']['#states']['visible'] = [ ':input[name="_header_style_options"]' => ['value' => 'corner'], ]; diff --git a/modules/tide_media/modules/tide_media_secure_files/tide_media_secure_files.install b/modules/tide_media/modules/tide_media_secure_files/tide_media_secure_files.install index ccf9536a8..9f807f47e 100644 --- a/modules/tide_media/modules/tide_media_secure_files/tide_media_secure_files.install +++ b/modules/tide_media/modules/tide_media_secure_files/tide_media_secure_files.install @@ -52,6 +52,38 @@ function tide_media_secure_files_uninstall() { \Drupal::service('module_installer')->uninstall(['pfdp']); } +/** + * Adds a secure file widget to entity browser. + */ +function _create_secure_file_widget() { + if (\Drupal::moduleHandler()->moduleExists('entity_browser')) { + $uuid = \Drupal::service('uuid')->generate(); + $secure_file_widget = [ + 'id' => 'entity_form', + 'uuid' => $uuid, + 'label' => 'Add secure file', + 'weight' => 6, + 'settings' => [ + 'submit_text' => 'Save secure file', + 'entity_type' => 'media', + 'bundle' => 'secure_file', + 'form_mode' => 'default', + ], + ]; + + $config = \Drupal::configFactory()->getEditable('entity_browser.browser.tide_media_browser_iframe'); + $widgets = $config->get('widgets'); + if (!is_array($widgets)) { + $widgets = []; + } + if (!in_array($secure_file_widget, $widgets)) { + $widgets[$uuid] = $secure_file_widget; + $config->set('widgets', $widgets); + $config->save(); + } + } +} + /** * Implements hook_install(). */ @@ -71,4 +103,13 @@ function tide_media_secure_files_install() { user_role_grant_permissions($role->id(), ['view field_secure_file']); } } + + _create_secure_file_widget(); +} + +/** + * Adds secure file widget to entity browser. + */ +function tide_media_secure_files_update_10001() { + _create_secure_file_widget(); } diff --git a/modules/tide_media/tide_media.install b/modules/tide_media/tide_media.install index dc5a250da..a1ea1f3cb 100644 --- a/modules/tide_media/tide_media.install +++ b/modules/tide_media/tide_media.install @@ -81,3 +81,23 @@ function tide_media_update_10005() { $config->set('track_enabled_target_entity_types', $result); $config->save(); } + +/** + * Adds media_alias_display settings for document type. + */ +function tide_media_update_10006() { + // Check if the media_library module is enabled, enable it. + if (\Drupal::moduleHandler()->moduleExists('media_library') === FALSE) { + \Drupal::service('module_installer')->install(['media_library']); + } + + if (\Drupal::moduleHandler()->moduleExists('media_alias_display') === FALSE) { + \Drupal::service('module_installer')->install(['media_alias_display']); + } + + $media_config = \Drupal::service('config.factory')->getEditable('media_alias_display.settings'); + if ($media_config) { + $media_config->set('media_bundles', ['document' => 'document']); + $media_config->save(); + } +} diff --git a/modules/tide_media/tide_media.module b/modules/tide_media/tide_media.module index 9ee7eaf48..1a36ba83c 100644 --- a/modules/tide_media/tide_media.module +++ b/modules/tide_media/tide_media.module @@ -6,6 +6,7 @@ */ use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\Cache\RefinableCacheableDependencyInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; @@ -16,6 +17,7 @@ use Drupal\Core\Link; use Drupal\Core\Url; use Drupal\file\FileInterface; use Drupal\views\ViewExecutable; +use Symfony\Component\HttpFoundation\RedirectResponse; /** * Implements hook_views_pre_view(). @@ -464,3 +466,37 @@ function tide_media_file_presave(FileInterface $file) { $file->setFilename($filename_new); } } + +/** + * Implements hook_preprocess_HOOK(). + */ +function tide_media_preprocess_page(&$variables) { + $route_name = \Drupal::routeMatch()->getRouteName(); + $current_user = \Drupal::currentUser(); + $roles = $current_user->getRoles(); + + if ($route_name === 'entity.user.edit_form' && in_array('secure_file_user', $roles)) { + $url = Url::fromRoute('entity.user.canonical', ['user' => $current_user->id()]); + $response = new RedirectResponse($url->toString()); + $response->send(); + } +} + +/** + * Implements hook_menu_local_tasks_alter(). + */ +function tide_media_menu_local_tasks_alter(&$data, $route_name, RefinableCacheableDependencyInterface &$cacheability) { + $current_user = \Drupal::currentUser(); + $roles = $current_user->getRoles(); + if (in_array('secure_file_user', $roles, TRUE) && isset($data['tabs'])) { + foreach ($data['tabs'] as $key => &$tabs) { + if (is_array($tabs)) { + foreach ($tabs as $tab_key => $tab) { + if ($tab_key === 'entity.user.edit_form') { + unset($tabs[$tab_key]); + } + } + } + } + } +} diff --git a/modules/tide_paragraphs_enhanced_modal/css/paragraphs.enhanced_modal.css b/modules/tide_paragraphs_enhanced_modal/css/paragraphs.enhanced_modal.css index a92c74493..edd95d0fb 100644 --- a/modules/tide_paragraphs_enhanced_modal/css/paragraphs.enhanced_modal.css +++ b/modules/tide_paragraphs_enhanced_modal/css/paragraphs.enhanced_modal.css @@ -33,6 +33,7 @@ box-shadow: none !important; border: none !important; padding: 0 0 0.5em; + text-wrap: pretty; } .paragraphs-add-dialog-enhanced .paragraphs-add-dialog-list .paragraphs-add-dialog-row .description { diff --git a/modules/tide_publication/config/install/core.entity_form_display.node.publication.default.yml b/modules/tide_publication/config/install/core.entity_form_display.node.publication.default.yml index 76843c195..019d29b8d 100644 --- a/modules/tide_publication/config/install/core.entity_form_display.node.publication.default.yml +++ b/modules/tide_publication/config/install/core.entity_form_display.node.publication.default.yml @@ -133,8 +133,8 @@ third_party_settings: label: 'Customised Header' parent_name: group_section_header children: - - field_landing_page_hero_image - field_landing_page_hero_theme + - field_landing_page_hero_image format_type: tab format_settings: description: '' diff --git a/modules/tide_publication/config/install/core.entity_form_display.node.publication_page.default.yml b/modules/tide_publication/config/install/core.entity_form_display.node.publication_page.default.yml index a1a808a0c..6d99612e6 100644 --- a/modules/tide_publication/config/install/core.entity_form_display.node.publication_page.default.yml +++ b/modules/tide_publication/config/install/core.entity_form_display.node.publication_page.default.yml @@ -126,8 +126,8 @@ third_party_settings: label: 'Customised Header' parent_name: group_section_header children: - - field_landing_page_hero_image - field_landing_page_hero_theme + - field_landing_page_hero_image format_type: tab format_settings: description: '' diff --git a/modules/tide_publication/config/install/field.field.node.publication.field_landing_page_hero_theme.yml b/modules/tide_publication/config/install/field.field.node.publication.field_landing_page_hero_theme.yml index de8ea2328..24c69d439 100644 --- a/modules/tide_publication/config/install/field.field.node.publication.field_landing_page_hero_theme.yml +++ b/modules/tide_publication/config/install/field.field.node.publication.field_landing_page_hero_theme.yml @@ -10,11 +10,13 @@ id: node.publication.field_landing_page_hero_theme field_name: field_landing_page_hero_theme entity_type: node bundle: publication -label: 'Hero image theme' -description: 'If your hero image is mostly dark, apply the dark theme. This changes how the page title is displayed.' -required: false +label: 'Page title display style' +description: 'By default the page title will display in the site’s primary colour. If you choose ‘Reverse blocked text’ the heading and introduction text will be white with a coloured block behind the text (the site’s ‘accent contrast’ and ‘accent alternate’ colours). See Ripple header page to understand the header component design.' +required: true translatable: true -default_value: { } +default_value: + - + value: light default_value_callback: '' settings: { } field_type: list_string diff --git a/modules/tide_publication/config/install/field.field.node.publication_page.field_landing_page_hero_theme.yml b/modules/tide_publication/config/install/field.field.node.publication_page.field_landing_page_hero_theme.yml index dc48f7135..6c4fc2800 100644 --- a/modules/tide_publication/config/install/field.field.node.publication_page.field_landing_page_hero_theme.yml +++ b/modules/tide_publication/config/install/field.field.node.publication_page.field_landing_page_hero_theme.yml @@ -10,11 +10,13 @@ id: node.publication_page.field_landing_page_hero_theme field_name: field_landing_page_hero_theme entity_type: node bundle: publication_page -label: 'Hero image theme' -description: 'If your hero image is mostly dark, apply the dark theme. This changes how the page title is displayed.' -required: false +label: 'Page title display style' +description: 'By default the page title will display in the site’s primary colour. If you choose ‘Reverse blocked text’ the heading and introduction text will be white with a coloured block behind the text (the site’s ‘accent contrast’ and ‘accent alternate’ colours). See Ripple header page to understand the header component design.' +required: true translatable: true -default_value: { } +default_value: + - + value: light default_value_callback: '' settings: { } field_type: list_string diff --git a/modules/tide_publication/tide_publication.module b/modules/tide_publication/tide_publication.module index 7dd65b6e5..322d63e7d 100644 --- a/modules/tide_publication/tide_publication.module +++ b/modules/tide_publication/tide_publication.module @@ -72,12 +72,6 @@ function tide_publication_form_node_form_alter(&$form, FormStateInterface $form_ $form['#process'][] = '_tide_publication_form_node_form_process'; - // Move Hero Image theme to Hero Image field group. - if (isset($form['field_landing_page_hero_theme']) && isset($form['field_landing_page_hero_image']['widget'])) { - $form['field_landing_page_hero_image']['widget']['field_landing_page_hero_theme'] = $form['field_landing_page_hero_theme']; - unset($form['field_landing_page_hero_theme']); - } - // Add conditional field for show table of content. if (isset($form['field_node_display_headings'])) { $form['field_node_display_headings']['#states'] = [ @@ -126,6 +120,13 @@ function _tide_publication_form_node_form_process(array $form, FormStateInterfac 'default' => t('Default appearance'), 'fullwidth' => t('Full-width background image'), ], + '#ajax' => [ + 'callback' => 'tide_landing_page_set_value_hero_image_theme', + ], + ]; + + $form['field_landing_page_hero_theme']['#states']['enabled'] = [ + ':input[name="_header_style_options"]' => ['value' => 'corner'], ]; $form['field_landing_page_hero_image']['#states']['visible'] = [ diff --git a/modules/tide_webform/tide_webform.module b/modules/tide_webform/tide_webform.module index 2ac1f487c..6fa79cf15 100644 --- a/modules/tide_webform/tide_webform.module +++ b/modules/tide_webform/tide_webform.module @@ -64,6 +64,36 @@ function tide_webform_form_alter(&$form, FormStateInterface $form_state, $form_i '255'); } } + // Check if the field type is either 'select' or 'term_select'. + $field_type = $form['properties']['type']['#value'] ?? ''; + if (in_array($field_type, ['select', 'webform_term_select'])) { + $current_path = \Drupal::service('path.current')->getPath(); + $matches = []; + if (preg_match('/webform\/manage\/([^\/]+)\/element\/([^\/]+)/', $current_path, $matches)) { + // Extract the Parent Webform ID. + $webform_id = $matches[1]; + } + // Fetch already saved default value from config. + $element_key = $form['properties']['element']['key']['#default_value']; + $element_settings = \Drupal::configFactory()->get('webform.settings')->get('element_settings') ?: []; + if (isset($element_key) && isset($element_settings[$webform_id][$element_key]['searchable'])) { + // Get the 'searchable' value for the specified element. + $searchable_value = $element_settings[$webform_id][$element_key]['searchable']; + } + else { + $searchable_value = 0; + } + $form['properties']['element']['searchable'] = [ + '#type' => 'checkbox', + '#title' => t('Enable search'), + '#description' => t('Check this box to allow select fields to opt into the searchable display.'), + '#default_value' => $searchable_value, + ]; + + $form['#submit'][] = 'tide_webform_webform_ui_element_form_submit'; + $form['#webform_id'] = $form_id; + $form['#parent_id'] = $webform_id; + } } if ($form_id == 'webform_submission_filter_form') { @@ -102,6 +132,43 @@ function tide_webform_form_alter(&$form, FormStateInterface $form_state, $form_i } +/** + * Submit callback. + * + * @param array $form + * The form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * Form state. + */ +function tide_webform_webform_ui_element_form_submit(array $form, FormStateInterface $form_state) { + + // Get the searchable value. + $searchable_value = $form_state->getValue(['searchable']) ?? 0; + // Fetch key from from_state for new element. + $key_new = $form_state->getValue(['key']) ?? ''; + $element_key = $form['properties']['element']['key']['#default_value'] ?? $key_new; + $element_settings = \Drupal::configFactory()->getEditable('webform.settings')->get('element_settings') ?: []; + // Save the 'searchable' value to the element settings. + $element_settings[$form['#parent_id']][$element_key]['searchable'] = $searchable_value; + + // Save the updated element settings back to the configuration. + \Drupal::configFactory()->getEditable('webform.settings') + ->set('element_settings', $element_settings) + ->save(); + + // Explicitly add elemet to parent webform. + $webform = Webform::load($form['#parent_id']); + // Get all elements. + $elements = $webform->getElementsDecoded(); + // Check if element exists and its type is 'select' or 'webform_term_select'. + if (isset($elements[$element_key]) && in_array($elements[$element_key]['#type'], ['select', 'webform_term_select'])) { + $elements[$element_key]['#searchable'] = $searchable_value; + // Update the Webform's elements. + $webform->setElements($elements); + $webform->save(); + } +} + /** * After_build callback. * diff --git a/tide_core.install b/tide_core.install index a60005191..05ce69116 100644 --- a/tide_core.install +++ b/tide_core.install @@ -5,6 +5,7 @@ * Installation functions for Tide Core. */ +use Drupal\field\Entity\FieldConfig; use Drupal\tide_core\TideCoreOperation; use Drupal\user\Entity\Role; use Drupal\user\Entity\User; @@ -316,3 +317,64 @@ function tide_core_update_10010() { $module_installer->install(['tide_tfa']); } } + +/** + * Enabled tide_data_driven_component module. + */ +function tide_core_update_10011() { + $moduleHandler = \Drupal::service('module_handler'); + $moduleInstaller = \Drupal::service('module_installer'); + // Enable tide_data_driven_component. + if (!$moduleHandler->moduleExists('tide_data_driven_component')) { + $moduleInstaller->install(['tide_data_driven_component']); + } + if ($moduleHandler->moduleExists('tide_landing_page')) { + // Define the fields to be updated. + $fields_to_update = [ + 'field_landing_page_component', + 'field_landing_page_header', + ]; + $new_component = 'data_driven_component'; + + foreach ($fields_to_update as $field_name) { + $field_config = FieldConfig::loadByName('node', 'landing_page', $field_name); + + if ($field_config) { + // Get the current handler settings. + $handler_settings = $field_config->getSetting('handler_settings'); + + // Ensure 'target_bundles' exists in handler settings. + if (isset($handler_settings['target_bundles'])) { + // Add the new component if it does not already exist. + if (!array_key_exists($new_component, $handler_settings['target_bundles'])) { + $handler_settings['target_bundles'][$new_component] = $new_component; + + // Update the field configuration with the new handler settings. + $field_config->setSetting('handler_settings', $handler_settings); + $field_config->save(); + } + } + } + } + } +} + +/** + * Enable shield module. + */ +function tide_core_update_10012() { + // Check if the shield module is disabled, enable it. + if (\Drupal::moduleHandler()->moduleExists('shield') === FALSE) { + \Drupal::service('module_installer')->install(['shield']); + } + // Add the new paths to exclude. + $exclude_paths = [ + '/oauth', + '/oauth/authorize', + '/oauth/token', + '/sites/default/files/*', + ]; + $paths_string = implode("\r\n", $exclude_paths); + $shield_config = \Drupal::configFactory()->getEditable('shield.settings'); + $shield_config->set('paths', $paths_string)->save(); +} diff --git a/tide_core.module b/tide_core.module index 7fab15386..b7f37c36d 100644 --- a/tide_core.module +++ b/tide_core.module @@ -10,14 +10,17 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Breadcrumb\Breadcrumb; use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Link; use Drupal\Core\Render\Markup; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; +use Drupal\media\Entity\Media; use Drupal\node\Entity\Node; use Drupal\node\NodeInterface; +use Drupal\paragraphs\Entity\Paragraph; use Drupal\redirect\Entity\Redirect; use Drupal\scheduled_transitions\Routing\ScheduledTransitionsRouteProvider; use Drupal\tide_core\Render\Element\AdminToolbar; @@ -694,6 +697,7 @@ function tide_core_node_presave(NodeInterface $node) { $node_state = isset($node->get('moderation_state')->getValue()[0]) ? $node->get('moderation_state')->getValue()[0]['value'] : ''; if ($node_state === 'published') { + tide_core_media_autopublish($node); $log = [ /* * Term the 'type' => 'node' as 'type' => 'page' @@ -786,3 +790,74 @@ function tide_core_user_role_insert(RoleInterface $role): void { $role->save(); } } + +/** + * Publish unpublished media(documents) on node publish. + */ +function tide_core_media_autopublish($node) { + // Loop through all fields of the node. + foreach ($node->getFields() as $field_name => $field) { + + // Check if the field is of type Entity Reference to Paragraphs. + if ($field->getFieldDefinition()->getType() == 'entity_reference_revisions' && + $field->getFieldDefinition()->getSetting('target_type') == 'paragraph') { + + // Loop through all referenced Paragraph entities. + foreach ($field->getValue() as $paragraph_item) { + $paragraph = Paragraph::load($paragraph_item['target_id']); + if ($paragraph) { + // Loop through fields in the paragraph. + foreach ($paragraph->getFields() as $sub_field_name => $sub_field) { + // Check if the field is of type "Text (formatted, long)". + if ($sub_field instanceof FieldItemListInterface && + $sub_field->getFieldDefinition()->getType() == 'text_long') { + $text_content = $sub_field->value; + preg_match_all('/data-entity-uuid="([a-f0-9\-]+)"/', $text_content, $matches); + if (!empty($matches[1])) { + tide_core_process_media_entity_status($matches[1]); + } + } + } + } + } + } + + // Check if the field is the "Body" field (common for content types) + // Ensure the body field is of type "Text (formatted, long)". + elseif ($field_name == 'body' && $field->getFieldDefinition()->getType() == 'text_long') { + $body_content = $field->value; + // Parse the body content for media entities using a regex pattern. + preg_match_all('/data-entity-uuid="([a-f0-9\-]+)"/', $body_content, $matches); + + // Loop through the found media UUIDs. + if (!empty($matches[1])) { + tide_core_process_media_entity_status($matches[1]); + } + } + } +} + +/** + * Helper function to check and update the media entity status. + * + * @param array $media_uuids + * Array of media UUIDs to process. + */ +function tide_core_process_media_entity_status(array $media_uuids) { + foreach ($media_uuids as $media_uuid) { + // Load the media entity by UUID. + $media = \Drupal::entityTypeManager()->getStorage('media')->loadByProperties(['uuid' => $media_uuid]); + if ($media) { + $media = reset($media); + // Check if the media is an instance of Media. + if ($media instanceof Media) { + $status = $media->get('status')->value; + // If unpublished, set the status to published (1) + if ($status == 0) { + $media->set('status', 1); + $media->save(); + } + } + } + } +}