Skip to content
Snippets Groups Projects
Commit 993a8603 authored by catch's avatar catch
Browse files

Issue #2154781 by ParisLiakos: Convert aggregator/sources and aggregator/opml to views.

parent 1cbe233f
Branches
Tags
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
Showing with 475 additions and 104 deletions
......@@ -8,9 +8,6 @@ aggregator.page_last:
title: 'Feed aggregator'
weight: 5
route_name: aggregator.page_last
aggregator.sources:
title: Sources
route_name: aggregator.sources
aggregator.feed_add:
title: 'Add feed'
route_name: aggregator.feed_add
......@@ -20,17 +20,22 @@
function aggregator_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.aggregator':
$path_validator = \Drupal::pathValidator();
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Aggregator module is an on-site syndicator and news reader that gathers and displays fresh content from RSS-, RDF-, and Atom-based feeds made available across the web. Thousands of sites (particularly news sites and blogs) publish their latest headlines in feeds, using a number of standardized XML-based formats. For more information, see the <a href="!aggregator-module">online documentation for the Aggregator module</a>.', array('!aggregator-module' => 'https://drupal.org/documentation/modules/aggregator')) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
if ($url = $path_validator->getUrlIfValid('aggregator/sources')) {
$output .= '<dt>' . t('Viewing feeds') . '</dt>';
$output .= '<dd>' . t('Users view feed content in the <a href="!aggregator">main aggregator display</a>, or by <a href="!aggregator-sources">their source</a> (usually via an RSS feed reader). The most recent content in a feed can be displayed as a block through the <a href="!admin-block">Blocks administration page</a>.', array('!aggregator' => \Drupal::url('aggregator.page_last'), '!aggregator-sources' => \Drupal::url('aggregator.sources'), '!admin-block' => \Drupal::url('block.admin_display'))) . '</dd>';
$output .= '<dd>' . t('Users view feed content in the <a href="!aggregator">main aggregator display</a>, or by <a href="!aggregator-sources">their source</a> (usually via an RSS feed reader). The most recent content in a feed can be displayed as a block through the <a href="!admin-block">Blocks administration page</a>.', array('!aggregator' => \Drupal::url('aggregator.page_last'), '!aggregator-sources' => $url->toString(), '!admin-block' => \Drupal::url('block.admin_display'))) . '</dd>';
}
$output .= '<dt>' . t('Adding, editing, and deleting feeds') . '</dt>';
$output .= '<dd>' . t('Administrators can add, edit, and delete feeds, and choose how often to check each feed for newly updated items on the <a href="!feededit">Feed aggregator administration page</a>.', array('!feededit' => \Drupal::url('aggregator.admin_overview'))) . '</dd>';
$output .= '<dt>' . t('<abbr title="Outline Processor Markup Language">OPML</abbr> integration') . '</dt>';
$output .= '<dd>' . t('A <a href="!aggregator-opml">machine-readable OPML file</a> of all feeds is available. OPML is an XML-based file format used to share outline-structured information such as a list of RSS feeds. Feeds can also be <a href="!import-opml">imported via an OPML file</a>.', array('!aggregator-opml' => \Drupal::url('aggregator.opml_page'), '!import-opml' => \Drupal::url('aggregator.opml_add'))) . '</dd>';
if ($url = $path_validator->getUrlIfValid('aggregator/opml')) {
$output .= '<dd>' . t('A <a href="!aggregator-opml">machine-readable OPML file</a> of all feeds is available. OPML is an XML-based file format used to share outline-structured information such as a list of RSS feeds. Feeds can also be <a href="!import-opml">imported via an OPML file</a>.', array('!aggregator-opml' => $url->toString(), '!import-opml' => \Drupal::url('aggregator.opml_add'))) . '</dd>';
}
$output .= '<dt>' . t('Configuring cron') . '</dt>';
$output .= '<dd>' . t('A working <a href="!cron">cron maintenance task</a> is required to update feeds automatically.', array('!cron' => \Drupal::url('system.cron_settings'))) . '</dd>';
$output .= '</dl>';
......@@ -70,10 +75,6 @@ function aggregator_theme() {
'file' => 'aggregator.theme.inc',
'template' => 'aggregator-item',
),
'aggregator_page_opml' => array(
'variables' => array('feeds' => NULL),
'file' => 'aggregator.theme.inc',
),
);
}
......
......@@ -84,19 +84,3 @@ aggregator.page_last:
_title: 'Feed aggregator'
requirements:
_permission: 'access news feeds'
aggregator.sources:
path: '/aggregator/sources'
defaults:
_content: '\Drupal\aggregator\Controller\AggregatorController::sources'
_title: 'Sources'
requirements:
_permission: 'access news feeds'
aggregator.opml_page:
path: '/aggregator/opml'
defaults:
_title: 'OPML feed'
_controller: '\Drupal\aggregator\Controller\AggregatorController::opmlPage'
requirements:
_permission: 'access news feeds'
......@@ -29,37 +29,6 @@ function template_preprocess_aggregator_item(&$variables) {
$variables['title'] = String::checkPlain($item->label());
}
/**
* Prints the OPML page for the feed.
*
* @param array $variables
* An associative array containing:
* - feeds: An array of the feeds to theme.
*
* @return string
* An OPML formatted string.
*
* @ingroup themeable
*/
function theme_aggregator_page_opml($variables) {
$feeds = $variables['feeds'];
$output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
$output .= "<opml version=\"1.1\">\n";
$output .= "<head>\n";
$output .= '<title>' . String::checkPlain(\Drupal::config('system.site')->get('name')) . "</title>\n";
$output .= '<dateModified>' . gmdate(DATE_RFC2822, REQUEST_TIME) . "</dateModified>\n";
$output .= "</head>\n";
$output .= "<body>\n";
foreach ($feeds as $feed) {
$output .= '<outline text="' . String::checkPlain($feed->label()) . '" xmlUrl="' . check_url($feed->getUrl()) . "\" />\n";
}
$output .= "</body>\n";
$output .= "</opml>\n";
return $output;
}
/**
* Prepares variables for aggregator feed templates.
*
......
id: aggregator_sources
label: 'Aggregator sources'
module: aggregator
description: ''
tag: aggregator
base_table: aggregator_feed
base_field: fid
core: 8.x
langcode: en
status: true
dependencies:
module:
- aggregator
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
provider: views
display_options:
access:
type: perm
options:
perm: 'access news feeds'
provider: null
cache:
type: none
options: { }
provider: views
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: false
query_tags: { }
provider: views
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
provider: views
pager:
type: full
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: ' previous'
next: 'next ›'
first: '« first'
last: 'last »'
quantity: 9
style:
type: default
row:
type: 'entity:aggregator_feed'
options:
relationship: none
view_mode: summary
fields:
fid:
table: aggregator_feed
field: fid
id: fid
plugin_id: numeric
provider: views
relationship: none
group_type: group
admin_label: ''
dependencies: { }
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: ''
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: 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_empty: false
empty_zero: false
hide_alter_empty: true
set_precision: false
precision: 0
decimal: .
separator: ','
format_plural: false
format_plural_singular: '1'
format_plural_plural: '@count'
prefix: ''
suffix: ''
filters: { }
sorts: { }
title: Sources
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
provider: views
display_options:
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
path: aggregator/sources
menu:
type: normal
title: Sources
description: ''
weight: 0
context: '0'
menu_name: tools
feed_1:
display_plugin: feed
id: feed_1
display_title: Feed
position: 2
provider: views
display_options:
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
style:
type: opml
options:
grouping: { }
provider: views
path: aggregator/opml
fields:
title:
id: title
table: aggregator_feed
field: title
relationship: none
group_type: group
admin_label: ''
dependencies:
module:
- aggregator
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: ''
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
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
display_as_link: false
plugin_id: aggregator_title_link
provider: aggregator
url:
id: url
table: aggregator_feed
field: url
relationship: none
group_type: group
admin_label: ''
dependencies:
module:
- views
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: ''
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
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
display_as_link: false
plugin_id: url
provider: views
description:
id: description
table: aggregator_feed
field: description
relationship: none
group_type: group
admin_label: ''
dependencies:
module:
- views
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: ''
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
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
plugin_id: xss
provider: views
link:
id: link
table: aggregator_feed
field: link
relationship: none
group_type: group
admin_label: ''
dependencies:
module:
- views
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: ''
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
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
display_as_link: false
plugin_id: url
provider: views
defaults:
fields: false
title: false
row:
type: opml_fields
options:
type_field: rss
text_field: title
created_field: ''
description_field: description
html_url_field: link
language_field: ''
xml_url_field: url
url_field: ''
provider: views
displays:
page_1: page_1
default: '0'
title: 'OPML feed'
sitename_title: true
# Schema for the views plugins of the Aggregator module.
"views.row.entity:aggregator_feed":
type: views_entity_row
label: 'Entity options'
"views.row.entity:aggregator_item":
type: views_entity_row
label: 'Entity options'
views.argument.aggregator_fid:
type: views.argument.numeric
label: 'Aggregator feed ID'
......
......@@ -179,52 +179,6 @@ public function pageLast() {
return $build;
}
/**
* Displays all the feeds used by the Aggregator module.
*
* @return array
* A render array as expected by drupal_render().
*/
public function sources() {
$entity_manager = $this->entityManager();
$feeds = $entity_manager->getStorage('aggregator_feed')->loadMultiple();
$build = $entity_manager->getViewBuilder('aggregator_feed')
->viewMultiple($feeds, 'summary');
$build['feed_icon'] = array(
'#theme' => 'feed_icon',
'#url' => 'aggregator/opml',
'#title' => $this->t('OPML feed'),
);
return $build;
}
/**
* Generates an OPML representation of all feeds.
*
* @return \Symfony\Component\HttpFoundation\Response
* The response containing the OPML.
*/
public function opmlPage() {
$feeds = $this->entityManager()
->getStorage('aggregator_feed')
->loadMultiple();
$feeds = $result->fetchAll();
$aggregator_page_opml = array(
'#theme' => 'aggregator_page_opml',
'#feeds' => $feeds,
);
$output = drupal_render($aggregator_page_opml);
$response = new Response();
$response->headers->set('Content-Type', 'text/xml; charset=utf-8');
$response->setContent($output);
return $response;
}
/**
* Route title callback.
*
......
......@@ -44,7 +44,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
$this->entity->delete();
$this->logger('aggregator')->notice('Feed %feed deleted.', array('%feed' => $this->entity->label()));
drupal_set_message($this->t('The feed %feed has been deleted.', array('%feed' => $this->entity->label())));
$form_state->setRedirect('aggregator.sources');
$form_state->setRedirect('aggregator.admin_overview');
}
}
......@@ -113,6 +113,18 @@ public function testFeedPage() {
$cache_tags = explode(' ', $cache_tags_header);
$this->assertTrue(in_array('aggregator_feed:' . $feed->id(), $cache_tags));
// Check the rss aggregator page.
$this->drupalGet('aggregator/rss');
$this->assertResponse(200);
$this->assertEqual($this->drupalGetHeader('Content-type'), 'application/rss+xml; charset=utf-8');
// Check the opml aggregator page.
$this->drupalGet('aggregator/opml');
$outline = $this->xpath('//outline[1]');
$this->assertEqual($outline[0]['type'], 'rss', 'The correct type attribute is used for rss OPML.');
$this->assertEqual($outline[0]['text'], $feed->label(), 'The correct text attribute is used for rss OPML.');
$this->assertEqual($outline[0]['xmlurl'], $feed->getUrl(), 'The correct xmlUrl attribute is used for rss OPML.');
// Check for the presence of a pager.
$this->drupalGet('aggregator/sources/' . $feed->id());
$elements = $this->xpath("//ul[@class=:class]", array(':class' => 'pager'));
......
......@@ -49,3 +49,32 @@ views.row.rss_fields:
guid_field_is_permalink:
type: boolean
label: 'GUID is permalink'
views.row.opml_fields:
type: views_row
label: 'OPML field options'
mapping:
type_field:
type: string
label: 'Type attribute'
text_field:
type: string
label: 'Text attribute'
created_field:
type: string
label: 'Created attribute'
description_field:
type: string
label: 'Description attribute'
html_url_field:
type: string
label: 'HTML URL attribute'
language_field:
type: string
label: 'Language attribute'
xml_url_field:
type: string
label: 'XML URL attribute'
url_field:
type: string
label: 'URL attribute'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment