WP RSS Aggregator - Version 4.17.4

Version Description

(2020-03-16) = Changed - The default template is now created based on type, not slug.

Fixed - Templates could not be saved if the request contained extra form data. - The default template would be copied multiple times if a post on the site had the "default" slug. - Feed item title did not escape HTML entities correctly. - Source name and link were sometimes incorrect in the custom feed. - Undefined index during error handling. - Better error messages when an error occurs.

Download this release

Release Info

Developer Mekku
Plugin Icon 128x128 WP RSS Aggregator
Version 4.17.4
Comparing to
See all releases

Code changes from version 4.17.3 to 4.17.4

CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  ## [4.17.3] - 2020-01-23
8
  ### Changed
9
  * Updated code to fix deprecation warnings on PHP version 7.4 and later.
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
 
7
+ ## [4.17.4] - 2020-03-16
8
+ ### Changed
9
+ * The default template is now created based on type, not slug.
10
+
11
+ ### Fixed
12
+ * Templates could not be saved if the request contained extra form data.
13
+ * The default template would be copied multiple times if a post on the site had the "default" slug.
14
+ * Feed item title did not escape HTML entities correctly.
15
+ * Source name and link were sometimes incorrect in the custom feed.
16
+ * Undefined index during error handling.
17
+ * Better error messages when an error occurs.
18
+
19
  ## [4.17.3] - 2020-01-23
20
  ### Changed
21
  * Updated code to fix deprecation warnings on PHP version 7.4 and later.
includes/admin-display.php CHANGED
@@ -424,30 +424,8 @@
424
  * @since 3.5
425
  * @param int $source_id The ID of the feed source
426
  */
427
- function wprss_delete_feed_items_of_feed_source( $source_id ) {
428
- $force_delete = apply_filters( 'wprss_force_delete_when_by_source', TRUE );
429
- // WPML fix: removes the current language from the query WHERE and JOIN clauses
430
- global $sitepress;
431
- if ( $sitepress !== NULL ) {
432
- remove_filter( 'posts_join', array( $sitepress,'posts_join_filter') );
433
- remove_filter( 'posts_where', array( $sitepress,'posts_where_filter') );
434
- }
435
- // Run the query
436
- $query = new WP_Query(
437
- array(
438
- 'meta_key' => 'wprss_feed_id',
439
- 'meta_value' => $source_id,
440
- 'post_type' => get_post_types(),
441
- 'post_status' => 'any',
442
- 'posts_per_page' => -1
443
- )
444
- );
445
- $query = apply_filters( 'wprss_delete_per_source_query', $query, $source_id );
446
- // Delete the results of the query
447
- while( $query->have_posts() ) {
448
- $query->the_post();
449
- wp_delete_post( get_the_ID(), $force_delete );
450
- }
451
 
452
  update_post_meta($source_id, 'wprss_feed_is_deleting_items', '');
453
  }
424
  * @since 3.5
425
  * @param int $source_id The ID of the feed source
426
  */
427
+ function wprss_delete_feed_items_of_feed_source($source_id) {
428
+ wprss_delete_feed_items($source_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
 
430
  update_post_meta($source_id, 'wprss_feed_is_deleting_items', '');
431
  }
includes/cron-jobs.php CHANGED
@@ -24,8 +24,8 @@ function wpra_on_cron_do($cron, $callback)
24
  // Cron events
25
  wpra_on_cron_do(WPRA_FETCH_ALL_FEEDS_HOOK, 'wprss_fetch_insert_all_feed_items_from_cron');
26
  wpra_on_cron_do(WPRA_TRUNCATE_ITEMS_HOOK, 'wprss_truncate_posts');
27
- wpra_on_cron_do(WPRA_ACTIVATE_FEED_HOOK, 'wprss_activate_feed_source', 10, 1);
28
- wpra_on_cron_do(WPRA_PAUSE_FEED_HOOK, 'wprss_pause_feed_source', 10, 1);
29
 
30
  // Initialize crons that must always be scheduled
31
  add_action('init', 'wpra_init_crons');
24
  // Cron events
25
  wpra_on_cron_do(WPRA_FETCH_ALL_FEEDS_HOOK, 'wprss_fetch_insert_all_feed_items_from_cron');
26
  wpra_on_cron_do(WPRA_TRUNCATE_ITEMS_HOOK, 'wprss_truncate_posts');
27
+ wpra_on_cron_do(WPRA_ACTIVATE_FEED_HOOK, 'wprss_activate_feed_source');
28
+ wpra_on_cron_do(WPRA_PAUSE_FEED_HOOK, 'wprss_pause_feed_source');
29
 
30
  // Initialize crons that must always be scheduled
31
  add_action('init', 'wpra_init_crons');
includes/feed-processing.php CHANGED
@@ -65,33 +65,54 @@
65
  }
66
 
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  /**
69
  * Returns all the feed items of a source.
70
  *
71
  * @since 3.8
72
  */
73
  function wprss_get_feed_items_for_source( $source_id ) {
74
- $args = apply_filters(
75
- 'wprss_get_feed_items_for_source_args',
76
- array(
77
- 'post_type' => get_post_types(),
78
- 'cache_results' => false, // Disable caching, used for one-off queries
79
- 'no_found_rows' => true, // We don't need pagination, so disable it
80
- 'posts_per_page' => -1,
81
- 'ignore_sticky_posts' => 'true',
82
- 'orderby' => 'date',
83
- 'order' => 'DESC',
84
- 'meta_query' => array(
85
- array(
86
- 'key' => 'wprss_feed_id',
87
- 'value' => $source_id,
88
- 'compare' => '=',
89
- ),
90
- ),
91
- 'suppress_filters' => 1
92
- ), $source_id
93
- );
94
- return new WP_Query( $args );
95
  }
96
 
97
 
@@ -343,29 +364,22 @@
343
  *
344
  * @since 2.0
345
  */
