FEEDZY RSS Feeds Lite - Version 3.5.0

Version Description

  • 2020-10-12
Download this release

Release Info

Developer codeinwp
Plugin Icon 128x128 FEEDZY RSS Feeds Lite
Version 3.5.0
Comparing to
See all releases

Code changes from version 3.4.3 to 3.5.0

CHANGELOG.md CHANGED
@@ -1,4 +1,9 @@
1
 
 
 
 
 
 
2
  ### v3.4.3 - 2020-08-26
3
  **Changes:**
4
  * [Fix] HTML tags being trimmed on save of the import job
1
 
2
+ ### v3.5.0 - 2020-10-12
3
+ **Changes:**
4
+ * [Feat] Improved interface for adding new imports and for the imports listing page
5
+ * [Feat] Improved checks for feeds validity
6
+
7
  ### v3.4.3 - 2020-08-26
8
  **Changes:**
9
  * [Fix] HTML tags being trimmed on save of the import job
css/feedzy-rss-feed-import.css CHANGED
@@ -61,17 +61,78 @@
61
  color: #ff0000;
62
  }
63
 
64
- table.wp-list-table th.column-feedzy-status {
65
- width: 100px;
 
66
  }
67
 
68
- table.wp-list-table td.column-feedzy-last_run .feedzy-api-error {
69
- max-height: 120px;
70
- overflow: hidden;
71
  }
72
 
73
- table.wp-list-table td.column-feedzy-last_run .feedzy-api-error.expand {
74
- height: auto;
75
- max-height: 1400px; /* arbitrary number */
76
- overflow: visible;
77
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  color: #ff0000;
62
  }
63
 
64
+ tr.feedzy-import-status-row > td {
65
+ margin: 0;
66
+ padding: 0
67
  }
68
 
69
+ tr.feedzy-import-status-row table {
70
+ width: 32%;
71
+ table-layout: fixed;
72
  }
73
 
74
+ tr.feedzy-import-status-row table tr td {
75
+ width: 25%;
76
+ background-color: #f1f1f1;
77
+ text-align: center;
78
+ }
79
+
80
+ tr.feedzy-import-status-row table tr:first-of-type td {
81
+ padding: 3px;
82
+ font-size: 22px;
83
+ }
84
+
85
+ tr.feedzy-import-status-row table tr:last-of-type td {
86
+ background-color: #5555559c;
87
+ color: #ffffff;
88
+ padding: 0px;
89
+ text-transform: lowercase;
90
+ }
91
+
92
+ .feedzy-error-status i {
93
+ font-size: 28px;
94
+ }
95
+
96
+ .feedzy-error-status.import-error i {
97
+ color: #ca4a1f;
98
+ }
99
+
100
+ .feedzy-error-status.import-success i {
101
+ color: #149714;
102
+ }
103
+
104
+ td.feedzy-error-status a {
105
+ vertical-align: middle;
106
+ }
107
+
108
+ a.feedzy-popup-details {
109
+ pointer-events: none;
110
+ color: inherit;
111
+ }
112
+
113
+ td.feedzy-has-popup {
114
+ cursor: pointer;
115
+ }
116
+
117
+ .feedzy-has-popup a.feedzy-popup-details {
118
+ cursor: pointer;
119
+ pointer-events: all;
120
+ color: #0073aa;
121
+ }
122
+
123
+ .feedzy_run_now_msg {
124
+ font-size: 14px !important;
125
+ color: #ca4a1f !important;
126
+ background-color: inherit !important;
127
+ }
128
+
129
+
130
+ @media screen and (max-width: 782px) {
131
+ tr.feedzy-import-status-row table {
132
+ width: 100%;
133
+ }
134
+
135
+ tr.feedzy-import-status-row table tr:last-of-type td {
136
+ font-size: smaller;
137
+ }
138
+ }
css/feedzy-rss-feeds.css CHANGED
@@ -2,7 +2,7 @@
2
  * feedzy-rss-feeds.css
3
  * Feedzy RSS Feed
4
  * Copyright: (c) 2016 Themeisle, themeisle.com
5
- * Version: 3.4.3
6
  * Plugin Name: FEEDZY RSS Feeds
7
  * Plugin URI: http://themeisle.com/plugins/feedzy-rss-feeds/
8
  * Author: Themeisle
2
  * feedzy-rss-feeds.css
3
  * Feedzy RSS Feed
4
  * Copyright: (c) 2016 Themeisle, themeisle.com
5
+ * Version: 3.5.0
6
  * Plugin Name: FEEDZY RSS Feeds
7
  * Plugin URI: http://themeisle.com/plugins/feedzy-rss-feeds/
8
  * Author: Themeisle
feedzy-rss-feed.php CHANGED
@@ -15,7 +15,7 @@
15
  * Plugin Name: Feedzy RSS Feeds Lite
16
  * Plugin URI: https://themeisle.com/plugins/feedzy-rss-feeds-lite/
17
  * Description: A small and lightweight RSS aggregator plugin. Fast and very easy to use, it allows you to aggregate multiple RSS feeds into your WordPress site through fully customizable shortcodes & widgets.
18
- * Version: 3.4.3
19
  * Author: Themeisle
20
  * Author URI: http://themeisle.com
21
  * License: GPL-2.0+
15
  * Plugin Name: Feedzy RSS Feeds Lite
16
  * Plugin URI: https://themeisle.com/plugins/feedzy-rss-feeds-lite/
17
  * Description: A small and lightweight RSS aggregator plugin. Fast and very easy to use, it allows you to aggregate multiple RSS feeds into your WordPress site through fully customizable shortcodes & widgets.
18
+ * Version: 3.5.0
19
  * Author: Themeisle
20
  * Author URI: http://themeisle.com
21
  * License: GPL-2.0+
includes/abstract/feedzy-rss-feeds-admin-abstract.php CHANGED
@@ -138,8 +138,9 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
138
  public function feedzy_default_error_notice( $errors, $feed, $feed_url ) {
139
  global $post;
140
  // Show the error message only if the user who has created this post (which contains the feed) is logged in.
 
141
  // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
142
- $show_error = is_user_logged_in() && $post && get_current_user_id() == $post->post_author;
143
  $error_msg = '';
144
 
145
  if ( is_array( $errors ) ) {
@@ -150,12 +151,18 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
150
  $error_msg = $errors;
151
  }
152
 
 
 
153
  if ( $show_error ) {
154
- return '<div id="message" class="error"><p>' . sprintf( __( 'Sorry, some part of this feed is currently unavailable or does not exist anymore. The detailed error is %1$s %2$s(Only you are seeing this detailed error because you are the creator of this post. Other users will see the error message as below.)%3$s', 'feedzy-rss-feeds' ), '<p style="font-weight: bold">' . $error_msg . '</p>', '<small>', '</small>' ) . '</p></div>';
 
 
 
 
155
  } else {
156
  error_log( 'Feedzy RSS Feeds - related feed: ' . print_r( $feed_url, true ) . ' - Error message: ' . $error_msg );
157
  }
158
- return '';
159
  }
160
 
161
  /**
@@ -379,6 +386,17 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
379
  return $html;
380
  }
381
 
 
 
 
 
 
 
 
 
 
 
 
382
  $feed = $this->fetch_feed( $feed_url, $cache, $sc );
383
  if ( is_string( $feed ) ) {
384
  return $feed;
@@ -500,6 +518,9 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
500
  'className' => '',
501
  // lazy loading of feeds?
502
  'lazy' => 'no',
 
 
 
503
  ),
504
  $atts,
505
  'feedzy_default'
@@ -524,10 +545,10 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
524
  $feed_url = apply_filters( 'feedzy_get_feed_url', $feeds );
525
  if ( is_array( $feed_url ) ) {
526
  foreach ( $feed_url as $index => $url ) {
527
- $feed_url[ $index ] = $this->smart_convert( $url );
528
  }
529
  } else {
530
- $feed_url = $this->smart_convert( $feed_url );
531
  }
532
 
533
  return $feed_url;
@@ -756,28 +777,33 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
756
  * Returns only valid URLs for fetching.
757
  *
758
  * @since 3.2.0
759
- * @access private
760
  *
761
  * @param array|string $feed_url The feeds URL/s.
762
  * @param string $cache The cache string (eg. 1_hour, 30_min etc.).
 
763
  *
764
  * @return array
765
  */
766
- private function get_valid_feed_urls( $feed_url, $cache ) {
767
  $valid_feed_url = array();
768
  if ( is_array( $feed_url ) ) {
769
  foreach ( $feed_url as $url ) {
770
  if ( $this->check_valid_xml( $url, $cache ) ) {
771
  $valid_feed_url[] = $url;
772
  } else {
773
- echo sprintf( __( 'Feed URL: %s not valid and removed from fetch.', 'feedzy-rss-feeds' ), '<b>' . $url . '</b>' );
 
 
774
  }
775
  }
776
  } else {
777
  if ( $this->check_valid_xml( $feed_url, $cache ) ) {
778
  $valid_feed_url[] = $feed_url;
779
  } else {
780
- echo sprintf( __( 'Feed URL: %s not valid and removed from fetch.', 'feedzy-rss-feeds' ), '<b>' . $feed_url . '</b>' );
 
 
781
  }
782
  }
783
 
@@ -788,15 +814,15 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
788
  * Checks if a url is a valid feed.
789
  *
790
  * @since 3.2.0
791
- * @access private
792
  *
793
  * @param string $url The URL to validate.
794
  * @param string $cache The cache string (eg. 1_hour, 30_min etc.).
795
  *
796
  * @return bool
797
  */
798
- private function check_valid_xml( $url, $cache ) {
799
- $feed = $this->init_feed( $url, $cache );
800
  if ( $feed->error() ) {
801
  return false;
802
  }
@@ -897,30 +923,84 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
897
 
898
  $anchor1 = '<a href="%s" target="%s" rel="%s noopener" title="%s" style="%s">%s</a>';
899
  $anchor2 = '<a href="%s" target="%s" rel="%s noopener">%s</a>';
 
 
 
900
  foreach ( $feed_items as $item ) {
901
- $content .= '
902
- <li ' . $item['itemAttr'] . '>
903
- ' . ( ( ! empty( $item['item_img'] ) && $sc['thumb'] !== 'no' ) ? '
904
- <div class="' . $item['item_img_class'] . '" style="' . $item['item_img_style'] . '">'
905
- . sprintf( $anchor1, $item['item_url'], $item['item_url_target'], $item['item_url_follow'], $item['item_url_title'], $item['item_img_style'], $item['item_img'] )
906
- . '</div>' : '' )
907
- . '<span class="title">'
908
- . sprintf( $anchor2, $item['item_url'], $item['item_url_target'], $item['item_url_follow'], $item['item_title'] )
909
- . '</span>
910
- <div class="' . $item['item_content_class'] . '" style="' . $item['item_content_style'] . '">
911
- ' . ( ! empty( $item['item_meta'] ) ? '<small>
912
- ' . $item['item_meta'] . '
913
- </small>' : '' ) . '
914
- ' . ( ! empty( $item['item_description'] ) ? '<p>' . $item['item_description'] . '</p>' : '' ) . '
915
- </div>
916
- </li>
917
- ';
 
 
 
918
  }
919
  $content .= '</ul> </div>';
920
- $content = apply_filters( 'feedzy_global_output', $content, $sc, $feed_title, $feed_items );
 
 
921
  return $content;
922
  }
923
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
924
  /**
925
  * Retrive the filter rss title array
926
  *
@@ -962,15 +1042,16 @@ abstract class Feedzy_Rss_Feeds_Admin_Abstract {
962
  $feed_url = array();
963
  // Remove SSL from HTTP request to prevent fetching errors
964
  foreach ( $feeds as $feed ) {
 
 
 
 
 
965
  if ( FEEDZY_ALLOW_HTTPS ) {
966
  $feed_url[] = $feed;
967
  } else {
968
  $feed_url[] = preg_replace( '/^https:/i', 'http:', $feed );
969
  }
970
- // scheme-less URLs.
971
- if ( strpos( $feed, 'http' ) !== 0 ) {
972
- $feed = 'http://' . $feed;
973
- }
974
  }
975
  if ( count( $feed_url ) === 1 ) {
976
  $feed_url = $feed_url[0];
138
  public function feedzy_default_error_notice( $errors, $feed, $feed_url ) {
139
  global $post;
140
  // Show the error message only if the user who has created this post (which contains the feed) is logged in.
141
+ // Or if this is in the dry run window.
142
  // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
143
+ $show_error = is_admin() || ( is_user_logged_in() && $post && get_current_user_id() == $post->post_author );
144
  $error_msg = '';
145
 
146
  if ( is_array( $errors ) ) {
151
  $error_msg = $errors;
152
  }
153
 
154
+ $final_msg = '';
155
+
156
  if ( $show_error ) {
157
+ $final_msg = '<div id="message" class="error"><p>' . sprintf( __( 'Sorry, some part of this feed is currently unavailable or does not exist anymore. The detailed error is %s', 'feedzy-rss-feeds' ), '<p style="font-weight: bold">' . $error_msg . '</p>' );
158
+ if ( ! is_admin() ) {
159
+ $final_msg .= sprintf( __( '%1$s(Only you are seeing this detailed error because you are the creator of this post. Other users will see the error message as below.)%2$s', 'feedzy-rss-feeds' ), '<small>', '</small>' );
160
+ }
161
+ $final_msg .= '</p></div>';
162
  } else {
163
  error_log( 'Feedzy RSS Feeds - related feed: ' . print_r( $feed_url, true ) . ' - Error message: ' . $error_msg );
164
  }
165
+ return $final_msg;
166
  }
167
 
168
  /**
386
  return $html;
387
  }
388
 
389
+ if ( isset( $sc['_dry_run_tags_'] ) ) {
390
+ if ( strpos( $sc['_dry_run_tags_'], 'item_full_content' ) !== false ) {
391
+ $sc_clone = $sc;
392
+ $sc_clone['__jobID'] = ''; // pro expects this but keep it empty.
393
+ $feedURL = apply_filters( 'feedzy_import_feed_url', $feed_url, '[#item_full_content]', $sc_clone );
394
+ if ( ! is_wp_error( $feedURL ) ) {
395
+ $feed_url = $feedURL;
396
+ }
397
+ }
398
+ }
399
+
400
  $feed = $this->fetch_feed( $feed_url, $cache, $sc );
401
  if ( is_string( $feed ) ) {
402
  return $feed;
518
  'className' => '',
519
  // lazy loading of feeds?
520
  'lazy' => 'no',
521
+ // this are only for internal purposes
522
+ '_dryrun_' => 'no',
523
+ '_dry_run_tags_' => '',
524
  ),
525
  $atts,
526
  'feedzy_default'
545
  $feed_url = apply_filters( 'feedzy_get_feed_url', $feeds );
546
  if ( is_array( $feed_url ) ) {
547
  foreach ( $feed_url as $index => $url ) {
548
+ $feed_url[ $index ] = trim( $this->smart_convert( $url ) );
549
  }
550
  } else {
551
+ $feed_url = trim( $this->smart_convert( $feed_url ) );
552
  }
553
 
554
  return $feed_url;
777
  * Returns only valid URLs for fetching.
778
  *
779
  * @since 3.2.0
780
+ * @access protected
781
  *
782
  * @param array|string $feed_url The feeds URL/s.
783
  * @param string $cache The cache string (eg. 1_hour, 30_min etc.).
784
+ * @param bool $echo Echo the results.
785
  *
786
  * @return array
787
  */
