WP RSS Aggregator - Version 4.19.3

Version Description

(2021-11-24) Fixed - An error during cron schedule filtering. - Not all image URLs in enclosure tags were being detected.

Download this release

Release Info

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

Code changes from version 4.19.2 to 4.19.3

CHANGELOG.md CHANGED
@@ -4,7 +4,12 @@ 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.19.2] = 2021-10-28
 
 
 
 
 
8
  ### Changed
9
  * Cleaned up the code significantly.
10
  * Consistent permalink normalization between the preview and importing.
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.19.3] - 2021-11-24
8
+ ### Fixed
9
+ * An error during cron schedule filtering.
10
+ * Not all image URLs in enclosure tags were being detected.
11
+
12
+ ## [4.19.2] - 2021-10-28
13
  ### Changed
14
  * Cleaned up the code significantly.
15
  * Consistent permalink normalization between the preview and importing.
includes/admin-ajax-notice.php CHANGED
@@ -58,28 +58,30 @@ define ('WPRSS_NOTICE_SERVICE_ID_PREFIX', WPRSS_SERVICE_ID_PREFIX . 'notice.');
58
  * @since 3.4.2
59
  */
60
  function wprss_dismiss_addon_notice() {
61
- $addon = ( isset( $_POST['addon'] ) === TRUE )? $_POST['addon'] : null;
62
- if ( $addon === null ) {
 
63
  echo 'false';
64
- die();
65
  }
66
- $notice = ( isset( $_POST['notice'] ) === TRUE )? $_POST['notice'] : null;
67
- if ( $notice === null ){
 
68
  echo 'false';
69
- die();
70
  }
71
 
72
  $notices = wprss_check_addon_notice_option();
73
- if ( isset( $notices[$addon] ) === FALSE ) {
74
  $notices[$addon] = array();
75
  }
76
- if ( isset( $notices[$addon][$addon] ) === FALSE ) {
77
  $notices[$addon][$notice] = '1';
78
  }
79
  update_option( 'wprss_addon_notices', $notices );
80
  echo 'true';
81
 
82
- die();
83
  }
84
 
85
  add_action( 'wp_ajax_wprss_dismiss_addon_notice', 'wprss_dismiss_addon_notice' );
58
  * @since 3.4.2
59
  */
60
  function wprss_dismiss_addon_notice() {
61
+ check_admin_referer('wprss_admin_addon_ajax');
62
+ $addon = isset($_POST['addon'])? $_POST['addon'] : null;
63
+ if ($addon === null) {
64
  echo 'false';
65
+ die;
66
  }
67
+ $addon = strip_tags($addon);
68
+ $notice = isset($_POST['notice'])? $_POST['notice'] : null;
69
+ if ($notice === null) {
70
  echo 'false';
71
+ die;
72
  }
73
 
74
  $notices = wprss_check_addon_notice_option();
75
+ if (isset($notices[$addon])) {
76
  $notices[$addon] = array();
77
  }
78
+ if (isset($notices[$addon][$addon])) {
79
  $notices[$addon][$notice] = '1';
80
  }
81
  update_option( 'wprss_addon_notices', $notices );
82
  echo 'true';
83
 
84
+ die;
85
  }
86
 
87
  add_action( 'wp_ajax_wprss_dismiss_addon_notice', 'wprss_dismiss_addon_notice' );
includes/black-friday-2021.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ add_action('admin_notices', function () {
4
+ if (!wprss_is_wprss_page() || count(wprss_get_addons()) > 0) {
5
+ return;
6
+ }
7
+
8
+ $year = (int) date('Y');
9
+ $month = (int) date('n');
10
+ $day = (int) date('j');
11
+
12
+ if ($year !== 2021 || $month !== 11 || $day < 22 || $day > 29) {
13
+ return;
14
+ }
15
+
16
+ printf(
17
+ '<div class="notice notice-info">
18
+ <p>
19
+ %s
20
+ <a href="https://www.wprssaggregator.com/pricing/" target="_blank"><b>%s</b></a>
21
+ %s
22
+ </p>
23
+ </div>',
24
+ __('Black Friday/Cyber Monday:', 'wprss'),
25
+ __('Get 30% off WP RSS Aggregator plans today!', 'wprss'),
26
+ __('Offer ends on the 29th of November.', 'wprss')
27
+ );
28
+ });
includes/cron-jobs.php CHANGED
@@ -317,22 +317,11 @@ function wpra_get_cron_schedules()
317
  */