346
- function wprss_delete_feed_items( $postid ) {
347
-
348
- $args = array(
349
- 'post_type' => 'wprss_feed_item',
350
- // Next 3 parameters for performance, see http://thomasgriffinmedia.com/blog/2012/10/optimize-wordpress-queries
351
- 'cache_results' => false, // Disable caching, used for one-off queries
352
- 'no_found_rows' => true, // We don't need pagination, so disable it
353
- 'fields' => 'ids', // Returns post IDs only
354
- 'posts_per_page'=> -1,
355
- 'meta_query' => array(
356
- array(
357
- 'key' => 'wprss_feed_id',
358
- 'value' => $postid,
359
- 'compare' => 'LIKE'
360
- )
361
- )
362
- );
363
 
364
- $feed_item_ids = get_posts( $args );
365
- foreach( $feed_item_ids as $feed_item_id ) {
366
- $purge = wp_delete_post( $feed_item_id, true ); // delete the feed item, skipping trash
 
 
367
  }
368
- wp_reset_postdata();
369
  }
370
 
371
 
@@ -376,27 +390,12 @@
376
  * @since 3.0
377
  */
378
  function wprss_delete_all_feed_items() {
379
- $args = [
380
- 'post_type' => get_post_types(),
381
- 'suppress_filters' => true,
382
- 'cache_results' => false,
383
- 'fields' => 'ids',
384
- 'posts_per_page' => -1,
385
- 'meta_query' => [
386
- 'relation' => 'AND',
387
- [
388
- 'key' => 'wprss_feed_id',
389
- 'compare' => 'EXISTS',
390
- ],
391
- ],
392
- ];
393
-
394
  $items = get_posts($args);
 
395
  foreach ($items as $item) {
396
- $purge = wp_delete_post($item, true);
397
  }
398
-
399
- wp_reset_postdata();
400
  }
401
 
402
 
65
  }
66
 
67
 
68
+ /**
69
+ * Retrieves the query to use for retrieving imported items.
70
+ *
71
+ * @since 4.17.4
72
+ */
73
+ function wprss_get_imported_items_query($source_id = null) {
74
+ $args = [
75
+ 'post_type' => array_values(get_post_types()),
76
+ 'post_status' => 'any',
77
+ 'cache_results' => false,
78
+ 'no_found_rows' => true,
79
+ 'posts_per_page' => -1,
80
+ 'ignore_sticky_posts' => 'true',
81
+ 'orderby' => 'date',
82
+ 'order' => 'DESC',
83
+ 'meta_query' => [
84
+ 'relation' => 'AND',
85
+ ],
86
+ 'suppress_filters' => 1
87
+ ];
88
+
89
+ if ($source_id !== null) {
90
+ $args['meta_query'][] = [
91
+ 'key' => 'wprss_feed_id',
92
+ 'value' => (string) $source_id,
93
+ 'compare' => '=',
94
+ ];
95
+ }
96
+
97
+ return apply_filters('wprss_get_feed_items_for_source_args', $args, $source_id);
98
+ }
99
+
100
+ /**
101
+ * Queries for imported items.
102
+ *
103
+ * @since 4.17.4
104
+ */
105
+ function wprss_get_imported_items($source_id = null) {
106
+ return new WP_Query(wprss_get_imported_items_query($source_id));
107
+ }
108
+
109
  /**
110
  * Returns all the feed items of a source.
111
  *
112
  * @since 3.8
113
  */