788
+ protected function get_valid_feed_urls( $feed_url, $cache, $echo = true ) {
789
  $valid_feed_url = array();
790
  if ( is_array( $feed_url ) ) {
791
  foreach ( $feed_url as $url ) {
792
  if ( $this->check_valid_xml( $url, $cache ) ) {
793
  $valid_feed_url[] = $url;
794
  } else {
795
+ if ( $echo ) {
796
+ echo sprintf( __( 'Feed URL: %s not valid and removed from fetch.', 'feedzy-rss-feeds' ), '<b>' . $url . '</b>' );
797
+ }
798
  }
799
  }
800
  } else {
801
  if ( $this->check_valid_xml( $feed_url, $cache ) ) {
802
  $valid_feed_url[] = $feed_url;
803
  } else {
804
+ if ( $echo ) {
805
+ echo sprintf( __( 'Feed URL: %s not valid and removed from fetch.', 'feedzy-rss-feeds' ), '<b>' . $feed_url . '</b>' );
806
+ }
807
  }
808
  }
809
 
814
  * Checks if a url is a valid feed.
815
  *
816
  * @since 3.2.0
817
+ * @access protected
818
  *
819
  * @param string $url The URL to validate.
820
  * @param string $cache The cache string (eg. 1_hour, 30_min etc.).
821
  *
822
  * @return bool
823
  */
824
+ protected function check_valid_xml( $url, $cache ) {
825
+ $feed = $this->init_feed( $url, $cache, array() );
826
  if ( $feed->error() ) {
827
  return false;
828
  }
923
 
924
  $anchor1 = '<a href="%s" target="%s" rel="%s noopener" title="%s" style="%s">%s</a>';
925
  $anchor2 = '<a href="%s" target="%s" rel="%s noopener">%s</a>';
926
+ $line_item = '<li %s>%s<span class="title">%s</span><div class="%s" style="%s">%s%s</div></li>';
927
+ $dry_run_item = '<li %s><span class="title">%s</span><div class="dry_run">%s</div></li>';
928
+ $is_dry_run = isset( $sc['_dryrun_'] ) && $sc['_dryrun_'] === 'yes';
929
  foreach ( $feed_items as $item ) {
930
+ if ( $is_dry_run ) {
931
+ $details = $this->get_dry_run_results( $sc, $item );
932
+ $content .= sprintf(
933
+ $dry_run_item,
934
+ $item['itemAttr'],
935
+ sprintf( $anchor2, $item['item_url'], $item['item_url_target'], $item['item_url_follow'], $item['item_title'] ),
936
+ $details
937
+ );
938
+ } else {
939
+ $content .= sprintf(
940
+ $line_item,
941
+ $item['itemAttr'],
942
+ ! empty( $item['item_img'] ) && $sc['thumb'] !== 'no' ? sprintf( '<div class="%s" style="%s">%s</div>', $item['item_img_class'], $item['item_img_style'], sprintf( $anchor1, $item['item_url'], $item['item_url_target'], $item['item_url_follow'], $item['item_url_title'], $item['item_img_style'], $item['item_img'] ) ) : '',
943
+ sprintf( $anchor2, $item['item_url'], $item['item_url_target'], $item['item_url_follow'], $item['item_title'] ),
944
+ $item['item_content_class'],
945
+ $item['item_content_style'],
946
+ empty( $item['item_meta'] ) ? '' : sprintf( '<small>%s</small>', $item['item_meta'] ),
947
+ empty( $item['item_description'] ) ? '' : sprintf( '<p>%s</p>', $item['item_description'] )
948
+ );
949
+ }
950
  }
951
  $content .= '</ul> </div>';
952
+ if ( ! $is_dry_run ) {
953
+ $content = apply_filters( 'feedzy_global_output', $content, $sc, $feed_title, $feed_items );
954
+ }
955
  return $content;
956
  }
957
 
958
+ /**
959
+ * Gets the results of the dry run.
960
+ *
961
+ * @since ?
962
+ * @access private
963
+ *
964
+ * @param array $sc The shorcode attributes array.
965
+ * @param object $item The feed item array.
966
+ *
967
+ * @return string
968
+ */
969
+ private function get_dry_run_results( $sc, $item ) {
970
+ $statuses = array();
971
+ $details = '';
972
+ if ( true === apply_filters( 'feedzy_is_license_of_type', false, 'business' ) ) {
973
+ if ( ! empty( $item['full_content_error'] ) ) {
974
+ $statuses[] = array( 'success' => false, 'msg' => sprintf( __( 'Full content: %s', 'feedzy-rss-feeds' ), $item['full_content_error'] ) );
975
+ } elseif ( isset( $item['item_full_content'] ) ) {
976
+ if ( ! empty( $item['item_full_content'] ) ) {
977
+ $statuses[] = array( 'success' => true, 'msg' => __( 'Full content extracted', 'feedzy-rss-feeds' ) );
978
+ } else {
979
+ $statuses[] = array( 'success' => true, 'msg' => __( 'Full content extracted (is empty)', 'feedzy-rss-feeds' ) );
980
+ }
981
+ }
982
+ }
983
+ if ( strpos( $sc['_dry_run_tags_'], 'item_image' ) !== false ) {
984
+ if ( ! empty( $item['item_img_path'] ) ) {
985
+ $statuses[] = array( 'success' => true, 'msg' => __( 'Image', 'feedzy-rss-feeds' ) );
986
+ } else {
987
+ $statuses[] = array( 'success' => false, 'msg' => __( 'Unable to find image', 'feedzy-rss-feeds' ) );
988
+ }
989
+ }
990
+
991
+ if ( $statuses ) {
992
+ foreach ( $statuses as $status ) {
993
+ $details .= sprintf(
994
+ '<span><i class="dashicons dashicons-%s %s"></i>%s',
995
+ $status['success'] ? 'yes' : 'no-alt',
996
+ $status['success'] ? 'pass' : 'fail',
997
+ $status['msg']
998
+ );
999
+ }
1000
+ }
1001
+ return $details;
1002
+ }
1003
+
1004
  /**
1005
  * Retrive the filter rss title array
1006
  *
1042
  $feed_url = array();
1043
  // Remove SSL from HTTP request to prevent fetching errors
1044
  foreach ( $feeds as $feed ) {
1045
+ $feed = trim( $feed );
1046
+ // scheme-less URLs.
1047
+ if ( strpos( $feed, 'http' ) !== 0 ) {
1048
+ $feed = 'http://' . $feed;
1049
+ }
1050
  if ( FEEDZY_ALLOW_HTTPS ) {
1051
  $feed_url[] = $feed;
1052
  } else {
1053
  $feed_url[] = preg_replace( '/^https:/i', 'http:', $feed );
1054
  }
 
 
 
 
1055
  }
1056
  if ( count( $feed_url ) === 1 ) {
1057
  $feed_url = $feed_url[0];
includes/admin/feedzy-rss-feeds-admin.php CHANGED
@@ -116,6 +116,32 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
116
  return;
117
  }
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  if ( in_array( $screen->base, array( 'post' ), true ) ) {
120
  wp_enqueue_style( $this->plugin_name . '-admin', FEEDZY_ABSURL . 'css/admin.css', array(), $this->version, 'all' );
121
  }
@@ -245,10 +271,13 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
245
  global $post;
246
  $nonce = wp_create_nonce( FEEDZY_BASEFILE );
247
  $feed = get_post_meta( $post->ID, 'feedzy_category_feed', true );
 
 
248
  $output = '
249
  <input type="hidden" name="feedzy_category_meta_noncename" id="feedzy_category_meta_noncename" value="' . $nonce . '" />
250
- <strong>' . sprintf( __( 'Please be aware that multiple feeds, when mashed together, may sometimes not work as expected as explained %1$shere%2$s.', 'feedzy-rss-feeds' ), '<a href="http://simplepie.org/wiki/faq/typical_multifeed_gotchas" target="_blank">', '</a>' ) . '</strong><br/><br/>
251
- <textarea name="feedzy_category_feed" rows="15" class="widefat" placeholder="' . __( 'Place your URL\'s here followed by a comma.', 'feedzy-rss-feeds' ) . '" >' . $feed . '</textarea>
 
252
  ';
253
  echo $output;
254
  }
@@ -316,9 +345,29 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
316
  $columns['slug'] = __( 'Slug', 'feedzy-rss-feeds' );
317
  }
318
 
 
 
 
 
 
 
319
  return $columns;
320
  }
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  /**
323
  * Method for displaying post type data in custom
324
  * added columns.
@@ -342,6 +391,9 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
342
  echo '<code>' . $slug . '</code>';
343
  }
344
  break;
 
 
 
345
  default:
346
  break;
347
  }
@@ -589,5 +641,135 @@ class Feedzy_Rss_Feeds_Admin extends Feedzy_Rss_Feeds_Admin_Abstract {
589
  }
590
  }
591
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
592
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  }
116
  return;
117
  }
118
 
119
+ if ( $screen->post_type === 'feedzy_categories' ) {
120
+ wp_enqueue_script(
121
+ $this->plugin_name . '_categories',
122
+ FEEDZY_ABSURL . 'js/categories.js',
123
+ array(
124
+ 'jquery',
125
+ ),
126
+ $this->version,
127
+ true
128
+ );
129
+ wp_localize_script(
130
+ $this->plugin_name . '_categories',
131
+ 'feedzy',
132
+ array(
133
+ 'ajax' => array(
134
+ 'security' => wp_create_nonce( FEEDZY_NAME ),
135
+ ),
136
+ 'l10n' => array(
137
+ 'validate' => __( 'Validate & Clean', 'feedzy-rss-feeds' ),
138
+ 'validating' => __( 'Validating', 'feedzy-rss-feeds' ) . '...',
139
+ 'validated' => __( 'Removed # URL(s)!', 'feedzy-rss-feeds' ),
140
+ ),
141
+ )
142
+ );
143
+ }
144
+
145
  if ( in_array( $screen->base, array( 'post' ), true ) ) {
146
  wp_enqueue_style( $this->plugin_name . '-admin', FEEDZY_ABSURL . 'css/admin.css', array(), $this->version, 'all' );
147
  }
271
  global $post;
272
  $nonce = wp_create_nonce( FEEDZY_BASEFILE );
273
  $feed = get_post_meta( $post->ID, 'feedzy_category_feed', true );
274
+ $invalid = $this->get_source_validity_error( '', $post );
275
+
276
  $output = '
277
  <input type="hidden" name="feedzy_category_meta_noncename" id="feedzy_category_meta_noncename" value="' . $nonce . '" />
278
+ <strong>' . sprintf( __( 'Please be aware that multiple feeds, when mashed together, may sometimes not work as expected as explained %1$shere%2$s.', 'feedzy-rss-feeds' ), '<a href="http://simplepie.org/wiki/faq/typical_multifeed_gotchas" target="_blank">', '</a>' ) . '</strong><br/><br/>'
279
+ . $invalid
280
+ . '<textarea name="feedzy_category_feed" rows="15" class="widefat" placeholder="' . __( 'Place your URL\'s here followed by a comma.', 'feedzy-rss-feeds' ) . '" >' . $feed . '</textarea>
281
  ';
282
  echo $output;
283
  }
345
  $columns['slug'] = __( 'Slug', 'feedzy-rss-feeds' );
346
  }
347
 
348
+ if ( $new_columns = $this->array_insert_before( 'date', $columns, 'actions', __( 'Actions', 'feedzy-rss-feeds' ) ) ) {
349
+ $columns = $new_columns;
350
+ } else {
351
+ $columns['actions'] = __( 'Actions', 'feedzy-rss-feeds' );
352
+ }
353
+
354
  return $columns;
355
  }
356
 
357
+ /**
358
+ * Add/remove row actions for each category.
359
+ *
360
+ * @since ?
361
+ * @access public
362
+ */
363
+ public function add_feedzy_category_actions( $actions, $post ) {
364
+ if ( $post->post_type === 'feedzy_categories' ) {
365
+ // don't need quick edit.
366
+ unset( $actions['inline hide-if-no-js'] );
367
+ }
368
+ return $actions;
369
+ }
370
+
371
  /**
372
  * Method for displaying post type data in custom
373
  * added columns.
391
  echo '<code>' . $slug . '</code>';
392
  }
393
  break;
394
+ case 'actions':
395
+ echo sprintf( '<button class="button button-primary validate-category" title="%s" data-category-id="%d">%s</button>', __( 'Click to remove invalid URLs from this category', 'feedzy-rss-feeds' ), $post_id, __( 'Validate & Clean', 'feedzy-rss-feeds' ) );
396
+ break;
397
  default:
398
  break;
399
  }
641
  }
642
  }
643
 
644
+ /**
645
+ * Validates the URLs and removes the ones that were found to be invalid.
646
+ *
647
+ * @access public
648
+ */
649
+ public function validate_category_feeds( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
650
+ if ( 'feedzy_category_feed' === $meta_key && 'feedzy_categories' === get_post_type( $object_id ) ) {
651
+ remove_filter( current_filter(), array( $this, 'validate_category_feeds' ) );
652
+ $valid = $this->check_source_validity( $meta_value, $object_id, true, true );
653
+ update_post_meta( $object_id, $meta_key, empty( $valid ) ? '' : implode( ', ', $valid ) );
654
+ return true;
655
+ }
656
+
657
+ return $check;
658
+ }
659
+
660
+ /**
661
+ * Validates the source (category or URL(s)) and returns only the ones that were found to be valid.
662
+ *
663
+ * @access public
664
+ */
665
+ public function check_source_validity( $src, $post_id, $add_pseudo_transient, $return_valid ) {
666
+ $urls_in = $src;
667
+ $post_type = get_post_type( $post_id );
668
+ if ( 'feedzy_imports' === $post_type && strpos( $src, 'http' ) === false && strpos( $src, 'https' ) === false ) {
669
+ // category
670
+ $category = get_page_by_path( $src, OBJECT, 'feedzy_categories' );
671
+ if ( $category ) {
672
+ $urls_in = get_post_meta( $category->ID, 'feedzy_category_feed', true );
673
+ }
674
+ }
675
+
676
+ // this method is fired through ajax when the category title is updated
677
+ // even without clicking the publish button
678
+ // thereby sending empty urls
679
+ if ( empty( $urls_in ) ) {
680
+ return array();
681
+ }
682
+
683
+ $urls = $this->normalize_urls( $urls_in );
684
+ if ( ! is_array( $urls ) ) {
685
+ $urls = array( $urls );
686
+ }
687
+ $valid = $this->get_valid_feed_urls( $urls, '1_mins', false );
688
+ $invalid = array_diff( $urls, $valid );
689
+
690
+ if ( $add_pseudo_transient && ( empty( $valid ) || ! empty( $invalid ) ) ) {
691
+ // let's save the invalid urls in a pseudo-transient so that we can show it in the import edit screen.
692
+ switch ( $post_type ) {
693
+ case 'feedzy_categories':
694
+ update_post_meta( $post_id, '__transient_feedzy_category_feed', $invalid );
695
+ break;
696
+ case 'feedzy_imports':
697
+ update_post_meta( $post_id, '__transient_feedzy_invalid_source', $invalid );
698
+ break;
699
+ }
700
+ }
701
+
702
+ if ( is_null( $return_valid ) ) {
703
+ return array(
704
+ 'valid' => $valid,
705
+ 'invalid' => $invalid,
706
+ );
707
+ }
708
+
709
+ if ( $return_valid ) {
710
+ return $valid;
711
+ }
712
+
713
+ return $invalid;
714
+ }
715
+
716
+ /**
717
+ * Returns the error message to display if invalid URLs are found in the source (category or URL(s)).
718
+ *
719
+ * @access public
720
+ */
721
+ public function get_source_validity_error( $message = '', $post, $class = '' ) {
722
+ $invalid = $text = null;
723
+ switch ( $post->post_type ) {
724
+ case 'feedzy_categories':
725
+ $text = __( 'We found the following invalid URLs that we have removed from the list', 'feedzy-rss-feeds' );
726
+ $invalid = get_post_meta( $post->ID, '__transient_feedzy_category_feed', true );
727
+ delete_post_meta( $post->ID, '__transient_feedzy_category_feed' );
728
+ break;
729
+ case 'feedzy_imports':
730
+ $text = __( 'This source has invalid URLs. Please correct/remove the following', 'feedzy-rss-feeds' );
731
+ $invalid = get_post_meta( $post->ID, '__transient_feedzy_invalid_source', true );
732
+ delete_post_meta( $post->ID, '__transient_feedzy_invalid_source' );
733
+ break;
734
+ default:
735
+ return $message;
736
+ }
737
+
738
+ if ( $invalid ) {
739
+ if ( empty( $class ) ) {
740
+ $class = 'notice notice-error notice-alt feedzy-error-critical';
741
+ }
742
+ $message .= '<div class="' . $class . '"><p style="color: inherit"><i class="dashicons dashicons-warning"></i>' . $text . ': <ol style="color: inherit">';
743
+ foreach ( $invalid as $url ) {
744
+ $message .= '<li>' . ( empty( $url ) ? __( 'Empty URL', 'feedzy-rss-feeds' ) : esc_html( $url ) ) . '</li>';
745
+ }
746
+ $message .= '</ol></p></div>';
747
+ }
748
+ return $message;
749
+ }
750
 
751
+ /**
752
+ * AJAX single-entry method.
753
+ *
754
+ * @since 3.4.1
755
+ * @access public
756
+ */
757
+ public function ajax() {
758
+ check_ajax_referer( FEEDZY_NAME, 'security' );
759
+
760
+ switch ( $_POST['_action'] ) {
761
+ case 'validate_clean':
762
+ // remove invalid URLs from this category.
763
+ $urls = get_post_meta( $_POST['id'], 'feedzy_category_feed', true );
764
+ $return = $this->check_source_validity( $urls, $_POST['id'], false, null );
765
+ $valid = $return['valid'];
766
+ $invalid = $return['invalid'];
767
+ if ( ! empty( $valid ) ) {
768
+ remove_filter( 'update_post_metadata', array( $this, 'validate_category_feeds' ) );
769
+ update_post_meta( $_POST['id'], 'feedzy_category_feed', implode( ', ', $valid ) );
770
+ }
771
+ wp_send_json_success( array( 'invalid' => count( $invalid ) ) );
772
+ break;
773
+ }
774
+ }
775
  }