318
  function wprss_filter_cron_schedules($schedules)
319
  {
320
- // Pluck out the intervals
321
- $intervals = array_map(function ($schedule) {
322
- return (isset($schedule['interval']) && is_numeric($schedule['interval']))
323
- ? $schedule['interval']
324
- : null;
325
- }, $schedules);
326
- // Remove null values
327
- $intervals = array_filter($intervals);
328
- // Get a map of intervals -> keys for fast interval lookup
329
- $intervalsMap = array_flip($intervals);
330
-
331
  // Register each WPRA schedule
332
  $wpraSchedules = wpra_get_cron_schedules();
333
  foreach ($wpraSchedules as $key => $schedule) {
334
  // If the interval already exists, skip the schedule
335
- if (array_key_exists($schedule['interval'], $intervalsMap)) {
336
  continue;
337
  }
338
 
@@ -342,6 +331,26 @@ function wprss_filter_cron_schedules($schedules)
342
  return $schedules;
343
  }
344
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
  /**
346
  * Deletes a custom cron schedule.
347
  *
317
  */
318
  function wprss_filter_cron_schedules($schedules)
319
  {
 
 
 
 
 
 
 
 
 
 
 
320
  // Register each WPRA schedule
321
  $wpraSchedules = wpra_get_cron_schedules();
322
  foreach ($wpraSchedules as $key => $schedule) {
323
  // If the interval already exists, skip the schedule
324
+ if (wprss_schedule_interval_already_exists($schedules, $schedule['interval'])) {
325
  continue;
326
  }
327
 
331
  return $schedules;
332
  }
333
 
334
+ /**
335
+ * Checks if a schedule interval already exists in a given list os schedules.
336
+ *
337
+ * @see wprss_filter_cron_schedules()
338
+ *
339
+ * @param array $schedules The schedules to search in.
340
+ * @param int $interval The interval to search for.
341
+ *
342
+ * @return bool
343
+ */
344
+ function wprss_schedule_interval_already_exists(array $schedules, $interval) {
345
+ foreach ($schedules as $schedule) {
346
+ if (isset($schedule['interval']) && $schedule['interval'] == $interval) {
347
+ return true;
348
+ }
349
+ }
350
+
351
+ return false;
352
+ }
353
+
354
  /**
355
  * Deletes a custom cron schedule.
356
  *
includes/feed-importing-images.php CHANGED
@@ -5,7 +5,8 @@ use Psr\Log\LoggerInterface;
5
  use RebelCode\Wpra\Core\Data\DataSetInterface;
6
  use RebelCode\Wpra\Core\Logger\FeedLoggerInterface;
7
 
8
- class Wpra_Rss_Namespace {
 
9
  const ITUNES = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
10
  }
11
 
@@ -23,9 +24,9 @@ add_filter('wprss_ftp_post_meta', function ($meta, $id, $source, $item) {
23
  * The "import" process here basically just fetches the images from the item's content/excerpt, the media:thumbnail
24
  * tag and the enclosures. The entire list of images is saved, along with the URL of the best image.
25
  *
26
- * @param int|string $itemId The ID of the feed item.
27
- * @param SimplePie_Item $item The simple pie item object.
28
- * @param int|string $sourceId The ID of the feed source from which the item was imported.
29
  */
30
  function wpra_detect_item_type($itemId, $item, $sourceId)
31
  {
@@ -70,9 +71,9 @@ function wpra_get_images_logger($feedId = null)
70
  * The "import" process here basically just fetches the images from the item's content/excerpt, the media:thumbnail
71
  * tag and the enclosures. The entire list of images is saved, along with the URL of the best image.
72
  *
73
- * @param int|string $itemId The ID of the feed item.
74
- * @param SimplePie_Item $item The simple pie item object.
75
- * @param int|string $sourceId The ID of the feed source from which the item was imported.
76
  */
77
  function wpra_import_item_images($itemId, $item, $sourceId)
78
  {
@@ -111,8 +112,7 @@ function wpra_import_item_images($itemId, $item, $sourceId)
111
  // If the featured image importing feature is enabled, import the featured image
112
  if (wpra_image_feature_enabled('import_ft_images')) {
113
  $ftImageUrl = null;
114
- switch ($ftImageOpt)
115
- {
116
  case 'auto':
117
  if (!empty($bestImage)) {
118
  $ftImageUrl = $bestImage;
@@ -172,9 +172,9 @@ function wpra_import_item_images($itemId, $item, $sourceId)
172
 
173
  if ($usedDefault) {
174
  update_post_meta($itemId, 'wprss_item_is_using_def_image', '1');
175
- $logger->notice('Used the feed source\'s default featured image for "{title}"', ['title' => $title]);
176
  } else {
177
- $logger->notice('No featured image was found for item "{title}"', ['title' => $title]);
178
  }
179
  }
180
  } else {
@@ -187,7 +187,7 @@ function wpra_import_item_images($itemId, $item, $sourceId)
187
 
188
  wp_update_post([
189
  'ID' => $itemId,
190
- 'post_content' => $newContent
191
  ]);
192
  }
193
  }
@@ -208,7 +208,7 @@ function wpra_import_item_images($itemId, $item, $sourceId)
208
  // Update the post content
209
  wp_update_post([
210
  'ID' => $itemId,
211
- 'post_content' => $content
212
  ]);
213
  }
214
 
@@ -319,8 +319,8 @@ function wpra_process_images($images, $source, &$bestImage = null)
319
  $minWidth = 0;
320
  $minHeight = 0;
321
  if (wpra_image_feature_enabled('image_min_size')) {
322
- $minWidth = (int)apply_filters('wprss_thumbnail_min_width', $source['image_min_width']);
323
- $minHeight = (int)apply_filters('wprss_thumbnail_min_height', $source['image_min_height']);
324
  }
325
 
326
  foreach ($images as $group => $urls) {
@@ -422,32 +422,25 @@ function wpra_get_item_media_thumbnail_image($item)
422
  return null;
423
  }
424
 
425
- // Stop if enclosure is not an image
 
426
  $type = $enclosure->get_type();
427
- if (!empty($type) && stripos($type, 'image/') !== 0) {
428
  return null;
429
  }
430
 
431
- // Stop if enclosure tag has no link
432
- $url = $enclosure->get_link();
433
- if (empty($url)) {
434
- return null;
435
- }
436
 
437
- // Check if image can be downloaded
438
- if (wpra_container()->has('wpra/images/container')) {
439
- try {
440
- /* @var $image WPRSS_Image_Cache_Image */
441
- $image = wpra_container()->get('wpra/images/container')->get($url);
442
- } catch (Exception $exception) {
443
- return null;
444
  }
445
  }
446
 
447
- if ($image->get_local_path()) {
448
- return $url;
449
- }
450
-
451
  return null;
452
  }
453
 
@@ -462,15 +455,27 @@ function wpra_get_item_media_thumbnail_image($item)
462
  */
463
  function wpra_get_item_enclosure_images($item)
464
  {
465
- $enclosure = $item->get_enclosure();
466
 
467
- // Stop if item has no enclosure image
468
- if (is_null($enclosure) || stripos($enclosure->get_type(), 'image') === false) {
469
- return [];
 
 
 
 
 
 
 
 
 
 
 
 
 
470
  }
471
 
472
- // Get all the thumbnails from the enclosure
473
- return (array) $enclosure->get_thumbnails();
474
  }
475
 
476
  /**
@@ -517,7 +522,7 @@ function wpra_get_item_content_images($item)
517
  */
518
  function wpra_get_item_itunes_images($item)
519
  {
520
- $tags = $item->get_item_tags(Wpra_Rss_Namespace::ITUNES,'image');
521
 
522
  if (!is_array($tags) || empty($tags)) {
523
  return [];
@@ -545,17 +550,17 @@ function wpra_get_item_itunes_images($item)
545
  * @since 4.14
546
  *
547
  * @param string $content The content in which to search for and remove the image.
548
- * @param string $url The URL of the image to remove.
549
- * @param int $limit Optional number of image occurrences to remove.
550
  *
551
  * @return string The new content, with any matching `img` HTML tags removed.
552
  */
553
  function wpra_remove_image_from_content($content, $url, $limit = 1)
554
  {
555
- $tag_search = array(
556
  '<img[^<>]*?src="%s"[^<>]*?>',
557
- '<img[^<>]*?srcset="[^<>]*?%s.[^<>]*?"[^<>]*?>'
558
- );
559
 
560
  foreach ($tag_search as $regex) {
561
  // This will transform the expression to match images in html-encoded content
@@ -625,7 +630,7 @@ function wpra_set_featured_image_from_url($post_id, $url)
625
  }
626
 
627
  // Otherwise, get the attachment ID for the URL from the database
628
- set_post_thumbnail( $post_id, wpra_get_attachment_id_from_url($url) );
629
  }
630
 
631
  /**
@@ -657,15 +662,13 @@ function wpra_is_url_local($url, $home_url = null)
657
  *
658
  * @see parse_url()
659
  *
660
- * @param string|array $url The URL which is to be rebuilt, or a result of parse_url().
661
- *
662
- * @param bool|array $parts An array of which parts to use for building the new URL. Boolean false for all.
663
  *
664
  * @return null|string The rebuilt URL on success, or null of given URL is malformed.
665
  */
666
  function wpra_rebuild_url($url, $parts = false)
667
  {
668
-
669
  // Allow parsed array
670
  if (is_string($url)) {
671
  $url = parse_url($url);
@@ -727,11 +730,11 @@ function wpra_encode_and_parse_url($url)
727
  *
728
  * @since 2.7.4
729
  *
730
- * @param string $url (required) The URL of the image to download
731
- * @param int $post_id (required) The post ID the media is to be associated with
732
- * @param bool $attach (optional) Whether to make this attachment the Featured Image for the post.
733
- * @param string $filename (optional) Replacement filename for the URL filename (do not include extension)
734
- * @param array $post_data (optional) Array of key => values for wp_posts table (ex: 'post_title' => 'foobar',
735
  * 'post_status' => 'draft')
736
  *
737
  * @return int|object The ID of the attachment or a WP_Error on failure
@@ -887,7 +890,7 @@ function wpra_media_sideload_image($url = null, $post_id = null, $attach = null,
887
 
888
  // Do a case insensitive check for the extension in the proper_filename. If not found, we
889
  // add the extension
890
- if (!preg_match('/'.$extension.'$/i', $filename)) {
891
  $image['proper_filename'] .= '.' . $extension;
892
  }
893
  }
@@ -925,7 +928,7 @@ function wpra_media_sideload_image($url = null, $post_id = null, $attach = null,
925
 
926
  // set as post thumbnail if desired
927
  if ($attach) {
928
- set_post_thumbnail( $post_id, $att_id );
929
  }
930
 
931
  // Save the original image URL in the attachment's meta data
@@ -939,7 +942,7 @@ function wpra_media_sideload_image($url = null, $post_id = null, $attach = null,
939
  *
940
  * @since 4.14
941
  *
942
- * @param string $local_image_path Local path of the downloaded image
943
  * @param string $remote_image_path Remote image url
944
  *
945
  * @return array Values with extension first and mime type.
@@ -982,7 +985,6 @@ function wpra_check_file_type($local_image_path, $remote_image_path)
982
  */
983
  function wpra_get_mime_type_ext_mapping()
984
  {
985
-
986
  // Get MIME to extension mappings ( from WordPress wp_check_filetype_and_ext() function )
987
  return apply_filters(
988
  'getimagesize_mimes_to_exts', [
@@ -1000,7 +1002,8 @@ function wpra_get_mime_type_ext_mapping()
1000
  *
1001
  * @since 4.14
1002
  */
1003
- function wpra_get_attachment_id_from_url( $image_src ) {
 
1004
  global $wpdb;
1005
  $query = "SELECT ID FROM {$wpdb->posts} WHERE guid='$image_src'";
1006
  $id = $wpdb->get_var($query);
@@ -1023,3 +1026,22 @@ function wpra_image_feature_enabled($feature)
1023
 
1024
  return $c->has($key) && $c->get($key) === true;
1025
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  use RebelCode\Wpra\Core\Data\DataSetInterface;
6
  use RebelCode\Wpra\Core\Logger\FeedLoggerInterface;
7
 
8
+ class Wpra_Rss_Namespace
9
+ {
10
  const ITUNES = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
11
  }
12
 
24
  * The "import" process here basically just fetches the images from the item's content/excerpt, the media:thumbnail
25
  * tag and the enclosures. The entire list of images is saved, along with the URL of the best image.
26
  *
27
+ * @param int|string $itemId The ID of the feed item.
28
+ * @param SimplePie_Item $item The simple pie item object.
29
+ * @param int|string $sourceId The ID of the feed source from which the item was imported.
30
  */
31
  function wpra_detect_item_type($itemId, $item, $sourceId)
32
  {
71
  * The "import" process here basically just fetches the images from the item's content/excerpt, the media:thumbnail
72
  * tag and the enclosures. The entire list of images is saved, along with the URL of the best image.
73
  *
74
+ * @param int|string $itemId The ID of the feed item.
75
+ * @param SimplePie_Item $item The simple pie item object.
76
+ * @param int|string $sourceId The ID of the feed source from which the item was imported.
77
  */
78
  function wpra_import_item_images($itemId, $item, $sourceId)
79
  {
112
  // If the featured image importing feature is enabled, import the featured image
113
  if (wpra_image_feature_enabled('import_ft_images')) {
114
  $ftImageUrl = null;
115
+ switch ($ftImageOpt) {
 
116
  case 'auto':
117
  if (!empty($bestImage)) {
118
  $ftImageUrl = $bestImage;
172
 
173
  if ($usedDefault) {
174
  update_post_meta($itemId, 'wprss_item_is_using_def_image', '1');
175
+ $logger->notice('Used the feed source\'s default featured image for "{0}"', [$title]);
176
  } else {
177
+ $logger->notice('No featured image was found for item "{0}"', [$title]);
178
  }
179
  }
180
  } else {
187
 
188
  wp_update_post([
189
  'ID' => $itemId,
190
+ 'post_content' => $newContent,
191
  ]);
192
  }
193
  }
208
  // Update the post content
209
  wp_update_post([
210
  'ID' => $itemId,
211
+ 'post_content' => $content,
212
  ]);
213
  }
214
 
319
  $minWidth = 0;
320
  $minHeight = 0;
321
  if (wpra_image_feature_enabled('image_min_size')) {
322
+ $minWidth = (int) apply_filters('wprss_thumbnail_min_width', $source['image_min_width']);
323
+ $minHeight = (int) apply_filters('wprss_thumbnail_min_height', $source['image_min_height']);
324
  }
325
 
326
  foreach ($images as $group => $urls) {
422
  return null;
423
  }
424
 
425
+ // Stop if enclosure is an audio file
426
+ // Prevents podcast stats from being tainted
427
  $type = $enclosure->get_type();
428
+ if (empty($type) || stripos($type, 'audio/') === 0) {
429
  return null;
430
  }
431
 
432
+ $urlsToTry = [
433
+ $enclosure->get_link(),
434
+ $enclosure->get_thumbnail(),
435
+ ];
 
436
 
437
+ foreach ($urlsToTry as $url) {
438
+ // Check if image can be downloaded
439
+ if (!empty($url) && wpra_is_url_an_image($url)) {
440
+ return $url;
 
 
 
441
  }
442
  }
443
 
 
 
 
 
444
  return null;
445
  }
446
 
455
  */
456
  function wpra_get_item_enclosure_images($item)
457
  {
458
+ $images = [];
459
 
460
+ foreach ($item->get_enclosures() as $enclosure) {
461
+ // Continue if enclosure is an audio file
462
+ // Prevents podcast stats from being tainted
463
+ if ($enclosure === null || stripos($enclosure->get_type(), 'audio/') === 0) {
464
+ continue;
465
+ }
466
+
467
+ foreach ($enclosure->get_thumbnails() as $thumbnail) {
468
+ if (empty($thumbnail)) {
469
+ continue;
470
+ }
471
+
472
+ if (wpra_is_url_an_image($thumbnail)) {
473
+ $images[] = $thumbnail;
474
+ }
475
+ }
476
  }
477
 
478
+ return $images;
 
479
  }
480
 
481
  /**
522
  */
523
  function wpra_get_item_itunes_images($item)
524
  {
525
+ $tags = $item->get_item_tags(Wpra_Rss_Namespace::ITUNES, 'image');
526
 
527
  if (!is_array($tags) || empty($tags)) {
528
  return [];
550
  * @since 4.14
551
  *
552
  * @param string $content The content in which to search for and remove the image.
553
+ * @param string $url The URL of the image to remove.
554
+ * @param int $limit Optional number of image occurrences to remove.
555
  *
556
  * @return string The new content, with any matching `img` HTML tags removed.
557
  */
558
  function wpra_remove_image_from_content($content, $url, $limit = 1)
559
  {
560
+ $tag_search = [
561
  '<img[^<>]*?src="%s"[^<>]*?>',
562
+ '<img[^<>]*?srcset="[^<>]*?%s.[^<>]*?"[^<>]*?>',
563
+ ];
564
 
565
  foreach ($tag_search as $regex) {
566
  // This will transform the expression to match images in html-encoded content
630
  }
631
 
632
  // Otherwise, get the attachment ID for the URL from the database
633
+ set_post_thumbnail($post_id, wpra_get_attachment_id_from_url($url));
634
  }
635
 
636
  /**
662
  *
663
  * @see parse_url()
664
  *
665
+ * @param string|array $url The URL which is to be rebuilt, or a result of parse_url().
666
+ * @param bool|array $parts An array of which parts to use for building the new URL. Boolean false for all.
 
667
  *
668
  * @return null|string The rebuilt URL on success, or null of given URL is malformed.
669
  */
670
  function wpra_rebuild_url($url, $parts = false)
671
  {
 
672
  // Allow parsed array
673
  if (is_string($url)) {
674
  $url = parse_url($url);
730
  *
731
  * @since 2.7.4
732
  *
733
+ * @param string $url (required) The URL of the image to download
734
+ * @param int $post_id (required) The post ID the media is to be associated with
735
+ * @param bool $attach (optional) Whether to make this attachment the Featured Image for the post.
736
+ * @param string $filename (optional) Replacement filename for the URL filename (do not include extension)
737
+ * @param array $post_data (optional) Array of key => values for wp_posts table (ex: 'post_title' => 'foobar',
738
  * 'post_status' => 'draft')
739
  *
740
  * @return int|object The ID of the attachment or a WP_Error on failure
890
 
891
  // Do a case insensitive check for the extension in the proper_filename. If not found, we
892
  // add the extension
893
+ if (!preg_match('/' . $extension . '$/i', $filename)) {
894
  $image['proper_filename'] .= '.' . $extension;
895
  }
896
  }
928
 
929
  // set as post thumbnail if desired
930
  if ($attach) {
931
+ set_post_thumbnail($post_id, $att_id);
932
  }
933
 
934
  // Save the original image URL in the attachment's meta data
942
  *
943
  * @since 4.14
944
  *
945
+ * @param string $local_image_path Local path of the downloaded image
946
  * @param string $remote_image_path Remote image url
947
  *
948
  * @return array Values with extension first and mime type.
985
  */
986
  function wpra_get_mime_type_ext_mapping()
987
  {
 
988
  // Get MIME to extension mappings ( from WordPress wp_check_filetype_and_ext() function )
989
  return apply_filters(
990
  'getimagesize_mimes_to_exts', [
1002
  *
1003
  * @since 4.14
1004
  */
1005
+ function wpra_get_attachment_id_from_url($image_src)
1006
+ {
1007
  global $wpdb;
1008
  $query = "SELECT ID FROM {$wpdb->posts} WHERE guid='$image_src'";
1009
  $id = $wpdb->get_var($query);
1026
 
1027
  return $c->has($key) && $c->get($key) === true;
1028
  }
1029
+
1030
+ /**
1031
+ * Checks if a URL refers to an image.
1032
+ *
1033
+ * @param string $url The URL to test.
1034
+ *
1035
+ * @return bool
1036
+ */
1037
+ function wpra_is_url_an_image($url)
1038
+ {
1039
+ $headers = get_headers($url, true);
1040
+ $headers = array_change_key_case($headers, CASE_LOWER);
1041
+
1042
+ if (empty($headers['content-type'])) {
1043
+ return false;
1044
+ }
1045
+
1046
+ return isset($headers['content-type']) && stripos(trim($headers['content-type']), 'image/') === 0;
1047
+ }
includes/scripts.php CHANGED
@@ -18,6 +18,7 @@ add_action('init', function () {
18
  wp_register_script('wprss-admin-addon-ajax', WPRSS_JS . 'admin-addon-ajax.js', ['jquery'], $version);
19
  wp_localize_script('wprss-admin-addon-ajax', 'wprss_admin_addon_ajax', [
20
  'please_wait' => __('Please wait ...', 'wprss'),
 
21
  ]);
22
 
23
  // Prepare the URL for removing bulk from blacklist, with a nonce
18
  wp_register_script('wprss-admin-addon-ajax', WPRSS_JS . 'admin-addon-ajax.js', ['jquery'], $version);
19
  wp_localize_script('wprss-admin-addon-ajax', 'wprss_admin_addon_ajax', [
20
  'please_wait' => __('Please wait ...', 'wprss'),
21
+ 'nonce' => wp_create_nonce('wprss_admin_addon_ajax'),
22
  ]);
23
 
24
  // Prepare the URL for removing bulk from blacklist, with a nonce
js/admin-addon-ajax.js CHANGED
@@ -12,6 +12,7 @@ jQuery( document ).ready( function($) {
12
  action: 'wprss_dismiss_addon_notice',
13
  addon: addon,
14
  notice: notice,
 
15
  },
16
  success: function( data, status, jqXHR) {
17
  if ( data === 'true' ) {
@@ -25,4 +26,4 @@ jQuery( document ).ready( function($) {
25
  }
26
  });
27
 
28
- });
12
  action: 'wprss_dismiss_addon_notice',
13
  addon: addon,
14
  notice: notice,
15
+ nonce: wprss_admin_addon_ajax.nonce,
16
  },
17
  success: function( data, status, jqXHR) {
18
  if ( data === 'true' ) {
26
  }
27
  });
28
 
29
+ });
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: RSS import, RSS aggregator, autoblog, feed to post, news aggregator, rss t
5
  Requires at least: 4.0 or higher
6
  Tested up to: 5.8
7
  Requires PHP: 5.4
8
- Stable tag: 4.19.2
9
  License: GPLv3
10
 
11
  The most powerful and reliable RSS aggregator for WordPress. Build a news aggregator, autoblog and more in minutes with unlimited RSS feeds.
@@ -254,6 +254,11 @@ Our complete Knowledge Base with FAQs can be found [here](https://kb.wprssaggreg
254
 
255
  == Changelog ==
256
 
 
 
 
 
 
257
  = 4.19.2 (2021-10-28)
258
  **Changed**
259
  - Cleaned up the code significantly.
5
  Requires at least: 4.0 or higher
6
  Tested up to: 5.8
7
  Requires PHP: 5.4
8
+ Stable tag: 4.19.3
9
  License: GPLv3
10
 
11
  The most powerful and reliable RSS aggregator for WordPress. Build a news aggregator, autoblog and more in minutes with unlimited RSS feeds.
254
 
255
  == Changelog ==
256
 
257
+ = 4.19.3 (2021-11-24)
258
+ **Fixed**
259
+ - An error during cron schedule filtering.
260
+ - Not all image URLs in enclosure tags were being detected.
261
+
262
  = 4.19.2 (2021-10-28)
263
  **Changed**
264
  - Cleaned up the code significantly.
vendor/composer/installed.php CHANGED
@@ -5,7 +5,7 @@
5
  'type' => 'wordpress-plugin',
6
  'install_path' => __DIR__ . '/../../',
7
  'aliases' => array(),
8
- 'reference' => '8b106ef99bd494492820d3d92a9a07a5af672dcf',
9
  'name' => 'wprss/core',
10
  'dev' => false,
11
  ),
@@ -343,7 +343,7 @@
343
  'type' => 'wordpress-plugin',
344
  'install_path' => __DIR__ . '/../../',
345
  'aliases' => array(),
346
- 'reference' => '8b106ef99bd494492820d3d92a9a07a5af672dcf',
347
  'dev_requirement' => false,
348
  ),
349
  ),
5
  'type' => 'wordpress-plugin',
6
  'install_path' => __DIR__ . '/../../',
7
  'aliases' => array(),
8
+ 'reference' => '6ac1322b90948d7d50b0db7ff5ef6e3d08506d11',
9
  'name' => 'wprss/core',
10
  'dev' => false,
11
  ),
343
  'type' => 'wordpress-plugin',
344
  'install_path' => __DIR__ . '/../../',
345
  'aliases' => array(),
346
+ 'reference' => '6ac1322b90948d7d50b0db7ff5ef6e3d08506d11',
347
  'dev_requirement' => false,
348
  ),
349
  ),
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.19.2
8
  * Author: RebelCode
9
  * Author URI: https://www.wprssaggregator.com
10
  * Text Domain: wprss
@@ -76,7 +76,7 @@ use RebelCode\Wpra\Core\Plugin;
76
 
77
  // Set the version number of the plugin.
78
  if( !defined( 'WPRSS_VERSION' ) )
79
- define( 'WPRSS_VERSION', '4.19.2' );
80
 
81
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
82
  define( 'WPRSS_WP_MIN_VERSION', '4.8' );
@@ -327,6 +327,9 @@ require_once ( WPRSS_INC . 'templates-update.php' );
327
  register_activation_hook(__FILE__, 'wprss_activate');
328
  register_deactivation_hook(__FILE__, 'wprss_deactivate');
329
 
 
 
 
330
  // Safe deactivation hook (for the error handler)
331
  add_action('plugins_loaded', 'wpra_safe_deactivate', 50);
332
  // Run WPRA
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.19.3
8
  * Author: RebelCode
9
  * Author URI: https://www.wprssaggregator.com
10
  * Text Domain: wprss
76
 
77
  // Set the version number of the plugin.
78
  if( !defined( 'WPRSS_VERSION' ) )
79
+ define( 'WPRSS_VERSION', '4.19.3' );
80
 
81
  if( !defined( 'WPRSS_WP_MIN_VERSION' ) )
82
  define( 'WPRSS_WP_MIN_VERSION', '4.8' );
327
  register_activation_hook(__FILE__, 'wprss_activate');
328
  register_deactivation_hook(__FILE__, 'wprss_deactivate');
329
 
330
+ // Black friday 2021 promotion
331
+ require_once __DIR__ . '/includes/black-friday-2021.php';
332
+
333
  // Safe deactivation hook (for the error handler)
334
  add_action('plugins_loaded', 'wpra_safe_deactivate', 50);
335
  // Run WPRA