unction complete() { // unschedule the cron healthcheck $this->clear_scheduled_event(); } /** * Schedule cron healthcheck * * @since 4.4.0 * @param array $schedules * @return array */ public function schedule_cron_healthcheck( $schedules ) { $interval = property_exists( $this, 'cron_interval' ) ? $this->cron_interval : 5; /** * Filter cron health check interval * * @since 4.4.0 * @param int $interval Interval in minutes */ $interval = apply_filters( "{$this->identifier}_cron_interval", $interval ); // adds every 5 minutes to the existing schedules. $schedules[ $this->identifier . '_cron_interval' ] = [ 'interval' => MINUTE_IN_SECONDS * $interval, /* translators: %d - interval in minutes. */ 'display' => sprintf( __( 'Every %d Minutes', 'facebook-for-woocommerce' ), $interval ), ]; return $schedules; } /** * Handle cron healthcheck * * Restart the background process if not already running * and data exists in the queue. * * @since 4.4.0 */ public function handle_cron_healthcheck() { if ( $this->is_process_running() ) { // background process already running exit; } if ( $this->is_queue_empty() ) { // no data to process $this->clear_scheduled_event(); exit; } $this->dispatch(); } /** * Schedule cron health check event * * @since 4.4.0 */ protected function schedule_event() { if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) { // schedule the health check to fire after 30 seconds from now, as to not create a race condition // with job process lock on servers that fire & handle cron events instantly wp_schedule_event( time() + 30, $this->cron_interval_identifier, $this->cron_hook_identifier ); } } /** * Clear scheduled health check event * * @since 4.4.0 */ protected function clear_scheduled_event() { $timestamp = wp_next_scheduled( $this->cron_hook_identifier ); if ( $timestamp ) { wp_unschedule_event( $timestamp, $this->cron_hook_identifier ); } } /** * Process an item from job data * * Implement this method to perform any actions required on each * item in job data. * * @since 4.4.2 * * @param mixed $item Job data item to iterate over * @param \stdClass|object $job Job instance * @return mixed */ abstract protected function process_item( $item, $job ); /** * Handles PHP shutdown, say after a fatal error. * * @since 4.5.0 * * @param \stdClass|object $job the job being processed */ public function handle_shutdown( $job ) { $error = error_get_last(); // if shutting down because of a fatal error, fail the job if ( $error && E_ERROR === $error['type'] ) { $this->fail_job( $job, $error['message'] ); $this->unlock_process(); } } /** * Update a job option in options database. * * @since 4.6.3 * * @param \stdClass|object $job the job instance to update in database * @return int|bool number of rows updated or false on failure, see wpdb::update() */ private function update_job_option( $job ) { global $wpdb; return $wpdb->update( $wpdb->options, [ 'option_value' => wp_json_encode( $job ) ], [ 'option_name' => "{$this->identifier}_job_{$job->id}" ] ); } /** Debug & Testing Methods ***********************************************/ /** * Tests the background handler's connection. * * @since 4.8.0 * * @return bool */ public function test_connection() { $test_url = add_query_arg( 'action', "{$this->identifier}_test", admin_url( 'admin-ajax.php' ) ); $result = wp_safe_remote_get( $test_url ); $body = ! is_wp_error( $result ) ? wp_remote_retrieve_body( $result ) : null; // some servers may add a UTF8-BOM at the beginning of the response body, so we check if our test // string is included in the body, as an equal check would produce a false negative test result return $body && Helper::str_exists( $body, '[TEST_LOOPBACK]' ); } /** * Handles the connection test request. * * @since 4.8.0 */ public function handle_connection_test_response() { echo '[TEST_LOOPBACK]'; exit; } /** * Adds the WooCommerce debug tool. * * @since 4.8.0 * * @param array $tools WooCommerce core tools * @return array */ public function add_debug_tool( $tools ) { // this key is not unique to the plugin to avoid duplicate tools $tools['sv_wc_background_job_test'] = [ 'name' => __( 'Background Processing Test', 'facebook-for-woocommerce' ), 'button' => __( 'Run Test', 'facebook-for-woocommerce' ), 'desc' => __( 'This tool will test whether your server is capable of processing background jobs.', 'facebook-for-woocommerce' ), 'callback' => [ $this, 'run_debug_tool' ], ]; return $tools; } /** * Runs the test connection debug tool. * * @since 4.8.0 * * @return string */ public function run_debug_tool() { if ( $this->test_connection() ) { $this->debug_message = esc_html__( 'Success! You should be able to process background jobs.', 'facebook-for-woocommerce' ); $result = true; } else { $this->debug_message = esc_html__( 'Could not connect. Please ask your hosting company to ensure your server has loopback connections enabled.', 'facebook-for-woocommerce' ); $result = false; } return $result; } /** * Translate the tool success message. * * This can be removed in favor of returning the message string in `run_debug_tool()` * when WC 3.1 is required, though that means the message will always be "success" styled. * * @since 4.8.0 * * @param string $translated the text to output * @param string $original the original text * @param string $domain the textdomain * @return string the updated text */ public function translate_success_message( $translated, $original, $domain ) { if ( 'woocommerce' === $domain && ( 'Tool ran.' === $original || 'There was an error calling %s' === $original ) ) { $translated = $this->debug_message; } return $translated; } /** Helper Methods ********************************************************/ /** * Gets the job handler identifier. * * @since 4.8.0 * * @return string */ public function get_identifier() { return $this->identifier; } } 1 - Uncaught Error: Class 'WooCommerce\Facebook\Framework\Utilities\BackgroundJobHandler' not found in /home/st20space2tech/public_html/site/wp-content/plugins/facebook-for-woocommerce/includes/Products/Sync/Background.php:17 Stack trace: #0 /home/st20space2tech/public_html/site/wp-content/plugins/facebook-for-woocommerce/vendor/composer/ClassLoader.php(576): include() #1 /home/st20space2tech/public_html/site/wp-content/plugins/facebook-for-woocommerce/vendor/composer/ClassLoader.php(427): Composer\Autoload\{closure}('/home/st20space...') #2 [internal function]: Composer\Autoload\ClassLoader->loadClass('WooCommerce\\Fac...') #3 /home/st20space2tech/public_html/site/wp-content/plugins/facebook-for-woocommerce/class-wc-facebookcommerce.php(216): spl_autoload_call('WooCommerce\\Fac...') #4 /home/st20space2tech/public_html/site/wp-content/plugins/facebook-for-woocommerce/class-wc-facebookcommerce.php(161): WC_Facebookcommerce->init() #5 /home/st20space2tech/public_html/site/wp-content/plugins/facebook-for-woocommerce - /home/st20space2tech/public_html/site/wp-content/plugins/facebook-for-woocommerce/includes/Products/Sync/Background.php - 17