includes/admin/feedzy-rss-feeds-import.php CHANGED
@@ -142,6 +142,14 @@ class Feedzy_Rss_Feeds_Import {
142
  'ajax' => array(
143
  'security' => wp_create_nonce( FEEDZY_BASEFILE ),
144
  ),
 
 
 
 
 
 
 
 
145
  )
146
  );
147
  }
@@ -287,6 +295,14 @@ class Feedzy_Rss_Feeds_Import {
287
  $import_content = get_post_meta( $post->ID, 'import_post_content', true );
288
  $import_featured_img = get_post_meta( $post->ID, 'import_post_featured_img', true );
289
 
 
 
 
 
 
 
 
 
290
  $import_link_author_admin = get_post_meta( $post->ID, 'import_link_author_admin', true );
291
  $import_link_author_public = get_post_meta( $post->ID, 'import_link_author_public', true );
292
 
@@ -304,12 +320,21 @@ class Feedzy_Rss_Feeds_Import {
304
 
305
  $import_custom_fields = get_post_meta( $post->ID, 'imports_custom_fields', true );
306
  $import_feed_limit = get_post_meta( $post->ID, 'import_feed_limit', true );
 
 
 
307
  $import_feed_delete_days = intval( get_post_meta( $post->ID, 'import_feed_delete_days', true ) );
 
 
 
308
  $post_status = $post->post_status;
309
  $nonce = wp_create_nonce( FEEDZY_BASEFILE );
 
310
  $output = '
311
  <input type="hidden" name="feedzy_category_meta_noncename" id="feedzy_category_meta_noncename" value="' . $nonce . '" />
312
  ';
 
 
313
  include FEEDZY_ABSPATH . '/includes/views/import-metabox-edit.php';
314
  echo $output;
315
  }
@@ -361,8 +386,17 @@ class Feedzy_Rss_Feeds_Import {
361
  delete_post_meta( $post_id, 'import_link_author_admin' );
362
  delete_post_meta( $post_id, 'import_link_author_public' );
363
 
 
 
 
364
  foreach ( $data_meta as $key => $value ) {
365
  $value = is_array( $value ) ? implode( ',', $value ) : implode( ',', (array) $value );
 
 
 
 
 
 
366
  if ( get_post_meta( $post_id, $key, false ) ) {
367
  update_post_meta( $post_id, $key, wp_kses( $value, wp_kses_allowed_html( 'post' ) ) );
368
  } else {
@@ -373,7 +407,7 @@ class Feedzy_Rss_Feeds_Import {
373
  }
374
  }
375
  // Added this to activate post if publish is clicked and sometimes it does not change status.
376
- if ( isset( $_POST['custom_post_status'] ) && $_POST['custom_post_status'] === 'Publish' ) {
377
  $activate = array(
378
  'ID' => $post_id,
379
  'post_status' => 'publish',
@@ -401,7 +435,13 @@ class Feedzy_Rss_Feeds_Import {
401
  public function redirect_post_location( $location, $post_id ) {
402
  $post = get_post( $post_id );
403
  if ( 'feedzy_imports' === $post->post_type ) {
404
- return admin_url( 'edit.php?post_type=feedzy_imports' );
 
 
 
 
 
 
405
  }
406
  return $location;
407
  }
@@ -430,18 +470,20 @@ class Feedzy_Rss_Feeds_Import {
430
  $columns['feedzy-status'] = __( 'Current Status', 'feedzy-rss-feeds' );
431
  }
432
 
433
- if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-last_run', __( 'Last Run Status', 'feedzy-rss-feeds' ) ) ) {
434
  $columns = $new_columns;
435
  } else {
436
- $columns['feedzy-last_run'] = __( 'Last Run Status', 'feedzy-rss-feeds' );
437
  }
438
 
439
- if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-next_run', __( 'Next Run', 'feedzy-rss-feeds' ) ) ) {
440
  $columns = $new_columns;
441
  } else {
442
- $columns['feedzy-next_run'] = __( 'Next Run', 'feedzy-rss-feeds' );
443
  }
444
 
 
 
445
  return $columns;
446
  }
447
 
@@ -513,6 +555,7 @@ class Feedzy_Rss_Feeds_Import {
513
  <div class="switch">
514
  <input id="feedzy-toggle_' . $post->ID . '" class="feedzy-toggle feedzy-toggle-round" type="checkbox" value="' . $post->ID . '" ' . $checked . '>
515
  <label for="feedzy-toggle_' . $post->ID . '"></label>
 
516
  </div>
517
  ';
518
  }
@@ -521,24 +564,20 @@ class Feedzy_Rss_Feeds_Import {
521
  $last = get_post_meta( $post_id, 'last_run', true );
522
  $msg = __( 'Never Run', 'feedzy-rss-feeds' );
523
  if ( $last ) {
524
- $msg = $this->get_import_status( $post_id );
525
- $msg .= $this->get_import_info( $post_id );
526
- $msg .= $this->get_import_errors( $post_id, false );
527
-
528
- // show the total items imported across all runs.
529
- $items = get_post_meta( $post_id, 'imported_items_hash', true );
530
- if ( empty( $items ) ) {
531
- $items = get_post_meta( $post_id, 'imported_items', true );
532
- }
533
- $count = $items ? count( $items ) : 0;
534
- $url = add_query_arg( array( 'feedzy_job_id' => $post_id, 'post_type' => get_post_meta( $post_id, 'import_post_type', true ) ), admin_url( 'edit.php' ) );
535
- if ( ! defined( 'TI_CYPRESS_TESTING' ) && $count > 0 ) {
536
- $msg .= '<hr>' . sprintf( '%s: <b><a href="%s" target="_blank" title="%s">%d</a></b>', __( 'Items imported across runs', 'feedzy-rss-feeds' ), $url, __( 'Click to view', 'feedzy-rss-feeds' ), $count );
537
- } else {
538
- $msg .= '<hr>' . sprintf( '%s: <b>%d</b>', __( 'Items imported across runs', 'feedzy-rss-feeds' ), $count );
539
- }
540
  }
 
 
541
  echo $msg;
 
 
 
 
 
542
  break;
543
  case 'feedzy-next_run':
544
  $next = wp_next_scheduled( 'feedzy_cron' );
@@ -548,9 +587,6 @@ class Feedzy_Rss_Feeds_Import {
548
  $then = $then->setTimestamp( $next );
549
  $in = $now->diff( $then );
550
  echo sprintf( __( 'In %1$d hours %2$d minutes', 'feedzy-rss-feeds' ), $in->format( '%h' ), $in->format( '%i' ) );
551
- if ( 'publish' === $post->post_status ) {
552
- echo sprintf( '<br/><input type="button" class="button button-primary feedzy-run-now" data-id="%d" value="%s"><span class="feedzy-spinner spinner"></span>', $post_id, __( 'Run Now', 'feedzy-rss-feeds' ) );
553
- }
554
  }
555
  break;
556
  default:
@@ -559,13 +595,141 @@ class Feedzy_Rss_Feeds_Import {
559
  }
560
 
561
  /**
562
- * Creates the basic message to show against each import.
563
  *
564
  * @since ?
565
  * @access private
 
 
566
  */
567
- private function get_import_status( $post_id ) {
 
568
  $last = get_post_meta( $post_id, 'last_run', true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
569
  $items_count = get_post_meta( $post_id, 'imported_items_count', true );
570
  $items = get_post_meta( $post_id, 'imported_items_hash', true );
571
  if ( empty( $items ) ) {
@@ -576,13 +740,42 @@ class Feedzy_Rss_Feeds_Import {
576
  // backward compatibility where imported_items_count post_meta has not been populated yet
577
  $count = count( $items );
578
  }
579
- $now = new DateTime();
580
- $then = new DateTime();
581
- $then = $then->setTimestamp( $last );
582
- $in = $now->diff( $then );
583
- $msg = sprintf( __( 'Imported %1$d item(s)<br>%2$d hours %3$d minutes ago', 'feedzy-rss-feeds' ), $count, $in->format( '%h' ), $in->format( '%i' ) );
584
 
585
- return apply_filters( 'feedzy_run_status_status', $msg, $post_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
  }
587
 
588
  /**
@@ -591,69 +784,39 @@ class Feedzy_Rss_Feeds_Import {
591
  * @since ?
592
  * @access private
593
  */
594
- private function get_import_errors( $post_id, $under_next_run ) {
595
  $msg = '';
596
  $import_errors = get_post_meta( $post_id, 'import_errors', true );
597
  if ( $import_errors ) {
598
- $title = ! $under_next_run ? __( 'Click to expand', 'feedzy-rss-feeds' ) : null;
599
- $msg = '<hr><div class="feedzy-error feedzy-api-error" title="' . esc_attr( $title ) . '"><i class="dashicons dashicons-warning"></i>' . implode( '<i class="dashicons dashicons-warning"></i>', $import_errors ) . '</div>';
 
 
 
 
 
 
 
600
  }
601
 
602
  $pro_msg = apply_filters( 'feedzy_run_status_errors', '', $post_id );
603
 
604
  // the pro messages may not have the dashicons, so let's add them.
605
  if ( $pro_msg && strpos( $pro_msg, 'dashicons-warning' ) === false ) {
606
- // we will have to add class="nothing" so that the <br> doesn't get overriden repeatedly.
607
- $pro_msg = '<hr>' . str_replace( '<br>', '<br class="nothing"><i class="dashicons dashicons-warning"></i>', $pro_msg );
608
- $pro_msg = str_replace( '<div class="feedzy-error feedzy-api-error"><br class="nothing">', '<div class="feedzy-error feedzy-api-error">', $pro_msg );
609
- }
610
-
611
- return $msg . $pro_msg;
612
- }
613
-
614
- /**
615
- * Creates the data by extracting the 'import_info' from each import.
616
- *
617
- * @since ?
618
- * @access private
619
- */
620
- private function get_import_info( $post_id ) {
621
- $msg = '';
622
- $import_info = get_post_meta( $post_id, 'import_info', true );
623
- if ( $import_info ) {
624
- $msg = '';
625
- foreach ( $import_info as $label => $value ) {
626
- switch ( $label ) {
627
- case 'total':
628
- if ( count( $value ) > 0 ) {
629
- $msg .= '<br>' . sprintf( '%s: %s%d%s', __( 'Total items found', 'feedzy-rss-feeds' ), '<a href="#" title="' . __( 'Click to view details', 'feedzy-rss-feeds' ) . '" class="feedzy-dialog-open" data-dialog="feedzy-items-found-' . $post_id . '">', count( $value ), '</a>' );
630
- } else {
631
- $msg .= '<br>' . sprintf( '%s: %d', __( 'Total items found', 'feedzy-rss-feeds' ), count( $value ) );
632
- }
633
- if ( $value ) {
634
- $msg .= '<div class="feedzy-items-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Total items found', 'feedzy-rss-feeds' ) . '"><ol>';
635
- foreach ( $value as $url => $title ) {
636
- $msg .= sprintf( '<li><p><a href="%s" target="_blank">%s</a></p></li>', esc_url( $url ), esc_html( $title ) );
637
- }
638
- $msg .= '</ol></div>';
639
- }
640
- break;
641
- case 'duplicates':
642
- if ( count( $value ) > 0 ) {
643
- $msg .= '<br>' . sprintf( '%s: %s%d%s', __( 'Duplicates found', 'feedzy-rss-feeds' ), '<a href="#" title="' . __( 'Click to view details', 'feedzy-rss-feeds' ) . '" class="feedzy-dialog-open" data-dialog="feedzy-dups-found-' . $post_id . '">', count( $value ), '</a>' );
644
- }
645
- if ( $value ) {
646
- $msg .= '<div class="feedzy-dups-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Duplicates found', 'feedzy-rss-feeds' ) . '"><ol>';
647
- foreach ( $value as $url => $title ) {
648
- $msg .= sprintf( '<li><p><a href="%s" target="_blank">%s</a></p></li>', esc_url( $url ), esc_html( $title ) );
649
- }
650
- $msg .= '</ol></div>';
651
- }
652
- break;
653
  }
 
 
654
  }
 
 
655
  }
656
- return apply_filters( 'feedzy_run_status_info', $msg, $post_id );
 
657
  }
658
 
659
  /**
@@ -665,6 +828,8 @@ class Feedzy_Rss_Feeds_Import {
665
  public function ajax() {
666
  check_ajax_referer( FEEDZY_BASEFILE, 'security' );
667
 
 
 
668
  switch ( $_POST['_action'] ) {
669
  case 'import_status':
670
  $this->import_status();
@@ -678,6 +843,9 @@ class Feedzy_Rss_Feeds_Import {
678
  case 'purge':
679
  $this->purge_data();
680
  break;
 
 
 
681
  }
682
  }
683
 
@@ -691,11 +859,19 @@ class Feedzy_Rss_Feeds_Import {
691
  global $wpdb;
692
  $id = $_POST['id'];
693
  $status = $_POST['status'];
694
- $_POST['feedzy_category_meta_noncename'] = $_POST['security'];
695
  $publish = 'draft';
 
 
696
  if ( $status === 'true' ) {
 
 
 
 
 
 
697
  $publish = 'publish';
698
  }
 
699
  $new_post_status = array(
700
  'ID' => $id,
701
  'post_status' => $publish,
@@ -707,11 +883,9 @@ class Feedzy_Rss_Feeds_Import {
707
 
708
  if ( is_wp_error( $post_id ) ) {
709
  $errors = $post_id->get_error_messages();
710
- foreach ( $errors as $error ) {
711
- echo $error;
712
- }
713
  }
714
- wp_die(); // this is required to terminate immediately and return a proper response
715
  }
716
 
717
  /**
@@ -753,13 +927,66 @@ class Feedzy_Rss_Feeds_Import {
753
  $job = get_post( $_POST['id'] );
754
  $count = $this->run_job( $job, 100 );
755
 
756
- $msg = $count > 0 ? sprintf( __( 'Successfully run! %d items imported.', 'feedzy-rss-feeds' ), $count ) : __( 'Nothing imported!', 'feedzy-rss-feeds' );
757
-
758
- $msg .= $this->get_import_errors( $job->ID, true );
759
 
760
  wp_send_json_success( array( 'msg' => $msg ) );
761
  }
762
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
763
  /**
764
  * The Cron Job.
765
  *
@@ -857,7 +1084,10 @@ class Feedzy_Rss_Feeds_Import {
857
 
858
  $options['__jobID'] = $job->ID;
859
 
860
- update_post_meta( $job->ID, 'last_run', time() );
 
 
 
861
  delete_post_meta( $job->ID, 'import_errors' );
862
  delete_post_meta( $job->ID, 'import_info' );
863
 
@@ -1114,6 +1344,9 @@ class Feedzy_Rss_Feeds_Import {
1114
  update_post_meta( $new_post_id, 'feedzy_job', $job->ID );
1115
  update_post_meta( $new_post_id, 'feedzy_item_author', sanitize_text_field( $author ) );
1116
 
 
 
 
1117
  do_action( 'feedzy_after_post_import', $new_post_id, $item, $this->settings );
1118
  }
1119
 
@@ -1586,7 +1819,6 @@ class Feedzy_Rss_Feeds_Import {
1586
  */
1587
  public function add_import_actions( $actions, $post ) {
1588
  if ( $post->post_type === 'feedzy_imports' ) {
1589
-
1590
  // don't need quick edit.
1591
  unset( $actions['inline hide-if-no-js'] );
1592
 
@@ -1595,6 +1827,10 @@ class Feedzy_Rss_Feeds_Import {
1595
  $post->ID,
1596
  esc_html( __( 'Purge &amp; Reset', 'feedzy-rss-feeds' ) )
1597
  );
 
 
 
 
1598
  }
1599
  return $actions;
1600
  }
@@ -1629,18 +1865,25 @@ class Feedzy_Rss_Feeds_Import {
1629
  */
1630
  public function pre_get_posts( $query ) {
1631
  if ( is_admin() && $query->is_main_query() && ! empty( $_GET['feedzy_job_id'] ) ) {
1632
- $query->set(
1633
- 'meta_query', array(
1634
- array(
1635
- 'key' => 'feedzy',
1636
- 'value' => 1,
1637
- ),
1638
- array(
1639
- 'key' => 'feedzy_job',
1640
- 'value' => $_GET['feedzy_job_id'],
1641
- ),
1642
- )
1643
  );
 
 
 
 
 
 
 
 
 
1644
  }
1645
  }
1646
  }
142
  'ajax' => array(
143
  'security' => wp_create_nonce( FEEDZY_BASEFILE ),
144
  ),
145
+ 'i10n' => array(
146
+ 'importing' => __( 'Importing', 'feedzy-rss-feeds' ) . '...',
147
+ 'run_now' => __( 'Run Now', 'feedzy-rss-feeds' ),
148
+ 'dry_run_loading' => '<p class="hide-when-loaded">' . __( 'Processing the source and loading the items that will be imported when it runs', 'feedzy-rss-feeds' ) . '...</p>'
149
+ . '<p><b>' . __( 'Please note that if some of these items have already have been imported in previous runs with the same filters, they may be shown here but will not be imported again.', 'feedzy-rss-feeds' ) . '</b></p>'
150
+ . '<p class="loading-img hide-when-loaded"><img src="' . includes_url( 'images/wpspin-2x.gif' ) . '"></p><div></div>',
151
+ 'dry_run_title' => __( 'Importable Items', 'feedzy-rss-feeds' ),
152
+ ),
153
  )
154
  );
155
  }
295
  $import_content = get_post_meta( $post->ID, 'import_post_content', true );
296
  $import_featured_img = get_post_meta( $post->ID, 'import_post_featured_img', true );
297
 
298
+ // default values so that post is not created empty.
299
+ if ( empty( $import_title ) ) {
300
+ $import_title = '[#item_title]';
301
+ }
302
+ if ( empty( $import_content ) ) {
303
+ $import_content = '[#item_content]';
304
+ }
305
+
306
  $import_link_author_admin = get_post_meta( $post->ID, 'import_link_author_admin', true );
307
  $import_link_author_public = get_post_meta( $post->ID, 'import_link_author_public', true );
308
 
320
 
321
  $import_custom_fields = get_post_meta( $post->ID, 'imports_custom_fields', true );
322
  $import_feed_limit = get_post_meta( $post->ID, 'import_feed_limit', true );
323
+ if ( empty( $import_feed_limit ) ) {
324
+ $import_feed_limit = 10;
325
+ }
326
  $import_feed_delete_days = intval( get_post_meta( $post->ID, 'import_feed_delete_days', true ) );
327
+ if ( empty( $import_feed_delete_days ) ) {
328
+ $import_feed_delete_days = 0;
329
+ }
330
  $post_status = $post->post_status;
331
  $nonce = wp_create_nonce( FEEDZY_BASEFILE );
332
+ $invalid_source_msg = apply_filters( 'feedzy_get_source_validity_error', '', $post );
333
  $output = '
334
  <input type="hidden" name="feedzy_category_meta_noncename" id="feedzy_category_meta_noncename" value="' . $nonce . '" />
335
  ';
336
+
337
+ add_thickbox();
338
  include FEEDZY_ABSPATH . '/includes/views/import-metabox-edit.php';
339
  echo $output;
340
  }
386
  delete_post_meta( $post_id, 'import_link_author_admin' );
387
  delete_post_meta( $post_id, 'import_link_author_public' );
388
 
389
+ // we will activate this import only if the source has no invalid URL(s)
390
+ $source_is_valid = false;
391
+
392
  foreach ( $data_meta as $key => $value ) {
393
  $value = is_array( $value ) ? implode( ',', $value ) : implode( ',', (array) $value );
394
+ if ( 'source' === $key ) {
395
+ // check if the source is valid
396
+ $invalid_urls = apply_filters( 'feedzy_check_source_validity', $value, $post_id, true, false );
397
+ $source_is_valid = empty( $invalid_urls );
398
+ }
399
+
400
  if ( get_post_meta( $post_id, $key, false ) ) {
401
  update_post_meta( $post_id, $key, wp_kses( $value, wp_kses_allowed_html( 'post' ) ) );
402
  } else {
407
  }
408
  }
409
  // Added this to activate post if publish is clicked and sometimes it does not change status.
410
+ if ( $source_is_valid && isset( $_POST['custom_post_status'] ) && $_POST['custom_post_status'] === 'Publish' ) {
411
  $activate = array(
412
  'ID' => $post_id,
413
  'post_status' => 'publish',
435
  public function redirect_post_location( $location, $post_id ) {
436
  $post = get_post( $post_id );
437
  if ( 'feedzy_imports' === $post->post_type ) {
438
+ // if invalid source has been found, redirect back to edit screen
439
+ // where errors can be shown
440
+ $invalid = get_post_meta( $post_id, '__transient_feedzy_invalid_source', true );
441
+ error_log( "redirect_post_location $post_id = " . print_r( $invalid, true ) );
442
+ if ( empty( $invalid ) ) {
443
+ return admin_url( 'edit.php?post_type=feedzy_imports' );
444
+ }
445
  }
446
  return $location;
447
  }
470
  $columns['feedzy-status'] = __( 'Current Status', 'feedzy-rss-feeds' );
471
  }
472
 
473
+ if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-next_run', __( 'Next Run', 'feedzy-rss-feeds' ) ) ) {
474
  $columns = $new_columns;
475
  } else {
476
+ $columns['feedzy-next_run'] = __( 'Next Run', 'feedzy-rss-feeds' );
477
  }
478
 
479
+ if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-last_run', __( 'Last Run Status', 'feedzy-rss-feeds' ) ) ) {
480
  $columns = $new_columns;
481
  } else {
482
+ $columns['feedzy-last_run'] = __( 'Last Run Status', 'feedzy-rss-feeds' );
483
  }
