Plugin Directory

source: feedzy-rss-feeds/tags/4.4.2/includes/admin/feedzy-rss-feeds-import.php

Last change on this file was 3026692, checked in by themeisle, 15 months ago

Update to version 4.4.0 from GitHub

File size: 100.6 KB
Line 
1<?php
2/**
3 * The admin-specific functionality of the plugin.
4 *
5 * @link       http://themeisle.com/plugins/feedzy-rss-feed/
6 * @since      1.0.0
7 *
8 * @package    feedzy-rss-feeds
9 * @subpackage feedzy-rss-feeds/includes/admin
10 */
11/**
12 * The admin-specific functionality of the plugin.
13 *
14 * Defines the plugin name, version, and two examples hooks for how to
15 * enqueue the admin-specific stylesheet and JavaScript.
16 *
17 * @package    feedzy-rss-feeds
18 * @subpackage feedzy-rss-feeds/includes/admin
19 * @author     Bogdan Preda <bogdan.preda@themeisle.com>
20 */
21
22/**
23 * Class Feedzy_Rss_Feeds_Import
24 */
25class Feedzy_Rss_Feeds_Import {
26        /**
27         * The ID of this plugin.
28         *
29         * @since    1.0.0
30         * @access   private
31         * @var      string $plugin_name The ID of this plugin.
32         */
33        private $plugin_name;
34
35        /**
36         * The version of this plugin.
37         *
38         * @since    1.0.0
39         * @access   private
40         * @var      string $version The current version of this plugin.
41         */
42        private $version;
43
44        /**
45         * The settings for Feedzy PRO services.
46         *
47         * @since   1.3.2
48         * @access  public
49         * @var     array $settings The settings for Feedzy PRO.
50         */
51        private $settings;
52
53        /**
54         * The settings for Feedzy free.
55         *
56         * @access  public
57         * @var     array $settings The settings for Feedzy free.
58         */
59        private $free_settings;
60
61        /**
62         * Initialize the class and set its properties.
63         *
64         * @param string $plugin_name The name of this plugin.
65         * @param string $version The version of this plugin.
66         *
67         * @since       1.0.0
68         * @access      public
69         */
70        public function __construct( $plugin_name, $version ) {
71                $this->plugin_name = $plugin_name;
72                $this->version     = $version;
73
74                $this->settings      = get_option( 'feedzy-rss-feeds-settings', array() );
75                $this->free_settings = get_option( 'feedzy-settings', array() );
76        }
77
78        /**
79         * Adds the class to the div that shows the upsell.
80         *
81         * @since       ?
82         * @access      public
83         */
84        public function upsell_class( $class ) {
85                if ( ! feedzy_is_pro() ) {
86                        $class = 'only-pro';
87                }
88
89                return $class;
90        }
91
92        /**
93         * Adds the content to the div that shows the upsell.
94         *
95         * @since       ?
96         * @access      public
97         */
98        public function upsell_content( $content, $area, $location ) {
99                if ( ! feedzy_is_pro() ) {
100                        $content = '
101                        <div class="only-pro-content">
102                                <div class="only-pro-container">
103                                        <div class="only-pro-inner upgrade-alert">
104                                                ' . __( 'This feature is available in the Pro version.  Unlock more features, by', 'feedzy-rss-feeds' ) . '
105                                                <a target="_blank" href="' . tsdk_utmify( FEEDZY_UPSELL_LINK, $area, $location ) . '" title="' . __( 'Buy Now', 'feedzy-rss-feeds' ) . '">' . __( 'upgrading to Feedzy Pro', 'feedzy-rss-feeds' ) . '</a>
106                                        </div>
107                                </div>
108                        </div>';
109                }
110
111                return $content;
112        }
113
114        /**
115         * Register the stylesheets for the admin area.
116         *
117         * @since       1.0.0
118         * @access      public
119         */
120        public function enqueue_styles() {
121                wp_enqueue_style( $this->plugin_name, FEEDZY_ABSURL . 'css/feedzy-rss-feed-import.css', array(), $this->version, 'all' );
122                wp_register_style( $this->plugin_name . '_chosen', FEEDZY_ABSURL . 'includes/views/css/chosen.css', array(), $this->version, 'all' );
123                wp_register_script( $this->plugin_name . '_chosen_script', FEEDZY_ABSURL . 'includes/views/js/chosen.js', array( 'jquery' ), $this->version, true );
124
125                if ( get_current_screen()->post_type === 'feedzy_imports' ) {
126                        if ( ! did_action( 'wp_enqueue_media' ) ) {
127                                wp_enqueue_media();
128                        }
129                        wp_enqueue_style( $this->plugin_name . '_chosen', FEEDZY_ABSURL . 'includes/views/css/chosen.css', array(), $this->version, 'all' );
130                        wp_enqueue_style( $this->plugin_name . '_tagify', FEEDZY_ABSURL . 'includes/views/css/tagify.css', array(), $this->version, 'all' );
131                        wp_enqueue_style( $this->plugin_name . '_metabox_edit', FEEDZY_ABSURL . 'includes/views/css/import-metabox-edit.css', array( 'wp-jquery-ui-dialog' ), $this->version, 'all' );
132                        wp_enqueue_script( $this->plugin_name . '_chosen_script', FEEDZY_ABSURL . 'includes/views/js/chosen.js', array( 'jquery' ), $this->version, true );
133                        wp_enqueue_script( $this->plugin_name . '_tagify_script', FEEDZY_ABSURL . 'includes/views/js/jquery.tagify.min.js', array( 'jquery' ), $this->version, true );
134                        wp_enqueue_script(
135                                $this->plugin_name . '_metabox_edit_script',
136                                FEEDZY_ABSURL . 'includes/views/js/import-metabox-edit.js',
137                                array(
138                                        'jquery',
139                                        'jquery-ui-dialog',
140                                        $this->plugin_name . '_chosen_script',
141                                ),
142                                $this->version,
143                                true
144                        );
145                        wp_localize_script(
146                                $this->plugin_name . '_metabox_edit_script',
147                                'feedzy',
148                                array(
149                                        'ajax' => array(
150                                                'security' => wp_create_nonce( FEEDZY_BASEFILE ),
151                                        ),
152                                        'i10n' => array(
153                                                'importing'       => __( 'Importing', 'feedzy-rss-feeds' ) . '...',
154                                                'run_now'         => __( 'Run Now', 'feedzy-rss-feeds' ),
155                                                '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>'
156                                                                                         . '<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>'
157                                                                                         . '<p class="loading-img hide-when-loaded"><img src="' . includes_url( 'images/wpspin-2x.gif' ) . '"></p><div></div>',
158                                                'dry_run_title'   => __( 'Importable Items', 'feedzy-rss-feeds' ),
159                                                'delete_post_message' => __( 'Would you also like to delete all the imported posts for this import job?', 'feedzy-rss-feeds' ),
160                                                'media_iframe_title'  => __( 'Select image', 'feedzy-rss-feeds' ),
161                                                'media_iframe_button' => __( 'Set default image', 'feedzy-rss-feeds' ),
162                                                'action_btn_text_1'   => __( 'Choose image', 'feedzy-rss-feeds' ),
163                                                'action_btn_text_2'   => __( 'Replace image', 'feedzy-rss-feeds' ),
164                                        ),
165                                )
166                        );
167                }
168        }
169
170        /**
171         * Add attributes to $itemArray.
172         *
173         * @param array  $itemArray The item attributes array.
174         * @param object $item The feed item.
175         * @param array  $sc The shorcode attributes array.
176         * @param int    $index The item number (may not be the same as the item_index).
177         * @param int    $item_index The real index of this items in the feed (maybe be different from $index if filters are used).
178         *
179         * @return mixed
180         * @since   1.0.0
181         * @access  public
182         */
183        public function add_data_to_item( $itemArray, $item, $sc = null, $index = null, $item_index = null ) {
184                $itemArray['item_categories'] = $this->retrieve_categories( null, $item );
185
186                // If set to true, SimplePie will return a unique MD5 hash for the item.
187                // If set to false, it will check <guid>, <link>, and <title> before defaulting to the hash.
188                $itemArray['item_id'] = $item->get_id( false );
189
190                $itemArray['item']       = $item;
191                $itemArray['item_index'] = $item_index;
192
193                return $itemArray;
194        }
195
196        /**
197         * Retrieve the categories.
198         *
199         * @param string $dumb The initial categories (only a placeholder argument for the filter).
200         * @param object $item The feed item.
201         *
202         * @return string
203         * @since   ?
204         * @access  public
205         */
206        public function retrieve_categories( $dumb, $item ) {
207                $cats       = array();
208                $categories = $item->get_categories();
209                if ( $categories ) {
210                        foreach ( $categories as $category ) {
211                                if ( is_string( $category ) ) {
212                                        $cats[] = $category;
213                                } else {
214                                        $cats[] = $category->get_label();
215                                }
216                        }
217                }
218
219                return apply_filters( 'feedzy_categories', implode( ', ', $cats ), $cats, $item );
220        }
221
222        /**
223         * Register a new post type for feed imports.
224         *
225         * @since   1.2.0
226         * @access  public
227         */
228        public function register_import_post_type() {
229                $labels   = array(
230                        'name'               => __( 'Import Posts', 'feedzy-rss-feeds' ),
231                        'singular_name'      => __( 'Import Post', 'feedzy-rss-feeds' ),
232                        'add_new'            => __( 'New Import', 'feedzy-rss-feeds' ),
233                        'add_new_item'       => false,
234                        'edit_item'          => false,
235                        'new_item'           => __( 'New Import Post', 'feedzy-rss-feeds' ),
236                        'view_item'          => __( 'View Import', 'feedzy-rss-feeds' ),
237                        'search_items'       => __( 'Search Imports', 'feedzy-rss-feeds' ),
238                        'not_found'          => __( 'No imports found', 'feedzy-rss-feeds' ),
239                        'not_found_in_trash' => __( 'No imports in the trash', 'feedzy-rss-feeds' ),
240                );
241                $supports = array(
242                        'title',
243                );
244                $args     = array(
245                        'labels'              => $labels,
246                        'supports'            => false,
247                        'public'              => true,
248                        'exclude_from_search' => true,
249                        'publicly_queryable'  => false,
250                        'capability_type'     => 'post',
251                        'show_in_nav_menus'   => false,
252                        'rewrite'             => array(
253                                'slug' => 'feedzy-import',
254                        ),
255                        'show_in_menu'        => 'feedzy-admin-menu',
256                        'show_ui'             => feedzy_current_user_can(),
257                        'show_in_rest'        => true,
258                );
259                $args     = apply_filters( 'feedzy_imports_args', $args );
260                register_post_type( 'feedzy_imports', $args );
261
262                // Register user meta field.
263                register_meta(
264                        'user',
265                        'feedzy_import_tour',
266                        array(
267                                'type'         => 'boolean',
268                                'description'  => __( 'Show tour for Feedzy.', 'feedzy-rss-feeds' ),
269                                'show_in_rest' => true,
270                                'single'       => true,
271                                'default'      => true,
272                        )
273                );
274                register_meta(
275                        'user',
276                        'feedzy_hide_action_message',
277                        array(
278                                'type'         => 'boolean',
279                                'description'  => __( 'Show intro message for Feedzy action popup.', 'feedzy-rss-feeds' ),
280                                'show_in_rest' => true,
281                                'single'       => true,
282                                'default'      => false,
283                        )
284                );
285
286        }
287
288        /**
289         * Method to add a meta box to `feedzy_imports`
290         * custom post type.
291         *
292         * @since   1.2.0
293         * @access  public
294         */
295        public function add_feedzy_import_metaboxes( $post_type, $post ) {
296                if ( 'feedzy_imports' !== $post_type ) {
297                        return;
298                }
299
300                add_meta_box(
301                        'feedzy_import_feeds',
302                        __( 'Feed Import Options', 'feedzy-rss-feeds' ),
303                        array(
304                                $this,
305                                'feedzy_import_feed_options',
306                        ),
307                        'feedzy_imports',
308                        'normal',
309                        'high'
310                );
311        }
312
313        /**
314         * Method to display metabox for import post type.
315         *
316         * @return mixed
317         * @since   1.2.0
318         * @access  public
319         */
320        public function feedzy_import_feed_options() {
321                global $post, $pagenow;
322                $args                  = array(
323                        'post_type'      => 'feedzy_categories',
324                        'posts_per_page' => 100,
325                );
326                $feed_categories       = get_posts( $args );
327                $post_types            = get_post_types( '', 'names' );
328                $post_types            = array_diff( $post_types, array( 'feedzy_imports', 'feedzy_categories' ) );
329                $published_status      = array( 'publish', 'draft' );
330                $keyword_filter_fields = array( __( 'Title', 'feedzy-rss-feeds' ) );
331                if ( feedzy_is_pro() ) {
332                        $keyword_filter_fields = array_merge(
333                                $keyword_filter_fields, array(
334                                        __( 'Description', 'feedzy-rss-feeds' ),
335                                        __( 'Author', 'feedzy-rss-feeds' ),
336                                        __( 'Full Content', 'feedzy-rss-feeds' ),
337                                )
338                        );
339                }
340                $import_post_type = get_post_meta( $post->ID, 'import_post_type', true );
341                $import_post_term = get_post_meta( $post->ID, 'import_post_term', true );
342                if ( metadata_exists( $import_post_type, $post->ID, 'import_post_status' ) ) {
343                        $import_post_status = get_post_meta( $post->ID, 'import_post_status', true );
344                } else {
345                        add_post_meta( $post->ID, 'import_post_status', 'publish' );
346                        $import_post_status = get_post_meta( $post->ID, 'import_post_status', true );
347                }
348                $source                   = get_post_meta( $post->ID, 'source', true );
349                $inc_key                  = get_post_meta( $post->ID, 'inc_key', true );
350                $exc_key                  = get_post_meta( $post->ID, 'exc_key', true );
351                $inc_on                   = get_post_meta( $post->ID, 'inc_on', true );
352                $exc_on                   = get_post_meta( $post->ID, 'exc_on', true );
353                $import_title             = get_post_meta( $post->ID, 'import_post_title', true );
354                $import_date              = get_post_meta( $post->ID, 'import_post_date', true );
355                $post_excerpt             = get_post_meta( $post->ID, 'import_post_excerpt', true );
356                $import_content           = get_post_meta( $post->ID, 'import_post_content', true );
357                $import_item_img_url      = get_post_meta( $post->ID, 'import_use_external_image', true );
358                $import_item_img_url      = 'yes' === $import_item_img_url ? 'checked' : '';
359                $import_featured_img      = get_post_meta( $post->ID, 'import_post_featured_img', true );
360                $import_remove_duplicates = get_post_meta( $post->ID, 'import_remove_duplicates', true );
361                $import_remove_duplicates = 'yes' === $import_remove_duplicates || 'post-new.php' === $pagenow ? 'checked' : '';
362                $import_selected_language = get_post_meta( $post->ID, 'language', true );
363                $from_datetime            = get_post_meta( $post->ID, 'from_datetime', true );
364                $to_datetime              = get_post_meta( $post->ID, 'to_datetime', true );
365                $import_auto_translation  = get_post_meta( $post->ID, 'import_auto_translation', true );
366                $import_auto_translation  = 'yes' === $import_auto_translation ? 'checked' : '';
367                $import_translation_lang  = get_post_meta( $post->ID, 'import_auto_translation_lang', true );
368                // default values so that post is not created empty.
369                if ( empty( $import_title ) ) {
370                        $import_title = '[#item_title]';
371                }
372                if ( empty( $import_content ) ) {
373                        $import_content = '[#item_content]';
374                }
375
376                $import_link_author_admin  = get_post_meta( $post->ID, 'import_link_author_admin', true );
377                $import_link_author_public = get_post_meta( $post->ID, 'import_link_author_public', true );
378
379                // Admin / Public
380                $import_link_author = array( '', '' );
381                if ( 'yes' === $import_link_author_admin ) {
382                        $import_link_author[0] = 'checked';
383                }
384                if ( 'yes' === $import_link_author_public ) {
385                        $import_link_author[1] = 'checked';
386                }
387
388                // maybe more options are required from pro?
389                $pro_options = apply_filters( 'feedzy_metabox_options', array(), $post->ID );
390
391                $import_custom_fields = get_post_meta( $post->ID, 'imports_custom_fields', true );
392                $import_feed_limit    = get_post_meta( $post->ID, 'import_feed_limit', true );
393                if ( empty( $import_feed_limit ) ) {
394                        $import_feed_limit = 10;
395                }
396                $import_feed_delete_days = intval( get_post_meta( $post->ID, 'import_feed_delete_days', true ) );
397                if ( empty( $import_feed_delete_days ) ) {
398                        $import_feed_delete_days = ! empty( $this->free_settings['general']['feedzy-delete-days'] ) ? (int) $this->free_settings['general']['feedzy-delete-days'] : 0;
399                }
400                $default_thumbnail_id = 0;
401                if ( feedzy_is_pro() ) {
402                        $default_thumbnail_id = get_post_meta( $post->ID, 'default_thumbnail_id', true );
403                        if ( empty( $default_thumbnail_id ) ) {
404                                $default_thumbnail_id = ! empty( $this->free_settings['general']['default-thumbnail-id'] ) ? (int) $this->free_settings['general']['default-thumbnail-id'] : 0;
405                        }
406                }
407                $post_status        = $post->post_status;
408                $nonce              = wp_create_nonce( FEEDZY_BASEFILE );
409                $invalid_source_msg = apply_filters( 'feedzy_get_source_validity_error', '', $post );
410                $output             = '
411            <input type="hidden" name="feedzy_category_meta_noncename" id="feedzy_category_meta_noncename" value="' . $nonce . '" />
412        ';
413
414                add_thickbox();
415                include FEEDZY_ABSPATH . '/includes/views/import-metabox-edit.php';
416                echo wp_kses( $output, apply_filters( 'feedzy_wp_kses_allowed_html', array() ) );
417        }
418
419        /**
420         * Change number of posts imported.
421         */
422        public function items_limit( $range, $post ) {
423                if ( ! feedzy_is_pro() ) {
424                        $range = range( 10, 10, 10 );
425                }
426
427                return $range;
428        }
429
430        /**
431         * Save method for custom post type
432         * import feeds.
433         *
434         * @param integer $post_id The post ID.
435         * @param object  $post The post object.
436         *
437         * @return bool
438         * @since   1.2.0
439         * @access  public
440         */
441        public function save_feedzy_import_feed_meta( $post_id, $post ) {
442                if ( empty( $_POST ) ) {
443                        return $post_id;
444                }
445                if ( ! isset( $_POST['feedzy_post_nonce'] ) ) {
446                        return $post_id;
447                }
448                if (
449                        get_post_type( $post_id ) !== 'feedzy_imports' ||
450                        ( ! defined( 'TI_UNIT_TESTING' ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['feedzy_post_nonce'] ) ), 'feedzy_post_nonce' ) ) ||
451                        ! current_user_can( 'edit_post', $post_id )
452                ) {
453                        return $post_id;
454                }
455
456                $data_meta = array();
457                if ( isset( $_POST['feedzy_meta_data'] ) && is_array( $_POST['feedzy_meta_data'] ) ) {
458                        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
459                        foreach ( wp_unslash( $_POST['feedzy_meta_data'] ) as $key => $val ) {
460                                if ( is_array( $val ) ) {
461                                        foreach ( $val as $sub_key => $sub_val ) {
462                                                $data_meta[ sanitize_text_field( $key ) ][ sanitize_text_field( $sub_key ) ] = wp_kses( $sub_val, apply_filters( 'feedzy_wp_kses_allowed_html', array() ) );
463                                        }
464                                } else {
465                                        if ( 'import_post_content' === $key ) {
466                                                $val = feedzy_custom_tag_escape( $val );
467                                        } else {
468                                                $val = wp_kses( $val, apply_filters( 'feedzy_wp_kses_allowed_html', array() ) );
469                                        }
470                                        $data_meta[ sanitize_text_field( $key ) ] = $val;
471                                }
472                        }
473                }
474                $custom_fields_keys = array();
475                if ( isset( $_POST['custom_vars_key'] ) && is_array( $_POST['custom_vars_key'] ) ) {
476                        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
477                        foreach ( wp_unslash( $_POST['custom_vars_key'] ) as $key => $val ) {
478                                $custom_fields_keys[ sanitize_text_field( $key ) ] = esc_html( $val );
479                        }
480                }
481                $custom_fields_values = array();
482                if ( isset( $_POST['custom_vars_value'] ) && is_array( $_POST['custom_vars_value'] ) ) {
483                        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
484                        foreach ( wp_unslash( $_POST['custom_vars_value'] ) as $key => $val ) {
485                                $custom_fields_values[ sanitize_text_field( $key ) ] = esc_html( $val );
486                        }
487                }
488                $custom_fields = array();
489                foreach ( $custom_fields_keys as $index => $key_value ) {
490                        $value = '';
491                        if ( isset( $custom_fields_values[ $index ] ) ) {
492                                $value = implode( ',', (array) $custom_fields_values[ $index ] );
493                        }
494                        $custom_fields[ $key_value ] = $value;
495                }
496                if ( $post->post_type !== 'revision' ) {
497                        // delete these checkbox related fields; if checked, they will be added below.
498                        delete_post_meta( $post_id, 'import_link_author_admin' );
499                        delete_post_meta( $post_id, 'import_link_author_public' );
500
501                        // we will activate this import only if the source has no invalid URL(s)
502                        $source_is_valid = false;
503                        // Check feeds remove duplicates checkbox checked OR not.
504                        $data_meta['import_remove_duplicates'] = isset( $data_meta['import_remove_duplicates'] ) ? $data_meta['import_remove_duplicates'] : 'no';
505                        // Check feeds automatically translation checkbox checked OR not.
506                        $data_meta['import_auto_translation'] = isset( $data_meta['import_auto_translation'] ) ? $data_meta['import_auto_translation'] : 'no';
507                        // Check feeds external image URL checkbox checked OR not.
508                        $data_meta['import_use_external_image'] = isset( $data_meta['import_use_external_image'] ) ? $data_meta['import_use_external_image'] : 'no';
509                        foreach ( $data_meta as $key => $value ) {
510                                $value = is_array( $value ) ? implode( ',', $value ) : implode( ',', (array) $value );
511                                if ( 'source' === $key ) {
512                                        // check if the source is valid
513                                        $invalid_urls    = apply_filters( 'feedzy_check_source_validity', $value, $post_id, true, false );
514                                        $source_is_valid = empty( $invalid_urls );
515                                }
516                                if ( 'import_post_content' === $key ) {
517                                        add_filter( 'wp_kses_allowed_html', array( $this, 'feedzy_wp_kses_allowed_html' ), 10, 2 );
518                                        $value = feedzy_custom_tag_escape( $value );
519                                } else {
520                                        $value = wp_kses( $value, wp_kses_allowed_html( 'post' ) );
521                                }
522                                if ( get_post_meta( $post_id, $key, false ) ) {
523                                        update_post_meta( $post_id, $key, $value );
524                                } else {
525                                        add_post_meta( $post_id, $key, $value );
526                                }
527                                if ( ! $value ) {
528                                        delete_post_meta( $post_id, $key );
529                                }
530                        }
531                        // Added this to activate post if publish is clicked and sometimes it does not change status.
532                        if ( $source_is_valid && isset( $_POST['custom_post_status'] ) && $_POST['custom_post_status'] === 'Publish' ) {
533                                $activate = array(
534                                        'ID'          => $post_id,
535                                        'post_status' => 'publish',
536                                );
537                                remove_action( 'save_post_feedzy_imports', array( $this, 'save_feedzy_import_feed_meta' ), 1, 2 );
538                                wp_update_post( $activate );
539                                add_action( 'save_post_feedzy_imports', array( $this, 'save_feedzy_import_feed_meta' ), 1, 2 );
540                        }
541
542                        do_action( 'feedzy_save_fields', $post_id, $post );
543                }
544
545                return true;
546        }
547
548        /**
549         * Redirect save post to post listing.
550         *
551         * @access  public
552         *
553         * @param string $location The url to redirect to.
554         * @param int    $post_id The post ID.
555         *
556         * @return string
557         */
558        public function redirect_post_location( $location, $post_id ) {
559                $post = get_post( $post_id );
560                if ( 'feedzy_imports' === $post->post_type ) {
561                        // if invalid source has been found, redirect back to edit screen
562                        // where errors can be shown
563                        $invalid = get_post_meta( $post_id, '__transient_feedzy_invalid_source', true );
564                        $invalid_dc_namespace  = get_post_meta( $post_id, '__transient_feedzy_invalid_dc_namespace', true );
565                        $invalid_source_errors = get_post_meta( $post_id, '__transient_feedzy_invalid_source_errors', true );
566                        if ( empty( $invalid ) && empty( $invalid_dc_namespace ) && empty( $invalid_source_errors ) ) {
567                                return admin_url( 'edit.php?post_type=feedzy_imports' );
568                        }
569                }
570
571                return $location;
572        }
573
574        /**
575         * Method to add header columns to import feeds table.
576         *
577         * @param array $columns The columns array.
578         *
579         * @return array|bool
580         * @since   1.2.0
581         * @access  public
582         */
583        public function feedzy_import_columns( $columns ) {
584                $columns['title'] = __( 'Import Title', 'feedzy-rss-feeds' );
585                if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-source', __( 'Source', 'feedzy-rss-feeds' ) ) ) {
586                        $columns = $new_columns;
587                } else {
588                        $columns['feedzy-source'] = __( 'Source', 'feedzy-rss-feeds' );
589                }
590
591                if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-status', __( 'Current Status', 'feedzy-rss-feeds' ) ) ) {
592                        $columns = $new_columns;
593                } else {
594                        $columns['feedzy-status'] = __( 'Current Status', 'feedzy-rss-feeds' );
595                }
596
597                if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-next_run', __( 'Next Run', 'feedzy-rss-feeds' ) ) ) {
598                        $columns = $new_columns;
599                } else {
600                        $columns['feedzy-next_run'] = __( 'Next Run', 'feedzy-rss-feeds' );
601                }
602
603                if ( $new_columns = $this->array_insert_before( 'date', $columns, 'feedzy-last_run', __( 'Last Run Status', 'feedzy-rss-feeds' ) ) ) {
604                        $columns = $new_columns;
605                } else {
606                        $columns['feedzy-last_run'] = __( 'Last Run Status', 'feedzy-rss-feeds' );
607                }
608
609                unset( $columns['date'] );
610
611                return $columns;
612        }
613
614        /**
615         * Utility method to insert before specific key
616         * in an associative array.
617         *
618         * @param string $key The key before to insert.
619         * @param array  $array The array in which to insert the new key.
620         * @param string $new_key The new key name.
621         * @param mixed  $new_value The new key value.
622         *
623         * @return array|bool
624         * @since   1.2.0
625         * @access  public
626         */
627        protected function array_insert_before( $key, &$array, $new_key, $new_value ) {
628                if ( array_key_exists( $key, $array ) ) {
629                        $new = array();
630                        foreach ( $array as $k => $value ) {
631                                if ( $k === $key ) {
632                                        $new[ $new_key ] = $new_value;
633                                }
634                                $new[ $k ] = $value;
635                        }
636
637                        return $new;
638                }
639
640                return false;
641        }
642
643        /**
644         * Method to add a columns in the import feeds table.
645         *
646         * @param string  $column The current column to check.
647         * @param integer $post_id The post ID.
648         *
649         * @since   1.2.0
650         * @access  public
651         */
652        public function manage_feedzy_import_columns( $column, $post_id ) {
653                global $post;
654                switch ( $column ) {
655                        case 'feedzy-source':
656                                $src = get_post_meta( $post_id, 'source', true );
657                                // if the source is a category, link it.
658                                if ( strpos( $src, 'http' ) === false && strpos( $src, 'https' ) === false ) {
659                                        if ( function_exists( 'feedzy_amazon_get_locale_hosts' ) ) {
660                                                $amazon_hosts = feedzy_amazon_get_locale_hosts();
661                                                $src_path     = 'webservices.' . wp_parse_url( $src, PHP_URL_PATH );
662                                                if ( in_array( $src_path, $amazon_hosts, true ) ) {
663                                                        $src = sprintf( '%s: %s%s%s', __( 'Amazon Product Advertising API', 'feedzy-rss-feeds' ), '<a>', $src, '</a>' );
664                                                } else {
665                                                        $src = sprintf( '%s: %s%s%s', __( 'Feed Category', 'feedzy-rss-feeds' ), '<a href="' . admin_url( 'edit.php?post_type=feedzy_categories' ) . '" target="_blank">', $src, '</a>' );
666                                                }
667                                        } else {
668                                                $src = sprintf( '%s: %s%s%s', __( 'Feed Category', 'feedzy-rss-feeds' ), '<a href="' . admin_url( 'edit.php?post_type=feedzy_categories' ) . '" target="_blank">', $src, '</a>' );
669                                        }
670                                } else {
671                                        // else link it to the feed but shorten it if it is too long.
672                                        $too_long = 65;
673                                        $src      = sprintf( '%s%s%s', '<a href="' . $src . '" target="_blank" title="' . __( 'Click to view', 'feedzy-rss-feeds' ) . '">', ( strlen( $src ) > $too_long ? substr( $src, 0, $too_long ) . '...' : $src ), '</a>' );
674                                }
675                                echo wp_kses_post( $src );
676                                break;
677                        case 'feedzy-status':
678                                $status = $post->post_status;
679                                if ( empty( $status ) ) {
680                                        esc_html_e( 'Undefined', 'feedzy-rss-feeds' );
681                                } else {
682                                        if ( $status === 'publish' ) {
683                                                $checked = 'checked';
684                                        } else {
685                                                $checked = '';
686                                        }
687                                        echo wp_kses(
688                                                '<div class="switch">
689                                                        <input id="feedzy-toggle_' . $post->ID . '" class="feedzy-toggle feedzy-toggle-round" type="checkbox" value="' . $post->ID . '" ' . $checked . '>
690                                                        <label for="feedzy-toggle_' . $post->ID . '"></label>
691                                                        <span class="feedzy-spinner spinner"></span>
692                                                </div>',
693                                                apply_filters( 'feedzy_wp_kses_allowed_html', array() )
694                                        );
695                                }
696                                break;
697                        case 'feedzy-last_run':
698                                $last = get_post_meta( $post_id, 'last_run', true );
699                                $msg  = __( 'Never Run', 'feedzy-rss-feeds' );
700                                if ( $last ) {
701                                        $now  = new DateTime();
702                                        $then = new DateTime();
703                                        $then = $then->setTimestamp( $last );
704                                        $in   = $now->diff( $then );
705                                        $msg  = sprintf( __( 'Ran %1$d hours %2$d minutes ago', 'feedzy-rss-feeds' ), $in->format( '%h' ), $in->format( '%i' ) );
706                                }
707
708                                $msg .= $this->get_last_run_details( $post_id );
709                                echo( $msg ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
710
711                                if ( 'publish' === $post->post_status ) {
712                                        echo sprintf( '<p><input type="button" class="button button-primary feedzy-run-now" data-id="%d" value="%s"></p>', esc_attr( $post_id ), esc_attr__( 'Run Now', 'feedzy-rss-feeds' ) );
713                                }
714
715                                break;
716                        case 'feedzy-next_run':
717                                $next = wp_next_scheduled( 'feedzy_cron' );
718                                if ( $next ) {
719                                        $now  = new DateTime();
720                                        $then = new DateTime();
721                                        $then = $then->setTimestamp( $next );
722                                        $in   = $now->diff( $then );
723                                        echo wp_kses_post( sprintf( __( 'In %1$d hours %2$d minutes', 'feedzy-rss-feeds' ), $in->format( '%h' ), $in->format( '%i' ) ) );
724                                }
725                                break;
726                        default:
727                                break;
728                }
729        }
730
731        /**
732         * Generate the markup that displays the status.
733         *
734         * @param integer $post_id The post ID.
735         *
736         * @since   ?
737         * @access  private
738         */
739        private function get_last_run_details( $post_id ) {
740                $msg    = '';
741                $last   = get_post_meta( $post_id, 'last_run', true );
742                $status = array(
743                        'total'      => '-',
744                        'items'      => '-',
745                        'duplicates' => '-',
746                        'cumulative' => '-',
747                );
748                if ( $last ) {
749                        $status = array(
750                                'total'      => 0,
751                                'items'      => 0,
752                                'duplicates' => 0,
753                                'cumulative' => 0,
754                        );
755                        $status = $this->get_complete_import_status( $post_id );
756                }
757
758                // link to the posts listing for this job.
759                $job_linked_posts = add_query_arg(
760                        array(
761                                'feedzy_job_id' => $post_id,
762                                'post_type'     => get_post_meta(
763                                        $post_id,
764                                        'import_post_type',
765                                        true
766                                ),
767                                '_nonce'        => wp_create_nonce( 'job_run_linked_posts' ),
768                        ),
769                        admin_url( 'edit.php' )
770                );
771
772                // link to the posts listing for this job run.
773                $job_run_linked_posts = '';
774                $job_run_id           = get_post_meta( $post_id, 'last_run_id', true );
775                if ( ! empty( $job_run_id ) ) {
776                        $job_run_linked_posts = add_query_arg(
777                                array(
778                                        'feedzy_job_id'   => $post_id,
779                                        'feedzy_job_time' => $job_run_id,
780                                        '_nonce'          => wp_create_nonce( 'job_run_linked_posts' ),
781                                        'post_type'       => get_post_meta(
782                                                $post_id,
783                                                'import_post_type',
784                                                true
785                                        ),
786                                ),
787                                admin_url( 'edit.php' )
788                        );
789                }
790
791                // popup for items found.
792                if ( is_array( $status['items'] ) ) {
793                        $msg .= '<div class="feedzy-items-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Items found', 'feedzy-rss-feeds' ) . '"><ol>';
794                        foreach ( $status['items'] as $url => $title ) {
795                                $msg .= sprintf( '<li><p><a href="%s" target="_blank">%s</a></p></li>', esc_url( $url ), esc_html( $title ) );
796                        }
797                        $msg .= '</ol></div>';
798                }
799
800                // popup for duplicates found.
801                if ( is_array( $status['duplicates'] ) ) {
802                        $msg .= '<div class="feedzy-duplicates-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Duplicates found', 'feedzy-rss-feeds' ) . '"><ol>';
803                        foreach ( $status['duplicates'] as $url => $title ) {
804                                $msg .= sprintf( '<li><p><a href="%s" target="_blank">%s</a></p></li>', esc_url( $url ), esc_html( $title ) );
805                        }
806                        $msg .= '</ol></div>';
807                }
808
809                $errors = $this->get_import_errors( $post_id );
810                // popup for errors found.
811                if ( ! empty( $errors ) ) {
812                        $msg .= '<div class="feedzy-errors-found-' . $post_id . ' feedzy-dialog" title="' . __( 'Errors', 'feedzy-rss-feeds' ) . '">' . $errors . '</div>';
813                }
814
815                // remember, cypress will work off the data-value attributes.
816                $msg .= sprintf(
817                        '<script class="feedzy-last-run-data" type="text/template">
818                                <tr style="display: none"></tr>
819                                <tr class="feedzy-import-status-row">
820                                        <td colspan="6" align="right">
821                                                <table>
822                                                        <tr>
823                                                                <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>
824                                                                <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>
825                                                                <td class="feedzy-imported %s" data-value="%d"><a target="%s" href="%s" class="feedzy-popup-details" title="%s">%s</a></td>
826                                                                <td class="feedzy-cumulative %s" data-value="%d"><a target="%s" href="%s" class="feedzy-popup-details" title="%s">%s</a></td>
827                                                                <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>
828                                                        </tr>
829                                                        <tr>
830                                                                <td>%s</td>
831                                                                <td>%s</td>
832                                                                <td>%s</td>
833                                                                <td>%s</td>
834                                                                <td>%s</td>
835                                                        </tr>
836                                                </table>
837                                        </td>
838                                </tr>
839                        </script>',
840                        // first cell
841                        is_array( $status['items'] ) ? 'feedzy-has-popup' : '',
842                        is_array( $status['items'] ) ? count( $status['items'] ) : $status['items'],
843                        __( 'Items that were found in the feed', 'feedzy-rss-feeds' ),
844                        $post_id,
845                        is_array( $status['items'] ) ? count( $status['items'] ) : $status['items'],
846                        // second cells
847                        is_array( $status['duplicates'] ) ? 'feedzy-has-popup' : '',
848                        is_array( $status['duplicates'] ) ? count( $status['duplicates'] ) : $status['duplicates'],
849                        __( 'Items that were discarded as duplicates', 'feedzy-rss-feeds' ),
850                        $post_id,
851                        is_array( $status['duplicates'] ) ? count( $status['duplicates'] ) : $status['duplicates'],
852                        // third cell
853                        $status['total'] > 0 && ! empty( $job_run_linked_posts ) ? 'feedzy-has-popup' : '',
854                        $status['total'],
855                        defined( 'TI_CYPRESS_TESTING' ) ? '' : '_blank',
856                        $status['total'] > 0 && ! empty( $job_run_linked_posts ) ? $job_run_linked_posts : '',
857                        __( 'Items that were imported', 'feedzy-rss-feeds' ),
858                        $status['total'],
859                        // fourth cell
860                        $status['cumulative'] > 0 ? 'feedzy-has-popup' : '',
861                        $status['cumulative'],
862                        defined( 'TI_CYPRESS_TESTING' ) ? '' : '_blank',
863                        $status['cumulative'] > 0 ? $job_linked_posts : '',
864                        __( 'Items that were imported across all runs', 'feedzy-rss-feeds' ),
865                        $status['cumulative'],
866                        // fifth cell
867                        empty( $last ) ? '' : ( ! empty( $errors ) ? 'feedzy-has-popup import-error' : 'import-success' ),
868                        empty( $last ) ? '-1' : ( ! empty( $errors ) ? 0 : 1 ),
869                        $post_id,
870                        __( 'View the errors', 'feedzy-rss-feeds' ),
871                        empty( $last ) ? '-' : ( ! empty( $errors ) ? '<i class="dashicons dashicons-warning"></i>' : '<i class="dashicons dashicons-yes-alt"></i>' ),
872                        // second row
873                        __( 'Found', 'feedzy-rss-feeds' ),
874                        __( 'Duplicates', 'feedzy-rss-feeds' ),
875                        __( 'Imported', 'feedzy-rss-feeds' ),
876                        __( 'Cumulative', 'feedzy-rss-feeds' ),
877                        __( 'Status', 'feedzy-rss-feeds' )
878                );
879
880                return $msg;
881        }
882
883        /**
884         * Gets every aspect of the import job that would reflect its status.
885         *
886         * @since   ?
887         * @access  private
888         */
889        private function get_complete_import_status( $post_id ) {
890                $items_count = get_post_meta( $post_id, 'imported_items_count', true );
891                $items       = get_post_meta( $post_id, 'imported_items_hash', true );
892                if ( empty( $items ) ) {
893                        $items = get_post_meta( $post_id, 'imported_items', true );
894                }
895                $count = $items_count;
896                if ( '' === $count && $items ) {
897                        // backward compatibility where imported_items_count post_meta has not been populated yet
898                        $count = count( $items );
899                }
900
901                $status = array(
902                        'total'      => $count,
903                        'items'      => 0,
904                        'duplicates' => 0,
905                        'cumulative' => 0,
906                );
907
908                $import_info = get_post_meta( $post_id, 'import_info', true );
909                if ( $import_info ) {
910                        foreach ( $import_info as $label => $value ) {
911                                switch ( $label ) {
912                                        case 'total':
913                                                if ( count( $value ) > 0 ) {
914                                                        $status['items'] = $value;
915                                                }
916                                                break;
917                                        case 'duplicates':
918                                                if ( count( $value ) > 0 ) {
919                                                        $status['duplicates'] = $value;
920                                                }
921                                                break;
922                                }
923                        }
924                }
925
926                $items = get_post_meta( $post_id, 'imported_items_hash', true );
927                if ( empty( $items ) ) {
928                        $items = get_post_meta( $post_id, 'imported_items', true );
929                }
930                if ( $items ) {
931                        $status['cumulative'] = count( $items );
932                }
933
934                return $status;
935
936        }
937
938        /**
939         * Creates the data by extracting the 'import_errors' from each import.
940         *
941         * @since   ?
942         * @access  private
943         */
944        private function get_import_errors( $post_id ) {
945                $msg           = '';
946                $import_errors = get_post_meta( $post_id, 'import_errors', true );
947                if ( $import_errors ) {
948                        $errors = '';
949                        if ( is_array( $import_errors ) ) {
950                                foreach ( $import_errors as $err ) {
951                                        $errors .= '<div><i class="dashicons dashicons-warning"></i>' . $err . '</div>';
952                                }
953                        } else {
954                                $errors = '<div><i class="dashicons dashicons-warning"></i>' . $import_errors . '</div>';
955                        }
956                        $msg = '<div class="feedzy-error feedzy-api-error">' . $errors . '</div>';
957                }
958
959                $pro_msg = apply_filters( 'feedzy_run_status_errors', '', $post_id );
960
961                // the pro messages may not have the dashicons, so let's add them.
962                if ( $pro_msg && strpos( $pro_msg, 'dashicons-warning' ) === false ) {
963                        $errors     = '';
964                        $pro_errors = explode( '<br>', $pro_msg );
965                        if ( is_array( $pro_errors ) ) {
966                                foreach ( $pro_errors as $err ) {
967                                        $errors .= '<div><i class="dashicons dashicons-warning"></i>' . $err . '</div>';
968                                }
969                        } else {
970                                $errors = '<div><i class="dashicons dashicons-warning"></i>' . $pro_errors . '</div>';
971                        }
972                        $pro_msg = '<div class="feedzy-error feedzy-api-error">' . $errors . '</div>';
973
974                }
975
976                return $msg . $pro_msg;
977        }
978
979        /**
980         * AJAX single-entry method.
981         *
982         * @since   3.4.1
983         * @access  public
984         */
985        public function ajax() {
986                check_ajax_referer( FEEDZY_BASEFILE, 'security' );
987
988                $_POST['feedzy_category_meta_noncename'] = filter_input( INPUT_POST, 'security', FILTER_UNSAFE_RAW );
989                $_action                                 = filter_input( INPUT_POST, '_action', FILTER_UNSAFE_RAW );
990
991                switch ( $_action ) {
992                        case 'import_status':
993                                $this->import_status();
994                                break;
995                        case 'get_taxonomies':
996                                $this->get_taxonomies();
997                                break;
998                        case 'run_now':
999                                $this->run_now();
1000                                break;
1001                        case 'purge':
1002                                $this->purge_data();
1003                                break;
1004                        case 'dry_run':
1005                                $this->dry_run();
1006                                break;
1007                        case 'fetch_custom_fields':
1008                                $this->fetch_custom_fields();
1009                                break;
1010                        case 'wizard_import_feed':
1011                                $this->wizard_import_feed();
1012                                break;
1013                }
1014        }
1015
1016        /**
1017         * AJAX called method to update post status.
1018         *
1019         * @since   1.2.0
1020         * @access  private
1021         */
1022        private function import_status() {
1023                global $wpdb;
1024
1025                check_ajax_referer( FEEDZY_BASEFILE, 'security' );
1026
1027                $id      = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
1028                $status  = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : '';
1029                $publish = 'draft';
1030                // no activation till source is not valid.
1031                if ( 'true' === $status ) {
1032                        $invalid_urls = apply_filters( 'feedzy_check_source_validity', get_post_meta( $id, 'source', true ), $id, true, false );
1033                        if ( ! empty( $invalid_urls ) ) {
1034                                $msg = apply_filters( 'feedzy_get_source_validity_error', '', get_post( $id ), '' );
1035                                wp_send_json_error( array( 'msg' => $msg ) );
1036                        }
1037
1038                        $publish = 'publish';
1039                }
1040
1041                $new_post_status = array(
1042                        'ID'          => $id,
1043                        'post_status' => $publish,
1044                );
1045
1046                remove_action( 'save_post_feedzy_imports', array( $this, 'save_feedzy_import_feed_meta' ), 1, 2 );
1047                $post_id = wp_update_post( $new_post_status );
1048                add_action( 'save_post_feedzy_imports', array( $this, 'save_feedzy_import_feed_meta' ), 1, 2 );
1049
1050                if ( is_wp_error( $post_id ) ) {
1051                        $errors = $post_id->get_error_messages();
1052                        wp_send_json_error( array( 'msg' => implode( ', ', $errors ) ) );
1053                }
1054                wp_send_json_success();
1055        }
1056
1057        /**
1058         * AJAX method to get taxonomies for a given post_type.
1059         *
1060         * @since   1.2.0
1061         * @access  private
1062         */
1063        private function get_taxonomies() {
1064                check_ajax_referer( FEEDZY_BASEFILE, 'security' );
1065
1066                $post_type  = filter_input( INPUT_POST, 'post_type', FILTER_UNSAFE_RAW );
1067                $taxonomies = get_object_taxonomies(
1068                        array(
1069                                'post_type' => $post_type,
1070                        )
1071                );
1072                $results    = array();
1073                if ( ! empty( $taxonomies ) ) {
1074                        foreach ( $taxonomies as $taxonomy ) {
1075                                $terms                = get_terms(
1076                                        array(
1077                                                'taxonomy'   => $taxonomy,
1078                                                'hide_empty' => false,
1079                                                'fields'     => 'id=>name',
1080                                                'number'     => apply_filters( 'feedzy_post_taxonomy_limit', 999, $taxonomy ),
1081                                        )
1082                                );
1083                                $results[ $taxonomy ] = $terms;
1084                        }
1085                }
1086                echo wp_json_encode( $results );
1087                wp_die();
1088        }
1089
1090        /**
1091         * Run a specific job.
1092         *
1093         * @since   1.6.1
1094         * @access  private
1095         */
1096        private function run_now() {
1097                check_ajax_referer( FEEDZY_BASEFILE, 'security' );
1098
1099                $job   = get_post( filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT ) );
1100                $count = $this->run_job( $job, 100 );
1101
1102                $msg = $count > 0 ? __( 'Successfully run!', 'feedzy-rss-feeds' ) : __( 'Nothing imported!', 'feedzy-rss-feeds' );
1103                $msg .= ' (' . __( 'Refresh this page for the updated status', 'feedzy-rss-feeds' ) . ')';
1104
1105                wp_send_json_success( array( 'msg' => $msg, 'import_success' => $count > 0 ) );
1106        }
1107
1108        /**
1109         * Dry run a specific job so that the user is aware what would be imported.
1110         *
1111         * @since  ?
1112         * @access  private
1113         */
1114        private function dry_run() {
1115                check_ajax_referer( FEEDZY_BASEFILE, 'security' );
1116
1117                $fields = urldecode( filter_input( INPUT_POST, 'fields', FILTER_SANITIZE_URL ) );
1118                parse_str( $fields, $data );
1119
1120                $feedzy_meta_data = $data['feedzy_meta_data'];
1121
1122                add_filter(
1123                        'feedzy_default_error',
1124                        function ( $errors, $feed, $url ) {
1125                                $errors .=
1126                                        sprintf( __( 'For %1$ssingle feeds%2$s, this could be because of the following reasons:', 'feedzy-rss-feeds' ), '<b>', '</b>' )
1127                                        . '<ol>'
1128                                        . '<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>'
1129                                        . '<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>'
1130                                        . '<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>'
1131                                        . '</ol>'
1132                                        . 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>' )
1133                                        . '<ol>'
1134                                        . '<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>'
1135                                        . '</ol>';
1136
1137                                return $errors;
1138                        },
1139                        11,
1140                        3
1141                );
1142
1143                // we will add tags corresponding to the most potential problems.
1144                $tags = array();
1145                if ( $this->feedzy_is_business() && strpos( $feedzy_meta_data['import_post_content'], 'full_content' ) !== false ) {
1146                        $tags[] = 'item_full_content';
1147                }
1148                if ( strpos( $feedzy_meta_data['import_post_content'], 'item_image' ) !== false || strpos( $feedzy_meta_data['import_post_featured_img'], 'item_image' ) !== false ) {
1149                        $tags[] = 'item_image';
1150                }
1151
1152                $shortcode = sprintf(
1153                        '[feedzy-rss feeds="%s" max="%d" feed_title=no meta=no summary=no thumb=no error_empty="%s" keywords_inc="%s" %s="%s" %s="%s" _dry_run_tags_="%s" _dryrun_="yes"]',
1154                        $feedzy_meta_data['source'],
1155                        $feedzy_meta_data['import_feed_limit'],
1156                        '', // should be empty
1157                        $feedzy_meta_data['inc_key'],
1158                        feedzy_is_pro() ? 'keywords_exc' : '',
1159                        feedzy_is_pro() ? $feedzy_meta_data['exc_key'] : '',
1160                        feedzy_is_pro() ? 'keywords_ban' : '',
1161                        feedzy_is_pro() ? $feedzy_meta_data['exc_key'] : '',
1162                        implode( ',', $tags )
1163                );
1164
1165                wp_send_json_success( array( 'output' => do_shortcode( $shortcode ) ) );
1166        }
1167
1168
1169        /**
1170         * The Cron Job.
1171         *
1172         * @since   1.2.0
1173         * @access  public
1174         */
1175        public function run_cron( $max = 100 ) {
1176                if ( empty( $max ) ) {
1177                        $max = 10;
1178                }
1179                global $post;
1180                $args           = array(
1181                        'post_type'   => 'feedzy_imports',
1182                        'post_status' => 'publish',
1183                        'numberposts' => 99,
1184                );
1185                $feedzy_imports = get_posts( $args );
1186                foreach ( $feedzy_imports as $job ) {
1187                        $result = $this->run_job( $job, $max );
1188                        if ( empty( $result ) ) {
1189                                $this->run_job( $job, $max );
1190                        }
1191                        do_action( 'feedzy_run_cron_extra', $job );
1192                }
1193        }
1194
1195        /**
1196         * Runs a specific job.
1197         *
1198         * @return  int
1199         * @since   1.6.1
1200         * @access  private
1201         */
1202        private function run_job( $job, $max ) {
1203                $source                   = get_post_meta( $job->ID, 'source', true );
1204                $inc_key                  = get_post_meta( $job->ID, 'inc_key', true );
1205                $exc_key                  = get_post_meta( $job->ID, 'exc_key', true );
1206                $inc_on                   = get_post_meta( $job->ID, 'inc_on', true );
1207                $exc_on                   = get_post_meta( $job->ID, 'exc_on', true );
1208                $import_title             = get_post_meta( $job->ID, 'import_post_title', true );
1209                $import_title             = $this->feedzy_import_trim_tags( $import_title );
1210                $import_date              = get_post_meta( $job->ID, 'import_post_date', true );
1211                $post_excerpt             = get_post_meta( $job->ID, 'import_post_excerpt', true );
1212                $post_excerpt             = $this->feedzy_import_trim_tags( $post_excerpt );
1213                $import_content           = get_post_meta( $job->ID, 'import_post_content', true );
1214                $import_featured_img      = get_post_meta( $job->ID, 'import_post_featured_img', true );
1215                $import_post_type         = get_post_meta( $job->ID, 'import_post_type', true );
1216                $import_post_term         = get_post_meta( $job->ID, 'import_post_term', true );
1217                $import_feed_limit        = get_post_meta( $job->ID, 'import_feed_limit', true );
1218                $import_item_img_url      = get_post_meta( $job->ID, 'import_use_external_image', true );
1219                $import_remove_duplicates = get_post_meta( $job->ID, 'import_remove_duplicates', true );
1220                $import_selected_language = get_post_meta( $job->ID, 'language', true );
1221                $from_datetime            = get_post_meta( $job->ID, 'from_datetime', true );
1222                $to_datetime              = get_post_meta( $job->ID, 'to_datetime', true );
1223                $import_auto_translation  = get_post_meta( $job->ID, 'import_auto_translation', true );
1224                $import_auto_translation  = $this->feedzy_is_agency() && 'yes' === $import_auto_translation ? true : false;
1225                $import_translation_lang  = get_post_meta( $job->ID, 'import_auto_translation_lang', true );
1226                $max                      = $import_feed_limit;
1227
1228                if ( metadata_exists( $import_post_type, $job->ID, 'import_post_status' ) ) {
1229                        $import_post_status = get_post_meta( $job->ID, 'import_post_status', true );
1230                } else {
1231                        add_post_meta( $job->ID, 'import_post_status', 'publish' );
1232                        $import_post_status = get_post_meta( $job->ID, 'import_post_status', true );
1233                }
1234
1235                // the array of imported items that uses the old scheme of custom hashing the url and date
1236                $imported_items     = array();
1237                $imported_items_old = get_post_meta( $job->ID, 'imported_items', true );
1238                if ( ! is_array( $imported_items_old ) ) {
1239                        $imported_items_old = array();
1240                }
1241
1242                // the array of imported items that uses the new scheme of SimplePie's hash/id
1243                $imported_items_new = get_post_meta( $job->ID, 'imported_items_hash', true );
1244                if ( ! is_array( $imported_items_new ) ) {
1245                        $imported_items_new = array();
1246                }
1247
1248                // Get default thumbnail ID.
1249                $default_thumbnail = ! empty( $this->free_settings['general']['default-thumbnail-id'] ) ? (int) $this->free_settings['general']['default-thumbnail-id'] : 0;
1250                if ( feedzy_is_pro() ) {
1251                        $default_thumbnail = get_post_meta( $job->ID, 'default_thumbnail_id', true );
1252                }
1253
1254                // Note: this implementation will only work if only one of the fields is allowed to provide
1255                // the date, because if the title can have UTC date and content can have local date then it
1256                // all goes sideways.
1257                // also if the user provides multiple date types, local will win.
1258                $meta = 'yes';
1259                if ( strpos( $import_title, '[#item_date_local]' ) !== false ) {
1260                        $meta = 'author, date, time, tz=local';
1261                } elseif ( strpos( $import_title, '[#item_date_feed]' ) !== false ) {
1262                        $meta = 'author, date, time, tz=no';
1263                }
1264
1265                $options = apply_filters(
1266                        'feedzy_shortcode_options',
1267                        array(
1268                                'feeds'           => $source,
1269                                'max'             => $max,
1270                                'feed_title'      => 'no',
1271                                'target'          => '_blank',
1272                                'title'           => '',
1273                                'meta'            => $meta,
1274                                'summary'         => 'yes',
1275                                'summarylength'   => '',
1276                                'thumb'           => 'auto',
1277                                'default'         => '',
1278                                'size'            => '250',
1279                                'keywords_inc'    => $inc_key, // this is not keywords_title
1280                                'keywords_ban'    => $exc_key, // to support old pro that does not support keywords_exc
1281                                'keywords_exc'    => $exc_key, // this is not keywords_ban
1282                                'keywords_inc_on' => $inc_on,
1283                                'keywords_exc_on' => $exc_on,
1284                                'columns'         => 1,
1285                                'offset'          => 0,
1286                                'multiple_meta'   => 'no',
1287                                'refresh'         => '55_mins',
1288                                'from_datetime'   => $from_datetime,
1289                                'to_datetime'     => $to_datetime,
1290                        ),
1291                        $job
1292                );
1293
1294                $admin   = Feedzy_Rss_Feeds::instance()->get_admin();
1295                $options = $admin->sanitize_attr( $options, $source );
1296
1297                $options['__jobID'] = $job->ID;
1298
1299                $last_run = time();
1300                update_post_meta( $job->ID, 'last_run', $last_run );
1301                // we will use this last_run_id to associate imports with a specific job run.
1302                update_post_meta( $job->ID, 'last_run_id', $last_run );
1303                delete_post_meta( $job->ID, 'import_errors' );
1304                delete_post_meta( $job->ID, 'import_info' );
1305
1306                // let's increase this time in case spinnerchief/wordai is being used.
1307                set_time_limit( apply_filters( 'feedzy_max_execution_time', 500 ) );
1308
1309                $count = $index = $import_image_errors = $duplicates = 0;
1310
1311                // the array that captures errors about the import.
1312                $import_errors = array();
1313
1314                // the array that captures additional information about the import.
1315                $import_info   = array();
1316                $results       = $this->get_job_feed( $options, $import_content, true );
1317                $language_code = $results['feed']->get_language();
1318
1319                $xml_results = '';
1320                if ( str_contains( $import_content, '_full_content' ) ) {
1321                        $xml_results = $this->get_job_feed( $options, '[#item_content]', true );
1322                }
1323
1324                if ( is_wp_error( $results ) ) {
1325                        $import_errors[] = $results->get_error_message();
1326                        update_post_meta( $job->ID, 'import_errors', $import_errors );
1327                        update_post_meta( $job->ID, 'imported_items_count', 0 );
1328
1329                        return;
1330                }
1331
1332                $result = $results['items'];
1333                do_action( 'feedzy_run_job_pre', $job, $result );
1334
1335                // check if we should be using the old scheme of custom hashing the url and date
1336                // or the new scheme of depending on SimplePie's hash/id
1337                // basically if the old scheme hasn't be used before, use the new scheme
1338                // BUT if the old scheme has been used, continue with it.
1339                $use_new_hash   = empty( $imported_items_old );
1340                $imported_items = $use_new_hash ? $imported_items_new : $imported_items_old;
1341
1342                $start_import = true;
1343                // bail if both title and content are empty because the post will not be created.
1344                if ( empty( $import_title ) && empty( $import_content ) ) {
1345                        $import_errors[] = __( 'Title & Content are both empty.', 'feedzy-rss-feeds' );
1346                        $start_import    = false;
1347                }
1348
1349                if ( ! $start_import ) {
1350                        update_post_meta( $job->ID, 'import_errors', $import_errors );
1351
1352                        return 0;
1353                }
1354
1355                $rewrite_service_endabled = $this->rewrite_content_service_endabled();
1356
1357                $duplicates       = $items_found = array();
1358                $found_duplicates = array();
1359                foreach ( $result as $key => $item ) {
1360                        $item_obj = $item;
1361                        // find item index key when import full content.
1362                        if ( ! empty( $xml_results ) ) {
1363                                $item_unique_hash = array_column( $xml_results['items'], 'item_unique_hash' );
1364                                $real_index_key   = array_search( $item['item_unique_hash'], $item_unique_hash, true );
1365                                if ( isset( $xml_results['items'][ $real_index_key ] ) ) {
1366                                        $item_obj = $xml_results['items'][ $real_index_key ];
1367                                }
1368                        }
1369                        $item_hash                        = $use_new_hash ? $item['item_id'] : hash( 'sha256', $item['item_url'] . '_' . $item['item_date'] );
1370                        $is_duplicate                     = $use_new_hash ? in_array( $item_hash, $imported_items_new, true ) : in_array( $item_hash, $imported_items_old, true );
1371                        $items_found[ $item['item_url'] ] = $item['item_title'];
1372
1373                        if ( 'yes' === $import_remove_duplicates && ! $is_duplicate ) {
1374                                $is_duplicate_post = $this->is_duplicate_post( $import_post_type, 'feedzy_item_url', esc_url_raw( $item['item_url'] ) );
1375                                if ( ! empty( $is_duplicate_post ) ) {
1376                                        foreach ( $is_duplicate_post as $p ) {
1377                                                $found_duplicates[] = get_post_meta( $p, 'feedzy_item_url', true );
1378                                                wp_delete_post( $p, true );
1379                                        }
1380                                }
1381                        }
1382                        if ( $is_duplicate ) {
1383                                do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Ignoring %s as it is a duplicate (%s hash).', $item_hash, $use_new_hash ? 'new' : 'old' ), 'warn', __FILE__, __LINE__ );
1384                                $index ++;
1385                                $duplicates[ $item['item_url'] ] = $item['item_title'];
1386                                continue;
1387                        }
1388
1389                        $author = '';
1390                        if ( $item['item_author'] ) {
1391                                if ( is_string( $item['item_author'] ) ) {
1392                                        $author = $item['item_author'];
1393                                } elseif ( is_object( $item['item_author'] ) ) {
1394                                        $author = $item['item_author']->get_name();
1395                                        if ( empty( $author ) ) {
1396                                                $author = $item['item_author']->get_email();
1397                                        }
1398                                }
1399                        } else {
1400                                do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Author is empty for %s.', $item['item_title'] ), 'warn', __FILE__, __LINE__ );
1401                        }
1402
1403                        // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
1404                        $item_date = date( get_option( 'date_format' ) . ' at ' . get_option( 'time_format' ), $item['item_date'] );
1405                        $item_date = $item['item_date_formatted'];
1406
1407                        // Get translated item title.
1408                        $translated_title = '';
1409                        if ( $import_auto_translation && ( false !== strpos( $import_title, '[#translated_title]' ) || false !== strpos( $post_excerpt, '[#translated_title]' ) ) ) {
1410                                $translated_title = apply_filters( 'feedzy_invoke_auto_translate_services', $item['item_title'], '[#translated_title]', $import_translation_lang, $job, $language_code, $item );
1411                        }
1412
1413                        $post_title = str_replace(
1414                                array(
1415                                        '[#item_title]',
1416                                        '[#item_author]',
1417                                        '[#item_date]',
1418                                        '[#item_date_local]',
1419                                        '[#item_date_feed]',
1420                                        '[#item_source]',
1421                                        '[#translated_title]',
1422                                ),
1423                                array(
1424                                        $item['item_title'],
1425                                        $author,
1426                                        $item_date,
1427                                        $item_date,
1428                                        $item_date,
1429                                        $item['item_source'],
1430                                        $translated_title,
1431                                ),
1432                                $import_title
1433                        );
1434
1435                        if ( $this->feedzy_is_business() ) {
1436                                $post_title = apply_filters( 'feedzy_parse_custom_tags', $post_title, $item_obj );
1437                        }
1438
1439                        $post_title = apply_filters( 'feedzy_invoke_services', $post_title, 'title', $item['item_title'], $job );
1440
1441                        // Get translated item link text.
1442                        $item_link_txt = __( 'Read More', 'feedzy-rss-feeds' );
1443                        if ( $import_auto_translation && false !== strpos( $import_content, '[#item_url]' ) ) {
1444                                $item_link_txt = apply_filters( 'feedzy_invoke_auto_translate_services', $item_link_txt, '[#item_url]', $import_translation_lang, $job, $language_code, $item );
1445                        }
1446
1447                        $item_link = '<a href="' . $item['item_url'] . '" target="_blank" class="feedzy-rss-link-icon">' . $item_link_txt . '</a>';
1448
1449                        // Rewriter item title from feedzy API.
1450                        if ( $rewrite_service_endabled && false !== strpos( $post_title, '[#title_feedzy_rewrite]' ) ) {
1451                                $title_feedzy_rewrite = apply_filters( 'feedzy_invoke_content_rewrite_services', $item['item_title'], '[#title_feedzy_rewrite]', $job, $item );
1452                                $post_title           = str_replace( '[#title_feedzy_rewrite]', $title_feedzy_rewrite, $post_title );
1453                        }
1454
1455                        $item_link = '<a href="' . $item['item_url'] . '" target="_blank" class="feedzy-rss-link-icon">' . __( 'Read More', 'feedzy-rss-feeds' ) . '</a>';
1456
1457                        $image_html = '';
1458                        if ( ! empty( $item['item_img_path'] ) ) {
1459                                $image_html = '<img src="' . $item['item_img_path'] . '" title="' . $item['item_title'] . '" />';
1460                        }
1461
1462                        // Get translated item description.
1463                        $translated_description = '';
1464                        if ( $import_auto_translation && ( false !== strpos( $import_content, '[#translated_description]' ) || false !== strpos( $post_excerpt, '[#translated_description]' ) ) ) {
1465                                $translated_description = apply_filters( 'feedzy_invoke_auto_translate_services', $item['item_full_description'], '[#translated_description]', $import_translation_lang, $job, $language_code, $item );
1466                        }
1467
1468                        // Get translated item content.
1469                        $translated_content = '';
1470                        if ( $import_auto_translation && ( false !== strpos( $import_content, '[#translated_content]' ) || false !== strpos( $post_excerpt, '[#translated_content]' ) ) ) {
1471                                $translated_content = ! empty( $item['item_content'] ) ? $item['item_content'] : $item['item_description'];
1472                                $translated_content = apply_filters( 'feedzy_invoke_auto_translate_services', $translated_content, '[#translated_content]', $import_translation_lang, $job, $language_code, $item );
1473                        }
1474
1475                        // Used as a new line character in import content.
1476                        $import_content = rawurldecode( $import_content );
1477                        $import_content = str_replace( PHP_EOL, "\r\n", $import_content );
1478                        $import_content = trim( $import_content );
1479
1480                        $post_content = str_replace(
1481                                array(
1482                                        '[#item_description]',
1483                                        '[#item_content]',
1484                                        '[#item_image]',
1485                                        '[#item_url]',
1486                                        '[#item_categories]',
1487                                        '[#item_source]',
1488                                        '[#translated_description]',
1489                                        '[#translated_content]',
1490                                        '[#item_price]',
1491                                        '[#item_author]',
1492                                ),
1493                                array(
1494                                        $item['item_description'],
1495                                        ! empty( $item['item_content'] ) ? $item['item_content'] : $item['item_description'],
1496                                        $image_html,
1497                                        $item_link,
1498                                        $item['item_categories'],
1499                                        $item['item_source'],
1500                                        $translated_description,
1501                                        $translated_content,
1502                                        ! empty( $item['item_price'] ) ? $item['item_price'] : '',
1503                                        $author,
1504                                ),
1505                                $import_content
1506                        );
1507
1508                        if ( $this->feedzy_is_business() ) {
1509                                $full_content = ! empty( $item['item_full_content'] ) ? $item['item_full_content'] : $item['item_content'];
1510                                if ( str_contains( $import_content, '_full_content' ) ) {
1511                                        // if full content is empty, log a message
1512                                        if ( empty( $full_content ) ) {
1513                                                // let's see if there is an error.
1514                                                $full_content_error = isset( $item['full_content_error'] ) && ! empty( $item['full_content_error'] ) ? $item['full_content_error'] : '';
1515                                                if ( empty( $full_content_error ) ) {
1516                                                        $full_content_error = __( 'Unknown', 'feedzy-rss-feeds' );
1517                                                }
1518                                                $import_errors[] = sprintf( __( 'Full content is empty. Error: %s', 'feedzy-rss-feeds' ), $full_content_error );
1519                                        }
1520
1521                                        $post_content = str_replace(
1522                                                array(
1523                                                        '[#item_full_content]',
1524                                                ),
1525                                                array(
1526                                                        $full_content,
1527                                                ),
1528                                                $post_content
1529                                        );
1530                                }
1531                                $post_content = apply_filters( 'feedzy_invoke_services', $post_content, 'full_content', $full_content, $job );
1532                        }
1533                        // Item content action.
1534                        $content_action = $this->handle_content_actions( $post_content, 'item_content' );
1535                        $post_content   = $content_action->get_tags();
1536                        // Item content action process.
1537                        $post_content = $content_action->run_action_job( $post_content, $import_translation_lang, $job, $language_code, $item );
1538                        // Parse custom tags.
1539                        if ( $this->feedzy_is_business() ) {
1540                                $post_content = apply_filters( 'feedzy_parse_custom_tags', $post_content, $item_obj );
1541                        }
1542
1543                        $post_content = apply_filters( 'feedzy_invoke_services', $post_content, 'content', $item['item_description'], $job );
1544
1545                        // Translate full-content.
1546                        if ( $import_auto_translation && false !== strpos( $post_content, '[#translated_full_content]' ) ) {
1547                                $translated_full_content = apply_filters( 'feedzy_invoke_auto_translate_services', $item['item_url'], '[#translated_full_content]', $import_translation_lang, $job, $language_code, $item );
1548                                $post_content            = str_replace( '[#translated_full_content]', rtrim( $translated_full_content, '.' ), $post_content );
1549                        }
1550                        // Rewriter item content from feedzy API.
1551                        if ( $rewrite_service_endabled && false !== strpos( $post_content, '[#content_feedzy_rewrite]' ) ) {
1552                                $item_content           = ! empty( $item['item_content'] ) ? $item['item_content'] : $item['item_description'];
1553                                $content_feedzy_rewrite = apply_filters( 'feedzy_invoke_content_rewrite_services', $item_content, '[#content_feedzy_rewrite]', $job, $item );
1554                                $post_content           = str_replace( '[#content_feedzy_rewrite]', $content_feedzy_rewrite, $post_content );
1555                        }
1556
1557                        // Rewriter item full content from feedzy API.
1558                        if ( $rewrite_service_endabled && false !== strpos( $post_content, '[#full_content_feedzy_rewrite]' ) ) {
1559                                $full_content_feedzy_rewrite = apply_filters( 'feedzy_invoke_content_rewrite_services', $item['item_url'], '[#full_content_feedzy_rewrite]', $job, $item );
1560                                $post_content                = str_replace( '[#full_content_feedzy_rewrite]', $full_content_feedzy_rewrite, $post_content );
1561                        }
1562
1563                        // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
1564                        $item_date = date( 'Y-m-d H:i:s', $item['item_date'] );
1565                        // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
1566                        $now = date( 'Y-m-d H:i:s' );
1567                        if ( trim( $import_date ) === '' ) {
1568                                $post_date = $now;
1569                        }
1570                        $post_date = str_replace( '[#item_date]', $item_date, $import_date );
1571                        $post_date = str_replace( '[#post_date]', $now, $post_date );
1572
1573                        if ( ! defined( 'FEEDZY_ALLOW_UNSAFE_HTML' ) || ! FEEDZY_ALLOW_UNSAFE_HTML ) {
1574                                $post_content = wp_kses( $post_content, apply_filters( 'feedzy_wp_kses_allowed_html', array() ) );
1575
1576                                if ( ! function_exists( 'use_block_editor_for_post_type' ) ) {
1577                                        require_once ABSPATH . 'wp-admin/includes/post.php';
1578                                }
1579
1580                                if ( function_exists( 'use_block_editor_for_post_type' ) && use_block_editor_for_post_type( $import_post_type ) ) {
1581                                        $post_content = ! empty( $post_content ) ? '<!-- wp:html -->' . trim( force_balance_tags( wpautop( $post_content, 'br' ) ) ) . '<!-- /wp:html -->' : $post_content;
1582                                        $post_content = trim( $post_content );
1583                                }
1584                        }
1585
1586                        $item_post_excerpt = str_replace(
1587                                array(
1588                                        '[#item_title]',
1589                                        '[#item_content]',
1590                                        '[#item_description]',
1591                                        '[#translated_title]',
1592                                        '[#translated_content]',
1593                                        '[#translated_description]',
1594                                ),
1595                                array(
1596                                        $post_title,
1597                                        $post_content,
1598                                        $item['item_description'],
1599                                        $translated_title,
1600                                        $translated_content,
1601                                        $translated_description,
1602                                ),
1603                                $post_excerpt
1604                        );
1605
1606                        if ( $this->feedzy_is_business() ) {
1607                                $item_post_excerpt = apply_filters( 'feedzy_parse_custom_tags', $item_post_excerpt, $item_obj );
1608                        }
1609
1610                        $new_post = apply_filters(
1611                                'feedzy_insert_post_args',
1612                                array(
1613                                        'post_type'    => $import_post_type,
1614                                        'post_title'   => wp_kses( $post_title, apply_filters( 'feedzy_wp_kses_allowed_html', array() ) ),
1615                                        'post_content' => $post_content,
1616                                        'post_date'    => $post_date,
1617                                        'post_status'  => $import_post_status,
1618                                        'post_excerpt' => $item_post_excerpt,
1619                                ),
1620                                $item_obj,
1621                                $post_title,
1622                                $post_content,
1623                                $item_post_excerpt,
1624                                $index,
1625                                $job
1626                        );
1627
1628                        // no point creating a post if either the title or the content is null.
1629                        if ( is_null( $post_title ) || is_null( $post_content ) ) {
1630                                do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'NOT creating a new post as title (%s) or content (%s) is null.', $post_title, $post_content ), 'info', __FILE__, __LINE__ );
1631                                $index ++;
1632                                $import_errors[] = __( 'Title or Content is empty.', 'feedzy-rss-feeds' );
1633                                continue;
1634                        }
1635
1636                        if ( 'attachment' === $import_post_type ) {
1637                                $image_url       = '';
1638                                $img_success     = true;
1639                                $new_post_id     = 0;
1640                                $default_img_tag = ! empty( $import_featured_img ) ? '[#item_image]' : '';
1641
1642                                // image tag
1643                                if ( strpos( $default_img_tag, '[#item_image]' ) !== false ) {
1644                                        // image exists in item
1645                                        if ( ! empty( $item['item_img_path'] ) ) {
1646                                                $image_url = str_replace( '[#item_image]', $item['item_img_path'], $default_img_tag );
1647                                        } else {
1648                                                $img_success = false;
1649                                        }
1650                                } elseif ( strpos( $default_img_tag, '[#item_custom' ) !== false ) {
1651                                        // custom image tag
1652                                        if ( $this->feedzy_is_business() || $this->feedzy_is_personal() ) {
1653                                                $value = apply_filters( 'feedzy_parse_custom_tags', $default_img_tag, $item_obj );
1654                                        }
1655
1656                                        if ( ! empty( $value ) && strpos( $value, '[#item_custom' ) === false ) {
1657                                                $image_url = $value;
1658                                        } else {
1659                                                $img_success = false;
1660                                        }
1661                                } else {
1662                                        $image_url = $default_img_tag;
1663                                }
1664
1665                                if ( ! empty( $image_url ) ) {
1666                                        $img_success = $this->generate_featured_image( $image_url, 0, $item['item_title'], $import_errors, $import_info, $new_post );
1667                                        $new_post_id = $img_success;
1668                                }
1669
1670                                if ( ! $img_success ) {
1671                                        $import_image_errors ++;
1672                                }
1673                        } else {
1674                                $new_post_id = wp_insert_post( $new_post, true );
1675                        }
1676
1677                        // Set post language.
1678                        if ( function_exists( 'pll_set_post_language' ) && ! empty( $import_selected_language ) ) {
1679                                pll_set_post_language( $new_post_id, $import_selected_language );
1680                        } elseif ( function_exists( 'icl_get_languages' ) && ! empty( $import_selected_language ) ) {
1681                                $this->set_wpml_element_language_details( $import_post_type, $new_post_id, $import_selected_language );
1682                        }
1683
1684                        if ( $new_post_id === 0 || is_wp_error( $new_post_id ) ) {
1685                                $error_reason = 'N/A';
1686                                if ( is_wp_error( $new_post_id ) ) {
1687                                        $error_reason = $new_post_id->get_error_message();
1688                                        if ( ! empty( $error_reason ) ) {
1689                                                $import_errors[] = $error_reason;
1690                                        }
1691                                }
1692                                do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Unable to create a new post with params %s. Error: %s', print_r( $new_post, true ), $error_reason ), 'error', __FILE__, __LINE__ );
1693                                $index ++;
1694                                continue;
1695                        }
1696                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'created new post with ID %d with post_content %s', $new_post_id, $post_content ), 'debug', __FILE__, __LINE__ );
1697                        if ( ! in_array( $item_hash, $found_duplicates, true ) ) {
1698                                $imported_items[] = $item_hash;
1699                                $count ++;
1700                        }
1701
1702                        if ( $import_post_term !== 'none' && strpos( $import_post_term, '_' ) > 0 ) {
1703                                // let's get the slug of the uncategorized category, even if it renamed.
1704                                $uncategorized    = get_category( 1 );
1705                                $terms            = explode( ',', $import_post_term );
1706                                $terms            = array_filter(
1707                                        $terms,
1708                                        function( $term ) {
1709                                                if ( empty( $term ) ) {
1710                                                        return;
1711                                                }
1712                                                if ( false !== strpos( $term, '[#item_' ) ) {
1713                                                        return;
1714                                                }
1715                                                return $term;
1716                                        }
1717                                );
1718                                $default_category = (int) get_option( 'default_category' );
1719                                foreach ( $terms as $term ) {
1720                                        // this handles both x_2, where 2 is the term id and x is the taxonomy AND x_2_3_4 where 4 is the term id and the taxonomy name is "x 2 3 4".
1721                                        $array    = explode( '_', $term );
1722                                        $term_id  = array_pop( $array );
1723                                        $taxonomy = implode( '_', $array );
1724
1725                                        // uncategorized
1726                                        // 1. may be the unmodified category ID 1
1727                                        // 2. may have been recreated ('uncategorized') and may have a different slug in different languages.
1728                                        if ( $default_category === $uncategorized->term_id ) {
1729                                                wp_remove_object_terms(
1730                                                        $new_post_id, apply_filters(
1731                                                                'feedzy_uncategorized', array(
1732                                                                        1,
1733                                                                        'uncategorized',
1734                                                                        $uncategorized->slug,
1735                                                                ), $job->ID
1736                                                        ), 'category'
1737                                                );
1738                                        }
1739
1740                                        $result = wp_set_object_terms( $new_post_id, intval( $term_id ), $taxonomy, true );
1741                                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'After creating post in %s/%d, result = %s', $taxonomy, $term_id, print_r( $result, true ) ), 'debug', __FILE__, __LINE__ );
1742                                }
1743                        }
1744
1745                        do_action( 'feedzy_import_extra', $job, $item_obj, $new_post_id, $import_errors, $import_info );
1746
1747                        $default_img_tag = ! empty( $import_featured_img ) ? '[#item_image]' : '';
1748                        if ( ! empty( $default_img_tag ) && 'attachment' !== $import_post_type ) {
1749                                $image_url   = '';
1750                                $img_success = true;
1751
1752                                // image tag
1753                                if ( strpos( $default_img_tag, '[#item_image]' ) !== false ) {
1754                                        // image exists in item
1755                                        if ( ! empty( $item['item_img_path'] ) ) {
1756                                                $image_url = str_replace( '[#item_image]', $item['item_img_path'], $default_img_tag );
1757                                        } else {
1758                                                $img_success = false;
1759                                        }
1760                                } elseif ( strpos( $default_img_tag, '[#item_custom' ) !== false ) {
1761                                        // custom image tag
1762                                        if ( $this->feedzy_is_business() || $this->feedzy_is_personal() ) {
1763                                                $value = apply_filters( 'feedzy_parse_custom_tags', $default_img_tag, $item_obj );
1764                                        }
1765                                        if ( ! empty( $value ) && strpos( $value, '[#item_custom' ) === false ) {
1766                                                $image_url = $value;
1767                                        } else {
1768                                                $img_success = false;
1769                                        }
1770                                }
1771
1772                                // Fetch image from graby.
1773                                if ( empty( $image_url ) && ( wp_doing_cron() || defined( 'FEEDZY_PRO_FETCH_ITEM_IMG_URL' ) ) ) {
1774                                        // if license does not exist, use the site url
1775                                        // this should obviously never happen unless on dev instances.
1776                                        $license = apply_filters( 'product_feedzy_license_key', sprintf( 'n/a - %s', get_site_url() ) );
1777
1778                                        $response = wp_remote_post(
1779                                                FEEDZY_PRO_FETCH_ITEM_IMG_URL,
1780                                                apply_filters(
1781                                                        'feedzy_fetch_item_image',
1782                                                        array(
1783                                                                'timeout' => 100,
1784                                                                'body'    => array_merge(
1785                                                                        array(
1786                                                                                'item_url' => $item['item_url'],
1787                                                                                'license'  => $license,
1788                                                                                'site_url' => get_site_url(),
1789                                                                        )
1790                                                                ),
1791                                                        )
1792                                                )
1793                                        );
1794
1795                                        if ( ! is_wp_error( $response ) ) {
1796                                                if ( array_key_exists( 'response', $response ) && array_key_exists( 'code', $response['response'] ) && intval( $response['response']['code'] ) !== 200 ) {
1797                                                        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
1798                                                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'error in response = %s', print_r( $response, true ) ), 'error', __FILE__, __LINE__ );
1799                                                }
1800                                                $body = wp_remote_retrieve_body( $response );
1801                                                if ( ! is_wp_error( $body ) ) {
1802                                                        $response_data = json_decode( $body, true );
1803                                                        if ( isset( $response_data['url'] ) ) {
1804                                                                $image_url = $response_data['url'];
1805                                                        }
1806                                                } else {
1807                                                        // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
1808                                                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'error in body = %s', print_r( $body, true ) ), 'error', __FILE__, __LINE__ );
1809                                                }
1810                                        } else {
1811                                                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
1812                                                do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'error in request = %s', print_r( $response, true ) ), 'error', __FILE__, __LINE__ );
1813                                        }
1814                                }
1815
1816                                // Item image action.
1817                                $import_featured_img = rawurldecode( $import_featured_img );
1818                                $import_featured_img = trim( $import_featured_img );
1819                                $img_action          = $this->handle_content_actions( $import_featured_img, 'item_image' );
1820                                // Item image action process.
1821                                $image_url = $img_action->run_action_job( $import_featured_img, $import_translation_lang, $job, $language_code, $item, $image_url );
1822
1823                                if ( ! empty( $image_url ) ) {
1824                                        if ( 'yes' === $import_item_img_url ) {
1825                                                // Set external image URL.
1826                                                update_post_meta( $new_post_id, 'feedzy_item_external_url', $image_url );
1827                                        } else {
1828                                                // if import_featured_img is a tag.
1829                                                $img_success = $this->generate_featured_image( $image_url, $new_post_id, $item['item_title'], $import_errors, $import_info );
1830                                        }
1831                                }
1832                                // Set default thumbnail image.
1833                                if ( ! $img_success && ! empty( $default_thumbnail ) ) {
1834                                        $img_success = set_post_thumbnail( $new_post_id, $default_thumbnail );
1835                                }
1836
1837                                if ( ! $img_success ) {
1838                                        $import_image_errors ++;
1839                                }
1840                        }
1841
1842                        $index ++;
1843
1844                        // indicate that this post was imported by feedzy.
1845                        update_post_meta( $new_post_id, 'feedzy', 1 );
1846                        update_post_meta( $new_post_id, 'feedzy_item_url', esc_url_raw( $item['item_url'] ) );
1847                        update_post_meta( $new_post_id, 'feedzy_job', $job->ID );
1848                        update_post_meta( $new_post_id, 'feedzy_item_author', sanitize_text_field( $author ) );
1849
1850                        // we can use this to associate the items that were imported in a particular run.
1851                        update_post_meta( $new_post_id, 'feedzy_job_time', $last_run );
1852
1853                        do_action( 'feedzy_after_post_import', $new_post_id, $item, $this->settings );
1854                }
1855
1856                if ( $use_new_hash ) {
1857                        update_post_meta( $job->ID, 'imported_items_hash', $imported_items );
1858                } else {
1859                        update_post_meta( $job->ID, 'imported_items', $imported_items );
1860                }
1861                update_post_meta( $job->ID, 'imported_items_count', $count );
1862
1863                if ( $import_image_errors > 0 ) {
1864                        $import_errors[] = sprintf( __( 'Unable to find an image for %1$d out of %2$d items imported', 'feedzy-rss-feeds' ), $import_image_errors, $count );
1865                }
1866                update_post_meta( $job->ID, 'import_errors', $import_errors );
1867
1868                // the order of these matters in how they are finally shown in the summary.
1869                $import_info['total']      = $items_found;
1870                $import_info['duplicates'] = $duplicates;
1871
1872                update_post_meta( $job->ID, 'import_info', $import_info );
1873
1874                return $count;
1875        }
1876
1877        /**
1878         * Method to return feed items to use on cron job.
1879         *
1880         * @param array  $options The options for the job.
1881         * @param string $import_content The import content (along with the magic tags).
1882         * @param bool   $raw_feed_also Whether to return the raw SimplePie object as well.
1883         *
1884         * @return mixed
1885         * @since   1.2.0
1886         * @access  public
1887         */
1888        public function get_job_feed( $options, $import_content = null, $raw_feed_also = false ) {
1889                $admin = Feedzy_Rss_Feeds::instance()->get_admin();
1890                if ( ! method_exists( $admin, 'normalize_urls' ) ) {
1891                        return array();
1892                }
1893                $feedURL     = $admin->normalize_urls( $options['feeds'] );
1894                $source_type = get_post_meta( $options['__jobID'], '__feedzy_source_type', true );
1895
1896                if ( 'amazon' === $source_type ) {
1897                        $feed = $admin->init_amazon_api(
1898                                $feedURL,
1899                                isset( $options['refresh'] ) ? $options['refresh'] : '12_hours',
1900                                array(
1901                                        'number_of_item' => $options['max'],
1902                                        'no-cache'       => false,
1903                                )
1904                        );
1905                        if ( ! empty( $feed->get_errors() ) ) {
1906                                return array();
1907                        }
1908                } else {
1909                        $feedURL = apply_filters( 'feedzy_import_feed_url', $feedURL, $import_content, $options );
1910                        if ( is_wp_error( $feedURL ) ) {
1911                                return $feedURL;
1912                        }
1913                        $feed = $admin->fetch_feed( $feedURL, isset( $options['refresh'] ) ? $options['refresh'] : '12_hours', $options );
1914
1915                        $feed->force_feed( true );
1916                        $feed->enable_order_by_date( false );
1917
1918                        if ( is_string( $feed ) ) {
1919                                return array();
1920                        }
1921                }
1922                $sizes      = array(
1923                        'width'  => $options['size'],
1924                        'height' => $options['size'],
1925                );
1926                $sizes      = apply_filters( 'feedzy_thumb_sizes', $sizes, $feedURL );
1927                $feed_items = apply_filters( 'feedzy_get_feed_array', array(), $options, $feed, $feedURL, $sizes );
1928                if ( $raw_feed_also ) {
1929                        return array(
1930                                'items' => $feed_items,
1931                                'feed'  => $feed,
1932                        );
1933                }
1934
1935                return $feed_items;
1936        }
1937
1938        /**
1939         * Downloads and sets a post featured image if possible.
1940         *
1941         * @param string  $file The file URL.
1942         * @param integer $post_id The post ID.
1943         * @param string  $desc Description.
1944         * @param array   $import_errors Array of import error messages.
1945         * @param array   $import_info Array of import information messages.
1946         *
1947         * @return bool
1948         * @since   1.2.0
1949         * @access  private
1950         */
1951        private function generate_featured_image( $file, $post_id, $desc, &$import_errors, &$import_info, $post_data = array() ) {
1952                if ( ! function_exists( 'post_exists' ) ) {
1953                        require_once ABSPATH . 'wp-admin/includes/post.php';
1954                }
1955                // Find existing attachment by item title.
1956                $id = post_exists( $desc, '', '', 'attachment' );
1957
1958                if ( ! $id ) {
1959                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Trying to generate featured image for %s and postID %d', $file, $post_id ), 'debug', __FILE__, __LINE__ );
1960
1961                        require_once ABSPATH . 'wp-admin' . '/includes/image.php';
1962                        require_once ABSPATH . 'wp-admin' . '/includes/file.php';
1963                        require_once ABSPATH . 'wp-admin' . '/includes/media.php';
1964
1965                        $file_array = array();
1966                        $file       = trim( $file, chr( 0xC2 ) . chr( 0xA0 ) );
1967                        $local_file = download_url( $file );
1968                        if ( is_wp_error( $local_file ) ) {
1969                                do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Unable to download file = %s and postID %d', print_r( $local_file, true ), $post_id ), 'error', __FILE__, __LINE__ );
1970
1971                                return false;
1972                        }
1973
1974                        $type = mime_content_type( $local_file );
1975                        // the file is downloaded with a .tmp extension
1976                        // if the URL mentions the extension of the file, the upload succeeds
1977                        // but if the URL is like https://source.unsplash.com/random, then the upload fails
1978                        // so let's determine the file's mime type and then rename the .tmp file with that extension
1979                        if ( in_array( $type, array_values( get_allowed_mime_types() ), true ) ) {
1980                                $new_local_file = str_replace( '.tmp', str_replace( 'image/', '.', $type ), $local_file );
1981                                $renamed        = rename( $local_file, $new_local_file );
1982                                if ( $renamed ) {
1983                                        $local_file = $new_local_file;
1984                                } else {
1985                                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Unable to rename file for postID %d', $post_id ), 'error', __FILE__, __LINE__ );
1986
1987                                        return false;
1988                                }
1989                        }
1990
1991                        $file_array['tmp_name'] = $local_file;
1992                        $file_array['name']     = basename( $local_file );
1993
1994                        $id = media_handle_sideload( $file_array, $post_id, $desc, $post_data );
1995                        if ( is_wp_error( $id ) ) {
1996                                do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Unable to attach file for postID %d = %s', $post_id, print_r( $id, true ) ), 'error', __FILE__, __LINE__ );
1997                                unlink( $file_array['tmp_name'] );
1998
1999                                return false;
2000                        }
2001                } else {
2002                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Found an existing attachment(ID: %d) image for %s and postID %d', $id, $file, $post_id ), 'debug', __FILE__, __LINE__ );
2003                }
2004
2005                if ( ! empty( $post_data ) ) {
2006                        return $id;
2007                }
2008
2009                $success = set_post_thumbnail( $post_id, $id );
2010                if ( false === $success ) {
2011                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Unable to attach file for postID %d for no apparent reason', $post_id ), 'error', __FILE__, __LINE__ );
2012                } else {
2013                        do_action( 'themeisle_log_event', FEEDZY_NAME, sprintf( 'Attached file as featured image for postID %d', $post_id ), 'info', __FILE__, __LINE__ );
2014                }
2015
2016                return $success;
2017        }
2018
2019        /**
2020         * Registers a cron schedule.
2021         *
2022         * @since   1.2.0
2023         * @access  public
2024         */
2025        public function add_cron() {
2026                $time     = ! empty( $this->free_settings['general']['fz_cron_execution'] ) ? $this->get_cron_execution( $this->free_settings['general']['fz_cron_execution'] ) : time();
2027                $schedule = ! empty( $this->free_settings['general']['fz_cron_schedule'] ) ? $this->free_settings['general']['fz_cron_schedule'] : 'hourly';
2028                if ( ( isset( $_POST['nonce'] ) && isset( $_POST['tab'] ) ) && ( wp_verify_nonce( filter_input( INPUT_POST, 'nonce', FILTER_UNSAFE_RAW ), filter_input( INPUT_POST, 'tab', FILTER_UNSAFE_RAW ) ) ) ) {
2029                        if ( ! empty( $_POST['fz_cron_execution'] ) && ! empty( $_POST['fz_cron_schedule'] ) && ! empty( $_POST['fz_execution_offset'] ) ) {
2030                                $execution = sanitize_text_field( wp_unslash( $_POST['fz_cron_execution'] ) );
2031                                $offset    = sanitize_text_field( wp_unslash( $_POST['fz_execution_offset'] ) );
2032                                $time      = $this->get_cron_execution( $execution, $offset );
2033                                $schedule  = sanitize_text_field( wp_unslash( $_POST['fz_cron_schedule'] ) );
2034                                wp_clear_scheduled_hook( 'feedzy_cron' );
2035                        }
2036                }
2037                if ( false === wp_next_scheduled( 'feedzy_cron' ) ) {
2038                        wp_schedule_event( $time, $schedule, 'feedzy_cron' );
2039                }
2040        }
2041
2042        /**
2043         * Get cron job execution.
2044         *
2045         * @param string $execution Execution time.
2046         * @param int    $offset Offset.
2047         * @return int
2048         */
2049        public function get_cron_execution( $execution, $offset = 0 ) {
2050                if ( empty( $offset ) && ! empty( $this->free_settings['general']['fz_execution_offset'] ) ) {
2051                        $offset = $this->free_settings['general']['fz_execution_offset'];
2052                }
2053                $execution = strtotime( $execution ) ? strtotime( $execution ) + ( HOUR_IN_SECONDS * $offset ) : time() + ( HOUR_IN_SECONDS * $offset );
2054                return $execution;
2055        }
2056
2057        /**
2058         * Checks if WP Cron is enabled and if not, shows a notice.
2059         *
2060         * @access  public
2061         */
2062        public function admin_notices() {
2063                $screen  = get_current_screen();
2064                $allowed = array( 'edit-feedzy_categories', 'edit-feedzy_imports', 'feedzy-rss_page_feedzy-settings' );
2065                // only show in the feedzy screens.
2066                if ( ! in_array( $screen->id, $allowed, true ) ) {
2067                        return;
2068                }
2069
2070                if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
2071                        echo wp_kses_post( '<div class="notice notice-error feedzy-error-critical is-dismissible"><p>' . __( 'WP Cron is disabled. Your feeds would not get updated. Please contact your hosting provider or system administrator', 'feedzy-rss-feeds' ) . '</p></div>' );
2072                }
2073
2074                if ( false === wp_next_scheduled( 'feedzy_cron' ) ) {
2075                        echo wp_kses_post( '<div class="notice notice-error"><p>' . __( 'Unable to register cron job. Your feeds might not get updated', 'feedzy-rss-feeds' ) . '</p></div>' );
2076                }
2077
2078        }
2079
2080        /**
2081         * Method to return license status.
2082         * Used to filter PRO version types.
2083         *
2084         * @return bool
2085         * @since   1.2.0
2086         * @access  public
2087         */
2088        public function feedzy_is_business() {
2089                return $this->feedzy_is_license_of_type( false, 'business' );
2090        }
2091
2092        /**
2093         * Method to return if licence is agency.
2094         *
2095         * @return bool
2096         * @since   1.3.2
2097         * @access  public
2098         */
2099        public function feedzy_is_agency() {
2100                return $this->feedzy_is_license_of_type( false, 'agency' );
2101        }
2102
2103        /**
2104         * Method to return if licence is personal.
2105         *
2106         * @return bool
2107         * @since   1.8.2
2108         * @access  public
2109         */
2110        public function feedzy_is_personal() {
2111                return $this->feedzy_is_license_of_type( false, 'pro' );
2112        }
2113
2114        /**
2115         * Method to return the type of licence.
2116         *
2117         * @access  public
2118         * @return bool
2119         */
2120        public function feedzy_is_license_of_type( $default, $type ) {
2121                // proceed to check the plan only if the license is active.
2122                if ( ! ( defined( 'TI_UNIT_TESTING' ) || defined( 'TI_CYPRESS_TESTING' ) ) ) {
2123                        $status = apply_filters( 'feedzy_rss_feeds_pro_license_status', false );
2124                        if ( $status !== 'valid' ) {
2125                                return $default;
2126                        }
2127                }
2128                $plan = apply_filters( 'product_feedzy_license_plan', 0 );
2129                $plan = intval( $plan );
2130                switch ( $type ) {
2131                        case 'agency':
2132                                return in_array( $plan, array( 3, 6, 7 ), true );
2133                        case 'business':
2134                                return in_array( $plan, array( 2, 3, 5, 6, 7, 8 ), true );
2135                        case 'pro':
2136                                return ( $plan > 0 );
2137                }
2138
2139                return $default;
2140        }
2141
2142
2143        /**
2144         * Method for updating settings page via AJAX.
2145         *
2146         * @since   1.3.2
2147         * @access  public
2148         */
2149        public function update_settings_page() {
2150                $this->save_settings();
2151                wp_die();
2152        }
2153
2154        /**
2155         * Display settings fields for the tab.
2156         *
2157         * @since   1.3.2
2158         * @access  public
2159         */
2160        public function display_tab_settings( $fields, $tab ) {
2161                $this->free_settings = get_option( 'feedzy-settings', array() );
2162
2163                $fields[] = array(
2164                        'content' => $this->render_view( $tab ),
2165                        'ajax'    => false,
2166                );
2167
2168                return $fields;
2169        }
2170
2171        /**
2172         * Method to save settings.
2173         *
2174         * @since   1.3.2
2175         * @access  private
2176         */
2177        private function save_settings() {
2178                update_option( 'feedzy-rss-feeds-settings', $this->settings );
2179        }
2180
2181        /**
2182         * Add settings tab.
2183         *
2184         * @since   1.3.2
2185         * @access  public
2186         */
2187        public function settings_tabs( $tabs ) {
2188                $tabs['misc']   = __( 'Miscellaneous', 'feedzy-rss-feeds' );
2189                if ( $this->feedzy_is_business() || $this->feedzy_is_agency() ) {
2190                        $tabs['openai'] = __( 'OpenAI', 'feedzy-rss-feeds' );
2191                }
2192                if ( ! feedzy_is_pro() ) {
2193                        $tabs['wordai']       = sprintf( '%s <span class="pro-label">PRO</span>', __( 'WordAi', 'feedzy-rss-feeds' ) );
2194                        $tabs['spinnerchief'] = sprintf( '%s <span class="pro-label">PRO</span>', __( 'SpinnerChief', 'feedzy-rss-feeds' ) );
2195                        $tabs['amazon-product-advertising'] = sprintf( '%s <span class="pro-label">PRO</span>', __( 'Amazon Product Advertising', 'feedzy-rss-feeds' ) );
2196                        $tabs['openai'] = sprintf( '%s <span class="pro-label">PRO</span>', __( 'OpenAI', 'feedzy-rss-feeds' ) );
2197                }
2198
2199                return $tabs;
2200        }
2201
2202        /**
2203         * Save settings for the tab.
2204         *
2205         * @access  public
2206         */
2207        public function save_tab_settings( $settings, $tab ) {
2208                if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( filter_input( INPUT_POST, 'nonce', FILTER_UNSAFE_RAW ), $tab ) ) {
2209                        return;
2210                }
2211
2212                if ( 'misc' === $tab ) {
2213                        $settings['canonical'] = isset( $_POST['canonical'] ) ? filter_input( INPUT_POST, 'canonical', FILTER_SANITIZE_NUMBER_INT ) : 0;
2214                        $settings['general']['rss-feeds'] = isset( $_POST['rss-feeds'] ) ? (int) filter_input( INPUT_POST, 'rss-feeds', FILTER_SANITIZE_NUMBER_INT ) : '';
2215                }
2216
2217                return $settings;
2218        }
2219
2220        /**
2221         * Render a view page.
2222         *
2223         * @param string $name The name of the view.
2224         *
2225         * @return string
2226         * @since   1.3.2
2227         * @access  public
2228         */
2229        private function render_view( $name ) {
2230                $file = null;
2231                switch ( $name ) {
2232                        case 'misc':
2233                                $file = FEEDZY_ABSPATH . '/includes/views/' . $name . '-view.php';
2234                                break;
2235                        case 'wordai':
2236                        case 'spinnerchief':
2237                        case 'amazon-product-advertising':
2238                        case 'openai':
2239                                if ( ! feedzy_is_pro() ) {
2240                                        $file = FEEDZY_ABSPATH . '/includes/views/' . $name . '-view.php';
2241                                } else {
2242                                        $file = apply_filters( 'feedzy_render_view', $file, $name );
2243                                }
2244                                break;
2245                        default:
2246                                $file = apply_filters( 'feedzy_render_view', $file, $name );
2247                                break;
2248                }
2249
2250                if ( ! $file ) {
2251                        return;
2252                }
2253
2254                ob_start();
2255                include $file;
2256
2257                return ob_get_clean();
2258        }
2259
2260        /**
2261         * Renders the HTML for the tags.
2262         *
2263         * @since   1.4.2
2264         * @access  public
2265         */
2266        public function render_magic_tags( $default, $tags, $type ) {
2267                if ( $tags ) {
2268                        $disabled = array();
2269                        foreach ( $tags as $tag => $label ) {
2270                                if ( strpos( $tag, ':disabled' ) !== false ) {
2271                                        $disabled[ str_replace( ':disabled', '', $tag ) ] = $label;
2272                                        continue;
2273                                }
2274                                if ( in_array( $type, array( 'import_post_content', 'import_post_featured_img' ), true ) ) {
2275                                        if ( in_array( $tag, array( 'item_content', 'item_description', 'item_full_content', 'item_categories', 'item_image' ), true ) ) {
2276                                                $default .= '<a class="dropdown-item" href="#" data-field-name="' . $type . '" data-field-tag="' . $tag . '" data-action_popup="' . $tag . '">' . $label . ' <small>[#' . $tag . ']</small></a>';
2277                                                continue;
2278                                        }
2279                                        $default .= '<a class="dropdown-item" href="#" data-field-name="' . $type . '" data-field-tag="' . $tag . '">' . $label . ' <small>[#' . $tag . ']</small></a>';
2280                                        continue;
2281                                }
2282                                $default .= '<a class="dropdown-item" href="#" data-field-name="' . $type . '" data-field-tag="' . $tag . '">' . $label . ' -- <small>[#' . $tag . ']</small></a>';
2283                        }
2284
2285                        if ( $disabled ) {
2286                                foreach ( $disabled as $tag => $label ) {
2287                                        $default .= '<span disabled title="' . __( 'Upgrade your license to use this tag', 'feedzy-rss-feeds' ) . '" class="dropdown-item">' . $label . ' -- <small>[#' . $tag . ']</small></span>';
2288                                }
2289                        }
2290                }
2291
2292                return $default;
2293        }
2294
2295        /**
2296         * Renders the tags for the title.
2297         *
2298         * @param array $default The default tags, empty.
2299         *
2300         * @since   1.4.2
2301         * @access  public
2302         */
2303        public function magic_tags_title( $default ) {
2304                $default['item_title']      = __( 'Item Title', 'feedzy-rss-feeds' );
2305                $default['item_author']     = __( 'Item Author', 'feedzy-rss-feeds' );
2306                $default['item_date']       = __( 'Item Date (UTC/GMT)', 'feedzy-rss-feeds' );
2307                $default['item_date_local'] = __( 'Item Date (local timezone)', 'feedzy-rss-feeds' );
2308                $default['item_date_feed']  = __( 'Item Date (feed timezone)', 'feedzy-rss-feeds' );
2309                $default['item_source']     = __( 'Item Source', 'feedzy-rss-feeds' );
2310
2311                // disabled tags.
2312                if ( ! feedzy_is_pro() ) {
2313                        $default['title_spinnerchief:disabled'] = __( '🚫 Title from SpinnerChief', 'feedzy-rss-feeds' );
2314                        $default['title_wordai:disabled']       = __( '🚫 Title from WordAI', 'feedzy-rss-feeds' );
2315
2316                        $default['translated_title:disabled'] = __( '🚫 Translated Title', 'feedzy-rss-feeds' );
2317
2318                        $default['title_feedzy_rewrite:disabled'] = __( '🚫 Paraphrased Title using Feedzy', 'feedzy-rss-feeds' );
2319
2320                }
2321
2322                return $default;
2323        }
2324
2325        /**
2326         * Renders the tags for the date.
2327         *
2328         * @param array $default The default tags, empty.
2329         *
2330         * @since   1.4.2
2331         * @access  public
2332         */
2333        public function magic_tags_date( $default ) {
2334                $default['item_date'] = __( 'Item Date', 'feedzy-rss-feeds' );
2335                $default['post_date'] = __( 'Post Date', 'feedzy-rss-feeds' );
2336
2337                return $default;
2338        }
2339
2340        /**
2341         * Renders the tags for the content.
2342         *
2343         * @param array $default The default tags, empty.
2344         *
2345         * @since   1.4.2
2346         * @access  public
2347         */
2348        public function magic_tags_content( $default ) {
2349                $default['item_content']     = __( 'Item Content', 'feedzy-rss-feeds' );
2350                $default['item_description'] = __( 'Item Description', 'feedzy-rss-feeds' );
2351                $default['item_image']       = __( 'Item Image', 'feedzy-rss-feeds' );
2352                $default['item_url']         = __( 'Item URL', 'feedzy-rss-feeds' );
2353                $default['item_categories']  = __( 'Item Categories', 'feedzy-rss-feeds' );
2354                $default['item_source']      = __( 'Item Source', 'feedzy-rss-feeds' );
2355
2356                // disabled tags.
2357                if ( ! feedzy_is_pro() ) {
2358                        $default['item_full_content:disabled'] = __( '🚫 Item Full Content', 'feedzy-rss-feeds' );
2359                }
2360
2361                return $default;
2362        }
2363
2364        /**
2365         * Renders the tags for the featured image.
2366         *
2367         * @param array $default The default tags, empty.
2368         *
2369         * @since   1.4.2
2370         * @access  public
2371         */
2372        public function magic_tags_image( $default ) {
2373                $default['item_image'] = __( 'Item Image', 'feedzy-rss-feeds' );
2374
2375                return $default;
2376        }
2377
2378        /**
2379         * Register the meta tags.
2380         *
2381         * @access      public
2382         */
2383        public function wp() {
2384                global $wp_version;
2385
2386                $free_settings = get_option( 'feedzy-settings', array() );
2387                if ( ! isset( $free_settings['canonical'] ) || 1 !== intval( $free_settings['canonical'] ) ) {
2388                        return;
2389                }
2390
2391                // Yoast.
2392                add_filter( 'wpseo_canonical', array( $this, 'get_canonical_url' ) );
2393
2394                // All In One SEO.
2395                add_filter( 'aioseop_canonical_url', array( $this, 'get_canonical_url' ) );
2396
2397                if ( version_compare( $wp_version, '4.6.0', '>=' ) ) {
2398                        // Fallback if none of the above plugins is present.
2399                        add_filter( 'get_canonical_url', array( $this, 'get_canonical_url' ) );
2400                }
2401        }
2402
2403        /**
2404         * Return the canonical URL.
2405         *
2406         * @access      public
2407         */
2408        public function get_canonical_url( $canonical_url ) {
2409                if ( ! is_singular() ) {
2410                        return $canonical_url;
2411                }
2412
2413                global $post;
2414                if ( ! $post ) {
2415                        return $canonical_url;
2416                }
2417
2418                // let's check if the post has been imported by feedzy.
2419                if ( 1 === intval( get_post_meta( $post->ID, 'feedzy', true ) ) ) {
2420                        $url = get_post_meta( $post->ID, 'feedzy_item_url', true );
2421                        if ( ! empty( $url ) ) {
2422                                $canonical_url = $url;
2423                        }
2424                }
2425
2426                return $canonical_url;
2427        }
2428
2429        /**
2430         * Add/remove row actions for each import.
2431         *
2432         * @since   ?
2433         * @access  public
2434         */
2435        public function add_import_actions( $actions, $post ) {
2436                if ( $post->post_type === 'feedzy_imports' ) {
2437                        // don't need quick edit.
2438                        unset( $actions['inline hide-if-no-js'] );
2439
2440                        $actions['feedzy_purge'] = sprintf(
2441                                '<a href="#" class="feedzy-purge" data-id="%d">%2$s</a><span class="feedzy-spinner spinner"></span>',
2442                                $post->ID,
2443                                esc_html( __( 'Purge &amp; Reset', 'feedzy-rss-feeds' ) )
2444                        );
2445                } elseif ( 1 === intval( get_post_meta( $post->ID, 'feedzy', true ) ) ) {
2446                        // show an unclickable action that mentions that it is imported by us
2447                        // so that users are aware
2448                        $feedzy_job_id     = get_post_meta( $post->ID, 'feedzy_job', true );
2449                        $actions['feedzy'] = sprintf( '(%s %s)', __( 'Imported by Feedzy from', 'feedzy-rss-feeds' ), get_the_title( $feedzy_job_id ) );
2450                }
2451
2452                return $actions;
2453        }
2454
2455        /**
2456         * AJAX called method to purge imported items.
2457         *
2458         * @since   ?
2459         * @access  private
2460         */
2461        private function purge_data() {
2462                check_ajax_referer( FEEDZY_BASEFILE, 'security' );
2463
2464                $id                 = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT );
2465                $del_imported_posts = filter_input( INPUT_POST, 'del_imported_posts', FILTER_VALIDATE_BOOLEAN );
2466                $post               = get_post( $id );
2467                if ( 'feedzy_imports' !== $post->post_type ) {
2468                        wp_die();
2469                }
2470
2471                // Delete imported posts.
2472                if ( $del_imported_posts ) {
2473                        $post_types    = get_post_meta( $id, 'import_post_type', true );
2474                        $imported_post = get_posts(
2475                                array(
2476                                        'post_type'      => $post_types,
2477                                        'post_status'    => 'any',
2478                                        'fields'         => 'ids',
2479                                        'meta_key'       => 'feedzy_job', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
2480                                        'meta_value'     => $id, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
2481                                        'meta_compare'   => '=',
2482                                        'posts_per_page' => 999, // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page
2483                                )
2484                        );
2485                        if ( ! empty( $imported_post ) ) {
2486                                foreach ( $imported_post as $post_id ) {
2487                                        wp_delete_post( $post_id, true );
2488                                }
2489                        }
2490                }
2491
2492                delete_post_meta( $id, 'imported_items_hash' );
2493                delete_post_meta( $id, 'imported_items' );
2494                delete_post_meta( $id, 'imported_items_count' );
2495                delete_post_meta( $id, 'import_errors' );
2496                delete_post_meta( $id, 'import_info' );
2497                delete_post_meta( $id, 'last_run' );
2498                wp_die();
2499        }
2500
2501        /**
2502         * Load only those posts that are linked to a particular import job.
2503         *
2504         * @since   ?
2505         * @access  public
2506         */
2507        public function pre_get_posts( $query ) {
2508
2509                if ( ! function_exists( 'wp_verify_nonce' ) || ( ! wp_verify_nonce( filter_input( INPUT_GET, '_nonce', FILTER_UNSAFE_RAW ), 'job_run_linked_posts' ) ) ) {
2510                        return;
2511                }
2512
2513                $feedzy_job_id   = filter_input( INPUT_GET, 'feedzy_job_id', FILTER_SANITIZE_NUMBER_INT );
2514                $feedzy_job_time = filter_input( INPUT_GET, 'feedzy_job_time', FILTER_UNSAFE_RAW );
2515
2516                if ( is_admin() && $query->is_main_query() && ! empty( $feedzy_job_id ) ) {
2517                        $meta_query = array(
2518                                array(
2519                                        'key'   => 'feedzy',
2520                                        'value' => 1,
2521                                ),
2522                                array(
2523                                        'key'   => 'feedzy_job',
2524                                        'value' => $feedzy_job_id,
2525                                ),
2526                        );
2527
2528                        if ( ! empty( $feedzy_job_time ) ) {
2529                                $meta_query[] = array(
2530                                        'key'   => 'feedzy_job_time',
2531                                        'value' => $feedzy_job_time,
2532                                );
2533                        }
2534
2535                        $query->set( 'meta_query', $meta_query );
2536                }
2537        }
2538
2539        /**
2540         * Add iframe to allowed wp_kses_post tags.
2541         *
2542         * @param array  $tags Allowed tags, attributes, and/or entities.
2543         * @param string $context Context.
2544         *
2545         * @return array
2546         */
2547        public function feedzy_wp_kses_allowed_html( $tags, $context ) {
2548                if ( ! isset( $tags['iframe'] ) ) {
2549                        $tags['iframe'] = array(
2550                                'src'             => true,
2551                                'height'          => true,
2552                                'width'           => true,
2553                                'frameborder'     => true,
2554                                'allowfullscreen' => true,
2555                                'data-*'          => true,
2556                        );
2557                }
2558                if ( isset( $tags['span'] ) ) {
2559                        $tags['span']['disabled'] = true;
2560                }
2561
2562                return $tags;
2563        }
2564
2565        /**
2566         * Get post data using meta key and value.
2567         *
2568         * @param string $post_type Post type Default post.
2569         * @param string $key Meta Key.
2570         * @param string $value Meta value.
2571         * @param string $compare Compare operator.
2572         *
2573         * @return mixed
2574         */
2575        public function is_duplicate_post( $post_type = 'post', $key = '', $value = '', $compare = '=' ) {
2576                if ( empty( $key ) || empty( $value ) ) {
2577                        return false;
2578                }
2579                // Check post exists OR Not.
2580                $data = get_posts(
2581                        array(
2582                                'posts_per_page' => 80,
2583                                'post_type'      => $post_type,
2584                                'meta_key'       => $key, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
2585                                'meta_value'     => $value, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
2586                                'meta_compare'   => $compare,
2587                                'fields'         => 'ids',
2588                        )
2589                );
2590
2591                return $data;
2592        }
2593
2594        /**
2595         * Get post data using meta key and value.
2596         *
2597         * @param string $post_type Post type Default post.
2598         * @param int    $post_id Post ID.
2599         * @param string $language_code Selected language code.
2600         */
2601        public function set_wpml_element_language_details( $post_type = 'post', $post_id = 0, $language_code = '' ) {
2602                global $sitepress;
2603                if ( $post_id && ! empty( $language_code ) ) {
2604                        // Get the translation id.
2605                        $trid = $sitepress->get_element_trid( $post_id, 'post_' . $post_type );
2606
2607                        // Update the post language info.
2608                        $language_args = array(
2609                                'element_id'           => $post_id,
2610                                'element_type'         => 'post_' . $post_type,
2611                                'trid'                 => $trid,
2612                                'language_code'        => $language_code,
2613                                'source_language_code' => null,
2614                        );
2615
2616                        do_action( 'wpml_set_element_language_details', $language_args );
2617                }
2618        }
2619
2620        /**
2621         * Fetch custom field by selected post type.
2622         */
2623        public function fetch_custom_fields() {
2624                global $wpdb;
2625
2626                // @codingStandardsIgnoreStart
2627                $post_type  = isset( $_POST['post_type'] ) ? filter_input( INPUT_POST, 'post_type', FILTER_UNSAFE_RAW ) : '';
2628                $search_key = isset( $_POST['search_key'] ) ? filter_input( INPUT_POST, 'search_key', FILTER_UNSAFE_RAW ) : '';
2629                // @codingStandardsIgnoreEnd
2630
2631                $like = '';
2632                if ( ! empty( $search_key ) ) {
2633                        $like = " AND $wpdb->postmeta.meta_key LIKE '%$search_key%'";
2634                }
2635
2636                // phpcs:ignore
2637                $query_result = $wpdb->get_results( $wpdb->prepare( "SELECT DISTINCT($wpdb->postmeta.meta_key) FROM $wpdb->posts LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id WHERE $wpdb->posts.post_type = '%s' AND $wpdb->postmeta.meta_key != '' AND $wpdb->postmeta.meta_key NOT RegExp '(^[_0-9].+$)' AND $wpdb->postmeta.meta_key NOT RegExp '(^[_feedzy].+$)' AND $wpdb->postmeta.meta_key NOT RegExp '(^[0-9]+$)'$like LIMIT 0, 9999", $post_type ), ARRAY_A );
2638
2639                $acf_fields = array();
2640                if ( function_exists( 'acf_get_field_groups' ) ) {
2641                        $groups = acf_get_field_groups( array( 'post_type' => $post_type ) );
2642                        if ( ! empty( $groups ) ) {
2643                                foreach ( $groups as $group ) {
2644                                        $fields = acf_get_fields( $group['key'] );
2645                                        if ( ! empty( $fields ) ) {
2646                                                foreach ( $fields as $field ) {
2647                                                        if ( ! empty( $search_key ) ) {
2648                                                                if ( stripos( $field['name'], $search_key ) !== false ) {
2649                                                                        $acf_fields[] = $field['name'];
2650                                                                }
2651                                                        } else {
2652                                                                $acf_fields[] = $field['name'];
2653                                                        }
2654                                                }
2655                                        }
2656                                }
2657                        }
2658                }
2659                $query_result = is_array( $query_result ) ? $query_result : array();
2660                $query_result = array_column( $query_result, 'meta_key' );
2661                $query_result = array_merge( $acf_fields, $query_result );
2662                $query_result = array_unique( $query_result );
2663
2664                if ( ! empty( $query_result ) ) {
2665                        wp_send_json_success( $query_result );
2666                } else {
2667                        wp_send_json_error(
2668                                array(
2669                                        'not_found_msg' => __( 'No matches found', 'feedzy-rss-feeds' ),
2670                                )
2671                        );
2672                }
2673                wp_die();
2674        }
2675
2676        /**
2677         * Renders the tags for the post excerpt.
2678         *
2679         * @access  public
2680         *
2681         * @param array $default The default tags, empty.
2682         */
2683        public function magic_tags_post_excerpt( $default ) {
2684                $default['item_title']       = __( 'Item Title', 'feedzy-rss-feeds' );
2685                $default['item_content']     = __( 'Item Content', 'feedzy-rss-feeds' );
2686                $default['item_description'] = __( 'Item Description', 'feedzy-rss-feeds' );
2687                // disabled tags.
2688                if ( ! feedzy_is_pro() ) {
2689                        $default['translated_title:disabled']       = __( '🚫 Translated Title', 'feedzy-rss-feeds' );
2690                        $default['translated_content:disabled']     = __( '🚫 Translated Content', 'feedzy-rss-feeds' );
2691                        $default['translated_description:disabled'] = __( '🚫 Translated Description', 'feedzy-rss-feeds' );
2692                }
2693
2694                return $default;
2695        }
2696
2697        /**
2698         * Check feedzy rewrite content tool enabled or not.
2699         *
2700         * @return bool
2701         */
2702        private function rewrite_content_service_endabled() {
2703                // Check license type.
2704                if ( $this->feedzy_is_business() || $this->feedzy_is_agency() ) {
2705                        return true;
2706                }
2707
2708                return false;
2709        }
2710
2711        /**
2712         * Clone import job.
2713         */
2714        public function feedzy_clone_import_job() {
2715                // Check if import job ID has been provided and action.
2716                if ( empty( $_GET['feedzy_job_id'] ) ) {
2717                        wp_die( esc_html__( 'No post to duplicate has been provided!', 'feedzy-rss-feeds' ) );
2718                }
2719
2720                // Nonce verification.
2721                if ( ! isset( $_GET['clone_import'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_GET['clone_import'] ) ), FEEDZY_BASENAME ) ) {
2722                        return;
2723                }
2724
2725                // Get the original import job ID.
2726                $feedzy_job_id = absint( $_GET['feedzy_job_id'] );
2727                // Get the original import job.
2728                $feedzy_job = get_post( $feedzy_job_id );
2729
2730                if ( $feedzy_job ) {
2731                        $current_user    = wp_get_current_user();
2732                        $new_post_author = $current_user->ID;
2733
2734                        // new post data array
2735                        $args = array(
2736                                'post_author' => $new_post_author,
2737                                'post_status' => 'draft',
2738                                'post_title'  => $feedzy_job->post_title,
2739                                'post_type'   => $feedzy_job->post_type,
2740                        );
2741
2742                        // insert the new import job by wp_insert_post() function.
2743                        $new_post_id = wp_insert_post( $args );
2744                        // Get all post meta.
2745                        $post_meta = get_post_meta( $feedzy_job_id );
2746                        // Exclude metakey.
2747                        $blacklist_metakey = array(
2748                                'import_errors',
2749                                'import_info',
2750                                '_edit_lock',
2751                                'last_run_id',
2752                                'last_run',
2753                                'imported_items_hash',
2754                                'imported_items_count',
2755                        );
2756
2757                        if ( $post_meta ) {
2758                                foreach ( $post_meta as $meta_key => $meta_values ) {
2759                                        if ( in_array( $meta_key, $blacklist_metakey, true ) ) {
2760                                                continue;
2761                                        }
2762                                        foreach ( $meta_values as $meta_value ) {
2763                                                add_post_meta( $new_post_id, $meta_key, $meta_value );
2764                                        }
2765                                }
2766                        }
2767
2768                        wp_safe_redirect(
2769                                add_query_arg(
2770                                        array(
2771                                                'post_type' => ( 'post' !== get_post_type( $feedzy_job ) ? get_post_type( $feedzy_job ) : false ),
2772                                                'saved'     => 'fz_duplicate_import_job_created',
2773                                        ),
2774                                        admin_url( 'edit.php' )
2775                                )
2776                        );
2777                        exit;
2778                } else {
2779                        wp_die( esc_html__( 'Post creation failed, could not find original post.', 'feedzy-rss-feeds' ) );
2780                }
2781        }
2782
2783        /**
2784         * Display import job clone notice.
2785         */
2786        public function feedzy_import_clone_success_notice() {
2787                // Get the current screen.
2788                $screen = get_current_screen();
2789
2790                if ( 'edit' !== $screen->base ) {
2791                        return;
2792                }
2793
2794                // Display success notice if clone succeed.
2795                if ( isset( $_GET['saved'] ) && 'fz_duplicate_import_job_created' === $_GET['saved'] ) { // phpcs:ignore WordPress.Security.NonceVerification
2796                        ?>
2797<div class="notice notice-success is-dismissible">
2798        <p><?php esc_html_e( 'Duplicate import job created', 'feedzy-rss-feeds' ); ?></p>
2799</div>
2800                        <?php
2801                }
2802        }
2803
2804        /**
2805         * Trim tags.
2806         *
2807         * @param string $content Field value.
2808         *
2809         * @return string
2810         */
2811        public function feedzy_import_trim_tags( $content = '' ) {
2812                if ( ! empty( $content ) && is_string( $content ) ) {
2813                        $content = explode( ',', $content );
2814                        $content = array_map( 'trim', $content );
2815                        $content = implode( ' ', $content );
2816                }
2817
2818                return $content;
2819        }
2820
2821        /**
2822         * Run a wizard import feed.
2823         */
2824        private function wizard_import_feed() {
2825                check_ajax_referer( FEEDZY_BASEFILE, 'security' );
2826
2827                $post_type   = ! empty( $_POST['post_type'] ) ? filter_input( INPUT_POST, 'post_type', FILTER_UNSAFE_RAW ) : '';
2828                $wizard_data = get_option( 'feedzy_wizard_data', array() );
2829                $wizard_data = ! empty( $wizard_data ) ? $wizard_data : array();
2830                $wizard_data['post_type'] = $post_type;
2831
2832                $post_title = __( 'Setup Wizard', 'feedzy-rss-feeds' );
2833                $job_id     = post_exists( $post_title, '', '', 'feedzy_imports' );
2834
2835                $response = array(
2836                        'status' => 0,
2837                );
2838
2839                // Delete previous meta data.
2840                if ( $job_id ) {
2841                        $meta = get_post_meta( $job_id );
2842                        foreach ( $meta as $key => $value ) {
2843                                delete_post_meta( $job_id, $key );
2844                        }
2845                }
2846
2847                // Create new import job.
2848                if ( ! $job_id ) {
2849                        $job_id = wp_insert_post(
2850                                array(
2851                                        'post_title' => $post_title,
2852                                        'post_type' => 'feedzy_imports',
2853                                        'post_status' => 'publish',
2854                                )
2855                        );
2856                }
2857
2858                if ( ! is_wp_error( $job_id ) ) {
2859                        update_post_meta( $job_id, 'source', $wizard_data['feed'] );
2860                        update_post_meta( $job_id, 'import_post_title', '[#item_title]' );
2861                        update_post_meta( $job_id, 'import_post_date', '[#item_date]' );
2862                        update_post_meta( $job_id, 'import_post_content', '[#item_content]' );
2863                        update_post_meta( $job_id, 'import_post_content', '[#item_content]' );
2864                        update_post_meta( $job_id, 'import_post_type', $post_type );
2865                        update_post_meta( $job_id, 'import_post_status', 'publish' );
2866                        update_post_meta( $job_id, 'import_post_featured_img', '[#item_image]' );
2867
2868                        // Update wizard data.
2869                        update_option( 'feedzy_wizard_data', $wizard_data );
2870
2871                        $job   = get_post( $job_id );
2872                        $count = $this->run_job( $job, 10 );
2873                        do_action( 'feedzy_run_cron_extra', $job );
2874                        $response = array(
2875                                'status' => $count > 0,
2876                        );
2877                }
2878                wp_send_json( $response );
2879        }
2880
2881        /**
2882         * Handle item content actions.
2883         *
2884         * @param string $actions Item content actions.
2885         * @param string $type Action type.
2886         * @return object `Feedzy_Rss_Feeds_Actions` class instance.
2887         */
2888        public function handle_content_actions( $actions = '', $type = '' ) {
2889                $action_instance       = Feedzy_Rss_Feeds_Actions::instance();
2890                $action_instance->type = $type;
2891                $action_instance->set_actions( $actions );
2892                $action_instance->set_settings( $this->settings );
2893                return $action_instance;
2894        }
2895}
Note: See TracBrowser for help on using the repository browser.