HEX
Server: Apache/2.4.65 (Ubuntu)
System: Linux ielts-store-v2 6.8.0-1036-gcp #38~22.04.1-Ubuntu SMP Thu Aug 14 01:19:18 UTC 2025 x86_64
User: root (0)
PHP: 7.2.34-54+ubuntu20.04.1+deb.sury.org+1
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,
Upload Files
File: /var/www/html/ielts-store/wp-content/plugins/automatewoo/includes/Background_Processes/Base.php
<?php
// phpcs:ignoreFile

namespace AutomateWoo\Background_Processes;

use AutomateWoo\Logger;

if ( ! defined( 'ABSPATH' ) ) exit;

if ( ! class_exists( 'AW_WP_Async_Request', false ) ) {
	require_once AW()->lib_path( '/wp-async-request.php' );
}

if ( ! class_exists( 'AW_WP_Background_Process', false ) ) {
	require_once AW()->lib_path( '/wp-background-process.php' );
}

/**
 * Base background process class
 */
abstract class Base extends \AW_WP_Background_Process {

	/** @var string */
	public $action;


	/**
	 * Background Processor base constructor.
	 * Deliberately doesn't call parent method.
	 */
	public function __construct() {
		$this->prefix                   = is_multisite() ? 'aw_' . get_current_blog_id() : 'aw';
		$this->identifier               = $this->prefix . '_' . $this->action;
		$this->cron_hook_identifier     = $this->identifier . '_background_process_cron';
		$this->cron_interval_identifier = $this->identifier . '_cron_interval';

		add_action( 'wp_ajax_' . $this->get_ajax_action(), [ $this, 'maybe_handle' ] );
		add_action( 'wp_ajax_nopriv_' . $this->get_ajax_action(), [ $this, 'maybe_handle' ] );
		add_action( $this->cron_hook_identifier, [ $this, 'handle_cron_healthcheck' ] );
		add_filter( 'cron_schedules', [ $this, 'schedule_cron_healthcheck' ] );
	}


	/**
	 * @return boolean
	 */
	public function has_queued_items() {
		return false === $this->is_queue_empty();
	}


	/**
	 * Use this instead of dispatch to start process
	 * @return bool|\WP_Error
	 */
	public function start() {
		if ( empty( $this->data ) ) {
			$this->log( 'Started process but there were no items.' );
			return false;
		}

		$count = count( $this->data );
		$this->save();
		$dispatched = $this->dispatch();

		if ( is_wp_error( $dispatched ) ) {
			$this->log( sprintf( 'Unable to start process: %s', $dispatched->get_error_message() ) );
		}
		else {
			$this->log( sprintf( 'Process started for %s items.', $count ) );
		}

		return $dispatched;
	}


	/**
	 * Process completed
	 */
	protected function complete() {
		$this->log( 'Process completed.' );
		parent::complete();
	}


	/**
	 * Reduce time limit to 10s
	 * @return bool
	 */
	protected function time_exceeded() {
		$finish = $this->start_time + apply_filters( 'automatewoo/background_process/time_limit', 10 ); // 10 seconds
		$return = false;

		if ( time() >= $finish ) {
			$return = true;
		}

		return $return;
	}


	/**
	 * Reduce memory limit
	 * @return bool
	 */
	protected function memory_exceeded() {

		// use only 40% of max memory
		$memory_limit_percentage = apply_filters( 'automatewoo/background_process/memory_limit_percentage', 0.4 );

		$memory_limit = $this->get_memory_limit() * $memory_limit_percentage;
		$current_memory = memory_get_usage( true );
		$return = false;

		if ( $current_memory >= $memory_limit ) {
			$return = true;
		}

		return $return;
	}


	/**
	 * Handle
	 *
	 * Pass each queue item to the task handler, while remaining
	 * within server memory and time limit constraints.
	 */
	protected function handle() {

		do_action( 'automatewoo/background_process/before_handle', $this );

		$this->lock_process();

		do {
			$batch = $this->get_batch();

			foreach ( $batch->data as $key => $value ) {
				$task = $this->task( $value );

				if ( false !== $task ) {
					$batch->data[ $key ] = $task;
				} else {
					unset( $batch->data[ $key ] );
				}

				if ( $this->time_exceeded() || $this->memory_exceeded() ) {
					// Batch limits reached.
					break;
				}
			}

			// Update or delete current batch.
			if ( ! empty( $batch->data ) ) {
				$this->update( $batch->key, $batch->data );
			} else {
				$this->delete( $batch->key );
			}
		} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );

		// throttle process here with sleep to try and prevent crashing mysql
		$sleep_seconds = apply_filters( 'automatewoo/background_process/post_batch_sleep', 1, $this );

		if ( $sleep_seconds ) {
			sleep( $sleep_seconds );
		}

		$this->unlock_process();

		// Start next batch or complete process.
		if ( ! $this->is_queue_empty() ) {
			$this->dispatch();
		} else {
			$this->complete();
		}
	}


	/**
	 * @param $message
	 */
	public function log( $message ) {
		Logger::info( 'background-process', $this->action. ': ' . $message );
	}


	/**
	 * over-ridden due to issue https://github.com/A5hleyRich/wp-background-processing/issues/7
	 *
	 * this method actually creates a new batch rather it doesn't replace existing queued items
	 *
	 * @return $this
	 */
	public function save() {
		$key = $this->generate_key();

		if ( ! empty( $this->data ) ) {
			update_site_option( $key, $this->data );
		}

		$this->data = [];
		return $this;
	}


	/**
	 * Dispatch background process.
	 *
	 * @return array|\WP_Error
	 */
	public function dispatch() {
		// Schedule the cron healthcheck.
		$this->schedule_event();

		// Perform remote post.
		$request = wp_remote_post( esc_url_raw( $this->get_post_url() ), $this->get_post_args() );

		if ( AUTOMATEWOO_BACKGROUND_PROCESS_DEBUG && is_wp_error( $request ) ) {
			Logger::error( 'background-process-debug', 'Dispatch: ' . $request->get_error_message() );
		}

		return $request;
	}


	/**
	 * Schedule health check if not scheduled
	 */
	public function maybe_schedule_health_check() {
		$this->schedule_event();
	}


	/**
	 * Replace parent method to schedule health check 1 minute from now.
	 * This is preferred rather than setting the health check to run instantly.
	 * This value could actually be set for longer but if there is an issue with the HTTP request
	 * this acts as a fallback method of processing events.
	 *
	 * @since 4.4
	 */
	protected function schedule_event() {
		if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
			wp_schedule_event( time() + 60, $this->cron_interval_identifier, $this->cron_hook_identifier );
		}
	}


	/**
	 * @return array
	 */
	function get_data() {
		return $this->data;
	}


	/**
	 * @return \stdClass
	 */
	function get_next_batch() {
		return $this->get_batch();
	}


	/**
	 * Get query args
	 *
	 * @return array
	 */
	protected function get_query_args() {
		if ( property_exists( $this, 'query_args' ) ) {
			return $this->query_args;
		}

		return array(
			'action' => $this->get_ajax_action(),
			'nonce'  => wp_create_nonce( $this->identifier ),
		);
	}


	/**
	 * Get post args
	 *
	 * @return array
	 */
	protected function get_post_args() {
		if ( property_exists( $this, 'post_args' ) ) {
			return $this->post_args;
		}

		$args = [];

		if ( ! AUTOMATEWOO_BACKGROUND_PROCESS_DEBUG ) {
			$args['timeout'] = 0.01;
			$args['blocking'] = false;
		}
		else {
			$args['timeout'] = 30;
		}

		$args['body'] = json_encode( $this->data );
		$args['cookies'] = $_COOKIE;
		$args['sslverify'] = apply_filters( 'https_local_ssl_verify', false );

		return apply_filters( 'automatewoo/background_process/post_args', $args, $this );
	}


	/**
	 * Get dispatch URL for HTTP post.
	 *
	 * @since 4.4.0
	 *
	 * @return string
	 */
	public function get_post_url() {
		$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
		return apply_filters( 'automatewoo/background_process/post_url', $url, $this );
	}


	/**
	 * @return string
	 */
	public function get_ajax_action() {
		return $this->identifier . '_background_process';
	}

}