484
 
485
+ unset( $columns['date'] );
486
+
487
  return $columns;
488
  }
489
 
555
  <div class="switch">
556
  <input id="feedzy-toggle_' . $post->ID . '" class="feedzy-toggle feedzy-toggle-round" type="checkbox" value="' . $post->ID . '" ' . $checked . '>
557
  <label for="feedzy-toggle_' . $post->ID . '"></label>
558
+ <span class="feedzy-spinner spinner"></span>
559
  </div>
560
  ';
561
  }
564
  $last = get_post_meta( $post_id, 'last_run', true );
565
  $msg = __( 'Never Run', 'feedzy-rss-feeds' );
566
  if ( $last ) {
567
+ $now = new DateTime();
568
+ $then = new DateTime();
569
+ $then = $then->setTimestamp( $last );
570
+ $in = $now->diff( $then );
571
+ $msg = sprintf( __( 'Ran %1$d hours %2$d minutes ago', 'feedzy-rss-feeds' ), $in->format( '%h' ), $in->format( '%i' ) );
 
 
 
 
 
 
 
 
 
 
 
572
  }
573
+
574
+ $msg .= $this->get_last_run_details( $post_id );
575
  echo $msg;
576
+
577
+ if ( 'publish' === $post->post_status ) {
578
+ echo sprintf( '<p><input type="button" class="button button-primary feedzy-run-now" data-id="%d" value="%s"></p>', $post_id, __( 'Run Now', 'feedzy-rss-feeds' ) );
579
+ }
580
+
581
  break;
582
  case 'feedzy-next_run':
583
  $next = wp_next_scheduled( 'feedzy_cron' );
587
  $then = $then->setTimestamp( $next );
588
  $in = $now->diff( $then );
589
  echo sprintf( __( 'In %1$d hours %2$d minutes', 'feedzy-rss-feeds' ), $in->format( '%h' ), $in->format( '%i' ) );
 
 
 
590
  }
591
  break;
592
  default:
595
  }
596
 
597
  /**
598
+ * Generate the markup that displays the status.
599
  *
600
  * @since ?
601
  * @access private
602
+ *
603
+ * @param integer $post_id The post ID.
604
  */
605
+ private function get_last_run_details( $post_id ) {
606
+ $msg = '';
607
  $last = get_post_meta( $post_id, 'last_run', true );
608
+ $status = array(
609
+ 'total' => '-',
610
+ 'items' => '-',
611
+ 'duplicates' => '-',
612
+ 'cumulative' => '-',
613
+ );
614
+ if ( $last ) {
615
+ $status = array(
616
+ 'total' => 0,
617
+ 'items' => 0,
618
+ 'duplicates' => 0,
619
+ 'cumulative' => 0,
620
+ );
621
+ $status = $this->get_complete_import_status( $post_id );
622
+ }
623
+
624
+ // link to the posts listing for this job.
625
+ $job_linked_posts = add_query_arg( array( 'feedzy_job_id' => $post_id, 'post_type' => get_post_meta( $post_id, 'import_post_type', true ) ), admin_url( 'edit.php' ) );
626
+
627
+ // link to the posts listing for this job run.
628
+ $job_run_linked_posts = '';
629
+ $job_run_id = get_post_meta( $post_id, 'last_run_id', true );
630
+ if ( ! empty( $job_run_id ) ) {
631
+ $job_run_linked_posts = add_query_arg( array( 'feedzy_job_id' => $post_id, 'feedzy_job_time' => $job_run_id, 'post_type' => get_post_meta( $post_id, 'import_post_type', true ) ), admin_url( 'edit.php' ) );
632
+ }
633
+
634
+ // popup for items found.
635
+ if ( is_array( $status['items'] ) ) {
636
+ $msg .= '<div class="feedzy-items-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Items found', 'feedzy-rss-feeds' ) . '"><ol>';
637
+ foreach ( $status['items'] as $url => $title ) {
638
+ $msg .= sprintf( '<li><p><a href="%s" target="_blank">%s</a></p></li>', esc_url( $url ), esc_html( $title ) );
639
+ }
640
+ $msg .= '</ol></div>';
641
+ }
642
+
643
+ // popup for duplicates found.
644
+ if ( is_array( $status['duplicates'] ) ) {
645
+ $msg .= '<div class="feedzy-duplicates-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Duplicates found', 'feedzy-rss-feeds' ) . '"><ol>';
646
+ foreach ( $status['duplicates'] as $url => $title ) {
647
+ $msg .= sprintf( '<li><p><a href="%s" target="_blank">%s</a></p></li>', esc_url( $url ), esc_html( $title ) );
648
+ }
649
+ $msg .= '</ol></div>';
650
+ }
651
+
652
+ $errors = $this->get_import_errors( $post_id );
653
+ // popup for errors found.
654
+ if ( ! empty( $errors ) ) {
655
+ $msg .= '<div class="feedzy-errors-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Errors', 'feedzy-rss-feeds' ) . '">' . $errors . '</div>';
656
+ }
657
+
658
+ // remember, cypress will work off the data-value attributes.
659
+ $msg .= sprintf(
660
+ '<script class="feedzy-last-run-data" type="text/template">
661
+ <tr style="display: none"></tr>
662
+ <tr class="feedzy-import-status-row">
663
+ <td colspan="6" align="right">
664
+ <table>
665
+ <tr>
666
+ <td class="feedzy-items %s" data-value="%d"><a class="feedzy-popup-details feedzy-dialog-open" title="%s" data-dialog="feedzy-items-found-%d">%s</a></td>
667
+ <td class="feedzy-duplicates %s" data-value="%d"><a class="feedzy-popup-details feedzy-dialog-open" title="%s" data-dialog="feedzy-duplicates-found-%d">%s</a></td>
668
+ <td class="feedzy-imported %s" data-value="%d"><a target="%s" href="%s" class="feedzy-popup-details" title="%s">%s</a></td>
669
+ <td class="feedzy-cumulative %s" data-value="%d"><a target="%s" href="%s" class="feedzy-popup-details" title="%s">%s</a></td>
670
+ <td class="feedzy-error-status %s" data-value="%d"><a class="feedzy-popup-details feedzy-dialog-open" data-dialog="feedzy-errors-found-%d" title="%s">%s</a></td>
671
+ </tr>
672
+ <tr>
673
+ <td>%s</td>
674
+ <td>%s</td>
675
+ <td>%s</td>
676
+ <td>%s</td>
677
+ <td>%s</td>
678
+ </tr>
679
+ </table>
680
+ </td>
681
+ </tr>
682
+ </script>',
683
+ // first cell
684
+ is_array( $status['items'] ) ? 'feedzy-has-popup' : '',
685
+ is_array( $status['items'] ) ? count( $status['items'] ) : $status['items'],
686
+ __( 'Items that were found in the feed', 'feedzy-rss-feeds' ),
687
+ $post_id,
688
+ is_array( $status['items'] ) ? count( $status['items'] ) : $status['items'],
689
+ // second cells
690
+ is_array( $status['duplicates'] ) ? 'feedzy-has-popup' : '',
691
+ is_array( $status['duplicates'] ) ? count( $status['duplicates'] ) : $status['duplicates'],
692
+ __( 'Items that were discarded as duplicates', 'feedzy-rss-feeds' ),
693
+ $post_id,
694
+ is_array( $status['duplicates'] ) ? count( $status['duplicates'] ) : $status['duplicates'],
695
+ // third cell
696
+ $status['total'] > 0 && ! empty( $job_run_linked_posts ) ? 'feedzy-has-popup' : '',
697
+ $status['total'],
698
+ defined( 'TI_CYPRESS_TESTING' ) ? '' : '_blank',
699
+ $status['total'] > 0 && ! empty( $job_run_linked_posts ) ? $job_run_linked_posts : '',
700
+ __( 'Items that were imported', 'feedzy-rss-feeds' ),
701
+ $status['total'],
702
+ // fourth cell
703
+ $status['cumulative'] > 0 ? 'feedzy-has-popup' : '',
704
+ $status['cumulative'],
705
+ defined( 'TI_CYPRESS_TESTING' ) ? '' : '_blank',
706
+ $status['cumulative'] > 0 ? $job_linked_posts : '',
707
+ __( 'Items that were imported across all runs', 'feedzy-rss-feeds' ),
708
+ $status['cumulative'],
709
+ // fifth cell
710
+ empty( $last ) ? '' : ( ! empty( $errors ) ? 'feedzy-has-popup import-error' : 'import-success' ),
711
+ empty( $last ) ? '-1' : ( ! empty( $errors ) ? 0 : 1 ),
712
+ $post_id,
713
+ __( 'View the errors', 'feedzy-rss-feeds' ),
714
+ empty( $last ) ? '-' : ( ! empty( $errors ) ? '<i class="dashicons dashicons-warning"></i>' : '<i class="dashicons dashicons-yes-alt"></i>' ),
715
+ // second row
716
+ __( 'Found', 'feedzy-rss-feeds' ),
717
+ __( 'Duplicates', 'feedzy-rss-feeds' ),
718
+ __( 'Imported', 'feedzy-rss-feeds' ),
719
+ __( 'Cumulative', 'feedzy-rss-feeds' ),
720
+ __( 'Status', 'feedzy-rss-feeds' )
721
+ );
722
+
723
+ return $msg;
724
+ }
725
+
726
+ /**
727
+ * Gets every aspect of the import job that would reflect its status.
728
+ *
729
+ * @since ?
730
+ * @access private
731
+ */
732
+ private function get_complete_import_status( $post_id ) {
733
  $items_count = get_post_meta( $post_id, 'imported_items_count', true );
734
  $items = get_post_meta( $post_id, 'imported_items_hash', true );
735
  if ( empty( $items ) ) {
740
  // backward compatibility where imported_items_count post_meta has not been populated yet
741
  $count = count( $items );
742
  }
 
 
 
 
 
743
 
744
+ $status = array(
745
+ 'total' => $count,
746
+ 'items' => 0,
747
+ 'duplicates' => 0,
748
+ 'cumulative' => 0,
749
+ );
750
+
751
+ $import_info = get_post_meta( $post_id, 'import_info', true );
752
+ if ( $import_info ) {
753
+ foreach ( $import_info as $label => $value ) {
754
+ switch ( $label ) {
755
+ case 'total':
756
+ if ( count( $value ) > 0 ) {
757
+ $status['items'] = $value;
758
+ }
759
+ break;
760
+ case 'duplicates':
761
+ if ( count( $value ) > 0 ) {
762
+ $status['duplicates'] = $value;
763
+ }
764
+ break;
765
+ }
766
+ }
767
+ }
768
+
769
+ $items = get_post_meta( $post_id, 'imported_items_hash', true );
770
+ if ( empty( $items ) ) {
771
+ $items = get_post_meta( $post_id, 'imported_items', true );
772
+ }
773
+ if ( $items ) {
774
+ $status['cumulative'] = count( $items );
775
+ }
776
+
777
+ return $status;
778
+
779
  }