114
  function wprss_get_feed_items_for_source( $source_id ) {
115
+ return wprss_get_imported_items($source_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
 
118
 
364
  *
365
  * @since 2.0
366
  */
367
+ function wprss_delete_feed_items ($source_id) {
368
+ $force_delete = apply_filters('wprss_force_delete_when_by_source', true);
369
+
370
+ // WPML fix: removes the current language from the query WHERE and JOIN clauses
371
+ global $sitepress;
372
+ if ($sitepress !== null) {
373
+ remove_filter('posts_join', [$sitepress,'posts_join_filter']);
374
+ remove_filter('posts_where', [$sitepress,'posts_where_filter']);
375
+ }
 
 
 
 
 
 
 
 
376
 
377
+ $args = wprss_get_imported_items_query($source_id);
378
+ $items = get_posts($args);
379
+
380
+ foreach ($items as $item) {
381
+ wp_delete_post($item->ID, $force_delete);
382
  }
 
383
  }
384
 
385
 
390
  * @since 3.0
391
  */
392
  function wprss_delete_all_feed_items() {
393
+ $args = wprss_get_imported_items_query();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
  $items = get_posts($args);
395
+
396
  foreach ($items as $item) {
397
+ wp_delete_post($item->ID, true);
398
  }
 
 
399
  }
400
 
401
 
lib/Entities/Entity.php CHANGED
@@ -91,7 +91,9 @@ class Entity implements EntityInterface
91
 
92
  foreach ($data as $key => $value) {
93
  if (!array_key_exists($key, $this->props)) {
94
- throw new OutOfBoundsException();
 
 
95
  }
96
 
97
  try {
91
 
92
  foreach ($data as $key => $value) {
93
  if (!array_key_exists($key, $this->props)) {
94
+ throw new OutOfBoundsException(
95
+ sprintf("Entity does not have key \"%s\" in: %s", $key, json_encode($data))
96
+ );
97
  }
98
 
99
  try {
readme.txt CHANGED
@@ -1,97 +1,95 @@
1
  === WP RSS Aggregator ===
2
- Contributors: RebelCode, jeangalea, markzahra, Mekku, xedin.unknown
3
  Plugin URI: https://www.wprssaggregator.com
4
- Tags: RSS import, RSS aggregator, feed import, content curation, feed to post
5
  Requires at least: 4.0 or higher
6
  Tested up to: 5.3
7
  Requires PHP: 5.4
8
- Stable tag: 4.17.3
9
  License: GPLv3
10
 
11
- WP RSS Aggregator is the original & most popular WordPress solution for importing RSS feeds, auto-blogging, content curation & aggregation.
12
 
13
  == Description ==
14
 
15
- WP RSS Aggregator is the original and best plugin for importing, merging and displaying RSS and Atom feeds on your WordPress site. It's the most comprehensive and elegant RSS feed importer for WordPress.
16
 
17
  == Automatically import RSS feeds & display them on your site ==
18
 
19
- * No limit on the number of sources to import from.
20
  * Manage all your sources from a single page.
21
- * No limit on the number of items to import.
22
- * Automate each feed's import with unique or global schedules.
23
- * Customisable [templates](https://kb.wprssaggregator.com/article/457-templates) with various styling options.
24
- * Built-in [shortcode](https://kb.wprssaggregator.com/article/54-how-to-use-the-shortcode-to-display-feed-items) and [block](https://kb.wprssaggregator.com/article/454-displaying-imported-items-block-gutenberg) to display items.
25
- * Feed auto-discovery (add sources without the exact RSS feed URL).
26
- * Youtube importing using just a channel or user URL.
27
- * Playable Youtube videos directly on your site.
28
- * Limit the items stored and fetched for better performance.
29
- * Create a custom RSS feed from imported items.
30
  * Extendable via action and filter hooks.
31
 
32
- [Click here to learn more about the free WP RSS Aggregator plugin.](https://www.wprssaggregator.com/extension/core-plugin/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_learn_more&utm_content=learn_more)
33
 
34
- == Who is the plugin for?? ==
35
 
36
- Importing and displaying RSS feeds is helpful for many types of sites:
37
 
38
- * Curate news, videos and more from the top sources in your niche.
39
- * Add related posts from other sites to your site.
40
- * Share Youtube videos anywhere on your site.
41
- * Curate job, real estate or other listings for your market or niche.
42
- * Embed videos from other sources (Youtube) to engage more visitors.
43
- * Aggregate podcast episodes related to your hobby or profession.
44
- * Writers, display your works from multiple sites in your portfolio.
45
- * And much more...
46
 
47
- For example...
48
 
49
- * [WP News Desk](http://wpnewsdesk.com/) curates WordPress news, tutorials and more from over 100 trusted sources.
50
- * [Travel Blogger Community](http://travelbloggercommunity.com/) does something similar to share blog posts from well-known travellers.
51
- * [Crypto Headlines](https://cryptoheadlines.com/youtube-videos/)' videos page shares Youtube videos from popular Youtubers in the Crypto world.
52
- * [Euro Finance Blogs](https://eurofinanceblogs.com/) curates content on investment, personal finance and early retirement.
53
 
54
- Browse through our [**Showcase**](https://www.wprssaggregator.com/showcase/) to see how WP RSS Aggregator is being put to great use on a large variety of WordPress sites.
55
 
56
- == Attention bloggers, content marketers, site owners ==
57
 
58
- Increase your WordPress site's credibility and popularity by importing full or partial posts, videos, and more into your site with our premium add-ons.
59
 
60
- * Beginner Bloggers and Copywriters - Find and display fresh, new content to **engage and grow your audience**.
61
- * Site Owners & Content Marketers - Curate content to **keep your avid readers on your site for longer**.
62
 
63
- == SEO benefits from importing RSS feeds ==
 
 
 
64
 
65
- Importing RSS feeds alone won't improve your site's SEO, however, if you curate content (articles, tutorials, videos, listings, etc) and bring in quality traffic, the benefits begin to appear:
66
 
 
 
 
 
 
67
  * Generate lots of new backlinks to your site.
68
  * Enhance your online presence and gain more trust.
69
- * And therefore, you can help boost your SEO! [Learn more from WP Mayor.](https://wpmayor.com/3-ways-content-curation-impacts-your-sites-seo/)
70
 
71
- *Quick note: Please don't steal other people's work; give credit where it's due.*
72
 
73
- == Premium add-ons for additional functionality ==
74
 
75
- WP RSS Aggregator can be extended through a set of [premium add-ons](https://www.wprssaggregator.com/extensions/) that are also available as part of our discounted [pricing plans](https://www.wprssaggregator.com/pricing/).
76
 
77
- * **[Templates](https://www.wprssaggregator.com/extension/templates/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_f2p_link&utm_content=f2p_link)** offers premium template types including the fully customisable Grid as well as an Excerpts & Thumbnails template that take your block or shortcake displays to a whole new level!
78
- * **[Feed to Post](https://www.wprssaggregator.com/extension/feed-to-post/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_f2p_link&utm_content=f2p_link)** is the most powerful add-on available, enabling you to import items as Posts or any other custom post type. It includes options such as automatically assigning post type, post status, categories, tags, images, authors and much more.
79
- * **[Full Text RSS Feeds](https://www.wprssaggregator.com/extension/full-text-rss-feeds/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_ftr_link&utm_content=ftr_link)** takes Feed to Post to the next level by connecting it to our premium full text service. This helps bring in content from sources that don't provide it in their RSS feeds.
 
 
80
  * **[Keyword Filtering](https://www.wprssaggregator.com/extension/keyword-filtering/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_kf_link&utm_content=kf_link)** enables you to filter the content imported from any source based on keywords, phrases and/or tags.
81
  * **[Categories](https://www.wprssaggregator.com/extension/categories/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)** provides a simple way to categorise your sources and keep them organised.
82
  * **[WordAi](https://www.wprssaggregator.com/extension/wordai/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)** and **[Spinner Chief](https://www.wprssaggregator.com/extension/spinnerchief/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)** integrate the Feed to Post add-on with the respective 3rd-party content spinning services.
83
 
84
- Here's a closer look at what the Feed to Post add-on offers:
85
-
86
- [youtube https://www.youtube.com/watch?v=-2z_bNws2MM]
87
-
88
  == We stand behind what we build ==
89
 
90
  Our comprehensive [Knowledge Base](https://kb.wprssaggregator.com/) provides you with everything you need to install, set up and customise the plugin to your needs. You can also browse through a number of FAQs to get started.
91
 
92
  If that doesn't do the trick, we provide support for the free version of WP RSS Aggregator via the support forum [here](https://wordpress.org/support/plugin/wp-rss-aggregator), while for premium support (owners of valid premium add-on licenses) and pre-sales questions please contact us via our [premium support channel](https://www.wprssaggregator.com/contact/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_contact_link&utm_content=contact_link).
93
 
94
- Our plugin also includes a Help Beacon within your dashboard through which you can search our knowledge base or contact our team (premium users only) without ever leaving your website!
95
 
96
  == Additional information ==
97
 
@@ -101,21 +99,17 @@ Our terms & conditions can be found [here](https://www.wprssaggregator.com/terms
101
 
102
  == High praise from trusted WordPress leaders ==
103
 
 
 
 
104
  * [Toolset](https://toolset.com/2019/03/import-content-post-typewp-rss-aggregator/)
105
  * [WP Explorer](https://www.wpexplorer.com/wp-rss-aggregator-review/)
106
  * [MH Themes](https://mhthemes.com/blog/create-news-aggregator-site-with-wordpress/)
107
- * [WP Mayor](http://www.wpmayor.com/rss-feeds-review-wp-rss-aggregator/)
108
- * [MobiLoud](https://www.mobiloud.com/blog/wordpress-rss-aggregator/)
109
  * [WPulsar](http://www.wpulsar.com/wp-rss-aggregator-plugin-feed-to-posts-keyword-filtering-review/)
110
- * [Elegant Themes](https://www.elegantthemes.com/blog/tips-tricks/how-to-get-the-most-from-your-wordpress-rss-feed)
111
  * [Cloudways](https://www.cloudways.com/blog/wp-rss-aggregator-plugin-rss-feed-importer-autoblogging-plugin/)
112
  * [WPKube](http://www.wpkube.com/wp-rss-aggregator-wordpress-review/)
113
- * [MyWPexpert](http://www.mywpexpert.com/wordpress-rss-aggregator-plugin)
114
  * [Kevin Muldoon](https://www.kevinmuldoon.com/wp-rss-aggregator-review/)
115
- * [Magazine3](http://magazine3.com/blog/news-aggregator-website/)
116
- * [WPBeginner](http://www.wpbeginner.com/plugins/how-to-fetch-feeds-in-wordpress-using-wp-rss-aggregator/)
117
- * [Torque](http://torquemag.io/wp-rss-aggregator-review-do-more-with-rss-feeds/)
118
- * [IndexWP](http://www.indexwp.com/wp-rss-aggregator-plugin-review/)
119
 
120
  == Installation ==
121
 
@@ -259,6 +253,18 @@ Our complete Knowledge Base with FAQs can be found [here](https://kb.wprssaggreg
259
 
260
  == Changelog ==
261
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  = 4.17.3 (2020-01-23) =
263
  **Changed**
264
  - Updated code to fix deprecation warnings on PHP version 7.4 and later.
1
  === WP RSS Aggregator ===
2
+ Contributors: RebelCode, jeangalea, markzahra, Mekku, xedinunknown
3
  Plugin URI: https://www.wprssaggregator.com
4
+ Tags: RSS import, RSS aggregator, feed import, content curation, feed to post, news aggregator, autoblog, rss to post, content syndication
5
  Requires at least: 4.0 or higher
6
  Tested up to: 5.3
7
  Requires PHP: 5.4
8
+ Stable tag: 4.17.4
9
  License: GPLv3
10
 
11
+ The most popular RSS importer for WordPress. Aggregate and curate content from as many RSS feeds as you want while keeping everything organised.
12
 
13
  == Description ==
14
 
15
+ WP RSS Aggregator is the original and most comprehensive plugin for importing, merging, and displaying RSS and Atom feeds anywhere on your site within minutes. Set up your feeds and let the plugin do the leg-work.
16
 
17
  == Automatically import RSS feeds & display them on your site ==
18
 
19
+ * Import unlimited feeds from an unlimited number of sources.
20
  * Manage all your sources from a single page.
21
+ * Set up a schedule to automatically fetch fresh content.
22
+ * Customise your [templates](https://kb.wprssaggregator.com/article/457-templates) to blend into your theme.
23
+ * Built-in [shortcode](https://kb.wprssaggregator.com/article/54-how-to-use-the-shortcode-to-display-feed-items) and [block](https://kb.wprssaggregator.com/article/454-displaying-imported-items-block-gutenberg) options to display feeds.
24
+ * Feed auto-discovery for sources with hard-to-find RSS feeds.
25
+ * Import Youtube videos and have them playable on your site.
26
+ * Limit the items stored and fetched for improved performance.
27
+ * Create a custom RSS feed from imported items to use elsewhere.
 
 
28
  * Extendable via action and filter hooks.
29
 
30
+ [Learn more about the free version of WP RSS Aggregator.](https://www.wprssaggregator.com/extension/core-plugin/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_learn_more&utm_content=learn_more)
31
 
32
+ == Who is WP RSS Aggregator for? ==
33
 
34
+ Importing and displaying RSS feeds is a powerful tool for many websites.
35
 
36
+ * Aggregator or curate news from the top sources in your market or niche to improve your SEO and build a better reputation.
37
+ * Show related content from other reputable sites to build a sense of trust with your readers.
38
+ * Since video content has become so popular, link to Youtube videos anywhere on your site to provide visitors with more reasons to stick around.
39
+ * Provide value to your readers by curating job openings, real estate listings, or other information to help them grow.
40
+ * Aggregate ever-popular podcast episodes related to the topic of your website to keep visitors engaged.
41
+ * Authors, writers, and other content creators, display a feed of your work from multiple sites in a single portfolio.
 
 
42
 
43
+ == Real-life case studies ==
44
 
45
+ Erik Tozier built up trust and credibility in the personal finance space by curating quality content for his readers, resulting in over 16,000 monthly page views within just 4 months. [Read the full case study](https://www.wprssaggregator.com/case-study-personal-finance-blogs-content-curation/) or watch the video below.
 
 
 
46
 
47
+ [youtube https://www.youtube.com/watch?v=6kADte55kcY]
48
 
49
+ Ronald Heijnes has created a multilingual community within the WordPress space by aggregating the latest WordPress news from various sources in multiple languages. [Read the full case study](https://www.wprssaggregator.com/case-study-worldofwp-multilingual-news-aggregator/) or watch the video below.
50
 
51
+ [youtube https://www.youtube.com/watch?v=wGHNrSrz8BU]
52
 
53
+ === More examples ===
 
54
 
55
+ * [WP News Desk](http://wpnewsdesk.com/) aggregates WordPress news, tutorials and more from over 100 trusted sources and organises them into categories automatically.
56
+ * [Travel Blogger Community](http://travelbloggercommunity.com/) does something similar to share incredible blog posts from well-known travellers around the world.
57
+ * [Crypto Headlines](https://cryptoheadlines.com/youtube-videos/)' videos section shares Youtube videos from popular Youtubers in the Crypto space to keep readers informed.
58
+ * [Euro Finance Blogs](https://eurofinanceblogs.com/) curates content on investment, personal finance, and early retirement, similar to Erik's story above.
59
 
60
+ Browse through our [**Showcase**](https://www.wprssaggregator.com/showcase/) to see how WP RSS Aggregator is being put to great use on a large variety of WordPress sites, from CrossFit to celebrity news, and gaming to government updates.
61
 
62
+ == SEO benefits and other perks ==
63
+
64
+ By using WP RSS Aggregator you can increase your WordPress site's credibility and improve your SEO by importing full or partial posts, videos, and more with our [premium add-ons](https://www.wprssaggregator.com/pricing/).
65
+
66
+ * Become an instant source of quality content.
67
  * Generate lots of new backlinks to your site.
68
  * Enhance your online presence and gain more trust.
69
+ * And therefore, boost your SEO!
70
 
71
+ Find out more... [**Content curation and SEO: What you need to know**](https://www.wprssaggregator.com/is-content-curation-good-for-seo/)
72
 
73
+ *A word of advice: Don't steal other people's work; give credit where it's due. WP RSS Aggregator makes it super easy to automatically link to the original source every single time.*
74
 
75
+ == Premium features ==
76
 
77
+ WP RSS Aggregator can be extended through its powerful [premium add-ons](https://www.wprssaggregator.com/extensions/) and [discounted plans](https://www.wprssaggregator.com/pricing/).
78
+
79
+ * **[Feed to Post](https://www.wprssaggregator.com/extension/feed-to-post/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_f2p_link&utm_content=f2p_link)** is the most powerful add-on available, enabling you to import feeds into WordPress Posts or any other custom post type. It includes options such as automatically assigning a post type, the post status, categories, tags, images, authors, and more.
80
+ * **[Full Text RSS Feeds](https://www.wprssaggregator.com/extension/full-text-rss-feeds/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_ftr_link&utm_content=ftr_link)** takes Feed to Post to the next level by connecting it to our premium full text service. This helps bring in content from sources that don't provide it in their RSS feeds. It's especially useful when missing certain important images or other content.
81
+ * **[Templates](https://www.wprssaggregator.com/extension/templates/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_f2p_link&utm_content=f2p_link)** offers premium template types including the fully customisable Grid as well as an Excerpts & Thumbnails template that take your block or shortcode displays to a whole new level.
82
  * **[Keyword Filtering](https://www.wprssaggregator.com/extension/keyword-filtering/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_kf_link&utm_content=kf_link)** enables you to filter the content imported from any source based on keywords, phrases and/or tags.
83
  * **[Categories](https://www.wprssaggregator.com/extension/categories/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)** provides a simple way to categorise your sources and keep them organised.
84
  * **[WordAi](https://www.wprssaggregator.com/extension/wordai/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)** and **[Spinner Chief](https://www.wprssaggregator.com/extension/spinnerchief/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)** integrate the Feed to Post add-on with the respective 3rd-party content spinning services.
85
 
 
 
 
 
86
  == We stand behind what we build ==
87
 
88
  Our comprehensive [Knowledge Base](https://kb.wprssaggregator.com/) provides you with everything you need to install, set up and customise the plugin to your needs. You can also browse through a number of FAQs to get started.
89
 
90
  If that doesn't do the trick, we provide support for the free version of WP RSS Aggregator via the support forum [here](https://wordpress.org/support/plugin/wp-rss-aggregator), while for premium support (owners of valid premium add-on licenses) and pre-sales questions please contact us via our [premium support channel](https://www.wprssaggregator.com/contact/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_contact_link&utm_content=contact_link).
91
 
92
+ Our plugin also includes a Help Beacon within your dashboard through which you can search our knowledge base without ever leaving your website.
93
 
94
  == Additional information ==
95
 
99
 
100
  == High praise from trusted WordPress leaders ==
101
 
102
+ * [WP Mayor](http://www.wpmayor.com/rss-feeds-review-wp-rss-aggregator/)
103
+ * [WPBeginner](https://www.wpbeginner.com/showcase/best-news-aggregator-websites-how-to-build-your-own/)
104
+ * [OSTraining](https://www.ostraining.com/blog/wordpress/wp-rss-aggregator/)
105
  * [Toolset](https://toolset.com/2019/03/import-content-post-typewp-rss-aggregator/)
106
  * [WP Explorer](https://www.wpexplorer.com/wp-rss-aggregator-review/)
107
  * [MH Themes](https://mhthemes.com/blog/create-news-aggregator-site-with-wordpress/)
 
 
108
  * [WPulsar](http://www.wpulsar.com/wp-rss-aggregator-plugin-feed-to-posts-keyword-filtering-review/)
109
+ * [MobiLoud](https://www.mobiloud.com/blog/wordpress-rss-aggregator/)
110
  * [Cloudways](https://www.cloudways.com/blog/wp-rss-aggregator-plugin-rss-feed-importer-autoblogging-plugin/)
111
  * [WPKube](http://www.wpkube.com/wp-rss-aggregator-wordpress-review/)
 
112
  * [Kevin Muldoon](https://www.kevinmuldoon.com/wp-rss-aggregator-review/)
 
 
 
 
113
 
114
  == Installation ==
115
 
253
 
254
  == Changelog ==
255
 
256
+ = 4.17.4 (2020-03-16) =
257
+ **Changed**
258
+ - The default template is now created based on type, not slug.
259
+
260
+ **Fixed**
261
+ - Templates could not be saved if the request contained extra form data.
262
+ - The default template would be copied multiple times if a post on the site had the "default" slug.
263
+ - Feed item title did not escape HTML entities correctly.
264
+ - Source name and link were sometimes incorrect in the custom feed.
265
+ - Undefined index during error handling.
266
+ - Better error messages when an error occurs.
267
+
268
  = 4.17.3 (2020-01-23) =
269
  **Changed**
270
  - Updated code to fix deprecation warnings on PHP version 7.4 and later.
src/Data/AbstractDataSet.php CHANGED
@@ -29,7 +29,7 @@ abstract class AbstractDataSet implements DataSetInterface
29
  }
30
  } catch (Exception $exception) {
31
  throw new RuntimeException(
32
- sprintf('An error occurred while reading the value for the "%s" key', $key), null, $exception
33
  );
34
  }
35
 
@@ -47,7 +47,7 @@ abstract class AbstractDataSet implements DataSetInterface
47
  return $this->has($key);
48
  } catch (Exception $exception) {
49
  throw new RuntimeException(
50
- sprintf('An error occurred while looking up the "%s" key', $key), null, $exception
51
  );
52
  }
53
  }
@@ -63,7 +63,7 @@ abstract class AbstractDataSet implements DataSetInterface
63
  $this->set($key, $value);
64
  } catch (Exception $exception) {
65
  throw new RuntimeException(
66
- sprintf('An error occurred while writing to the "%s" key', $key), null, $exception
67
  );
68
  }
69
  }
@@ -79,7 +79,7 @@ abstract class AbstractDataSet implements DataSetInterface
79
  $this->delete($key);
80
  } catch (Exception $exception) {
81
  throw new RuntimeException(
82
- sprintf('An error occurred while deleting the "%s" key', $key), null, $exception
83
  );
84
  }
85
  }
29
  }
30
  } catch (Exception $exception) {
31
  throw new RuntimeException(
32
+ sprintf('Key read error ("%s"): %s', $key, $exception->getMessage()), null, $exception
33
  );
34
  }
35
 
47
  return $this->has($key);
48
  } catch (Exception $exception) {
49
  throw new RuntimeException(
50
+ sprintf('Key read error ("%s"): %s', $key, $exception->getMessage()), null, $exception
51
  );
52
  }
53
  }
63
  $this->set($key, $value);
64
  } catch (Exception $exception) {
65
  throw new RuntimeException(
66
+ sprintf('Key write error ("%s"): %s', $key, $exception->getMessage()), null, $exception
67
  );
68
  }
69
  }
79
  $this->delete($key);
80
  } catch (Exception $exception) {
81
  throw new RuntimeException(
82
+ sprintf('Key delete error ("%s"): %s', $key, $exception->getMessage()), null, $exception
83
  );
84
  }
85
  }
src/Entities/Properties/WpraItemSourceProperty.php CHANGED
@@ -68,17 +68,20 @@ class WpraItemSourceProperty implements PropertyInterface
68
  {
69
  $feed = $item->get('source');
70
 
71
- try {
72
- $control = $feed->get($this->controlProp);
73
- $value = $control ? $this->itemProp->getValue($item) : null;
 
74
 
75
- if (!empty($value)) {
76
- return $value;
 
 
 
77
  }
78
- } catch (OutOfBoundsException $exception) {
79
- // Do nothing
80
  }
81
 
 
82
  return $this->sourceProp->getValue($feed);
83
  }
84
 
68
  {
69
  $feed = $item->get('source');
70
 
71
+ if ($feed) {
72
+ try {
73
+ $control = $feed->get($this->controlProp);
74
+ $value = $control ? $this->itemProp->getValue($item) : null;
75
 
76
+ if (!empty($value)) {
77
+ return $value;
78
+ }
79
+ } catch (OutOfBoundsException $exception) {
80
+ // Do nothing
81
  }
 
 
82
  }
83
 
84
+ // Default to value from feed source
85
  return $this->sourceProp->getValue($feed);
86
  }
87
 
src/ErrorHandler.php CHANGED
@@ -107,7 +107,7 @@ class ErrorHandler
107
 
108
  // Detect an exception thrown from within the root directory
109
  foreach ($throwable->getTrace() as $trace) {
110
- if ($this->isErrorFromRootDir($trace['file'])) {
111
  $this->handleError($throwable);
112
  }
113
  }
107
 
108
  // Detect an exception thrown from within the root directory
109
  foreach ($throwable->getTrace() as $trace) {
110
+ if (array_key_exists('file', $trace) && $this->isErrorFromRootDir($trace['file'])) {
111
  $this->handleError($throwable);
112
  }
113
  }
src/Handlers/FeedTemplates/CreateDefaultFeedTemplateHandler.php CHANGED
@@ -48,9 +48,11 @@ class CreateDefaultFeedTemplateHandler
48
  */
49
  public function __invoke()
50
  {
51
- $slug = $this->data['slug'];
 
 
52
 
53
- if (!isset($this->collection[$slug])) {
54
  $this->collection[] = $this->data;
55
  }
56
  }
48
  */
49
  public function __invoke()
50
  {
51
+ $builtInTemplates = $this->collection->filter([
52
+ 'type' => $this->data['type']
53
+ ]);
54
 
55
+ if ($builtInTemplates->getCount() === 0) {
56
  $this->collection[] = $this->data;
57
  }
58
  }
src/Handlers/FeedTemplates/ReSaveTemplateHandler.php CHANGED
@@ -21,13 +21,13 @@ class ReSaveTemplateHandler
21
  protected $collection;
22
 
23
  /**
24
- * The slug name of the template.
25
  *
26
- * @since 4.13
27
  *
28
- * @var string
29
  */
30
- protected $slug;
31
 
32
  /**
33
  * Constructor.
@@ -35,12 +35,12 @@ class ReSaveTemplateHandler
35
  * @since 4.13
36
  *
37
  * @param DataSetInterface $collection The template collection.
38
- * @param string $slug The slug name of the template.
39
  */
40
- public function __construct(DataSetInterface $collection, $slug)
41
  {
42
  $this->collection = $collection;
43
- $this->slug = $slug;
44
  }
45
 
46
  /**
@@ -50,7 +50,11 @@ class ReSaveTemplateHandler
50
  */
51
  public function __invoke()
52
  {
53
- $template = $this->collection[$this->slug];
 
 
 
 
54
 
55
  foreach ($template as $key => $value) {
56
  $template[$key] = $value;
21
  protected $collection;
22
 
23
  /**
24
+ * The default template info.
25
  *
26
+ * @since 4.17.4
27
  *
28
+ * @var array
29
  */
30
+ protected $info;
31
 
32
  /**
33
  * Constructor.
35
  * @since 4.13
36
  *
37
  * @param DataSetInterface $collection The template collection.
38
+ * @param array $info The default template info.
39
  */
40
+ public function __construct(DataSetInterface $collection, $info)
41
  {
42
  $this->collection = $collection;
43
+ $this->info = $info;
44
  }
45
 
46
  /**
50
  */
51
  public function __invoke()
52
  {
53
+ $builtIn = $this->collection->filter([
54
+ 'type' => $this->info['type'],
55
+ ]);
56
+
57
+ $template = $builtIn[0];
58
 
59
  foreach ($template as $key => $value) {
60
  $template[$key] = $value;
src/Modules/CoreModule.php CHANGED
@@ -233,5 +233,11 @@ class CoreModule implements ModuleInterface
233
  public function run(ContainerInterface $c)
234
  {
235
  do_action('wpra/init');
 
 
 
 
 
 
236
  }
237
  }
233
  public function run(ContainerInterface $c)
234
  {
235
  do_action('wpra/init');
236
+
237
+ add_action('admin_init', function () {
238
+ if (wprss_is_wprss_page()) {
239
+ do_action('wpra/admin_init');
240
+ }
241
+ });
242
  }
243
  }
src/Modules/FeedTemplatesModule.php CHANGED
@@ -265,7 +265,6 @@ class FeedTemplatesModule implements ModuleInterface
265
  */
266
  'wpra/feeds/templates/master_template' => function (ContainerInterface $c) {
267
  return new MasterFeedsTemplate(
268
- $c->get('wpra/feeds/templates/default_template'),
269
  $c->get('wpra/feeds/templates/template_types'),
270
  $c->get('wpra/feeds/templates/collection'),
271
  $c->get('wpra/feeds/templates/feed_item_collection'),
@@ -327,7 +326,7 @@ class FeedTemplatesModule implements ModuleInterface
327
  * @since 4.13
328
  */
329
  'wpra/feeds/templates/master_template_logger' => function (ContainerInterface $c) {
330
- if ($c->has('wpra/logging/logger')) {
331
  return new NullLogger();
332
  }
333
 
@@ -389,7 +388,6 @@ class FeedTemplatesModule implements ModuleInterface
389
  'wpra/feeds/templates/default_template_data' => function (ContainerInterface $c) {
390
  return [
391
  'name' => __('Default', 'wprss'),
392
- 'slug' => $c->get('wpra/feeds/templates/default_template_slug'),
393
  'type' => $c->get('wpra/feeds/templates/default_template_type'),
394
  ];
395
  },
@@ -685,7 +683,7 @@ class FeedTemplatesModule implements ModuleInterface
685
  'wpra/feeds/templates/handlers/sync_default_template' => function (ContainerInterface $c) {
686
  return new ReSaveTemplateHandler(
687
  $c->get('wpra/feeds/templates/collection'),
688
- $c->get('wpra/feeds/templates/default_template')
689
  );
690
  },
691
 
@@ -838,7 +836,7 @@ class FeedTemplatesModule implements ModuleInterface
838
 
839
  // This ensures that there is always at least one template available, by constructing the core list template
840
  // from the old general display settings.
841
- add_action('init', $c->get('wpra/feeds/templates/create_default_template_handler'));
842
 
843
  // Filters the front-end content for templates to render them
844
  add_action('the_content', $c->get('wpra/feeds/templates/handlers/render_content'));
265
  */
266
  'wpra/feeds/templates/master_template' => function (ContainerInterface $c) {
267
  return new MasterFeedsTemplate(
 
268
  $c->get('wpra/feeds/templates/template_types'),
269
  $c->get('wpra/feeds/templates/collection'),
270
  $c->get('wpra/feeds/templates/feed_item_collection'),
326
  * @since 4.13
327
  */
328
  'wpra/feeds/templates/master_template_logger' => function (ContainerInterface $c) {
329
+ if (!$c->has('wpra/logging/logger')) {
330
  return new NullLogger();
331
  }
332
 
388
  'wpra/feeds/templates/default_template_data' => function (ContainerInterface $c) {
389
  return [
390
  'name' => __('Default', 'wprss'),
 
391
  'type' => $c->get('wpra/feeds/templates/default_template_type'),
392
  ];
393
  },
683
  'wpra/feeds/templates/handlers/sync_default_template' => function (ContainerInterface $c) {
684
  return new ReSaveTemplateHandler(
685
  $c->get('wpra/feeds/templates/collection'),
686
+ $c->get('wpra/feeds/templates/default_template_data')
687
  );
688
  },
689
 
836
 
837
  // This ensures that there is always at least one template available, by constructing the core list template
838
  // from the old general display settings.
839
+ add_action('wpra/admin_init', $c->get('wpra/feeds/templates/create_default_template_handler'));
840
 
841
  // Filters the front-end content for templates to render them
842
  add_action('the_content', $c->get('wpra/feeds/templates/handlers/render_content'));
src/RestApi/EndPoints/AbstractRestApiEndPoint.php CHANGED
@@ -85,20 +85,24 @@ abstract class AbstractRestApiEndPoint
85
  ];
86
 
87
  foreach ($exception->getTrace() as $trace) {
88
- $file = basename($trace['file']);
89
- $line = $trace['line'];
90
- $fn = $trace['function'];
91
- $args = array_map(function ($arg) {
92
- if (is_scalar($arg)) {
93
- return $arg;
94
- }
95
-
96
- return is_object($arg)
97
- ? get_class($arg)
98
- : gettype($arg);
99
- }, $trace['args']);
100
-
101
- $argsStr = implode(', ', $args);
 
 
 
 
102
 
103
  $data['trace'][] = sprintf('%s(%s) @ %s:%s', $fn, $argsStr, $file, $line);
104
  }
85
  ];
86
 
87
  foreach ($exception->getTrace() as $trace) {
88
+ $file = array_key_exists('file', $trace) ? basename($trace['file']) : '<unknown>';
89
+ $line = array_key_exists('line', $trace) ? $trace['line'] : '<unknown>';
90
+ $fn = array_key_exists('function', $trace) ? $trace['function'] : '<unknown>';
91
+
92
+ if (array_key_exists('args', $trace)) {
93
+ $args = array_map(function ($arg) {
94
+ if (is_scalar($arg)) {
95
+ return $arg;
96
+ }
97
+
98
+ return is_object($arg)
99
+ ? get_class($arg)
100
+ : gettype($arg);
101
+ }, $trace['args']);
102
+ $argsStr = implode(', ', $args);
103
+ } else {
104
+ $argsStr = '<unknown>';
105
+ }
106
 
107
  $data['trace'][] = sprintf('%s(%s) @ %s:%s', $fn, $argsStr, $file, $line);
108
  }
src/RestApi/EndPoints/FeedTemplates/CreateUpdateTemplateEndPoint.php CHANGED
@@ -65,7 +65,7 @@ class CreateUpdateTemplateEndPoint extends AbstractRestApiEndPoint
65
  }
66
 
67
  $data = $request->get_params();
68
- unset($data['id']);
69
 
70
  $this->collection[$id] = $data;
71
 
65
  }
66
 
67
  $data = $request->get_params();
68
+ $data = array_intersect_key($data, ['name' => null, 'slug' => null, 'type' => null, 'options' => null]);
69
 
70
  $this->collection[$id] = $data;
71
 
src/Templates/Feeds/MasterFeedsTemplate.php CHANGED
@@ -65,15 +65,6 @@ class MasterFeedsTemplate implements TemplateInterface
65
  */
66
  const CTX_OPTIONS_KEY = 'options';
67
 
68
- /**
69
- * The ID of the template to use by default.
70
- *
71
- * @since 4.13
72
- *
73
- * @var string
74
- */
75
- protected $default;
76
-
77
  /**
78
  * An associative array of template type instances.
79
  *
@@ -133,7 +124,6 @@ class MasterFeedsTemplate implements TemplateInterface
133
  *
134
  * @since 4.13
135
  *
136
- * @param string $default The name of the template to use by default.
137
  * @param array $templateTypes The available template types.
138
  * @param CollectionInterface $templateCollection The collection of templates.
139
  * @param CollectionInterface $feedItemCollection The collection of feed items.
@@ -142,7 +132,6 @@ class MasterFeedsTemplate implements TemplateInterface
142
  * @param LoggerInterface $logger The logger instance to use for recording errors.
143
  */
144
  public function __construct(
145
- $default,
146
  $templateTypes,
147
  CollectionInterface $templateCollection,
148
  CollectionInterface $feedItemCollection,
@@ -151,7 +140,6 @@ class MasterFeedsTemplate implements TemplateInterface
151
  LoggerInterface $logger
152
  ) {
153
  $this->types = $templateTypes;
154
- $this->default = $default;
155
  $this->templateCollection = $templateCollection;
156
  $this->feedItemCollection = $feedItemCollection;
157
  $this->containerTemplate = $containerTemplate;
@@ -273,20 +261,26 @@ class MasterFeedsTemplate implements TemplateInterface
273
  */
274
  protected function getTemplateModel($slug)
275
  {
276
- // If the template slug is empty, use the default slug
277
- $slug = empty($slug) ? $this->default : $slug;
278
 
279
- try {
280
- // Get the template model instance
281
- $model = $this->templateCollection[$slug];
282
- } catch (Exception $exception) {
 
 
 
 
 
 
 
 
 
 
 
283
  // Fetch the default template
284
- $model = $this->templateCollection[$this->default];
285
- // Include warning in log that the template was not found
286
- $this->logger->warning(
287
- __('Template "{0}" does not exist or could not be loaded. The "{1}" template was used is instead.'),
288
- [$slug, $this->default]
289
- );
290
  }
291
 
292
  return $model;
65
  */
66
  const CTX_OPTIONS_KEY = 'options';
67
 
 
 
 
 
 
 
 
 
 
68
  /**
69
  * An associative array of template type instances.
70
  *
124
  *
125
  * @since 4.13
126
  *
 
127
  * @param array $templateTypes The available template types.
128
  * @param CollectionInterface $templateCollection The collection of templates.
129
  * @param CollectionInterface $feedItemCollection The collection of feed items.
132
  * @param LoggerInterface $logger The logger instance to use for recording errors.
133
  */
134
  public function __construct(
 
135
  $templateTypes,
136
  CollectionInterface $templateCollection,
137
  CollectionInterface $feedItemCollection,
140
  LoggerInterface $logger
141
  ) {
142
  $this->types = $templateTypes;
 
143
  $this->templateCollection = $templateCollection;
144
  $this->feedItemCollection = $feedItemCollection;
145
  $this->containerTemplate = $containerTemplate;
261
  */
262
  protected function getTemplateModel($slug)
263
  {
264
+ $model = null;
 
265
 
266
+ // Get the template model instance
267
+ if (!empty($slug)) {
268
+ try {
269
+ $model = $this->templateCollection[$slug];
270
+ } catch (Exception $exception) {
271
+ // Include warning in log that the template with the given slug was not found
272
+ $this->logger->warning(
273
+ __('Template "{0}" does not exist or could not be loaded. The default template was used instead.'),
274
+ [$slug]
275
+ );
276
+ }
277
+ }
278
+
279
+ // If the slug is empty or failed to get the template
280
+ if (empty($model)) {
281
  // Fetch the default template
282
+ $builtIn = $this->templateCollection->filter(['type' => '__built_in']);
283
+ $model = $builtIn[0];
 
 
 
 
284
  }
285
 
286
  return $model;
templates/feeds/list/feed-item.twig CHANGED
@@ -9,9 +9,9 @@
9
 
10
  {# Show the title #}
11
  {% if options.title_is_link %}
12
- <a {{ wpra_link_attrs(item_url, options)|raw }}>{{ item_title }}</a>
13
  {% else %}
14
- {{ item_title }}
15
  {% endif %}
16
 
17
  {{ options.title_after }}
9
 
10
  {# Show the title #}
11
  {% if options.title_is_link %}
12
+ <a {{ wpra_link_attrs(item_url, options)|raw }}>{{ item_title|raw }}</a>
13
  {% else %}
14
+ {{ item_title|raw }}
15
  {% endif %}
16
 
17
  {{ options.title_after }}
wp-rss-aggregator.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin Name: WP RSS Aggregator
5
  * Plugin URI: https://www.wprssaggregator.com/#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wpraplugin
6
  * Description: Imports and aggregates multiple RSS Feeds.
7
- * Version: 4.17.3
8
  * Author: RebelCode
9
  * Author URI: https://www.wprssaggregator.com
10
  * Text Domain: wprss
@@ -78,7 +78,7 @@ use RebelCode\Wpra\Core\Plugin;
78
 
79
  // Set the version number of the plugin.
80
  if( !defined( 'WPRSS_VERSION' ) )
81
- define( 'WPRSS_VERSION', '4.17.3' );
82
 
83
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
84
  define( 'WPRSS_WP_MIN_VERSION', '4.8' );
4
  * Plugin Name: WP RSS Aggregator
5
  * Plugin URI: https://www.wprssaggregator.com/#utm_source=wpadmin&utm_medium=plugin&utm_campaign=wpraplugin
6
  * Description: Imports and aggregates multiple RSS Feeds.
7
+ * Version: 4.17.4
8
  * Author: RebelCode
9
  * Author URI: https://www.wprssaggregator.com
10
  * Text Domain: wprss
78
 
79
  // Set the version number of the plugin.
80
  if( !defined( 'WPRSS_VERSION' ) )
81
+ define( 'WPRSS_VERSION', '4.17.4' );
82
 
83
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
84
  define( 'WPRSS_WP_MIN_VERSION', '4.8' );