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/Queued_Event.php
<?php
// phpcs:ignoreFile

namespace AutomateWoo;

use AutomateWoo\DataTypes\DataTypes;
use AutomateWoo\Workflows\Factory;

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

/**
 * @class Queued_Event
 *
 * @property array $data_items (legacy)
 */
class Queued_Event extends Abstract_Model_With_Meta_Table {

	/** @var string */
	public $table_id = 'queue';

	/** @var string  */
	public $object_type = 'queue';

	/** @var bool|array */
	private $uncompressed_data_layer;


	// error messages
	const F_WORKFLOW_INACTIVE = 100;
	const F_MISSING_DATA = 101;
	const F_FATAL_ERROR = 102;

	/**
	 * Returns the ID of the model's meta table.
	 *
	 * @return string
	 */
	public function get_meta_table_id() {
		return 'queue-meta';
	}

	/**
	 * @param bool|int $id
	 */
	function __construct( $id = false ) {
		if ( $id ) $this->get_by( 'id', $id );
	}


	/**
	 * Set workflow ID prop.
	 *
	 * @param int $id
	 *
	 * @return $this
	 */
	public function set_workflow_id( $id ) {
		$this->set_prop( 'workflow_id', Clean::id( $id ) );
		return $this;
	}


	/**
	 * @return int
	 */
	function get_workflow_id() {
		return Clean::id( $this->get_prop( 'workflow_id' ) );
	}


	/**
	 * Set failed prop.
	 *
	 * @param bool $failed
	 *
	 * @return $this
	 */
	function set_failed( $failed = true ) {
		$this->set_prop( 'failed', aw_bool_int( $failed ) );
		return $this;
	}


	/**
	 * @return bool
	 */
	function is_failed() {
		return (bool) $this->get_prop( 'failed' );
	}


	/**
	 * @param int $failure_code
	 *
	 * @return $this
	 */
	function set_failure_code( $failure_code ) {
		$this->set_prop( 'failure_code', absint( $failure_code ) );
		return $this;
	}

	/**
	 * @return int
	 */
	function get_failure_code() {
		return absint( $this->get_prop( 'failure_code' ) );
	}


	/**
	 * @param DateTime $date
	 *
	 * @return $this
	 */
	function set_date_created( $date ) {
		$this->set_date_column( 'created', $date );
		return $this;
	}


	/**
	 * @return bool|DateTime
	 */
	function get_date_created() {
		return $this->get_date_column( 'created' );
	}


	/**
	 * @param DateTime $date
	 *
	 * @return $this
	 */
	function set_date_due( $date ) {
		$this->set_date_column( 'date', $date );
		return $this;
	}


	/**
	 * @return bool|DateTime
	 */
	function get_date_due() {
		return $this->get_date_column( 'date' );
	}


	/**
	 * @param Data_Layer $data_layer
	 */
	function store_data_layer( $data_layer ) {

		$this->uncompressed_data_layer = $data_layer->get_raw_data();

		foreach ( $this->uncompressed_data_layer as $data_type_id => $data_item ) {
			$this->store_data_item( $data_type_id, $data_item );
		}
	}


	/**
	 * @param $data_type_id
	 * @param $data_item
	 */
	private function store_data_item( $data_type_id, $data_item ) {
		$data_type = DataTypes::get( $data_type_id );

		if (
			! $data_type ||
			! $data_type->validate( $data_item ) ||
			DataTypes::is_non_stored_data_type( $data_type_id )
		) {
			return;
		}

		$storage_key = Queue_Manager::get_data_layer_storage_key( $data_type_id );
		$storage_value = $data_type->compress( $data_item );

		if ( $storage_key ) {
			$this->update_meta( $storage_key, $storage_value );
		}
	}


	/**
	 * @return Data_Layer
	 */
	function get_data_layer() {

		if ( ! isset( $this->uncompressed_data_layer ) ) {

			$uncompressed_data_layer = [];
			$compressed_data_layer = $this->get_compressed_data_layer();

			if ( $compressed_data_layer ) {
				foreach ( $compressed_data_layer as $data_type_id => $compressed_item ) {
					if ( $data_type = DataTypes::get( $data_type_id ) ) {
						$uncompressed_data_layer[$data_type_id] = $data_type->decompress( $compressed_item, $compressed_data_layer );
					}
				}
			}

			$this->uncompressed_data_layer = new Data_Layer( $uncompressed_data_layer );
		}

		return $this->uncompressed_data_layer;
	}