780
 
781
  /**
784
  * @since ?
785
  * @access private
786
  */
787
+ private function get_import_errors( $post_id ) {
788
  $msg = '';
789
  $import_errors = get_post_meta( $post_id, 'import_errors', true );
790
  if ( $import_errors ) {
791
+ $errors = '';
792
+ if ( is_array( $import_errors ) ) {
793
+ foreach ( $import_errors as $err ) {
794
+ $errors .= '<div><i class="dashicons dashicons-warning"></i>' . $err . '</div>';
795
+ }
796
+ } else {
797
+ $errors = '<div><i class="dashicons dashicons-warning"></i>' . $import_errors . '</div>';
798
+ }
799
+ $msg = '<div class="feedzy-error feedzy-api-error">' . $errors . '</div>';
800
  }
801
 
802
  $pro_msg = apply_filters( 'feedzy_run_status_errors', '', $post_id );
803
 
804
  // the pro messages may not have the dashicons, so let's add them.
805
  if ( $pro_msg && strpos( $pro_msg, 'dashicons-warning' ) === false ) {
806
+ $errors = '';
807
+ $pro_errors = explode( '<br>', $pro_msg );
808
+ if ( is_array( $pro_errors ) ) {
809
+ foreach ( $pro_errors as $err ) {
810
+ $errors .= '<div><i class="dashicons dashicons-warning"></i>' . $err . '</div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
811
  }
812
+ } else {
813
+ $errors = '<div><i class="dashicons dashicons-warning"></i>' . $pro_errors . '</div>';
814
  }
815
+ $pro_msg = '<div class="feedzy-error feedzy-api-error">' . $errors . '</div>';
816
+
817
  }
818
+
819
+ return $msg . $pro_msg;
820
  }
821
 
822
  /**
828
  public function ajax() {
829
  check_ajax_referer( FEEDZY_BASEFILE, 'security' );
830
 
831
+ $_POST['feedzy_category_meta_noncename'] = $_POST['security'];
832
+
833
  switch ( $_POST['_action'] ) {
834
  case 'import_status':
835
  $this->import_status();
843
  case 'purge':
844
  $this->purge_data();
845
  break;
846
+ case 'dry_run':
847
+ $this->dry_run();
848
+ break;
849
  }
850
  }
851
 
859
  global $wpdb;
860
  $id = $_POST['id'];
861
  $status = $_POST['status'];
 
862
  $publish = 'draft';
863
+
864
+ // no activation till source is not valid.
865
  if ( $status === 'true' ) {
866
+ $invalid_urls = apply_filters( 'feedzy_check_source_validity', get_post_meta( $id, 'source', true ), $id, true, false );
867
+ if ( ! empty( $invalid_urls ) ) {
868
+ $msg = apply_filters( 'feedzy_get_source_validity_error', '', get_post( $id ), '' );
869
+ wp_send_json_error( array( 'msg' => $msg ) );
870
+ }
871
+
872
  $publish = 'publish';
873
  }
874
+
875
  $new_post_status = array(
876
  'ID' => $id,
877
  'post_status' => $publish,
883
 
884
  if ( is_wp_error( $post_id ) ) {
885
  $errors = $post_id->get_error_messages();
886
+ wp_send_json_error( array( 'msg' => implode( ', ', $errors ) ) );
 
 
887
  }
888
+ wp_send_json_success();
889
  }
890
 
891
  /**
927
  $job = get_post( $_POST['id'] );
928
  $count = $this->run_job( $job, 100 );
929
 
930
+ $msg = $count > 0 ? __( 'Successfully run!', 'feedzy-rss-feeds' ) : __( 'Nothing imported!', 'feedzy-rss-feeds' );
931
+ $msg .= ' (' . __( 'Refresh this page for the updated status', 'feedzy-rss-feeds' ) . ')';
 
932
 
933
  wp_send_json_success( array( 'msg' => $msg ) );
934
  }
935
 
936
+ /**
937
+ * Dry run a specific job so that the user is aware what would be imported.
938
+ *
939
+ * @since ?
940
+ * @access private
941
+ */
942
+ private function dry_run() {
943
+ $fields = urldecode( $_POST['fields'] );
944
+ parse_str( $fields, $data );
945
+
946
+ $feedzy_meta_data = $data['feedzy_meta_data'];
947
+
948
+ add_filter(
949
+ 'feedzy_default_error', function( $errors, $feed, $url ) {
950
+ $errors .=
951
+ sprintf( __( 'For %1$ssingle feeds%2$s, this could be because of the following reasons:', 'feedzy-rss-feeds' ), '<b>', '</b>' )
952
+ . '<ol>'
953
+ . '<li>' . sprintf( __( '%1$sSource invalid%2$s: Check that your source is valid by clicking the validate button adjacent to the source box.', 'feedzy-rss-feeds' ), '<b>', '</b>' ) . '</li>'
954
+ . '<li>' . sprintf( __( '%1$sSource unavailable%2$s: Copy the source and paste it on the browser to check that it is available. It could be an intermittent issue.', 'feedzy-rss-feeds' ), '<b>', '</b>' ) . '</li>'
955
+ . '<li>' . sprintf( __( '%1$sSource inaccessible from server%2$s: Check that your source is accessible from the server (not the browser). It could be an intermittent issue.', 'feedzy-rss-feeds' ), '<b>', '</b>' ) . '</li>'
956
+ . '</ol>'
957
+ . sprintf( __( 'For %1$smultiple feeds%2$s (comma-separated or in a Feedzy Category), this could be because of the following reasons:', 'feedzy-rss-feeds' ), '<b>', '</b>' )
958
+ . '<ol>'
959
+ . '<li>' . sprintf( __( '%1$sSource invalid%2$s: One or more feeds may be misbehaving. Check each feed individually as mentioned above to weed out the problematic feed.', 'feedzy-rss-feeds' ), '<b>', '</b>' ) . '</li>'
960
+ . '</ol>';
961
+
962
+ return $errors;
963
+ }, 11, 3
964
+ );
965
+
966
+ // we will add tags corresponding to the most potential problems.
967
+ $tags = array();
968
+ if ( $this->feedzy_is_business() && strpos( $feedzy_meta_data['import_post_content'], 'full_content' ) !== false ) {
969
+ $tags[] = 'item_full_content';
970
+ }
971
+ if ( strpos( $feedzy_meta_data['import_post_content'], 'item_image' ) !== false || strpos( $feedzy_meta_data['import_post_featured_img'], 'item_image' ) !== false ) {
972
+ $tags[] = 'item_image';
973
+ }
974
+
975
+ $shortcode = sprintf(
976
+ '[feedzy-rss feeds="%s" max="%d" feed_title=no meta=no summary=no thumb=no error_empty="%s" keywords_title="%s" %s="%s" _dry_run_tags_="%s" _dryrun_="yes"]',
977
+ $feedzy_meta_data['source'],
978
+ $feedzy_meta_data['import_feed_limit'],
979
+ '', // should be empty
980
+ $feedzy_meta_data['inc_key'],
981
+ feedzy_is_pro() ? 'keywords_ban' : '',
982
+ feedzy_is_pro() ? $feedzy_meta_data['exc_key'] : '',
983
+ implode( ',', $tags )
984
+ );
985
+
986
+ wp_send_json_success( array( 'output' => do_shortcode( $shortcode ) ) );
987
+ }
988
+
989
+
990
  /**
991
  * The Cron Job.
992
  *
1084
 
1085
  $options['__jobID'] = $job->ID;
1086
 
1087
+ $last_run = time();
1088
+ update_post_meta( $job->ID, 'last_run', $last_run );
1089
+ // we will use this last_run_id to associate imports with a specific job run.
1090
+ update_post_meta( $job->ID, 'last_run_id', $last_run );
1091
  delete_post_meta( $job->ID, 'import_errors' );
1092
  delete_post_meta( $job->ID, 'import_info' );
1093
 
1344
  update_post_meta( $new_post_id, 'feedzy_job', $job->ID );
1345
  update_post_meta( $new_post_id, 'feedzy_item_author', sanitize_text_field( $author ) );
1346
 
1347
+ // we can use this to associate the items that were imported in a particular run.
1348
+ update_post_meta( $new_post_id, 'feedzy_job_time', $last_run );
1349
+
1350
  do_action( 'feedzy_after_post_import', $new_post_id, $item, $this->settings );
1351
  }
1352
 
1819
  */
1820
  public function add_import_actions( $actions, $post ) {
1821
  if ( $post->post_type === 'feedzy_imports' ) {
 
1822
  // don't need quick edit.
1823
  unset( $actions['inline hide-if-no-js'] );
1824
 
1827
  $post->ID,
1828
  esc_html( __( 'Purge &amp; Reset', 'feedzy-rss-feeds' ) )
1829
  );
1830
+ } elseif ( 1 === intval( get_post_meta( $post->ID, 'feedzy', true ) ) ) {
1831
+ // show an unclickable action that mentions that it is imported by us
1832
+ // so that users are aware
1833
+ $actions['feedzy'] = sprintf( '(%s)', __( 'Imported by Feedzy', 'feedzy-rss-feeds' ) );
1834
  }
1835
  return $actions;
1836
  }
1865
  */
1866
  public function pre_get_posts( $query ) {
1867
  if ( is_admin() && $query->is_main_query() && ! empty( $_GET['feedzy_job_id'] ) ) {
1868
+ $meta_query = array(
1869
+ array(
1870
+ 'key' => 'feedzy',
1871
+ 'value' => 1,
1872
+ ),
1873
+ array(
1874
+ 'key' => 'feedzy_job',
1875
+ 'value' => $_GET['feedzy_job_id'],
1876
+ ),
 
 
1877
  );
1878
+
1879
+ if ( ! empty( $_GET['feedzy_job_time'] ) ) {
1880
+ $meta_query[] = array(
1881
+ 'key' => 'feedzy_job_time',
1882
+ 'value' => $_GET['feedzy_job_time'],
1883
+ );
1884
+ }
1885
+
1886
+ $query->set( 'meta_query', $meta_query );
1887
  }
1888
  }
1889
  }
