r full refresh. * For ongoing changes, event-driven hooks handle individual review updates. * * @see documentation/WOOCOMMERCE_EVENT_DRIVEN_CACHE_ARCHITECTURE.md * * @since 2.3.0 */ private static function reset_bulk_update_states(): void { // Google + Yelp: drop the per-source bulk-history state so the source // list warning clears, then reschedule bulk-history for any provider // with an API key configured. Same gating as BulkHistoryRoutine — keyless // customers stay keyless, but they no longer see a permanent warning // rooted in a stale option (regression-pin: pre-fix Bulk_Reviews_Update // could leave entries at {retry: true, is_done: false} indefinitely with // no UI path to clear them). if (Util::sbr_is_pro() && class_exists(Bulk_Reviews_Update::class)) { delete_option('sbr_bulk_sources'); // Clear any in-flight bulk-cron events before rescheduling so a // repeated "Clear All Caches" click doesn't enqueue a backlog. // schedule_task uses wp_schedule_single_event which dedupes within // 10 minutes for identical args, but Clear All Caches is on a manual // click cadence — defensive cleanup is the safer contract. if (function_exists('wp_clear_scheduled_hook')) { wp_clear_scheduled_hook('sbr_reviews_bulk_cron'); } Bulk_Reviews_Update::schedule_needed_sources_history(); } // External providers (Airbnb, Booking, AliExpress): Reset and schedule background fetch if (Util::sbr_is_pro() && class_exists(Bulk_External_Reviews_Update::class)) { Bulk_External_Reviews_Update::reset_all_sources(true); } // WooCommerce: Resync all reviews from wp_comments table // This provides users a way to force a full refresh if needed if (Util::sbr_is_pro() && class_exists(Bulk_WooCommerce_Reviews_Update::class)) { Bulk_WooCommerce_Reviews_Update::reset_all_sources(true); } } /** * Clear All Plugin Caches * * @return void * * @since 1.0 */ public static function clear_plugin_cache() { global $wpdb; $cache_table_name = $wpdb->prefix . 'sbr_feed_caches'; $sql = " UPDATE $cache_table_name SET cache_value = '' WHERE cache_key NOT IN ('posts_backup', 'header_backup');"; $wpdb->query($sql); $posts_table_name = $wpdb->prefix . 'sbr_reviews_posts'; $sql_posts = " UPDATE $posts_table_name SET images_done = 0"; $wpdb->query($sql_posts); $table_name = $wpdb->prefix . "options"; $wpdb->query(" DELETE FROM $table_name WHERE `option_name` LIKE ('%\_transient\_sbr\_%') "); $wpdb->query(" DELETE FROM $table_name WHERE `option_name` LIKE ('%\_transient\_sbr\_ej\_%') "); $wpdb->query(" DELETE FROM $table_name WHERE `option_name` LIKE ('%\_transient\_sbr\_tle\_%') "); $wpdb->query(" DELETE FROM $table_name WHERE `option_name` LIKE ('%\_transient\_sbr\_album\_%') "); $wpdb->query(" DELETE FROM $table_name WHERE `option_name` LIKE ('%\_transient\_timeout\_sbr\_%') "); self::flush_third_party_caches(); } /** * Purge known 3rd-party page-cache plugins (WP Rocket, W3TC, LiteSpeed, etc). * * Called twice per Clear-All-Caches cycle: * 1. Inside clear_plugin_cache() — clears stale HTML right after the feed * cache is emptied. * 2. After the async cron refresh completes (via `sbr_after_cron_refresh` * handler in register()) — re-flushes so page caches that rebaked the * empty-feed render during the 5-30s warm-up window are evicted and * the next visitor gets a fresh render off the now-warm feed cache. * * @since 2.5.6 */ public static function flush_third_party_caches(): void { // Clear cache of major caching plugins. if (isset($GLOBALS['wp_fastest_cache']) && method_exists($GLOBALS['wp_fastest_cache'], 'deleteCache')) { $GLOBALS['wp_fastest_cache']->deleteCache(); } // WP Super Cache. if (function_exists('wp_cache_clear_cache')) { wp_cache_clear_cache(); } // W3 Total Cache. if (function_exists('w3tc_flush_all')) { w3tc_flush_all(); } if (function_exists('sg_cachepress_purge_cache')) { sg_cachepress_purge_cache(); } if (class_exists('W3_Plugin_TotalCacheAdmin')) { $plugin_totalcacheadmin = & w3_instance('W3_Plugin_TotalCacheAdmin'); $plugin_totalcacheadmin->flush_all(); } if (function_exists('rocket_clean_domain')) { rocket_clean_domain(); } if (has_action('litespeed_purge_all')) { do_action('litespeed_purge_all'); } } public static function sanitize_settings($raw_settings) { $sanitized_values = array(); foreach ($raw_settings as $key => $value) { if (is_bool($value)) { // already a safe value $sanitized_values[$key] = $value; } elseif (is_int($value)) { // already a safe value $sanitized_values[$key] = $value; } elseif (is_array($value)) { if (empty($value)) { $sanitized_values[$key] = array(); } else { foreach ($value as $key2 => $item) { if (is_bool($item)) { // already a safe value $sanitized_values[$key][$key2] = $item; } elseif (is_int($item)) { // already a safe value $sanitized_values[$key][$key2] = $item; } else { $sanitized_values[$key][$key2] = sanitize_text_field($item); } } } } else { $sanitized_values[$key] = sanitize_text_field($value); } } return $sanitized_values; } /** * Get a list of feeds with a limit and offset like a page * * @since 1.1 */ public static function get_feed_list_page() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } $args = array( 'page' => isset($_POST['page']) ? (int) sanitize_text_field(wp_unslash($_POST['page'])) : 1 ); // Add search parameter if provided if (!empty($_POST['search'])) { $args['search'] = sanitize_text_field(wp_unslash($_POST['search'])); } $feeds_data = DB::get_feeds_list($args); $total_count = DB::feeds_list_count($args); $per_page = DB::RESULTS_PER_PAGE; echo wp_json_encode([ 'feeds' => $feeds_data, 'total' => $total_count, 'page' => $args['page'], 'perPage' => $per_page, 'totalPages' => ceil($total_count / $per_page) ]); wp_die(); } /** * Cache Single Posts form Posts List * * @since 1..1 */ public static function cache_single_posts_from_set($posts, $provider) { $settings = wp_parse_args(get_option('sbr_settings', []), sbr_plugin_settings_defaults()); $lang = $settings['localization']; $providers_no_media = sbr_get_no_media_providers(); $providers_lang = sbr_get_lang_providers(); foreach ($posts as $single_review) { self::cache_single_review( $single_review, $provider, $lang, $providers_no_media, $providers_lang ); } } public static function cache_single_review( $single_review, $provider, $lang, $providers_no_media, $providers_lang ) { // Decode HTML entities in review text and reviewer name (fixes Danish characters, emojis, etc.) if (isset($single_review['text'])) { $single_review['text'] = html_entity_decode($single_review['text'], ENT_QUOTES | ENT_HTML5, 'UTF-8'); } if (isset($single_review['reviewer']['name'])) { $single_review['reviewer']['name'] = html_entity_decode($single_review['reviewer']['name'], ENT_QUOTES | ENT_HTML5, 'UTF-8'); } $single_review['source'] = $provider; $single_post_cache = Util::sbr_is_pro() ? new \SmashBalloon\Reviews\Pro\SinglePostCache($single_review, new \SmashBalloon\Reviews\Pro\MediaFinder($single_review['source'])) : new \SmashBalloon\Reviews\Common\SinglePostCache($single_review); $single_post_cache->set_provider_id($provider['id']); if (in_array($provider['provider'], $providers_lang, true)) { $single_post_cache->set_lang($lang); } if ( Util::sbr_is_pro() && method_exists($single_post_cache, 'check_api_media') ) { $single_post_cache->check_api_media(); } if (! $single_post_cache->db_record_exists()) { $single_post_cache->resize_avatar(150); if (in_array($provider['provider'], $providers_no_media, true)) { $single_post_cache->set_storage_data('images_done', 1); } $single_post_cache->store(); } else { $single_post_cache->update_single(); } } /** * Create Or Update Collection Review * * @since 1.3 */ public static function create_new_collection() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if (isset($_POST['collection_name']) && !empty($_POST['collection_name'])) { $id = 'collection-' . time() . wp_rand(); $collection_name = sanitize_text_field($_POST['collection_name']); $collection_info = [ 'id' => $id, 'account_id' => $id, 'name' => $collection_name, 'provider' => 'collection', 'rating' => 0, 'total_rating' => 0, ]; SBR_Sources::update_or_insert($collection_info); $collection_info['info'] = $collection_info; echo sbr_json_encode( [ 'newCollection' => $collection_info, 'sourcesCount' => SBR_Sources::get_sources_count(), 'sourcesList' => SBR_Sources::get_sources_list() ] ); } wp_die(); } /** * Create Or Update Collection Review * * @since 1.3 */ public static function create_update_collection_review() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } $review = json_decode(stripslashes($_POST['reviewContent']), true); if (!isset($review['provider_id']) || empty($review['provider_id'])) { wp_send_json_error( [ "message" => __("Please make sure the collection exists", "reviews-feed") ] ); } $is_duplicate = isset($_POST['is_duplicate']) && $_POST['is_duplicate']; $is_new = (isset($review['new']) && $review['new'] === true) || $is_duplicate; $provider_id = sanitize_text_field($review['provider_id']); $page_number = absint($_POST['page_number']); $review_id = $is_new ? $provider_id . time() . wp_rand() : sanitize_text_field($review['review_id']); $time = isset($review['time']) ? sanitize_text_field($review['time']) : ''; $sanitized_review = [ 'time' => empty($time) ? time() : (($is_new && !$is_duplicate) || !is_numeric($time) ? strtotime($time) : $time), 'rating' => absint($review['rating']), 'provider_id' => $provider_id, 'review_id' => $review_id, 'text' => sanitize_text_field($review['text']), 'title' => sanitize_text_field($review['title']), 'reviewer' => [ 'name' => sanitize_text_field($review['reviewer']['first_name']) . ' ' . sanitize_text_field($review['reviewer']['last_name']), 'first_name' => sanitize_text_field($review['reviewer']['first_name']), 'last_name' => sanitize_text_field($review['reviewer']['last_name']), 'avatar' => sanitize_text_field($review['reviewer']['avatar']) ], 'provider' => [ 'name' => sanitize_text_field($review['provider']['name']) ], 'source' => [ 'id' => $provider_id, 'url' => sanitize_text_field($review['source']['url']) ] ]; if (isset($review['media']) && is_array($review['media'])) { $sanitized_review['media'] = $review['media']; } //JSON Data $sanitized_review['json_data'] = $sanitized_review; $single_post_cache = new \SmashBalloon\Reviews\Pro\SinglePostCache($sanitized_review, new \SmashBalloon\Reviews\Pro\MediaFinder($sanitized_review['source'])); $single_post_cache->set_provider_id($provider_id); if ($is_new) { $single_post_cache->store(); } else { $single_post_cache->update_single(); } if (isset($sanitized_review['media']) && Util::should_store_local_images()) { $aggregator = new PostAggregator(); $single_post_cache->resize_images(array(640, 150)); $single_post_data = $single_post_cache->get_post_data(); $single_post_storage_data = $single_post_cache->get_storage_data(); $single_post_data = $aggregator->add_local_image_urls($single_post_data, $single_post_storage_data); $single_post_cache->update( [ array('images_done', 1, '%d'), array('json_data', wp_json_encode($single_post_data), '%s') ] ); } SBR_Sources::update_collection_ratings($provider_id); echo sbr_json_encode( [ 'postsList' => PostAggregator::get_source_posts_list($provider_id, $page_number) ] ); wp_die(); } /** * Update Collection Name * * @since 1.3 */ public static function update_collection_name() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if ( isset($_POST['id'], $_POST['collection_name'], $_POST['provider_id'], $_POST['provider']) && !empty($_POST['collection_name']) && !empty($_POST['provider_id']) && !empty($_POST['provider']) && !empty($_POST['id']) ) { $id = sanitize_text_field($_POST['id']); $provider = sanitize_text_field($_POST['provider']); $provider_id = sanitize_text_field($_POST['provider_id']); $collection_name = sanitize_text_field($_POST['collection_name']); $collection_info_search = [ 'id' => $provider_id, 'provider' => $provider ]; $db = new DB(); $results = $db->get_single_source($collection_info_search); if (sizeof($results) === 0) { wp_send_json_error( [ "message" => __("Please make sure the collection exists", "reviews-feed") ] ); } $collection_db = $results[0]; $collection_db['name'] = $collection_name; /** @phpstan-ignore-next-line info key exists in database results */ unset($collection_db['info']); $collection_db['last_updated'] = date('Y-m-d H:i:s'); $collection_db['id'] = $provider_id; $collection_db['info'] = wp_json_encode($collection_db); SBR_Sources::update($collection_db); echo sbr_json_encode( [ 'newCollectionData' => $collection_db, 'sourcesCount' => SBR_Sources::get_sources_count(), 'sourcesList' => SBR_Sources::get_sources_list() ] ); } wp_die(); } /** * Update Source Provider Posts List * * @since 1.4 */ public static function get_source_posts() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if ( isset($_POST['provider_id'], $_POST['provider'], $_POST['page_number']) && !empty($_POST['provider_id']) && !empty($_POST['provider']) && !empty($_POST['page_number']) ) { $provider = sanitize_text_field($_POST['provider']); $provider_id = sanitize_text_field($_POST['provider_id']); $page_number = absint($_POST['page_number']); echo sbr_json_encode( [ 'postsList' => PostAggregator::get_source_posts_list($provider_id, $page_number) ] ); } wp_die(); } /** * Delete Review from a Collection * * @since 1.4 */ public static function delete_review_from_collection() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if ( isset($_POST['review_id'], $_POST['provider_id'], $_POST['provider'], $_POST['page_number']) && !empty($_POST['review_id']) && !empty($_POST['provider_id']) && !empty($_POST['provider']) && !empty($_POST['page_number']) ) { $provider = sanitize_text_field($_POST['provider']); $review_id = sanitize_text_field($_POST['review_id']); $provider_id = sanitize_text_field($_POST['provider_id']); $page_number = absint($_POST['page_number']); PostAggregator::delete_review($provider_id, $review_id, $provider); SBR_Sources::update_collection_ratings($provider_id); echo sbr_json_encode( [ 'postsList' => PostAggregator::get_source_posts_list($provider_id, $page_number) ] ); } wp_die(); } /** * Add Multiple Selected Reviews to a Collection * * @since 1.4 */ public static function add_multiple_reviews_collection() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if ( isset($_POST['provider_id'], $_POST['selected_reviews']) && !empty($_POST['provider_id']) && !empty($_POST['selected_reviews']) ) { $provider_id = sanitize_text_field($_POST['provider_id']); $selected_reviews = json_decode(stripslashes($_POST['selected_reviews'])); PostAggregator::insert_multiple_reviews($provider_id, $selected_reviews); echo sbr_json_encode( [ 'postsList' => PostAggregator::get_source_posts_list($provider_id, 1) ] ); wp_die(); } } /** * Advanced Reviews Search * * @since 1.4 */ public static function advanced_search_reviews() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if ( isset($_POST['provider_id'], $_POST['search_text']) && !empty($_POST['provider_id']) && !empty($_POST['search_text']) ) { $provider_id = sanitize_text_field($_POST['provider_id']); $search_text = sanitize_text_field($_POST['search_text']); echo sbr_json_encode( [ 'postsList' => PostAggregator::search_source_posts_list($provider_id, $search_text) ] ); wp_die(); } } /** * Duplicate Collection * * @since 1.4 */ public static function duplicate_collection() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if (!empty($_POST['collection_id'])) { $collection_id = sanitize_text_field($_POST['collection_id']); $db = new DB(); $args = [ 'id' => $collection_id, 'provider' => 'collection' ]; $results = $db->get_single_source($args); if (!isset($results[0])) { wp_send_json_error( [ 'message' => __('Cannot duplicate Collection, something went wrong!', 'reviews-feed') ] ); } $collection = $results[0]; $collection_info = json_decode($collection['info'], true); $id = 'collection-' . time() . wp_rand(); $collection_insert = [ 'id' => $id, 'account_id' => $id, 'name' => $collection['name'] . ' (copy)', 'provider' => 'collection', 'rating' => $collection_info['rating'], 'total_rating' => $collection_info['total_rating'] ]; SBR_Sources::update_or_insert($collection_insert); $collection_reviews = PostAggregator::get_source_all_posts($collection_id); foreach ($collection_reviews as $s_review) { $review_json = json_decode($s_review['json_data'], true); $review_id = $id . time() . wp_rand(); $sanitized_review = [ 'time' => absint($review_json['time']), 'rating' => absint($review_json['rating']), 'provider_id' => $id, 'review_id' => $review_id, 'text' => sanitize_text_field($review_json['text']), 'title' => sanitize_text_field($review_json['title']), 'reviewer' => [ 'name' => sanitize_text_field($review_json['reviewer']['name']), 'first_name' => isset($review_json['reviewer']['first_name']) ? sanitize_text_field($review_json['reviewer']['first_name']) : '', 'last_name' => isset($review_json['reviewer']['last_name']) ? sanitize_text_field($review_json['reviewer']['last_name']) : '', 'avatar' => sanitize_text_field($review_json['reviewer']['avatar']) ], 'provider' => [ 'name' => sanitize_text_field($review_json['provider']['name']) ], 'source' => [ 'id' => $id, 'url' => sanitize_text_field($review_json['source']['url']) ] ]; if (isset($review['media']) && is_array($review_json['media'])) { $sanitized_review['media'] = $review_json['media']; } //JSON Data $sanitized_review['json_data'] = $sanitized_review; $single_post_cache = new \SmashBalloon\Reviews\Pro\SinglePostCache($sanitized_review, new \SmashBalloon\Reviews\Pro\MediaFinder($sanitized_review['source'])); $single_post_cache->set_provider_id($id); $single_post_cache->store(); /** @phpstan-ignore-next-line media key may or may not exist depending on review data */ if (isset($sanitized_review['media']) && Util::should_store_local_images()) { $aggregator = new PostAggregator(); $single_post_cache->resize_images(array(640, 150)); $single_post_data = $single_post_cache->get_post_data(); $single_post_storage_data = $single_post_cache->get_storage_data(); $single_post_data = $aggregator->add_local_image_urls($single_post_data, $single_post_storage_data); $single_post_cache->update( [ array('images_done', 1, '%d'), array('json_data', wp_json_encode($single_post_data), '%s') ] ); } } echo sbr_json_encode( [ 'sourcesCount' => SBR_Sources::get_sources_count(), 'sourcesList' => SBR_Sources::get_sources_list() ] ); wp_die(); } } /** * Load More Sources * * @since 1.4 */ public static function load_more_sources() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } $args = array( 'page' => isset($_POST['sources_page']) ? absint($_POST['sources_page']) : 1 ); // Add search parameter if provided if (!empty($_POST['search'])) { $args['search'] = sanitize_text_field(wp_unslash($_POST['search'])); } $sources_list = SBR_Sources::get_sources_list($args); $total_count = SBR_Sources::get_sources_count($args); $per_page = DB::SOURCES_PER_PAGE; echo sbr_json_encode([ 'sourcesList' => $sources_list, 'sourcesCount' => $total_count, 'page' => $args['page'], 'perPage' => $per_page, 'totalPages' => ceil($total_count / $per_page) ]); wp_die(); } /** * Export Single Collection Reviews * * @since 1.4 */ public static function export_collection() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if (!empty($_POST['collection_id'])) { $collection_id = sanitize_text_field($_POST['collection_id']); $collection_data = DB::get_collections_reviews($collection_id); //Will Return Collection Data + The Reviews List echo sbr_json_encode( [ 'collection' => $collection_data ] ); } wp_die(); } /** * IMport Full Collection Data * * * @since 1.0 */ public static function import_full_collection() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } $collection_json = self::parse_collection_json(); $info = json_decode($collection_json['info'], true); if (!empty($info)) { $collection_info = [ 'id' => sanitize_text_field($collection_json['account_id']), 'account_id' => sanitize_text_field($collection_json['account_id']), 'name' => sanitize_text_field($collection_json['name']), 'provider' => 'collection', 'rating' => absint($info['rating']), 'total_rating' => absint($info['total_rating']), ]; SBR_Sources::update_or_insert($collection_info); foreach ($collection_json['reviewsList'] as $single_review) { unset($single_review['id']); $single_review = json_decode($single_review['json_data'], true); if (!empty($single_review)) { $review_store = Util::parse_single_review($single_review, $collection_json['account_id'], $single_review['review_id']); $review_store['json_data'] = $review_store; $single_post_cache = new \SmashBalloon\Reviews\Pro\SinglePostCache($review_store, new \SmashBalloon\Reviews\Pro\MediaFinder($review_store['source'])); $single_post_cache->set_provider_id($collection_json['account_id']); $single_post_cache->store(); } } } echo sbr_json_encode( [ 'message' => __("Collection imported successfully", "reviews-feed") ] ); wp_die(); } /** * Import Only reviews to Collection * * * @since 1.0 */ public static function import_reviews_collection() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if (!empty($_POST['collection_id'])) { $collection_json = self::parse_collection_json(); $collection_id = sanitize_text_field($_POST['collection_id']); foreach ($collection_json['reviewsList'] as $single_review) { unset($single_review['id']); $single_review = json_decode($single_review['json_data'], true); if (!empty($single_review)) { $single_review['review_id'] = $collection_id . time() . wp_rand(); $single_review['retimeview_id'] = time(); $review_store = Util::parse_single_review($single_review, $collection_id, $single_review['review_id']); $review_store['json_data'] = $review_store; $single_post_cache = new \SmashBalloon\Reviews\Pro\SinglePostCache($review_store, new \SmashBalloon\Reviews\Pro\MediaFinder($review_store['source'])); $single_post_cache->set_provider_id($collection_id); $single_post_cache->store(); if (isset($sanitized_review['media']) && Util::should_store_local_images()) { $aggregator = new PostAggregator(); $single_post_cache->resize_images(array(640, 150)); $single_post_data = $single_post_cache->get_post_data(); $single_post_storage_data = $single_post_cache->get_storage_data(); $single_post_data = $aggregator->add_local_image_urls($single_post_data, $single_post_storage_data); $single_post_cache->update( [ array('images_done', 1, '%d'), array('json_data', wp_json_encode($single_post_data), '%s') ] ); } } } SBR_Sources::update_collection_ratings($collection_id); echo sbr_json_encode( [ 'postsList' => PostAggregator::get_source_posts_list($collection_id, 1) ] ); } wp_die(); } /** * Parse Collections JSON file * * * @since 1.0 */ public static function parse_collection_json() { check_ajax_referer('sbr-admin', 'nonce'); if (!sbr_current_user_can('manage_reviews_feed_options')) { wp_send_json_error(); } if (empty($_FILES['feedFile'])) { wp_send_json_error( [ 'message' => __('JSON file needed. Your file is not in the correct format.', 'reviews-feed') ] ); } $filename = $_FILES['feedFile']['name']; $ext = pathinfo($filename, PATHINFO_EXTENSION); if ('json' !== $ext) { wp_send_json_error( [ 'message' => __('JSON file needed. Your file is not in the correct format.', 'reviews-feed') ] ); } $imported_file = file_get_contents($_FILES['feedFile']['tmp_name']); if (empty($imported_file)) { wp_send_json_error( [ "message" => __("JSON file needed. Your file is not in the correct format.", "reviews-feed") ] ); } $collection_json = json_decode($imported_file, true); if (empty($collection_json['reviewsList'])) { wp_send_json_error( [ "message" => __("Something went wrong. This doesn't look like a collections import file.", "reviews-feed") ] ); } return $collection_json; } }