/** * Process a new post * * Insert the post into WP, then if successful, * insert the posts meta and terms. * * @param Types\Post $post The post for processing. * @param int $site_id The id of the site being processed. * @param obj $client The syndication client class instance. * * @return int $post_id The ID of the newly inserted post, or false if processing skipped. */ public function process_post(Types\Post $post, $site_id, $client) { global $settings_manager; // @todo hooks // @todo Validate the post. // @todo Bail if post exists and in-progress marker is set. // @todo Mark post as in-progress (if post exists). /** * Filter a post before it is processed for insert/update. * * @param Types\Post $post The post being processing. * * @todo Consider adding $site_id, $slient, $client_transport_type for context. */ $post = apply_filters('syn_before_insert_post', $post); $syndicated_guid = $post->post_data['post_guid']; /** * Filter the $post id retrieved when locating by guid. * * Enabled altering the post id that will be tied to a specific pulled post update. Return a post * id to force updated to happen to that post, return falsde to leave update behavior unchanged. * * @param string $syndicated_guid The post's guid. * @param Types\Post $post The post for processing. * @param int $site_id The id of the site being processed. */ $filtered_post_id = apply_filters('syn_pre_find_post_by_guid', false, $syndicated_guid, $post, $site_id); // Query for posts with a matching syndicated_guid $query_args = array('meta_key' => 'syn_post_guid', 'meta_value' => $syndicated_guid, 'post_status' => 'any', 'post_per_page' => 1); $existing_post_query = new \WP_Query($query_args); // Get the client transport type, passed to some hooks. $client_transport_type = get_post_meta($site_id, 'syn_transport_type', true); // If the post has already been consumed, update it; otherwise insert it. if ($existing_post_query->have_posts() || $filtered_post_id) { // Update existing posts? if ('on' !== $settings_manager->get_setting('update_pulled_posts')) { Syndication_Logger::log_post_info($site_id, $status = 'skip_update_pulled_posts', $message = sprintf(__('skipping post update per update_pulled_posts setting', 'push-syndication')), $log_time = null, $extra = array('post' => $post)); return false; } if (false === $filtered_post_id) { // Existing post, set the post ID for update. $existing_post_query->the_post(); $post->post_data['ID'] = get_the_ID(); } else { $post->post_data['ID'] = $syndicated_guid; } /** * Filter to short circuit the processing of a pulled post update (edit). * * Return true to short circuit the processing of this post update. * * @param bool $edit_shortcircuit Whether to short-circuit the updating of a post. * @param int $site_id The id of the site being processed. * @param string $transport_type The client transport type. * @param obj $client The syndication client class instance. */ $edit_shortcircuit = apply_filters('syn_pre_pull_edit_post_shortcircuit', false, $post, $site_id, $transport_type, $client); if (true === $pull_new_shortcircuit) { Syndication_Logger::log_post_info($site_id, $status = 'syn_pre_pull_edit_post_shortcircuit', $message = sprintf(__('skipping post per syn_pre_pull_edit_post_shortcircuit', 'push-syndication')), $log_time = null, $extra = array('post' => $post)); return false; } // Maintain the post's status. $post->post_data['post_status'] = get_post_status(); /** * Filter the post data, just before updating a post during pull post processing. * * Enables adjusting the data used to update a post. * * @param Types\Post $post The Post object containing the post update data. * @param int $site_id The id of the site being processed. * @param obj $client The syndication client class instance. */ $post = apply_filters('syn_pull_edit_post', $post, $site_id, $client); // Update the existing post. $post_id = wp_update_post($post->post_data, true); /** * Fires just after updating a post during pull post processing. * * @param int $post_id The result of `wp_update_post` (0 if update failed, otherwise post id). * @param Types\Post $post The Post object containing the post update data. * @param int $site_id The id of the site being processed. * @param string $transport_type The client transport type. * @param obj $client The syndication client class instance. */ do_action('syn_post_pull_edit_post', $post_id, $post, $site_id, $transport_type, $client); } else { /** * Filter to short circuit the processing of a pulled post insert. * * Return true to short circuit the processing of this post insert. * * @param bool $insert_shortcircuit Whether to short-circuit the inserting of a post. * @param int $site_id The id of the site being processed. * @param string $transport_type The client transport type. * @param obj $client The syndication client class instance. */ $insert_shortcircuit = apply_filters('syn_pre_pull_new_post_shortcircuit', false, $post, $site_id, $transport_type, $client); if (true === $pull_new_shortcircuit) { Syndication_Logger::log_post_info($site_id, $status = 'syn_pre_pull_edit_post_shortcircuit', $message = sprintf(__('skipping post per syn_pre_pull_new_post_shortcircuit', 'push-syndication')), $log_time = null, $extra = array('post' => $post)); return false; } // Include the syndicated_guid so we can update this post later. $post->post_meta['syn_post_guid'] = $post->post_data['post_guid']; /** * Filter the post data, just before inserting a new post during pull post processing. * * Enables adjusting the data used to insert a new post. * * @param Types\Post $post The Post object containing the post insert data. * @param int $site_id The id of the site being processed. * @param obj $client The syndication client class instance. */ $post = apply_filters('syn_pull_new_post', $post, $site_id, $client); // The post is new, insert it. $post_id = wp_insert_post($post->post_data, true); /** * Fires just after inserting a new post during pull post processing. * * @param int $post_id The result of `wp_update_post` (0 if update failed, otherwise post id). * @param Types\Post $post The Post object containing the post insert data. * @param int $site_id The id of the site being processed. * @param string $transport_type The client transport type. * @param obj $client The syndication client class instance. */ do_action('syn_post_pull_new_post', $post_id, $post, $site, $transport_type, $client); } wp_reset_postdata(); if (!is_wp_error_do_throw($post_id)) { $this->process_post_meta($post_id, $post->post_meta); $this->process_post_terms($post_id, $post->post_terms); } return $post_id; // @todo Mark post as done. }
/** * Handle a site pull failure event * * @param $site_id int The post id of the site we need to retry * @param $failed_attempts int The number of pull failures this site has experienced * * @return null */ public function handle_pull_failure_event($site_id = 0, $failed_attempts = 0) { global $settings_manager; $site_auto_retry_count = 0; $site_id = (int) $site_id; $failed_attempts = (int) $failed_attempts; $cleanup = false; // Fetch the allowable number of max pull attempts before the site is marked as 'disabled' $max_pull_attempts = (int) $settings_manager->get_setting('push_syndication_max_pull_attempts', 0); error_log('max times to retry: ' . $max_pull_attempts); // Bail if auto retry feature disabled if (!$max_pull_attempts) { return; } // Only proceed if we have a valid site id if (0 !== $site_id) { // Fetch the site post $site = get_post($site_id); // Fetch the site url $site_url = get_post_meta($site->ID, 'syn_feed_url', true); // Fetch the number of times we've tried to auto-retry $site_auto_retry_count = (int) get_post_meta($site_id, 'syn_failed_auto_retry_attempts', true); // Store the current time for repeated use below $time_now = time(); // Create a string time to be sent to the logger // Add 1 so our log items appear to occur a second later // and hence order better in the log viewer // without this, sometimes when the pull occurs quickly // these log items appear to occur at the same time as the failure $log_time = date('Y-m-d H:i:s', $time_now + 1); // Only proceed if we haven't hit the pull attempt ceiling if ($failed_attempts < $max_pull_attempts) { /** * Filter the auto retry limit. * * @param int $retry_limit The maximum number of times a client should auto_retry * when failing. Default is 3. */ $auto_retry_limit = apply_filters('pull_syndication_failure_auto_retry_limit', 3); // Are we still below the auto retry limit? if ($site_auto_retry_count <= $auto_retry_limit) { // Yes we are.. // Run in one minute by default /** * Filter the time to next retry when triggering an auto-retry. * * @param int $timestamp The time you want the auto-retry to occur. Default is one * minute from now ( time() + MINUTE_IN_SECONDS ). */ $auto_retry_interval = apply_filters('syndication_failure_auto_retry_interval', $time_now + MINUTE_IN_SECONDS); Syndication_Logger::log_post_info($site->ID, $status = 'start_auto_retry', $message = sprintf(__('Connection retry %d of %d to %s in %s..', 'push-syndication'), $site_auto_retry_count + 1, $auto_retry_limit, $site_url, human_time_diff($time_now, $auto_retry_interval)), '', $extra = array()); // Schedule a pull retry for one minute in the future wp_schedule_single_event($auto_retry_interval, 'syn_pull_content', array(array($site->ID))); // Increment our auto retry counter $site_auto_retry_count++; // And update the post meta auto retry count update_post_meta($site->ID, 'syn_failed_auto_retry_attempts', $site_auto_retry_count); } else { // Auto Retry limit met // Let's cleanup after ourselves $cleanup = true; } } else { // Retry attempt limit met // The site has been disabled, let's cleanup after ourselves $cleanup = true; } // Should we cleanup after ourselves? if ($cleanup) { // Remove the auto retry if there was one delete_post_meta($site->ID, 'syn_failed_auto_retry_attempts'); Syndication_Logger::log_post_error($site->ID, $status = 'end_auto_retry', $message = sprintf(__('Failed %d times to reconnect to %s', 'push-syndication'), ++$site_auto_retry_count, $site_url), $log_time, $extra = array()); } } }