includes/feedzy-rss-feeds.php CHANGED
@@ -104,7 +104,7 @@ class Feedzy_Rss_Feeds {
104
  */
105
  public function init() {
106
  self::$plugin_name = 'feedzy-rss-feeds';
107
- self::$version = '3.4.3';
108
  self::$instance->load_dependencies();
109
  self::$instance->set_locale();
110
  self::$instance->define_admin_hooks();
@@ -188,16 +188,20 @@ class Feedzy_Rss_Feeds {
188
  private function define_admin_hooks() {
189
  $plugin_ui = new Feedzy_Rss_Feeds_Ui( self::$instance->get_plugin_name(), self::$instance->get_version(), self::$instance->loader );
190
  self::$instance->loader->add_action( 'admin_init', $plugin_ui, 'register_init' );
 
191
  self::$instance->loader->add_action( 'init', self::$instance->admin, 'register_post_type' );
192
  self::$instance->loader->add_action( 'save_post', self::$instance->admin, 'save_feedzy_post_type_meta', 1, 2 );
193
  self::$instance->loader->add_action( 'feedzy_pre_http_setup', self::$instance->admin, 'pre_http_setup', 10, 1 );
194
  self::$instance->loader->add_action( 'feedzy_post_http_teardown', self::$instance->admin, 'post_http_teardown', 10, 1 );
195
  self::$instance->loader->add_action( 'admin_init', self::$instance->admin, 'admin_init', 10, 1 );
196
-
197
  self::$instance->loader->add_action( 'manage_feedzy_categories_posts_custom_column', self::$instance->admin, 'manage_feedzy_category_columns', 10, 2 );
198
- self::$instance->loader->add_filter( 'manage_feedzy_categories_posts_columns', self::$instance->admin, 'feedzy_category_columns' );
199
-
200
  self::$instance->loader->add_action( 'admin_menu', self::$instance->admin, 'feedzy_menu_pages' );
 
 
 
 
 
 
201
  self::$instance->loader->add_filter( 'plugin_row_meta', self::$instance->admin, 'feedzy_filter_plugin_row_meta', 10, 2 );
202
  self::$instance->loader->add_filter( 'feedzy_default_image', self::$instance->admin, 'feedzy_define_default_image' );
203
  self::$instance->loader->add_filter( 'feedzy_default_error', self::$instance->admin, 'feedzy_default_error_notice', 9, 3 );
@@ -210,11 +214,16 @@ class Feedzy_Rss_Feeds {
210
  self::$instance->loader->add_filter( 'feedzy_process_feed_source', self::$instance->admin, 'process_feed_source', 10, 1 );
211
  self::$instance->loader->add_filter( 'feedzy_get_feed_url', self::$instance->admin, 'get_feed_url', 10, 1 );
212
  self::$instance->loader->add_filter( 'feedzy_get_settings', self::$instance->admin, 'get_settings', 10, 1 );
213
- add_shortcode( 'feedzy-rss', array( self::$instance->admin, 'feedzy_rss' ) );
214
- self::$instance->loader->add_action( 'wp_ajax_get_tinymce_form', self::$instance->admin, 'get_tinymce_form' );
215
- self::$instance->loader->add_action( 'wp_enqueue_scripts', self::$instance->admin, 'enqueue_styles' );
216
- self::$instance->loader->add_action( 'admin_enqueue_scripts', self::$instance->admin, 'enqueue_styles_admin' );
217
  self::$instance->loader->add_filter( 'feedzy_rss_feeds_logger_data', self::$instance->admin, 'get_usage_data', 10 );
 
 
 
 
 
 
 
 
 
218
 
219
  $plugin_widget = new feedzy_wp_widget();
220
  self::$instance->loader->add_action( 'widgets_init', $plugin_widget, 'registerWidget', 10 );
104
  */
105
  public function init() {
106
  self::$plugin_name = 'feedzy-rss-feeds';
107
+ self::$version = '3.5.0';
108
  self::$instance->load_dependencies();
109
  self::$instance->set_locale();
110
  self::$instance->define_admin_hooks();
188
  private function define_admin_hooks() {
189
  $plugin_ui = new Feedzy_Rss_Feeds_Ui( self::$instance->get_plugin_name(), self::$instance->get_version(), self::$instance->loader );
190
  self::$instance->loader->add_action( 'admin_init', $plugin_ui, 'register_init' );
191
+
192
  self::$instance->loader->add_action( 'init', self::$instance->admin, 'register_post_type' );
193
  self::$instance->loader->add_action( 'save_post', self::$instance->admin, 'save_feedzy_post_type_meta', 1, 2 );
194
  self::$instance->loader->add_action( 'feedzy_pre_http_setup', self::$instance->admin, 'pre_http_setup', 10, 1 );
195
  self::$instance->loader->add_action( 'feedzy_post_http_teardown', self::$instance->admin, 'post_http_teardown', 10, 1 );
196
  self::$instance->loader->add_action( 'admin_init', self::$instance->admin, 'admin_init', 10, 1 );
 
197
  self::$instance->loader->add_action( 'manage_feedzy_categories_posts_custom_column', self::$instance->admin, 'manage_feedzy_category_columns', 10, 2 );
 
 
198
  self::$instance->loader->add_action( 'admin_menu', self::$instance->admin, 'feedzy_menu_pages' );
199
+ self::$instance->loader->add_action( 'wp_ajax_get_tinymce_form', self::$instance->admin, 'get_tinymce_form' );
200
+ self::$instance->loader->add_action( 'wp_enqueue_scripts', self::$instance->admin, 'enqueue_styles' );
201
+ self::$instance->loader->add_action( 'admin_enqueue_scripts', self::$instance->admin, 'enqueue_styles_admin' );
202
+ self::$instance->loader->add_action( 'wp_ajax_feedzy_categories', self::$instance->admin, 'ajax' );
203
+
204
+ self::$instance->loader->add_filter( 'manage_feedzy_categories_posts_columns', self::$instance->admin, 'feedzy_category_columns' );
205
  self::$instance->loader->add_filter( 'plugin_row_meta', self::$instance->admin, 'feedzy_filter_plugin_row_meta', 10, 2 );
206
  self::$instance->loader->add_filter( 'feedzy_default_image', self::$instance->admin, 'feedzy_define_default_image' );
207
  self::$instance->loader->add_filter( 'feedzy_default_error', self::$instance->admin, 'feedzy_default_error_notice', 9, 3 );
214
  self::$instance->loader->add_filter( 'feedzy_process_feed_source', self::$instance->admin, 'process_feed_source', 10, 1 );
215
  self::$instance->loader->add_filter( 'feedzy_get_feed_url', self::$instance->admin, 'get_feed_url', 10, 1 );
216
  self::$instance->loader->add_filter( 'feedzy_get_settings', self::$instance->admin, 'get_settings', 10, 1 );
 
 
 
 
217
  self::$instance->loader->add_filter( 'feedzy_rss_feeds_logger_data', self::$instance->admin, 'get_usage_data', 10 );
218
+ self::$instance->loader->add_filter( 'feedzy_check_source_validity', self::$instance->admin, 'check_source_validity', 10, 4 );
219
+ self::$instance->loader->add_filter( 'feedzy_get_source_validity_error', self::$instance->admin, 'get_source_validity_error', 10, 3 );
220
+ self::$instance->loader->add_filter( 'post_row_actions', self::$instance->admin, 'add_feedzy_category_actions', 10, 2 );
221
+
222
+ // do not load this with the loader as this will need a corresponding remove_filter also.
223
+ add_filter( 'update_post_metadata', array( self::$instance->admin, 'validate_category_feeds' ), 10, 5 );
224
+ add_filter( 'add_post_metadata', array( self::$instance->admin, 'validate_category_feeds' ), 10, 5 );
225
+
226
+ add_shortcode( 'feedzy-rss', array( self::$instance->admin, 'feedzy_rss' ) );
227
 
228
  $plugin_widget = new feedzy_wp_widget();
229
  self::$instance->loader->add_action( 'widgets_init', $plugin_widget, 'registerWidget', 10 );
includes/views/css/import-metabox-edit.css CHANGED
@@ -1668,15 +1668,24 @@ a:focus.dropdown-item {
1668
  }
1669
 
1670
  .f1 {
1671
- padding: 25px;
 
1672
  border-radius: 4px;
1673
  background: #fff;
1674
  }
1675
 
1676
  .f1 h3 {
1677
  margin-top: 0;
1678
- margin-bottom: 5px;
1679
  text-transform: uppercase;
 
 
 
 
 
 
 
 
1680
  }
1681
 
1682
  .f1-steps {
@@ -1775,7 +1784,6 @@ a:focus.dropdown-item {
1775
  }
1776
 
1777
  .f1 fieldset {
1778
- display: none;
1779
  text-align: left;
1780
  }
1781
 
@@ -1789,6 +1797,7 @@ a:focus.dropdown-item {
1789
 
1790
  input[type="text"],
1791
  input[type="password"],
 
1792
  textarea,
1793
  textarea.form-control {
1794
  width: 100%;
@@ -1816,6 +1825,7 @@ textarea.form-control {
1816
 
1817
  input[type="text"]:focus,
1818
  input[type="password"]:focus,
 
1819
  textarea:focus,
1820
  textarea.form-control:focus {
1821
  border: 1px solid #ccc;
@@ -1826,6 +1836,7 @@ textarea.form-control:focus {
1826
 
1827
  input[type="text"]:-moz-placeholder,
1828
  input[type="password"]:-moz-placeholder,
 
1829
  textarea:-moz-placeholder,
1830
  textarea.form-control:-moz-placeholder {
1831
  color: #888;
@@ -1833,6 +1844,7 @@ textarea.form-control:-moz-placeholder {
1833
 
1834
  input[type="text"]:-ms-input-placeholder,
1835
  input[type="password"]:-ms-input-placeholder,
 
1836
  textarea:-ms-input-placeholder,
1837
  textarea.form-control:-ms-input-placeholder {
1838
  color: #888;
@@ -1840,6 +1852,7 @@ textarea.form-control:-ms-input-placeholder {
1840
 
1841
  input[type="text"]::-webkit-input-placeholder,
1842
  input[type="password"]::-webkit-input-placeholder,
 
1843
  textarea::-webkit-input-placeholder,
1844
  textarea.form-control::-webkit-input-placeholder {
1845
  color: #888;
@@ -2086,8 +2099,10 @@ span.feedzy-spinner {
2086
  .only-pro:hover textarea,
2087
  .only-pro:hover select,
2088
  .only-pro:hover button,
 
2089
  .only-pro:hover .chosen-container,
2090
  .only-pro:hover .chosen-single,
 
2091
  .only-pro:hover select option {
2092
  opacity: 0.3;
2093
  }
@@ -2126,10 +2141,77 @@ span.feedzy-spinner {
2126
  }
2127
 
2128
  .feedzy-highlight {
2129
- background-color: #ccff00;
2130
  padding: 1%;
2131
  }
2132
 
2133
  .feedzy-dialog {
2134
  display: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2135
  }
1668
  }
1669
 
1670
  .f1 {
1671
+ padding: 30px;
1672
+ padding-top: 10px;
1673
  border-radius: 4px;
1674
  background: #fff;
1675
  }
1676
 
1677
  .f1 h3 {
1678
  margin-top: 0;
1679
+ margin-bottom: 10px;
1680
  text-transform: uppercase;
1681
+ background-color: #f1f1f1;
1682
+ padding: 5px;
1683
+ border-radius: 5px;
1684
+ text-indent: 1%;
1685
+ }
1686
+
1687
+ .f1 h3:nth-of-type(n+2) {
1688
+ margin-top: 30px;
1689
  }
1690
 
1691
  .f1-steps {
1784
  }
1785
 
1786
  .f1 fieldset {
 
1787
  text-align: left;
1788
  }
1789
 
1797
 
1798
  input[type="text"],
1799
  input[type="password"],
1800
+ input[type="number"],
1801
  textarea,
1802
  textarea.form-control {
1803
  width: 100%;
1825
 
1826
  input[type="text"]:focus,
1827
  input[type="password"]:focus,
1828
+ input[type="number"]:focus,
1829
  textarea:focus,
1830
  textarea.form-control:focus {
1831
  border: 1px solid #ccc;
1836
 
1837
  input[type="text"]:-moz-placeholder,
1838
  input[type="password"]:-moz-placeholder,
1839
+ input[type="number"]:-moz-placeholder,
1840
  textarea:-moz-placeholder,
1841
  textarea.form-control:-moz-placeholder {
1842
  color: #888;
1844
 
1845
  input[type="text"]:-ms-input-placeholder,
1846
  input[type="password"]:-ms-input-placeholder,
1847
+ input[type="number"]:-ms-input-placeholder,
1848
  textarea:-ms-input-placeholder,
1849
  textarea.form-control:-ms-input-placeholder {
1850
  color: #888;
1852
 
1853
  input[type="text"]::-webkit-input-placeholder,
1854
  input[type="password"]::-webkit-input-placeholder,
1855
+ input[type="number"]::-webkit-input-placeholder,
1856
  textarea::-webkit-input-placeholder,
1857
  textarea.form-control::-webkit-input-placeholder {
1858
  color: #888;
2099
  .only-pro:hover textarea,
2100
  .only-pro:hover select,
2101
  .only-pro:hover button,
2102
+ .only-pro:hover ~ button,
2103
  .only-pro:hover .chosen-container,
2104
  .only-pro:hover .chosen-single,
2105
+ .only-pro:hover .label_description,
2106
  .only-pro:hover select option {
2107
  opacity: 0.3;
2108
  }
2141
  }
2142
 
2143
  .feedzy-highlight {
2144
+ background-color: #f1f1f1;
2145
  padding: 1%;
2146
  }
2147
 
2148
  .feedzy-dialog {
2149
  display: none;
2150
+ }
2151
+
2152
+ .feedzy-button-inside {
2153
+ position: relative;
2154
+ }
2155
+
2156
+ .feedzy-button-inside input {
2157
+ outline: none;
2158
+ }
2159
+
2160
+ .feedzy-button-inside input ~ a,
2161
+ .feedzy-button-inside input ~ a:hover,
2162
+ .feedzy-button-inside input ~ a:visited {
2163
+ position: absolute;
2164
+ right: 0px;
2165
+ top: 0px;
2166
+ border: none;
2167
+ height: 43px;
2168
+ width: 43px;
2169
+ outline: none;
2170
+ text-align: center;
2171
+ font-weight: bold;
2172
+ z-index: 999;
2173
+ background-color: #f1f1f1;
2174
+ text-decoration: none;
2175
+ color: #e14c53;
2176
+ }
2177
+
2178
+ .feedzy-button-inside input ~ a > i {
2179
+ line-height: 44px;
2180
+ outline: none;
2181
+ border: none;
2182
+ }
2183
+
2184
+ .form-group small i {
2185
+ font-size: 15px;
2186
+ line-height: 1.5;
2187
+ }
2188
+
2189
+ #TB_ajaxContent ul {
2190
+ list-style: decimal;
2191
+ margin-left: 20px;
2192
+ }
2193
+
2194
+ #TB_ajaxContent ul li {
2195
+ padding: 5px !important;
2196
+ }
2197
+
2198
+
2199
+ #TB_ajaxContent p.loading-img {
2200
+ text-align: center;
2201
+ }
2202
+
2203
+ #TB_ajaxContent.loaded p.hide-when-loaded {
2204
+ display: none;
2205
+ }
2206
+
2207
+ #TB_ajaxContent div.dry_run span {
2208
+ display: block;
2209
+ }
2210
+
2211
+ #TB_ajaxContent div.dry_run span i.pass {
2212
+ color: #149714;
2213
+ }
2214
+
2215
+ #TB_ajaxContent div.dry_run span i.fail {
2216
+ color: #ca4a1f;
2217
  }
includes/views/import-metabox-edit.php CHANGED
@@ -6,41 +6,28 @@
6
  * @package feedzy-rss-feeds-pro
7
  */
8
  ?>
9
- <div class="f1">
10
 
11
- <h3><?php echo __( 'Import Setup Wizard', 'feedzy-rss-feeds' ); ?></h3>
12
- <p><?php echo __( 'Follow the steps to setup an import rule.', 'feedzy-rss-feeds' ); ?></p>
13
- <div class="f1-steps">
14
- <div class="f1-progress">
15
- <div class="f1-progress-line" data-now-value="16.66" data-number-of-steps="3" style="width: 16.66%;"></div>
16
- </div>
17
- <div class="f1-step active">
18
- <div class="f1-step-icon"><span class="dashicons dashicons-rss"></span></div>
19
- <p><?php echo __( 'Sources', 'feedzy-rss-feeds' ); ?></p>
20
- </div>
21
- <div class="f1-step">
22
- <div class="f1-step-icon"><span class="dashicons dashicons-filter"></span></div>
23
- <p><?php echo __( 'Filters', 'feedzy-rss-feeds' ); ?></p>
24
- </div>
25
- <div class="f1-step">
26
- <div class="f1-step-icon"><span class="dashicons dashicons-randomize"></span></div>
27
- <p><?php echo __( 'Assign', 'feedzy-rss-feeds' ); ?></p>
28
- </div>
29
- </div>
30
 
31
- <fieldset class="feedzy-screen1">
32
- <h4><?php echo __( 'Feed sources:', 'feedzy-rss-feeds' ); ?></h4>
33
  <div class="form-group">
34
- <label class="feedzy-sr-only"><?php echo __( 'Feedzy RSS Feed sources (comma separated URLs or Feed Categories slug)', 'feedzy-rss-feeds' ); ?></label>
35
  </div>
 
 
 
36
  <div class="form-group input-group">
37
- <input type="text" name="feedzy_meta_data[source]" placeholder="<?php echo __( 'Source', 'feedzy-rss-feeds' ); ?>" class="form-control " value="<?php echo $source; ?>"/>
 
 
 
 
38
  <div class="input-group-btn">
39
  <?php
40
  if ( isset( $feed_categories ) && ! empty( $feed_categories ) ) {
41
  ?>
42
  <button type="button" class="btn btn-add-fields dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
43
- <?php echo __( 'Add Feed Category', 'feedzy-rss-feeds' ); ?> <span class="dashicons dashicons-arrow-down-alt2"></span>
44
  </button>
45
  <div class="dropdown-menu dropdown-menu-right">
46
  <?php
@@ -63,89 +50,75 @@
63
  ?>
64
  </div>
65
  </div>
66
- <div class="f1-buttons">
67
- <button type="button" class="btn btn-next"><?php echo __( 'Next', 'feedzy-rss-feeds' ); ?></button>
68
- </div>
69
- </fieldset>
70
 
71
- <fieldset class="feedzy-screen2">
72
- <h4><?php echo __( 'Feed filters:', 'feedzy-rss-feeds' ); ?></h4>
73
- <div class="form-group <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
74
- <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
75
- <label class="feedzy-sr-only"><?php echo __( 'Only display item if title contains specific keyword(s) (comma-separated list/case sensitive).', 'feedzy-rss-feeds' ); ?></label>
76
- <input type="text" name="feedzy_meta_data[inc_key]" placeholder="<?php echo __( '(eg. news, sports etc.)', 'feedzy-rss-feeds' ); ?>" class="form-control" value="<?php echo $inc_key; ?>"/>
77
- </div>
78
- <div class="form-group <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
79
- <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
80
- <label class="feedzy-sr-only"><?php echo __( 'Exclude items if title contains specific keyword(s) (comma-separated list/case sensitive).', 'feedzy-rss-feeds' ); ?></label>
81
- <input type="text" name="feedzy_meta_data[exc_key]" placeholder="<?php echo __( '(eg. news, sports etc.)', 'feedzy-rss-feeds' ); ?>" class="form-control" value="<?php echo $exc_key; ?>"/>
82
- </div>
83
- <div class="form-group">
84
- <label class="feedzy-sr-only"><?php _e( 'How many feed items to process from the feed?', 'feedzy-rss-feeds' ); ?></label>
85
- <select id="feedzy_item_limit" class="form-control feedzy-chosen" name="feedzy_meta_data[import_feed_limit]" >
86
- <?php
87
- $limits = apply_filters( 'feedzy_items_limit', range( 10, 100, 10 ), $post );
88
- $limits[] = 9999;
89
- if ( '' === $import_feed_limit ) {
90
- $import_feed_limit = 20;
91
- }
92
- foreach ( $limits as $v ) {
93
- $selected = '';
94
- // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
95
- if ( $v == $import_feed_limit ) {
96
- $selected = 'selected';
97
- }
98
- $display = $v;
99
- if ( $v === 9999 ) {
100
- $display = __( 'All (check that your server configuration can support this)', 'feedzy-rss-feeds' );
101
- if ( ! feedzy_is_pro() ) {
102
- $display = __( 'More options available in PRO.', 'feedzy-rss-feeds' );
103
- $selected = 'disabled';
104
- $v = '';
105
- }
106
- }
107
- ?>
108
- <option value="<?php echo $v; ?>" <?php echo $selected; ?>><?php echo $display; ?></option>
109
- <?php
110
- }
111
- ?>
112
- </select>
113
- </div>
114
- <div class="form-group <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
115
- <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
116
- <label class="feedzy-sr-only"><?php _e( 'Delete the posts created for this import after how many days?', 'feedzy-rss-feeds' ); ?></label>
117
- <select id="feedzy_delete_limit" class="form-control feedzy-chosen" name="feedzy_meta_data[import_feed_delete_days]" >
118
- <?php
119
- // 0 is never delete.
120
- $days = apply_filters( 'feedzy_items_delete_days', range( 0, 100, 1 ), $post );
121
- if ( '' === $import_feed_delete_days ) {
122
- $import_feed_delete_days = 0;
123
- }
124
- foreach ( $days as $v ) {
125
- $selected = '';
126
- if ( $v === $import_feed_delete_days ) {
127
- $selected = 'selected';
128
- }
129
- $display = $v;
130
- if ( $v === 0 ) {
131
- $display = __( 'Never', 'feedzy-rss-feeds' );
132
- }
133
- ?>
134
- <option value="<?php echo $v; ?>" <?php echo $selected; ?>><?php echo $display; ?></option>
135
- <?php
136
- }
137
- ?>
138
- </select>
139
- </div>
140
- <div class="f1-buttons">
141
- <button type="button" class="btn btn-previous"><?php echo __( 'Previous', 'feedzy-rss-feeds' ); ?></button>
142
- <button type="button" class="btn btn-next"><?php echo __( 'Next', 'feedzy-rss-feeds' ); ?></button>
143
  </div>
144
- </fieldset>
145
 
146
- <fieldset class="feedzy-screen3">
147
- <h4><?php echo __( 'Feed assign:', 'feedzy-rss-feeds' ); ?></h4>
148
- <p><?php echo __( 'Map post elements to custom post from feed imports.', 'feedzy-rss-feeds' ); ?></p>
 
 
 
 
 
149
 
150
  <div class="feedzy-rows">
151
  <div class="feedzy-row">
@@ -182,7 +155,7 @@
182
  <div class="feedzy-row">
183
  <div class="label_description">
184
  <label class="feedzy-sr-only" for="f1-post-type"><?php echo __( 'Post Taxonomy', 'feedzy-rss-feeds' ); ?></label><br/>
185
- <small><?php _e( 'Assign to a taxonomy term (eg. "Category", "Tags" etc.)', 'feedzy-rss-feeds' ); ?></small>
186
  </div>
187
  <div class="feedzy-separator dashicons dashicons-leftright"></div>
188
  <div class="form-group input-group form_item">
@@ -228,9 +201,7 @@
228
  );
229
  $magic_tags = apply_filters( 'feedzy_get_service_magic_tags', $magic_tags, 'title' );
230
 
231
- echo __( 'The title for the generated post. You can use ', 'feedzy-rss-feeds' ) .
232
- '<b>[#' . implode( ']</b>, <b>[#', $magic_tags ) . ']</b>' .
233
- __( ' tags to append the feed item title to the generated post title or mix and match your own.', 'feedzy-rss-feeds' );
234
  ?>
235
  </small>
236
  </div>
@@ -252,9 +223,7 @@
252
  <label class="feedzy-sr-only" for="f1-post-title"><?php echo __( 'Post Date', 'feedzy-rss-feeds' ); ?></label><br/>
253
  <small>
254
  <?php
255
- echo __( 'The date for the generated post. You can use ', 'feedzy-rss-feeds' ) .
256
- '<b>[#item_date]</b>, <b>[#post_date]</b>' .
257
- __( ' tags or leave blank.', 'feedzy-rss-feeds' );
258
  ?>
259
  </small>
260
  </div>
@@ -292,16 +261,14 @@
292
  }
293
  $magic_tags = apply_filters( 'feedzy_get_service_magic_tags', $magic_tags, 'content' );
294
 
295
- echo __( 'The content for the generated post. You can use ', 'feedzy-rss-feeds' ) .
296
- '<b>[#' . implode( ']</b>, <b>[#', $magic_tags ) . ']</b>' .
297
- __( ' tags to append the feed item content for the generated post content.', 'feedzy-rss-feeds' );
298
  ?>
299
  </small>
300
 
301
  <p class="feedzy-highlight"><i class="dashicons dashicons-megaphone"></i>
302
  <?php
303
  if ( apply_filters( 'feedzy_is_license_of_type', false, 'business' ) ) {
304
- echo sprintf( __( 'You can add custom magic tags to extract custom elements from your feed as explained %1$shere%2$s. This will work only for single-feeds (not if you have specified a feed category that contains multiple feeds).', 'feedzy-rss-feeds' ), '<a href="https://docs.themeisle.com/article/977-how-do-i-extract-values-from-custom-tags-in-feedzy" target="_blank">', '</a>' );
305
  } else {
306
  echo sprintf( __( 'Want to extract custom elements from your feed as explained %1$shere%2$s? Upgrade your %3$slicense%4$s today!', 'feedzy-rss-feeds' ), '<a href="https://docs.themeisle.com/article/977-how-do-i-extract-values-from-custom-tags-in-feedzy" target="_blank">', '</a>', '<a href="' . FEEDZY_UPSELL_LINK . '" target="_blank">', '</a>' );
307
  }
@@ -330,9 +297,7 @@
330
  <label class="feedzy-sr-only" for="f1-post-content"><?php echo __( 'Featured Image', 'feedzy-rss-feeds' ); ?></label><br/>
331
  <small>
332
  <?php
333
- echo __( 'The URL for the featured image. You can use ', 'feedzy-rss-feeds' ) .
334
- '<b>[#item_image]</b>' .
335
- __( ' tag, use your own URL or leave it empty. (*optional)', 'feedzy-rss-feeds' );
336
  ?>
337
  </small>
338
  </div>
@@ -349,25 +314,27 @@
349
  </div>
350
  </div>
351
  </div>
352
- <div class="feedzy-row">
 
353
  <div class="label_description">
354
  <label class="feedzy-sr-only" for="f1-post-content"><?php echo __( 'Post Author', 'feedzy-rss-feeds' ); ?></label><br/>
355
  <small>
356
  <?php
357
- _e( 'Show the original author', 'feedzy-rss-feeds' );
358
  ?>
359
  </small>
360
  </div>
361
  <div class="feedzy-separator dashicons dashicons-leftright"></div>
362
- <div class="form-group input-group form_item <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
363
- <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
364
  <div>
365
- <input type="checkbox" name="feedzy_meta_data[import_link_author_admin]" id="import_link_author_admin" value="yes" <?php echo $import_link_author[0]; ?>/>
366
- <label class="feedzy-inline" for="import_link_author_admin"><?php echo __( 'In the backend', 'feedzy-rss-feeds' ); ?></label>
 
367
  </div>
368
  <div>
369
- <input type="checkbox" name="feedzy_meta_data[import_link_author_public]" id="import_link_author_public" value="yes" <?php echo $import_link_author[1]; ?>/>
370
- <label class="feedzy-inline" for="import_link_author_public"><?php echo __( 'Link to the original post in the frontend', 'feedzy-rss-feeds' ); ?></label>
 
371
  </div>
372
  </div>
373
  </div>
@@ -408,21 +375,20 @@
408
 
409
  <div class="f1-buttons">
410
  <input type="hidden" id="custom_post_status" name="custom_post_status" value="draft" />
411
- <button type="button" class="btn btn-previous"><?php echo __( 'Previous', 'feedzy-rss-feeds' ); ?></button>
412
  <?php
413
  if ( $post_status === 'publish' ) {
414
  ?>
415
- <button type="submit" name="publish" class="btn btn-submit" value="Publish"><?php echo __( 'Save', 'feedzy-rss-feeds' ); ?></button>
416
  <?php
417
  } else {
418
  ?>
419
- <button type="submit" name="save" class="btn btn-submit" value="Save Draft" style="float: none;"><?php echo __( 'Save', 'feedzy-rss-feeds' ); ?></button>
420
- <button type="submit" name="publish" class="btn btn-submit btn-activate" value="Publish" ><?php echo __( 'Save & Activate', 'feedzy-rss-feeds' ); ?></button>
421
  <?php
422
  }
423
  ?>
424
  </div>
425
- </fieldset>
426
  </div>
427
 
428
  <script id="empty_select_tpl" type="text/template">
6
  * @package feedzy-rss-feeds-pro
7
  */
8
  ?>
9
+ <div class="f1" id="feedzy-import-form">
10
 
11
+ <h3><span class="dashicons dashicons-rss"></span> <?php echo __( 'Sources', 'feedzy-rss-feeds' ); ?></h3>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
 
 
13
  <div class="form-group">
14
+ <label class="feedzy-sr-only"><?php echo __( 'RSS Feed sources (comma separated URLs or Feed Categories slug)', 'feedzy-rss-feeds' ); ?></label>
15
  </div>
16
+
17
+ <?php echo $invalid_source_msg; ?>
18
+
19
  <div class="form-group input-group">
20
+ <div class="feedzy-button-inside">
21
+ <input type="text" id="feedzy-import-source" title="<?php _e( 'Make sure you validate the feed by using the validate button on the right', 'feedzy-rss-feeds' ); ?>" name="feedzy_meta_data[source]" placeholder="<?php echo __( 'Source', 'feedzy-rss-feeds' ); ?>" class="form-control" value="<?php echo $source; ?>"/>
22
+ <a class="feedzy-inside" target="_blank" data-href-base="https://validator.w3.org/feed/check.cgi?url=" href="#" title="<?php _e( 'Validate Feed', 'feedzy-rss-feeds' ); ?>"><i title="<?php _e( 'Validate Feed', 'feedzy-rss-feeds' ); ?>" class="dashicons dashicons-external"></i></a>
23
+ </div>
24
+ <small><i class="dashicons dashicons-lightbulb"></i><?php _e( 'Make sure to use the validate button. Invalid feeds may not import anything.', 'feedzy-rss-feeds' ); ?></small>
25
  <div class="input-group-btn">
26
  <?php
27
  if ( isset( $feed_categories ) && ! empty( $feed_categories ) ) {
28
  ?>
29
  <button type="button" class="btn btn-add-fields dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
30
+ <?php echo __( 'Use Feed Category', 'feedzy-rss-feeds' ); ?> <span class="dashicons dashicons-arrow-down-alt2"></span>
31
  </button>
32
  <div class="dropdown-menu dropdown-menu-right">
33
  <?php
50
  ?>
51
  </div>
52
  </div>
 
 
 
 
53
 
54
+ <h3><span class="dashicons dashicons-filter"></span> <?php echo __( 'Filters', 'feedzy-rss-feeds' ); ?></h3>
55
+
56
+ <div class="feedzy-rows">
57
+ <div class="feedzy-row <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
58
+ <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
59
+ <div class="label_description">
60
+ <label class="feedzy-sr-only"><?php echo __( 'Display item only if the title contains specific keyword(s)', 'feedzy-rss-feeds' ); ?></label>
61
+ <div>
62
+ <small><?php echo sprintf( __( 'You can provide comma-separated words. Remember, these words are %1$scase sensitive%2$s .e.g. News, news, STOCK', 'feedzy-rss-feeds' ), '<b>', '</b>' ); ?></small>
63
+ </div>
64
+ </div>
65
+ <div class="feedzy-separator"></div>
66
+ <div class="form-group input-group form_item">
67
+ <input type="text" name="feedzy_meta_data[inc_key]" placeholder="<?php echo __( '(eg. news, sports etc.)', 'feedzy-rss-feeds' ); ?>" class="form-control" value="<?php echo $inc_key; ?>"/>
68
+ </div>
69
+ </div>
70
+
71
+ <div class="feedzy-row <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
72
+ <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
73
+ <div class="label_description">
74
+ <label class="feedzy-sr-only"><?php echo __( 'Exclude item if the title contains specific keyword(s)', 'feedzy-rss-feeds' ); ?></label>
75
+ <div>
76
+ <small><?php echo sprintf( __( 'You can provide comma-separated words. Remember, these words are %1$scase sensitive%2$s .e.g. News, news, STOCK', 'feedzy-rss-feeds' ), '<b>', '</b>' ); ?></small>
77
+ </div>
78
+ </div>
79
+ <div class="feedzy-separator"></div>
80
+ <div class="form-group input-group form_item">
81
+ <input type="text" name="feedzy_meta_data[exc_key]" placeholder="<?php echo __( '(eg. news, sports etc.)', 'feedzy-rss-feeds' ); ?>" class="form-control" value="<?php echo $exc_key; ?>"/>
82
+ </div>
83
+ </div>
84
+
85
+ <div class="feedzy-row">
86
+ <div class="label_description">
87
+ <label class="feedzy-sr-only"><?php _e( 'How many feed items to import from the source?', 'feedzy-rss-feeds' ); ?></label>
88
+ <div>
89
+ <small><?php echo sprintf( __( 'If you choose a high number, please check that you configuration can support it or your imports may fail.', 'feedzy-rss-feeds' ), '<b>', '</b>' ); ?></small>
90
+ </div>
91
+ </div>
92
+ <div class="feedzy-separator"></div>
93
+ <div class="form-group input-group form_item">
94
+ <input type="number" min="0" max="9999" id="feedzy_item_limit" name="feedzy_meta_data[import_feed_limit]" class="form-control" value="<?php echo $import_feed_limit; ?>"/>
95
+ </div>
96
+ </div>
97
+
98
+ <div class="feedzy-row <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
99
+ <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
100
+ <div class="label_description">
101
+ <label class="feedzy-sr-only"><?php _e( 'Automatically delete the posts created for this import after how many days?', 'feedzy-rss-feeds' ); ?></label>
102
+ <div>
103
+ <small><?php _e( 'Helpful if you want to remove stale or old items automatically. If you choose 0, the imported items will never be deleted.', 'feedzy-rss-feeds' ); ?></small>
104
+ </div>
105
+ </div>
106
+ <div class="feedzy-separator"></div>
107
+ <div class="form-group input-group form_item">
108
+ <input type="number" min="0" max="9999" id="feedzy_delete_days" name="feedzy_meta_data[import_feed_delete_days]" class="form-control" value="<?php echo $import_feed_delete_days; ?>"/>
109
+ </div>
110
+ </div>
111
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  </div>
 
113
 
114
+
115
+ <h3><span class="dashicons dashicons-feedback"></span> <?php echo __( 'Assign Elements', 'feedzy-rss-feeds' ); ?></h3>
116
+
117
+ <p><?php _e( 'Using magic tags, specify what part(s) of the source should form part of the imported post.', 'feedzy-rss-feeds' ); ?>
118
+ <?php if ( false === apply_filters( 'feedzy_is_license_of_type', false, 'agency' ) ) { ?>
119
+ <?php echo sprintf( __( 'The magic tags that are greyed out and disabled are unavailable for your current license. You can consider %1$supgrading%2$s.', 'feedzy-rss-feeds' ), '<a href="' . FEEDZY_UPSELL_LINK . '" target="_blank" title="' . __( 'Upgrade', 'feedzy-rss-feeds' ) . '">', '</a>' ); ?>
120
+ <?php } ?>
121
+ </p>
122
 
123
  <div class="feedzy-rows">
124
  <div class="feedzy-row">
155
  <div class="feedzy-row">
156
  <div class="label_description">
157
  <label class="feedzy-sr-only" for="f1-post-type"><?php echo __( 'Post Taxonomy', 'feedzy-rss-feeds' ); ?></label><br/>
158
+ <small><?php _e( 'Assign to a taxonomy (eg. "Post Category", "Post Tag" etc.). Leave blank, if unsure.', 'feedzy-rss-feeds' ); ?></small>
159
  </div>
160
  <div class="feedzy-separator dashicons dashicons-leftright"></div>
161
  <div class="form-group input-group form_item">
201
  );
202
  $magic_tags = apply_filters( 'feedzy_get_service_magic_tags', $magic_tags, 'title' );
203
 
204
+ _e( 'The title for the generated post. This field is mandatory - without this, a post will not be created.', 'feedzy-rss-feeds' );
 
 
205
  ?>
206
  </small>
207
  </div>
223
  <label class="feedzy-sr-only" for="f1-post-title"><?php echo __( 'Post Date', 'feedzy-rss-feeds' ); ?></label><br/>
224
  <small>
225
  <?php
226
+ _e( 'The date for the generated post. Leave blank, if unsure.', 'feedzy-rss-feeds' );
 
 
227
  ?>
228
  </small>
229
  </div>
261
  }
262
  $magic_tags = apply_filters( 'feedzy_get_service_magic_tags', $magic_tags, 'content' );
263
 
264
+ _e( 'The content for the generated post. This field is mandatory - without this, a post will not be created.', 'feedzy-rss-feeds' );
 
 
265
  ?>
266
  </small>
267
 
268
  <p class="feedzy-highlight"><i class="dashicons dashicons-megaphone"></i>
269
  <?php
270
  if ( apply_filters( 'feedzy_is_license_of_type', false, 'business' ) ) {
271
+ echo sprintf( __( 'You can add custom magic tags to extract custom elements from your feed as explained %1$shere%2$s. This will work only for single-feeds (i.e. not if you have specified a feed category that contains multiple feeds or using comma-separated feeds in the source).', 'feedzy-rss-feeds' ), '<a href="https://docs.themeisle.com/article/977-how-do-i-extract-values-from-custom-tags-in-feedzy" target="_blank">', '</a>' );
272
  } else {
273
  echo sprintf( __( 'Want to extract custom elements from your feed as explained %1$shere%2$s? Upgrade your %3$slicense%4$s today!', 'feedzy-rss-feeds' ), '<a href="https://docs.themeisle.com/article/977-how-do-i-extract-values-from-custom-tags-in-feedzy" target="_blank">', '</a>', '<a href="' . FEEDZY_UPSELL_LINK . '" target="_blank">', '</a>' );
274
  }
297
  <label class="feedzy-sr-only" for="f1-post-content"><?php echo __( 'Featured Image', 'feedzy-rss-feeds' ); ?></label><br/>
298
  <small>
299
  <?php
300
+ _e( 'The URL for the featured image. You can use the magic tags, use your own URL or leave it empty.', 'feedzy-rss-feeds' );
 
 
301
  ?>
302
  </small>
303
  </div>
314
  </div>
315
  </div>
316
  </div>
317
+ <div class="feedzy-row <?php echo apply_filters( 'feedzy_upsell_class', '' ); ?>">
318
+ <?php echo apply_filters( 'feedzy_upsell_content', '' ); ?>
319
  <div class="label_description">
320
  <label class="feedzy-sr-only" for="f1-post-content"><?php echo __( 'Post Author', 'feedzy-rss-feeds' ); ?></label><br/>
321
  <small>
322
  <?php
323
+ _e( 'Show the original author of the source item.', 'feedzy-rss-feeds' );
324
  ?>
325
  </small>
326
  </div>
327
  <div class="feedzy-separator dashicons dashicons-leftright"></div>
328
+ <div class="form-group input-group form_item">
 
329
  <div>
330
+ <input id="feedzy-toggle_author_admin" name="feedzy_meta_data[import_link_author_admin]" class="feedzy-toggle feedzy-toggle-round" type="checkbox" value="yes" <?php echo $import_link_author[0]; ?>>
331
+ <label for="feedzy-toggle_author_admin" class="feedzy-inline"></label>
332
+ <label class="feedzy-inline" style="margin-left: 10px;" for="import_link_author_admin"><?php echo __( 'In the backend, on the post listing screen', 'feedzy-rss-feeds' ); ?></label>
333
  </div>
334
  <div>
335
+ <input id="feedzy-toggle_author_public" name="feedzy_meta_data[import_link_author_public]" class="feedzy-toggle feedzy-toggle-round" type="checkbox" value="yes" <?php echo $import_link_author[1]; ?>>
336
+ <label for="feedzy-toggle_author_public" class="feedzy-inline"></label>
337
+ <label class="feedzy-inline" style="margin-left: 10px;" for="import_link_author_public"><?php echo __( 'In the frontend, link to the original post', 'feedzy-rss-feeds' ); ?></label>
338
  </div>
339
  </div>
340
  </div>
375
 
376
  <div class="f1-buttons">
377
  <input type="hidden" id="custom_post_status" name="custom_post_status" value="draft" />
378
+ <button type="button" id="preflight" name="check" class="btn btn-previous" value="Check" title="<?php _e( 'Click to see what items will be imported from the source, according to the filters specified', 'feedzy-rss-feeds' ); ?>"><?php _e( 'Dry Run', 'feedzy-rss-feeds' ); ?></button>
379
  <?php
380
  if ( $post_status === 'publish' ) {
381
  ?>
382
+ <button type="submit" name="publish" class="btn btn-submit" value="Publish"><?php _e( 'Save', 'feedzy-rss-feeds' ); ?></button>
383
  <?php
384
  } else {
385
  ?>
386
+ <button type="submit" name="save" class="btn btn-submit" value="Save Draft" style="float: none;"><?php _e( 'Save', 'feedzy-rss-feeds' ); ?></button>
387
+ <button type="submit" name="publish" class="btn btn-submit btn-activate" value="Publish" ><?php _e( 'Save & Activate', 'feedzy-rss-feeds' ); ?></button>
388
  <?php
389
  }
390
  ?>
391
  </div>
 
392
  </div>
393
 
394
  <script id="empty_select_tpl" type="text/template">
includes/views/js/import-metabox-edit.js CHANGED
@@ -5,7 +5,7 @@
5
  * @since 1.2.0
6
  * @package feedzy-rss-feeds-pro
7
  */
8
- /* global jQuery, ajaxurl, feedzy */
9
  (function($){
10
  function scroll_to_class(element_class, removed_height) {
11
  var scroll_to = $( element_class ).offset().top - removed_height;
@@ -62,6 +62,7 @@
62
  }
63
 
64
  function update_status() {
 
65
  var post_id = $( this ).val();
66
  var status = $( this ).is( ':checked' );
67
 
@@ -73,8 +74,22 @@
73
  'status': status
74
  };
75
 
76
- // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
77
- $.post( ajaxurl, data, function() {} );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  return true;
79
  }
80
 
@@ -142,6 +157,11 @@
142
  }
143
 
144
  $( document ).ready(function() {
 
 
 
 
 
145
  $( 'button.btn-submit' ).on( 'click', function( e ) {
146
  $( window ).unbind( 'beforeunload' );
147
  $( '#custom_post_status' ).val( $( this ).val() );
@@ -212,11 +232,47 @@
212
  });
213
  });
214
 
215
- initSummary();
 
 
 
 
216
 
217
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
  function initSummary() {
 
 
 
 
 
220
  // pop-ups for informational text
221
  $( '.feedzy-dialog' ).dialog({
222
  modal: true,
@@ -240,8 +296,12 @@
240
  $('.feedzy-run-now').on('click', function(e){
241
  e.preventDefault();
242
  var button = $(this);
243
- showSpinner(button);
244
- button.parent().find('.feedzy-error').remove();
 
 
 
 
245
  $.ajax({
246
  url : ajaxurl,
247
  method : 'post',
@@ -252,8 +312,10 @@
252
  _action : 'run_now'
253
  },
254
  success: function(data){
255
- hideSpinner(button);
256
- button.after($('<div class="feedzy-error feedzy-error-critical">' + data.data.msg + '</div>'));
 
 
257
  }
258
  });
259
  });
@@ -283,6 +345,9 @@
283
  _action : 'purge'
284
  },
285
  success: function(){
 
 
 
286
  hideSpinner(element);
287
  }
288
  });
5
  * @since 1.2.0
6
  * @package feedzy-rss-feeds-pro
7
  */
8
+ /* global jQuery, ajaxurl, feedzy, tb_show */
9
  (function($){
10
  function scroll_to_class(element_class, removed_height) {
11
  var scroll_to = $( element_class ).offset().top - removed_height;
62
  }
63
 
64
  function update_status() {
65
+ var toggle = $( this );
66
  var post_id = $( this ).val();
67
  var status = $( this ).is( ':checked' );
68
 
74
  'status': status
75
  };
76
 
77
+ showSpinner(toggle);
78
+ $.ajax({
79
+ url: ajaxurl,
80
+ data: data,
81
+ method: 'POST',
82
+ success: function(data){
83
+ if( ! data.success && status ) {
84
+ toggle.parents('tr').find('td.feedzy-source').find('.feedzy-error-critical').remove();
85
+ toggle.parents('tr').find('td.feedzy-source').append($(data.data.msg));
86
+ toggle.prop( 'checked', false );
87
+ }
88
+ },
89
+ complete: function(){
90
+ hideSpinner(toggle);
91
+ }
92
+ });
93
  return true;
94
  }
95
 
157
  }
158
 
159
  $( document ).ready(function() {
160
+ initImportScreen();
161
+ initSummary();
162
+ });
163
+
164
+ function initImportScreen() {
165
  $( 'button.btn-submit' ).on( 'click', function( e ) {
166
  $( window ).unbind( 'beforeunload' );
167
  $( '#custom_post_status' ).val( $( this ).val() );
232
  });
233
  });
234
 
235
+ $('#feedzy-import-source ~ a').on('click', function(e){
236
+ let $url = $('#feedzy-import-source').val();
237
+ let $anchor = $(this);
238
+ $anchor.attr('href', $anchor.attr('data-href-base') + $url);
239
+ });
240
 
241
+ $('#preflight').on('click', function(e){
242
+ e.preventDefault();
243
+ var $fields = {};
244
+ // collect all elements.
245
+ $('#feedzy-import-form').find(':input').each(function(index, element){
246
+ if ( 'undefined' === typeof $(element).attr('name') ) {
247
+ return;
248
+ }
249
+ $fields[ $(element).attr('name') ] = $(element).val();
250
+ });
251
+ tb_show( feedzy.i10n.dry_run_title, 'TB_inline?' );
252
+ $('#TB_ajaxContent').html(feedzy.i10n.dry_run_loading);
253
+ $.ajax({
254
+ url : ajaxurl,
255
+ method : 'post',
256
+ data : {
257
+ security : feedzy.ajax.security,
258
+ fields : $.param($fields),
259
+ action : 'feedzy',
260
+ _action : 'dry_run'
261
+ },
262
+ success: function(data){
263
+ $('#TB_ajaxContent').addClass('loaded');
264
+ $('#TB_ajaxContent div').html(data.data.output);
265
+ }
266
+ });
267
+ });
268
+ }
269
 
270
  function initSummary() {
271
+ $('tr.type-feedzy_imports').each(function(i, e){
272
+ var $lastRunData = $(e).find('script.feedzy-last-run-data').html();
273
+ $($lastRunData).insertAfter(e);
274
+ });
275
+
276
  // pop-ups for informational text
277
  $( '.feedzy-dialog' ).dialog({
278
  modal: true,
296
  $('.feedzy-run-now').on('click', function(e){
297
  e.preventDefault();
298
  var button = $(this);
299
+ button.val(feedzy.i10n.importing);
300
+
301
+ var numberRow = button.parents('tr').find('~ tr.feedzy-import-status-row:first').find('td tr:first');
302
+ numberRow.find('td').hide();
303
+ numberRow.find('td:first').addClass('feedzy_run_now_msg').attr('colspan', 5).html(feedzy.i10n.importing).show();
304
+
305
  $.ajax({
306
  url : ajaxurl,
307
  method : 'post',
312
  _action : 'run_now'
313
  },
314
  success: function(data){
315
+ numberRow.find('td:first').html(data.data.msg);
316
+ },
317
+ complete: function(){
318
+ button.val(feedzy.i10n.run_now);
319
  }
320
  });
321
  });
345
  _action : 'purge'
346
  },
347
  success: function(){
348
+ location.reload();
349
+ },
350
+ complete: function(){
351
  hideSpinner(element);
352
  }
353
  });
js/categories.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global feedzy, ajaxurl */
2
+ /* jshint unused:false */
3
+ (function($) {
4
+
5
+ $(document).ready(function(){
6
+ init();
7
+ });
8
+
9
+ function init(){
10
+ // listen to the validate button
11
+ $('button.validate-category').on('click', function(e){
12
+ e.preventDefault();
13
+ var button = $(this);
14
+ button.html(feedzy.l10n.validating);
15
+ $.ajax({
16
+ url: ajaxurl,
17
+ method: 'POST',
18
+ data: {
19
+ action: 'feedzy_categories',
20
+ _action: 'validate_clean',
21
+ security: feedzy.ajax.security,
22
+ id: button.attr('data-category-id')
23
+ },
24
+ success: function(data){
25
+ button.html(feedzy.l10n.validated.replace('#', data.data.invalid));
26
+ },
27
+ complete: function(){
28
+ setTimeout(function(){
29
+ button.html(feedzy.l10n.validate);
30
+ }, 5000 );
31
+ }
32
+ });
33
+ });
34
+ }
35
+
36
+ })(jQuery, feedzy);
readme.md CHANGED
@@ -461,6 +461,12 @@ You have to check first if your feed is valid. Please test it here: https://vali
461
 
462
 
463
  == Changelog ==
 
 
 
 
 
 
464
  ### 3.4.3 - 2020-08-26 ###
465
 
466
  * [Fix] HTML tags being trimmed on save of the import job
461
 
462
 
463
  == Changelog ==
464
+ ### 3.5.0 - 2020-10-12 ###
465
+
466
+ * [Feat] Improved interface for adding new imports and for the imports listing page
467
+ * [Feat] Improved checks for feeds validity
468
+
469
+
470
  ### 3.4.3 - 2020-08-26 ###
471
 
472
  * [Fix] HTML tags being trimmed on save of the import job
readme.txt CHANGED
@@ -461,6 +461,12 @@ You have to check first if your feed is valid. Please test it here: https://vali
461
 
462
 
463
  == Changelog ==
 
 
 
 
 
 
464
  = 3.4.3 - 2020-08-26 =
465
 
466
  * [Fix] HTML tags being trimmed on save of the import job
461
 
462
 
463
  == Changelog ==
464
+ = 3.5.0 - 2020-10-12 =
465
+
466
+ * [Feat] Improved interface for adding new imports and for the imports listing page
467
+ * [Feat] Improved checks for feeds validity
468
+
469
+
470
  = 3.4.3 - 2020-08-26 =
471
 
472
  * [Fix] HTML tags being trimmed on save of the import job
themeisle-hash.json CHANGED
@@ -1 +1 @@
1
- {"feedzy-rss-feed.php":"5179c1de2880c3ac87bb30a1ce26307b","index.php":"71c0755260138a4b7b2182c3c61179f6","uninstall.php":"cdb21f8648e005cbb9c73481d1750186"}
1
+ {"feedzy-rss-feed.php":"b987a3ed66b1465c85d317884f5a00ff","index.php":"71c0755260138a4b7b2182c3c61179f6","uninstall.php":"cdb21f8648e005cbb9c73481d1750186"}
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit27d7cef882b95754cf5c8cd833e05014::getLoader();
4
 
5
  require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit21a3a7dd973af49e9322f7c49b7edf5c::getLoader();
vendor/autoload_52.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
- return ComposerAutoloaderInitd0e413725483a6c1189ceadcfb8e99f3::getLoader();
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
+ return ComposerAutoloaderInit33ada9a75367c67d82882bee194c98e4::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit27d7cef882b95754cf5c8cd833e05014
6
  {
7
  private static $loader;
8
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit27d7cef882b95754cf5c8cd833e05014
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit27d7cef882b95754cf5c8cd833e05014', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit27d7cef882b95754cf5c8cd833e05014', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
@@ -42,14 +42,14 @@ class ComposerAutoloaderInit27d7cef882b95754cf5c8cd833e05014
42
 
43
  $includeFiles = require __DIR__ . '/autoload_files.php';
44
  foreach ($includeFiles as $fileIdentifier => $file) {
45
- composerRequire27d7cef882b95754cf5c8cd833e05014($fileIdentifier, $file);
46
  }
47
 
48
  return $loader;
49
  }
50
  }
51
 
52
- function composerRequire27d7cef882b95754cf5c8cd833e05014($fileIdentifier, $file)
53
  {
54
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
55
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit21a3a7dd973af49e9322f7c49b7edf5c
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit21a3a7dd973af49e9322f7c49b7edf5c', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit21a3a7dd973af49e9322f7c49b7edf5c', 'loadClassLoader'));
25
 
26
  $map = require __DIR__ . '/autoload_namespaces.php';
27
  foreach ($map as $namespace => $path) {
42
 
43
  $includeFiles = require __DIR__ . '/autoload_files.php';
44
  foreach ($includeFiles as $fileIdentifier => $file) {
45
+ composerRequire21a3a7dd973af49e9322f7c49b7edf5c($fileIdentifier, $file);
46
  }
47
 
48
  return $loader;
49
  }
50
  }
51
 
52
+ function composerRequire21a3a7dd973af49e9322f7c49b7edf5c($fileIdentifier, $file)
53
  {
54
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
55
  require $file;
vendor/composer/autoload_real_52.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real_52.php generated by xrstf/composer-php52
4
 
5
- class ComposerAutoloaderInitd0e413725483a6c1189ceadcfb8e99f3 {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
@@ -19,9 +19,9 @@ class ComposerAutoloaderInitd0e413725483a6c1189ceadcfb8e99f3 {
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitd0e413725483a6c1189ceadcfb8e99f3', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitd0e413725483a6c1189ceadcfb8e99f3', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(dirname(__FILE__));
27
  $baseDir = dirname($vendorDir);
2
 
3
  // autoload_real_52.php generated by xrstf/composer-php52
4
 
5
+ class ComposerAutoloaderInit33ada9a75367c67d82882bee194c98e4 {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit33ada9a75367c67d82882bee194c98e4', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit33ada9a75367c67d82882bee194c98e4', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(dirname(__FILE__));
27
  $baseDir = dirname($vendorDir);