diff --git a/core/modules/rest/src/Plugin/views/display/RestExport.php b/core/modules/rest/src/Plugin/views/display/RestExport.php index c907b1116d..cae15f7918 100644 --- a/core/modules/rest/src/Plugin/views/display/RestExport.php +++ b/core/modules/rest/src/Plugin/views/display/RestExport.php @@ -329,6 +329,8 @@ public function optionsSummary(&$categories, &$options) { 'value' => views_ui_truncate($auth, 24), ]; + $options['menu']['category'] = 'path'; + // Remove css/exposed form settings, as they are not used for the data // display. unset($options['exposed_form']); @@ -373,21 +375,11 @@ public function collectRoutes(RouteCollection $collection) { $display_id = $this->display['id']; if ($route = $collection->get("view.$view_id.$display_id")) { - $style_plugin = $this->getPlugin('style'); - // REST exports should only respond to GET methods. $route->setMethods(['GET']); - $formats = $style_plugin->getFormats(); - - // If there are no configured formats, add all formats that serialization - // is known to support. - if (!$formats) { - $formats = $this->getFormatOptions(); - } - // Format as a string using pipes as a delimiter. - $route->setRequirement('_format', implode('|', $formats)); + $route->setRequirement('_format', implode('|', $this->getFormats())); // Add authentication to the route if it was set. If no authentication was // set, the default authentication will be used, which is cookie based by @@ -536,4 +528,45 @@ protected function getFormatOptions() { return array_combine($formats, $formats); } + /** + * {@inheritdoc} + */ + protected function getRoute($view_id, $display_id) { + $route = parent::getRoute($view_id, $display_id); + + $route->setRequirement('_format', implode('|', $this->getFormats())); + + return $route; + } + + /** + * Returns the list of formats provided by this display. + * + * @return string[] + * An array of format ids. + */ + protected function getFormats() { + $style_plugin = $this->getPlugin('style'); + + $formats = $style_plugin->getFormats(); + + // If there are no configured formats, add all formats that serialization + // is known to support. + if (!$formats) { + $formats = $this->getFormatOptions(); + } + + return $formats; + } + + /** + * {@inheritdoc} + */ + public function getPath() { + $path = parent::getPath(); + $formats = $this->getFormats(); + + return $path . '?_format=' . reset($formats); + } + } diff --git a/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_rest_display_menu.yml b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_rest_display_menu.yml new file mode 100644 index 0000000000..bbceddff5c --- /dev/null +++ b/core/modules/rest/tests/modules/rest_test_views/test_views/views.view.test_rest_display_menu.yml @@ -0,0 +1,231 @@ +langcode: en +status: true +dependencies: + config: + - system.menu.main + module: + - node + - rest + - serialization + - user +id: test_rest_display_menu +label: 'REST Display Menu Test' +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: nid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + 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 + pager: + type: mini + options: + items_per_page: 10 + offset: 0 + id: 0 + total_pages: null + 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 + tags: + previous: ‹‹ + next: ›› + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: fields + options: + inline: { } + separator: '' + hide_empty: false + default_field_elements: true + fields: + title: + id: title + table: node_field_data + field: title + entity_type: node + entity_field: title + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + settings: + link_to_entity: true + plugin_id: field + relationship: none + group_type: group + admin_label: '' + exclude: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_alter_empty: true + click_sort_column: value + type: string + 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 + filters: + status: + value: '1' + table: node_field_data + field: status + plugin_id: boolean + entity_type: node + entity_field: status + id: status + expose: + operator: '' + group: 1 + sorts: + created: + id: created + table: node_field_data + field: created + order: DESC + entity_type: node + entity_field: created + plugin_id: date + relationship: none + group_type: group + admin_label: '' + exposed: false + expose: + label: '' + granularity: second + header: { } + footer: { } + empty: { } + relationships: { } + arguments: { } + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: test-view/rest-menu/page + menu: + type: normal + title: Page + description: '' + expanded: false + parent: '' + weight: 0 + context: '0' + menu_name: main + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + rest_export_1: + display_plugin: rest_export + id: rest_export_1 + display_title: 'REST export' + position: 2 + display_options: + display_extenders: { } + path: test-view/rest-menu/json + menu: + type: normal + title: JSON + description: '' + expanded: false + parent: '' + weight: 1 + context: '0' + menu_name: main + style: + type: serializer + options: + uses_fields: false + formats: + json: json + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - request_format + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/core/modules/rest/tests/src/Functional/Views/RestDisplayMenuTest.php b/core/modules/rest/tests/src/Functional/Views/RestDisplayMenuTest.php new file mode 100644 index 0000000000..301893d1d5 --- /dev/null +++ b/core/modules/rest/tests/src/Functional/Views/RestDisplayMenuTest.php @@ -0,0 +1,64 @@ +drupalLogin($this->drupalCreateUser(['access content', 'administer views'])); + + $this->drupalPlaceBlock('system_menu_block:main', [ + 'id' => 'test_menu', + ]); + } + + /** + * + */ + public function testRestMenuOption() { + $this->drupalGet('admin/structure/views'); + $this->assertSession()->statusCodeEquals(200); + + $this->drupalGet('admin/structure/views/view/test_rest_display_menu/edit/page_1'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->linkByHrefExists('admin/structure/views/nojs/display/test_rest_display_menu/page_1/menu'); + + $this->drupalGet('admin/structure/views/view/test_rest_display_menu/edit/rest_export_1'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->linkByHrefExists('admin/structure/views/nojs/display/test_rest_display_menu/rest_export_1/menu'); + + $this->drupalGet(''); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->linkExists('Page'); + $this->assertSession()->linkByHrefExists('test-view/rest-menu/page'); + $this->assertSession()->linkExists('JSON'); + $this->assertSession()->linkByHrefExists('test-view/rest-menu/json?_format=json'); + } + +}