	/**
	 * Fetches the data layer from queue meta, but does not decompress
	 * Uses the the supplied_data_items field on the workflows trigger
	 *
	 * @return array|false
	 */
	function get_compressed_data_layer() {

		if ( ! $workflow = $this->get_workflow() )
			return false; // workflow must be set

		if ( ! $this->exists )
			return false; // queue must be saved

		if ( ! $trigger = $workflow->get_trigger() )
			return false; // need a trigger

		$data_layer = [];

		$supplied_items = $trigger->get_supplied_data_items();

		foreach ( $supplied_items as $data_type_id ) {

			$data_item_value = $this->get_compressed_data_item( $data_type_id, $supplied_items );

			if ( $data_item_value !== false ) {
				$data_layer[ $data_type_id ] = $data_item_value;
			}
		}

		return $data_layer;
	}


	/**
	 * @param $data_type_id
	 * @param array $supplied_data_items
	 * @return string|false
	 */
	private function get_compressed_data_item( $data_type_id, $supplied_data_items ) {
		if ( DataTypes::is_non_stored_data_type( $data_type_id ) ) {
			return false; // storage not required
		}

		$storage_key = Queue_Manager::get_data_layer_storage_key( $data_type_id );;

		if ( ! $storage_key ) {
			return false;
		}

		return Clean::string( $this->get_meta( $storage_key ) );
	}


	/**
	 * Returns the workflow without a data layer
	 * @return Workflow|false
	 */
	function get_workflow() {
		return Factory::get( $this->get_workflow_id() );
	}


	/**
	 * @return bool
	 */
	function run() {

		if ( ! $this->exists ) {
			return false;
		}

		// mark as failed and then delete if complete, so fatal error will not cause it to run repeatedly
		$this->mark_as_failed( self::F_FATAL_ERROR );
		$this->save();
		$success = false;

		$workflow = $this->get_workflow();
		$workflow->setup( $this->get_data_layer() );

		$failure = $this->do_failure_check( $workflow );

		if ( $failure ) {
			// queued event failed
			$this->mark_as_failed( $failure );
		}
		else {
			$success = true;

			// passed fail check so validate workflow and then delete
			if ( $this->validate_workflow( $workflow ) ) {
				$workflow->run();
			}

			$this->delete();
		}

		// important to always clean up
		$workflow->cleanup();
		return $success;
	}


	/**
	 * Returns false if no failure occurred
	 * @param Workflow $workflow
	 * @return bool|int
	 */
	function do_failure_check( $workflow ) {

		if ( ! $workflow || ! $workflow->is_active() ) {
			return self::F_WORKFLOW_INACTIVE;
		}

		if ( $this->get_data_layer()->is_missing_data() ) {
			return self::F_MISSING_DATA;
		}

		return false;
	}


	/**
	 * Validate the workflow before running it from the queue.
	 * This validation is different from the initial trigger validation.
	 *
	 * @param $workflow Workflow
	 * @return bool
	 */
	function validate_workflow( $workflow ) {

		if ( ! $trigger = $workflow->get_trigger() )
			return false;

		if ( ! $trigger->validate_before_queued_event( $workflow ) )
			return false;

		if ( ! $workflow->validate_rules() )
			return false;

		return true;
	}


	function clear_cached_data() {

		if ( ! $this->get_workflow_id() )
			return;

		Cache::delete_transient( 'current_queue_count/workflow=' . $this->get_workflow_id() );
	}


	function save() {

		if ( ! $this->exists ) {
			$this->set_date_created( new DateTime() );
		}

		$this->clear_cached_data();

		parent::save();
	}


	function delete() {
		$this->clear_cached_data();
		parent::delete();
	}



	/**
	 * @param int $code
	 */
	function mark_as_failed( $code ) {
		$this->set_failed();
		$this->set_failure_code( $code );
		$this->save();
	}


	/**
	 * @return string
	 */
	function get_failure_message( ) {
		return Queue_Manager::get_failure_message( $this->get_failure_code() );
	}


	/**
	 * Just for unit tests
	 */
	function clear_in_memory_data_layer() {
		$this->uncompressed_data_layer = null;
	}



	/**
	 * @deprecated use set_date_due()
	 * @param $date DateTime
	 */
	function set_date( $date ) {
		wc_deprecated_function( __METHOD__, '5.2.0', 'set_date_due' );

		$this->set_date_due( $date );
	}

}