diff --git a/core/modules/comment/src/Plugin/views/row/Rss.php b/core/modules/comment/src/Plugin/views/row/Rss.php index f15b031e8c387cd8bad9840b50418600f22549fa..78a8d098edc3d12106d1c232e40314d29c1d74d1 100644 --- a/core/modules/comment/src/Plugin/views/row/Rss.php +++ b/core/modules/comment/src/Plugin/views/row/Rss.php @@ -66,8 +66,7 @@ public function preRender($result) { */ public function buildOptionsForm_summary_options() { $options = parent::buildOptionsForm_summary_options(); - $options['title'] = $this->t('Title only'); - $options['default'] = $this->t('Use site default RSS settings'); + $options[$this::TITLE_VIEW_MODE] = $this->t('Title only'); return $options; } @@ -83,9 +82,6 @@ public function render($row) { } $view_mode = $this->options['view_mode']; - if ($view_mode == 'default') { - $view_mode = \Drupal::config('system.rss')->get('items.view_mode'); - } // Load the specified comment and its associated node: /** @var \Drupal\comment\CommentInterface $comment */ @@ -113,7 +109,7 @@ public function render($row) { // The comment gets built and modules add to or modify // $comment->rss_elements and $comment->rss_namespaces. - $build = $this->entityTypeManager->getViewBuilder('comment')->view($comment, 'rss'); + $build = $this->entityTypeManager->getViewBuilder('comment')->view($comment, $view_mode); unset($build['#theme']); if (!empty($comment->rss_namespaces)) { @@ -121,7 +117,7 @@ public function render($row) { } $item = new \stdClass(); - if ($view_mode != 'title') { + if ($view_mode != $this::TITLE_VIEW_MODE) { // We render comment contents. $item->description = $build; } diff --git a/core/modules/config_translation/tests/src/Unit/ConfigNamesMapperTest.php b/core/modules/config_translation/tests/src/Unit/ConfigNamesMapperTest.php index 5bbe2b9a3098f3ecf944245ab0692f300a038dc5..cc17c6304e604094bd895be0c139e58d91ef0829 100644 --- a/core/modules/config_translation/tests/src/Unit/ConfigNamesMapperTest.php +++ b/core/modules/config_translation/tests/src/Unit/ConfigNamesMapperTest.php @@ -470,11 +470,6 @@ public function testGetConfigData(): void { 'enabled' => FALSE, 'message' => '@site is currently under maintenance.', ], - 'system.rss' => [ - 'items' => [ - 'view_mode' => 'rss', - ], - ], ]; $this->configNamesMapper->setConfigNames(array_keys($configs)); diff --git a/core/modules/node/src/Plugin/views/row/Rss.php b/core/modules/node/src/Plugin/views/row/Rss.php index 56549f01d124e7872766a866ea787c05bc75d325..6e33e522743d07a6b89781c4779308c5e3453294 100644 --- a/core/modules/node/src/Plugin/views/row/Rss.php +++ b/core/modules/node/src/Plugin/views/row/Rss.php @@ -51,8 +51,7 @@ class Rss extends RssPluginBase { */ public function buildOptionsForm_summary_options() { $options = parent::buildOptionsForm_summary_options(); - $options['title'] = $this->t('Title only'); - $options['default'] = $this->t('Use site default RSS settings'); + $options[$this::TITLE_VIEW_MODE] = $this->t('Title only'); return $options; } @@ -89,9 +88,6 @@ public function render($row) { } $display_mode = $this->options['view_mode']; - if ($display_mode == 'default') { - $display_mode = \Drupal::config('system.rss')->get('items.view_mode'); - } // Load the specified node: /** @var \Drupal\node\NodeInterface $node */ @@ -120,11 +116,9 @@ public function render($row) { // The node gets built and modules add to or modify $node->rss_elements // and $node->rss_namespaces. - $build_mode = $display_mode; - $build = \Drupal::entityTypeManager() ->getViewBuilder('node') - ->view($node, $build_mode); + ->view($node, $display_mode); // Add rss key to cache to differentiate this from other caches. $build['#cache']['keys'][] = 'view_rss'; @@ -135,7 +129,7 @@ public function render($row) { } $item = new \stdClass(); - if ($display_mode != 'title') { + if ($display_mode != $this::TITLE_VIEW_MODE) { // We render node contents. $item->description = $build; } diff --git a/core/modules/system/config/install/system.rss.yml b/core/modules/system/config/install/system.rss.yml deleted file mode 100644 index bb7c0c040a97a1ab32cd5cd4e705d1c126520010..0000000000000000000000000000000000000000 --- a/core/modules/system/config/install/system.rss.yml +++ /dev/null @@ -1,2 +0,0 @@ -items: - view_mode: rss diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index 88f34652b98607d7501214c6a510015c212ecf33..96cfabee126b87f0919e550f19e52ac01b310977 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -238,18 +238,6 @@ system.performance: type: boolean label: 'Compress JavaScript files.' -system.rss: - type: config_object - label: 'Feed settings' - mapping: - items: - type: mapping - label: 'Feed items' - mapping: - view_mode: - type: string - label: 'Feed content' - system.theme: type: config_object label: 'Theme settings' diff --git a/core/modules/system/migrations/system_rss.yml b/core/modules/system/migrations/system_rss.yml deleted file mode 100644 index 8a74ac6c84cfaceaa21d69b4470d1b78d8c1ef21..0000000000000000000000000000000000000000 --- a/core/modules/system/migrations/system_rss.yml +++ /dev/null @@ -1,16 +0,0 @@ -id: system_rss -label: RSS configuration -migration_tags: - - Drupal 6 - - Drupal 7 - - Configuration -source: - plugin: variable - variables: - - feed_item_length - source_module: system -process: - 'items/view_mode': feed_item_length -destination: - plugin: config - config_name: system.rss diff --git a/core/modules/system/src/Form/RssFeedsForm.php b/core/modules/system/src/Form/RssFeedsForm.php deleted file mode 100644 index 72617220f2c0edcf1462da1c29986d35a38c4531..0000000000000000000000000000000000000000 --- a/core/modules/system/src/Form/RssFeedsForm.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -namespace Drupal\system\Form; - -use Drupal\Core\Form\ConfigFormBase; -use Drupal\Core\Form\FormStateInterface; - -/** - * Configure RSS settings for this site. - * - * @internal - */ -class RssFeedsForm extends ConfigFormBase { - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'system_rss_feeds_settings'; - } - - /** - * {@inheritdoc} - */ - protected function getEditableConfigNames() { - return ['system.rss']; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state) { - $form['feed_view_mode'] = [ - '#type' => 'select', - '#title' => $this->t('Feed content'), - '#config_target' => 'system.rss:items.view_mode', - '#options' => [ - 'title' => $this->t('Titles only'), - 'teaser' => $this->t('Titles plus teaser'), - 'fulltext' => $this->t('Full text'), - ], - '#description' => $this->t('Global setting for the default display of content items in each feed.'), - ]; - - return parent::buildForm($form, $form_state); - } - -} diff --git a/core/modules/system/system.config_translation.yml b/core/modules/system/system.config_translation.yml index 87cc98ce8716967c5517b34d1005f1f944bfd551..e56f2395c36f2c1d6994e92970076a66013b0081 100644 --- a/core/modules/system/system.config_translation.yml +++ b/core/modules/system/system.config_translation.yml @@ -9,9 +9,3 @@ system.site_information_settings: base_route_name: system.site_information_settings names: - system.site - -system.rss_feeds_settings: - title: 'RSS publishing' - base_route_name: system.rss_feeds_settings - names: - - system.rss diff --git a/core/modules/system/system.links.menu.yml b/core/modules/system/system.links.menu.yml index 404bceeb7b366bafb2055c9ee0cedd39a5255761..ea9f1528530e7e1f0947d3e489d41121e25a5f42 100644 --- a/core/modules/system/system.links.menu.yml +++ b/core/modules/system/system.links.menu.yml @@ -53,11 +53,6 @@ system.admin_config_services: title: 'Web services' parent: system.admin_config route_name: system.admin_config_services -system.rss_feeds_settings: - title: 'RSS publishing' - parent: system.admin_config_services - description: 'Configure the site description, the number of items per feed, and whether feeds should be titles/teasers/full-text.' - route_name: system.rss_feeds_settings system.admin_config_development: route_name: system.admin_config_development parent: system.admin_config diff --git a/core/modules/system/system.links.task.yml b/core/modules/system/system.links.task.yml index ed66b0595e20b1316f4a42a1123014cb8ea75122..369cc253ad844c86e2b532c6158c5b76b89c1dfc 100644 --- a/core/modules/system/system.links.task.yml +++ b/core/modules/system/system.links.task.yml @@ -1,8 +1,3 @@ -system.rss_feeds_settings_tab: - route_name: system.rss_feeds_settings - title: Settings - base_route: system.rss_feeds_settings - system.site_maintenance_mode_tab: route_name: system.site_maintenance_mode title: Settings diff --git a/core/modules/system/system.post_update.php b/core/modules/system/system.post_update.php index ce110e2c2f36ca38b61bf1334a6b9372a8b288e2..2ad4b290ba926518f3c6bd088f74e84e60427dae 100644 --- a/core/modules/system/system.post_update.php +++ b/core/modules/system/system.post_update.php @@ -7,6 +7,8 @@ use Drupal\Core\Config\Entity\ConfigEntityUpdater; use Drupal\Core\Entity\EntityFormModeInterface; +use Drupal\views\ViewEntityInterface; +use Drupal\views\ViewsConfigUpdater; /** * Implements hook_removed_post_updates(). @@ -123,3 +125,26 @@ function system_post_update_convert_empty_description_entity_form_modes_to_null( }); } + +/** + * Delete obsolete system.rss configuration. + */ +function system_post_update_delete_rss_config(array &$sandbox): void { + $config = \Drupal::configFactory()->getEditable('system.rss'); + $previous_view_mode = $config->get('items.view_mode'); + if ($config->get('items.view_mode') !== NULL) { + $sandbox['#system_post_update_delete_rss_config__previous_view_mode'] = $previous_view_mode; + } + + if (\Drupal::moduleHandler()->moduleExists('views')) { + /** @var \Drupal\views\ViewsConfigUpdater $view_config_updater */ + $view_config_updater = \Drupal::classResolver(ViewsConfigUpdater::class); + $view_config_updater->setDeprecationsEnabled(FALSE); + \Drupal::classResolver(ConfigEntityUpdater::class) + ->update($sandbox, 'view', function (ViewEntityInterface $view) use ($view_config_updater, $sandbox): bool { + return $view_config_updater->needsRssViewModeUpdate($view, $sandbox['#system_post_update_delete_rss_config__previous_view_mode']); + }); + } + + $config->delete(); +} diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml index bf1ff4ca1f604f60d851b621df513d67f2cca858..d3b67dd7517740f5728e2d69db777226b5d9e1ed 100644 --- a/core/modules/system/system.routing.yml +++ b/core/modules/system/system.routing.yml @@ -191,14 +191,6 @@ system.file_system_settings: requirements: _permission: 'administer site configuration' -system.rss_feeds_settings: - path: '/admin/config/services/rss-publishing' - defaults: - _form: '\Drupal\system\Form\RssFeedsForm' - _title: 'RSS publishing' - requirements: - _permission: 'administer site configuration' - system.regional_settings: path: '/admin/config/regional/settings' defaults: diff --git a/core/modules/system/tests/src/Functional/Update/SystemRssDeleteTest.php b/core/modules/system/tests/src/Functional/Update/SystemRssDeleteTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e57357543742a252b415ee3d340212f7ac652aae --- /dev/null +++ b/core/modules/system/tests/src/Functional/Update/SystemRssDeleteTest.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\system\Functional\Update; + +use Drupal\FunctionalTests\Update\UpdatePathTestBase; + +/** + * Tests that system.rss config is deleted. + * + * @group Update + * @see system_post_update_delete_rss_config() + */ +class SystemRssDeleteTest extends UpdatePathTestBase { + + /** + * {@inheritdoc} + */ + protected function setDatabaseDumpFiles(): void { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../fixtures/update/drupal-10.3.0.bare.standard.php.gz', + ]; + } + + /** + * Ensures that system.rss is deleted after updating. + */ + public function testUpdate(): void { + $config = $this->config('system.rss'); + $this->assertFalse($config->isNew()); + + $this->runUpdates(); + + $config = $this->config('system.rss'); + $this->assertTrue($config->isNew()); + } + +} diff --git a/core/modules/system/tests/src/Kernel/Migrate/d6/MigrateSystemConfigurationTest.php b/core/modules/system/tests/src/Kernel/Migrate/d6/MigrateSystemConfigurationTest.php index eba36bada4bb4339c1b870c454434845c6b7e376..28572e4e26fdfa746ea5731ca86ef91bd41ce5c6 100644 --- a/core/modules/system/tests/src/Kernel/Migrate/d6/MigrateSystemConfigurationTest.php +++ b/core/modules/system/tests/src/Kernel/Migrate/d6/MigrateSystemConfigurationTest.php @@ -95,11 +95,6 @@ class MigrateSystemConfigurationTest extends MigrateDrupal6TestBase { 'gzip' => TRUE, ], ], - 'system.rss' => [ - 'items' => [ - 'view_mode' => 'title', - ], - ], 'system.site' => [ // Neither langcode nor default_langcode are not handled by the migration. 'langcode' => 'en', @@ -141,7 +136,6 @@ protected function setUp(): void { 'system_logging', 'system_maintenance', 'd6_system_performance', - 'system_rss', 'system_site', ]; $this->executeMigrations($migrations); diff --git a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php index b8b18a5c9ba2da0f1d40dedf2ce1dbcc8c251edf..b677e58d548244517119f3b92ca879e4f7198325 100644 --- a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php +++ b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php @@ -107,11 +107,6 @@ class MigrateSystemConfigurationTest extends MigrateDrupal7TestBase { 'gzip' => TRUE, ], ], - 'system.rss' => [ - 'items' => [ - 'view_mode' => 'fulltext', - ], - ], 'system.site' => [ // Neither langcode nor default_langcode are not handled by the migration. 'langcode' => 'en', @@ -176,7 +171,6 @@ protected function setUp(): void { 'd7_system_mail', 'system_maintenance', 'd7_system_performance', - 'system_rss', 'system_site', ]; $this->executeMigrations($migrations); diff --git a/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml b/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml index 9763c3c057dc847ccb6404bf38f9259a17499441..b34348136ad499a488665477a6964edcdb488569 100644 --- a/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml +++ b/core/modules/taxonomy/config/optional/views.view.taxonomy_term.yml @@ -2,6 +2,7 @@ langcode: en status: true dependencies: config: + - core.entity_view_mode.node.rss - core.entity_view_mode.node.teaser module: - node @@ -277,7 +278,7 @@ display: type: node_rss options: relationship: none - view_mode: default + view_mode: rss query: type: views_query options: { } diff --git a/core/modules/views/src/Plugin/views/row/RssPluginBase.php b/core/modules/views/src/Plugin/views/row/RssPluginBase.php index 3de7d7af3a7be389a7e0277ed1c9d49458759549..418736427b858e47e75df796ec0324838ffdb995 100644 --- a/core/modules/views/src/Plugin/views/row/RssPluginBase.php +++ b/core/modules/views/src/Plugin/views/row/RssPluginBase.php @@ -12,6 +12,11 @@ */ abstract class RssPluginBase extends RowPluginBase { + /** + * A fake view mode to only display titles. + */ + const string TITLE_VIEW_MODE = '_views.rss.title'; + /** * The entity type manager. * @@ -73,7 +78,15 @@ public static function create(ContainerInterface $container, array $configuratio protected function defineOptions() { $options = parent::defineOptions(); - $options['view_mode'] = ['default' => 'default']; + // Select the rss view mode by default, otherwise select the first available + // view mode. + $view_modes = $this->entityDisplayRepository->getViewModes($this->entityTypeId); + if (isset($view_modes['rss'])) { + $options['view_mode'] = ['default' => 'rss']; + } + else { + $options['view_mode'] = ['default' => key($view_modes)]; + } return $options; } diff --git a/core/modules/views/src/ViewsConfigUpdater.php b/core/modules/views/src/ViewsConfigUpdater.php index 9c5d38e10ac5ccecfe3be63febb951da65539013..5531d8934f8561c30b9f78c996439232dc391168 100644 --- a/core/modules/views/src/ViewsConfigUpdater.php +++ b/core/modules/views/src/ViewsConfigUpdater.php @@ -5,6 +5,7 @@ use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Config\TypedConfigManagerInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -78,6 +79,8 @@ class ViewsConfigUpdater implements ContainerInjectionInterface { * The views data service. * @param \Drupal\Component\Plugin\PluginManagerInterface $formatter_plugin_manager * The formatter plugin manager service. + * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entityDisplayRepository + * The entity display repository service. */ public function __construct( EntityTypeManagerInterface $entity_type_manager, @@ -85,6 +88,7 @@ public function __construct( TypedConfigManagerInterface $typed_config_manager, ViewsData $views_data, PluginManagerInterface $formatter_plugin_manager, + protected EntityDisplayRepositoryInterface $entityDisplayRepository, ) { $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; @@ -102,7 +106,8 @@ public static function create(ContainerInterface $container) { $container->get('entity_field.manager'), $container->get('config.typed'), $container->get('views.views_data'), - $container->get('plugin.manager.field.formatter') + $container->get('plugin.manager.field.formatter'), + $container->get('entity_display.repository') ); } @@ -137,6 +142,9 @@ public function updateAll(ViewEntityInterface $view) { if ($this->processTableCssClassUpdate($view)) { $changed = TRUE; } + if ($this->processRssViewModeUpdate($view)) { + $changed = TRUE; + } return $changed; }); } @@ -359,4 +367,81 @@ public function processTableCssClassUpdate(ViewEntityInterface $view): bool { return $changed; } + /** + * Checks for views needing a default RSS view mode. + * + * @param \Drupal\views\ViewEntityInterface $view + * The view entity. + * @param string|null $previous_view_mode + * The previous view mode. + * + * @return bool + * TRUE if the view has been updated. + */ + public function needsRssViewModeUpdate(ViewEntityInterface $view, ?string $previous_view_mode = NULL): bool { + return $this->processRssViewModeUpdate($view, $previous_view_mode); + } + + /** + * Processes views and sets the default RSS view mode if necessary. + * + * @param \Drupal\views\ViewEntityInterface $view + * The view entity. + * @param string|null $previous_view_mode + * The previous view mode. + * + * @return bool + * TRUE if the view was updated with a default RSS view mode. + */ + public function processRssViewModeUpdate(ViewEntityInterface $view, ?string $previous_view_mode = NULL) : bool { + $changed = FALSE; + $displays = $view->get('display'); + + // Row types that need updating. + $row_types = [ + 'comment_rss' => 'comment', + 'node_rss' => 'node', + ]; + + foreach ($displays as &$display) { + if (isset($display['display_options']['row']['options']['view_mode']) && + array_key_exists($display['display_options']['row']['type'], $row_types) && + $display['display_options']['row']['options']['view_mode'] === 'default') { + + // When system.rss is already removed but a view is saved, we still need + // to try and set the view_mode to something more sane. But detecting + // if the view mode was always default, or default because it used the + // system.rss setting is hard. So if there is a default mode available + // it will use that. + // It would make sense to use any RSS view_mode if available, but that + // would mean 'default' can never be set as a view mode. That is an + // issue, therefore, if we have a default view mode available, we will + // use that. + if ($previous_view_mode === NULL) { + $view_modes = $this->entityDisplayRepository->getViewModes($row_types[$display['display_options']['row']['type']]); + if (array_key_exists('default', $view_modes)) { + return FALSE; + } + + // If there is no default, the most likely view mode is RSS. If that + // is available we use that. Otherwise, fall back to the first + // available. + $probable_view_mode = isset($view_modes['rss']) ? 'rss' : array_key_first($view_modes); + $display['display_options']['row']['options']['view_mode'] = $probable_view_mode; + $changed = TRUE; + } + else { + $display['display_options']['row']['options']['view_mode'] = $previous_view_mode; + $changed = TRUE; + } + } + } + + if ($changed) { + $view->set('display', $displays); + } + + return $changed; + } + } diff --git a/core/modules/views/tests/fixtures/update/rss-default-view-mode.php b/core/modules/views/tests/fixtures/update/rss-default-view-mode.php new file mode 100644 index 0000000000000000000000000000000000000000..6d7c83ff89417e1bd412ee5213834daad8e9cef4 --- /dev/null +++ b/core/modules/views/tests/fixtures/update/rss-default-view-mode.php @@ -0,0 +1,21 @@ +<?php + +/** + * @file + * Test fixture. + */ + +use Drupal\Core\Database\Database; +use Drupal\Component\Serialization\Yaml; + +$connection = Database::getConnection(); + +$config = Yaml::decode(file_get_contents(__DIR__ . '/views.view.test_display_feed.yml')); + +$connection->insert('config') + ->fields([ + 'collection' => '', + 'name' => 'views.view.test_display_feed', + 'data' => serialize($config), + ]) + ->execute(); diff --git a/core/modules/views/tests/fixtures/update/views.view.test_display_feed.yml b/core/modules/views/tests/fixtures/update/views.view.test_display_feed.yml new file mode 100644 index 0000000000000000000000000000000000000000..0dd06c7ecf76af53f290b930615f243494e59519 --- /dev/null +++ b/core/modules/views/tests/fixtures/update/views.view.test_display_feed.yml @@ -0,0 +1,193 @@ +uuid: 06456283-a609-4646-aeb4-f2b918b13111 +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.rss + module: + - node + - user +id: test_display_feed +label: 'rss test view' +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: field + label: '' + exclude: false + alter: + alter_text: false + make_link: false + absolute: false + word_boundary: false + ellipsis: false + strip_tags: false + trim: false + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + pager: + type: mini + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 10 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + empty: { } + sorts: + created: + id: created + table: node_field_data + field: created + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: created + plugin_id: date + order: DESC + expose: + label: '' + field_identifier: '' + exposed: false + granularity: second + arguments: { } + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: { } + header: { } + footer: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + feed_1: + id: feed_1 + display_title: Feed + display_plugin: feed + position: 1 + display_options: + row: + type: node_rss + options: + view_mode: default + display_extenders: { } + path: my-feed.xml + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/core/modules/views/tests/fixtures/update/views.view.test_display_feed_no_update.yml b/core/modules/views/tests/fixtures/update/views.view.test_display_feed_no_update.yml new file mode 100644 index 0000000000000000000000000000000000000000..187ae2a2ddb016f2f209b04aff572be292ecf589 --- /dev/null +++ b/core/modules/views/tests/fixtures/update/views.view.test_display_feed_no_update.yml @@ -0,0 +1,193 @@ +uuid: 06456283-a609-4646-aeb4-f2b918b13111 +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.rss + module: + - node + - user +id: test_display_feed_no_update +label: 'rss test view' +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +display: + default: + id: default + display_title: Default + display_plugin: default + position: 0 + display_options: + fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: title + plugin_id: field + label: '' + exclude: false + alter: + alter_text: false + make_link: false + absolute: false + word_boundary: false + ellipsis: false + strip_tags: false + trim: false + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + pager: + type: mini + options: + offset: 0 + pagination_heading_level: h4 + items_per_page: 10 + total_pages: null + id: 0 + tags: + next: ›› + previous: ‹‹ + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + empty: { } + sorts: + created: + id: created + table: node_field_data + field: created + relationship: none + group_type: group + admin_label: '' + entity_type: node + entity_field: created + plugin_id: date + order: DESC + expose: + label: '' + field_identifier: '' + exposed: false + granularity: second + arguments: { } + filters: + status: + id: status + table: node_field_data + field: status + entity_type: node + entity_field: status + plugin_id: boolean + value: '1' + group: 1 + expose: + operator: '' + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + query: + type: views_query + options: + query_comment: '' + disable_sql_rewrite: false + distinct: false + replica: false + query_tags: { } + relationships: { } + header: { } + footer: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + feed_1: + id: feed_1 + display_title: Feed + display_plugin: feed + position: 1 + display_options: + row: + type: entity:node + options: + view_mode: default + display_extenders: { } + path: my-feed.xml + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/core/modules/views/tests/src/Functional/Update/RssDefaultRowViewModeUpdateTest.php b/core/modules/views/tests/src/Functional/Update/RssDefaultRowViewModeUpdateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e524362dd9ff0638348a3afc7cc909ad185eb667 --- /dev/null +++ b/core/modules/views/tests/src/Functional/Update/RssDefaultRowViewModeUpdateTest.php @@ -0,0 +1,48 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\views\Functional\Update; + +use Drupal\FunctionalTests\Update\UpdatePathTestBase; +use Drupal\views\Entity\View; + +/** + * Tests the update view mode when removing system.rss. + * + * @see system_post_update_delete_rss_config() + * + * @group Update + * @group legacy + */ +class RssDefaultRowViewModeUpdateTest extends UpdatePathTestBase { + + /** + * {@inheritdoc} + */ + protected function setDatabaseDumpFiles(): void { + $this->databaseDumpFiles = [ + __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-10.3.0.filled.standard.php.gz', + __DIR__ . '/../../../fixtures/update/rss-default-view-mode.php', + ]; + } + + /** + * Tests the upgrade path setting rss row view mode. + */ + public function testRssDefaultRowViewModeUpdate(): void { + $views = View::loadMultiple(); + $data = $views['test_display_feed']->toArray(); + + $this->assertEquals('default', $data['display']['feed_1']['display_options']['row']['options']['view_mode']); + + $this->runUpdates(); + + $views = View::loadMultiple(); + $data = $views['test_display_feed']->toArray(); + + $this->assertEquals('title', $data['display']['feed_1']['display_options']['row']['options']['view_mode']); + + } + +} diff --git a/core/modules/views/tests/src/Kernel/ViewsConfigUpdaterTest.php b/core/modules/views/tests/src/Kernel/ViewsConfigUpdaterTest.php index b99adcd105d8ebef58d957616eb72ea56e4f9990..ceeb56a4787ba332738fc49e7e7565f9ed124b2e 100644 --- a/core/modules/views/tests/src/Kernel/ViewsConfigUpdaterTest.php +++ b/core/modules/views/tests/src/Kernel/ViewsConfigUpdaterTest.php @@ -5,6 +5,7 @@ namespace Drupal\Tests\views\Kernel; use Drupal\Core\Config\FileStorage; +use Drupal\views\ViewsConfigUpdater; /** * @coversDefaultClass \Drupal\views\ViewsConfigUpdater @@ -20,7 +21,9 @@ class ViewsConfigUpdaterTest extends ViewsKernelTestBase { protected static $modules = [ 'views_config_entity_test', 'entity_test', + 'text', 'field', + 'node', ]; /** @@ -32,6 +35,120 @@ public function testViewsConfigUpdater(): void { $this->markTestSkipped(); } + /** + * Tests the `needsRssViewModeUpdate` method. + */ + public function testUpdateRssViewMode(): void { + $this->strictConfigSchema = FALSE; + + /** @var \Drupal\views\ViewsConfigUpdater $view_config_updater */ + $view_config_updater = \Drupal::classResolver(ViewsConfigUpdater::class); + + // Load the test view. + $view_id = 'views.view.test_display_feed'; + $test_view = $this->loadTestView($view_id); + $display = $test_view->getDisplay('feed_1'); + + // Check the initial view mode. + $rowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + $this->assertEquals('default', $rowViewMode); + + // Update the view mode using the method under test. + $view_config_updater->needsRssViewModeUpdate($test_view, 'old_view_mode'); + + // Assert if the view mode was updated correctly. + $display = $test_view->getDisplay('feed_1'); + $updatedRowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + $this->assertEquals('old_view_mode', $updatedRowViewMode); + } + + /** + * Tests the `needsRssViewModeUpdate` method. + */ + public function testUpdateRssViewModeWithoutKnownPreviousMode(): void { + $this->installEntitySchema('node'); + $this->installConfig(['text', 'field', 'node']); + + $this->strictConfigSchema = FALSE; + + /** @var \Drupal\views\ViewsConfigUpdater $view_config_updater */ + $view_config_updater = \Drupal::classResolver(ViewsConfigUpdater::class); + + // Load the test view. + $view_id = 'views.view.test_display_feed'; + $test_view = $this->loadTestView($view_id); + $display = $test_view->getDisplay('feed_1'); + + // Check the initial view mode. + $rowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + $this->assertEquals('default', $rowViewMode); + + // Update the view mode using the method under test. + $view_config_updater->needsRssViewModeUpdate($test_view); + + // Assert if the view mode was updated correctly. + $display = $test_view->getDisplay('feed_1'); + $updatedRowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + + // This should be the first node view mode since we have nothing else + $this->assertEquals('rss', $updatedRowViewMode); + } + + /** + * Tests if onSave also updates the view. + */ + public function testUpdateRssViewModeWithoutKnownPreviousModeOnSaveHandler(): void { + $this->installEntitySchema('node'); + $this->installConfig(['text', 'field', 'node']); + + $this->strictConfigSchema = FALSE; + + // Load the test view. + $view_id = 'views.view.test_display_feed'; + $test_view = $this->loadTestView($view_id); + $display = $test_view->getDisplay('feed_1'); + + // Check the initial view mode. + $rowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + $this->assertEquals('default', $rowViewMode); + + $test_view->save(); + + // Assert if the view mode was updated correctly onSave. + $display = $test_view->getDisplay('feed_1'); + $updatedRowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + + // This should be the first node view mode since we have nothing else + $this->assertEquals('rss', $updatedRowViewMode); + } + + /** + * Tests the `needsRssViewModeUpdate` method. + */ + public function testUpdateRssViewModeSkipsOtherType(): void { + $this->strictConfigSchema = FALSE; + + /** @var \Drupal\views\ViewsConfigUpdater $view_config_updater */ + $view_config_updater = \Drupal::classResolver(ViewsConfigUpdater::class); + + // Load the test view. + $view_id = 'views.view.test_display_feed_no_update'; + $test_view = $this->loadTestView($view_id); + $display = $test_view->getDisplay('feed_1'); + + // Check the initial view mode. + $rowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + $this->assertEquals('default', $rowViewMode); + + // Update the view mode using the method under test. + $view_config_updater->needsRssViewModeUpdate($test_view, 'old_view_mode'); + + // Assert if the view mode was updated correctly. + $display = $test_view->getDisplay('feed_1'); + $updatedRowViewMode = $display['display_options']['row']['options']['view_mode'] ?? FALSE; + $this->assertEquals('default', $updatedRowViewMode); + } + /** * Loads a test view. * diff --git a/core/profiles/demo_umami/config/install/views.view.taxonomy_term.yml b/core/profiles/demo_umami/config/install/views.view.taxonomy_term.yml index 4834b785f4f606bccd4c9bec0209181218e84047..1fd1315ab33170ed55da35b1d5fecbc719c02dd6 100644 --- a/core/profiles/demo_umami/config/install/views.view.taxonomy_term.yml +++ b/core/profiles/demo_umami/config/install/views.view.taxonomy_term.yml @@ -3,6 +3,7 @@ status: true dependencies: config: - core.entity_view_mode.node.card + - core.entity_view_mode.node.rss module: - node - taxonomy @@ -283,7 +284,7 @@ display: type: node_rss options: relationship: none - view_mode: default + view_mode: rss query: type: views_query options: { }