2026-03-27 11:54:51 +00:00

454 lines
12 KiB
PHP

<?php
abstract class TD_Async_Action_Model extends TD_DB_Model {
protected $slug = 'async_action';
protected $version = '1.8.5';
/**
* Get things started
*
* @access public
* @since 0.0.2
*/
public function __construct( $plugin ) {
parent::__construct( $plugin );
$this->hooks_hooks();
}
public function hooks_hooks() {
add_filter( 'query_'.$this->slug.'_db_where_conditions', array( $this, 'date_filter_where_conditions' ), 10, 2 );
}
public function date_filter_where_conditions( $where, $args ) {
global $wpdb;
if( ! empty( $args['action'] ) ) {
if( is_array( $args['action'] ) ) {
$actions = implode( ',', array_map( function ( $action ) {
return '"' . sanitize_text_field ( $action ) . '"';
}, $args['action'] ) );
} else {
$actions = sanitize_text_field( $args['action'] );
}
$where .= " AND `action` IN( $actions ) ";
}
if ( !empty( $this->schema['date_queued'] ) ) {
// Customers created for a specific date or in a date range
if( ! empty( $args['date_queued'] ) ) {
if( !is_array( $args['date_queued'] ) ) {
if ( $args['date_queued'] == '0000-00-00 00:00:00' ) {
$where .= " AND (`date_queued` = \"".$args['date_queued']."\" OR `date_queued` IS NULL ) ";
} else {
$where .= $wpdb->prepare( " AND `date_queued` = '" . '%s' . "' ", $args['date_queued'] );
}
}
} else {
if( ! empty( $args['date_queued_min'] ) ) {
$where .= $wpdb->prepare( " AND `date_queued` >= '" . '%s' . "' ", $args["date_queued_min"] );
}
if( ! empty( $args['date_queued_max'] ) ) {
$where .= $wpdb->prepare( " AND `date_queued` <= '" . '%s' . "' ", $args["date_queued_max"]);
}
}
}
if ( !empty( $this->schema['date_processed'] ) ) {
// Customers created for a specific date or in a date range
if( ! empty( $args['date_processed'] ) ) {
if( !is_array( $args['date_processed'] ) ) {
if ( $args['date_processed'] == '0000-00-00 00:00:00' ) {
$where .= " AND (`date_processed` = \"".$args['date_processed']."\" OR `date_processed` IS NULL ) ";
} else {
$where .= $wpdb->prepare( " AND `date_processed` = '" . '%s' . "' ", $args['date_processed'] );
}
}
} else {
if( ! empty( $args['date_processed_min'] ) ) {
$where .= $wpdb->prepare( " AND `date_processed` >= '" . '%s' . "' ", $args["date_processed_min"] );
}
if( ! empty( $args['date_processed_max'] ) ) {
$where .= $wpdb->prepare( " AND `date_processed` <= '" . '%s' . "' ", $args["date_processed_max"] );
}
}
}
if ( !empty( $this->schema['date_completed'] ) ) {
// Customers created for a specific date or in a date range
if( ! empty( $args['date_completed'] ) ) {
if( !is_array( $args['date_completed'] ) ) {
if ( $args['date_completed'] == '0000-00-00 00:00:00' ) {
$where .= " AND (`date_completed` = \"".$args['date_completed']."\" OR `date_completed` IS NULL ) ";
} else {
$where .= $wpdb->prepare( " AND `date_completed` = '" . '%s' . "' ", $args['date_completed'] );
}
}
} else {
if( ! empty( $args['date_completed_min'] ) ) {
$where .= $wpdb->prepare( " AND `date_completed` >= '" . '%s' . "' ", $args["date_completed_min"] );
}
if( ! empty( $args['date_completed_max'] ) ) {
$where .= $wpdb->prepare( " AND `date_completed` <= '" . '%s' . "' ", $args["date_completed_max"] );
}
}
}
return $where;
}
public function insert( $data, $type='' ) {
if ( empty( $data['date_queued'] ) ) {
$data['date_queued'] = gmdate( 'Y-m-d H:i:s' );
}
return parent::insert( $data, $type );
}
public function queue_action( $hook, $action = null, $priority = 10, $payload = array(), $object_type = null, $object_id = null, $action_group = null, $meta = array() ) {
if ( empty( $action ) ) {
$action = 'async_'.$hook;
}
$data = array(
'hook' => $hook,
'action' => $action,
'priority' => $priority,
'object_type' => $object_type,
'object_id' => $object_id,
'action_group' => $action_group,
'payload' => $payload,
);
$meta = shortcode_atts( array(
'date_queued' => null,
), $meta );
foreach ($meta as $key => $value) {
if ( empty( $value ) ) {
continue;
}
$data[$key] = $value;
}
return $this->insert( $data );
}
public function complete_action( $action_id, $response = array() ) {
$this->update( $action_id, array(
'response' => $response,
'date_completed' => gmdate( 'Y-m-d H:i:s' ),
) );
}
public function process( $query = array() ) {
$query = shortcode_atts( array(
'date_processed' => '0000-00-00 00:00:00',
'orderby' => 'priority',
'order' => 'ASC',
'date_queued_max' => gmdate( 'Y-m-d H:i:s' ),
), $query );
$actions_to_do = $this->query( $query );
foreach ($actions_to_do as $key => $action_to_do) {
if ( empty( $action_to_do['action'] ) ) {
continue;
}
if ( empty( $action_to_do['date_queued'] ) || $action_to_do['date_queued'] > gmdate( 'Y-m-d H:i:s' ) ) {
continue;
}
$action_to_do = $this->get( $action_to_do['id'] );
if ( !empty( $action_to_do['date_processed'] ) && $action_to_do['date_processed'] != '0000-00-00 00:00:00' ) {
continue;
}
$action_to_do['date_processed'] = gmdate( 'Y-m-d H:i:s' );
$this->update( $action_to_do['id'], array(
'date_processed' => $action_to_do['date_processed']
) );
do_action( $action_to_do['action'], $action_to_do['payload'], $action_to_do );
}
if ( apply_filters( 'ssa/async/retry_incomplete_actions', false ) && empty( $action_to_do ) ) {
// let's check for ones that started processing but never finished
$ten_minutes_ago_ymd = gmdate( 'Y-m-d H:i:s', time()-600 );
$query = shortcode_atts( array(
'date_completed' => '0000-00-00 00:00:00',
'date_processed_max' => $ten_minutes_ago_ymd,
'date_processed_min' => gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS * 6 ),
'orderby' => 'priority',
'order' => 'ASC',
'date_queued_max' => gmdate( 'Y-m-d H:i:s' ),
), $query );
$actions_to_do = $this->query( $query );
foreach ($actions_to_do as $key => $action_to_do) {
if ( empty( $action_to_do['action'] ) ) {
continue;
}
if ( empty( $action_to_do['date_queued'] ) || $action_to_do['date_queued'] > gmdate( 'Y-m-d H:i:s' ) ) {
continue;
}
$action_to_do = $this->get( $action_to_do['id'] );
if ( !empty( $action_to_do['date_processed'] ) && $action_to_do['date_processed'] > $ten_minutes_ago_ymd ) {
// this already got picked up another time
continue;
}
$action_to_do['date_processed'] = gmdate( 'Y-m-d H:i:s' );
$this->update( $action_to_do['id'], array(
'date_processed' => $action_to_do['date_processed'],
'date_completed' => $action_to_do['date_processed'], // we don't want it to infinitely loop, just try one more time
) );
do_action( $action_to_do['action'], $action_to_do['payload'], $action_to_do );
}
}
}
protected $indexes = array(
'author_id' => [ 'author_id' ],
'hook' => [ 'hook' ],
'action' => [ 'action' ],
'date_queued' => [ 'date_queued' ],
'date_processed' => [ 'date_processed' ],
'date_completed' => [ 'date_completed' ],
'process_batch_token' => [ 'process_batch_token' ],
);
protected $schema = array(
'author_id' => array(
'field' => 'author_id',
'label' => 'Author',
'default_value' => 0,
'format' => '%d',
'mysql_type' => 'BIGINT',
'mysql_length' => 11,
'mysql_unsigned' => true,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'hook' => array(
'field' => 'hook',
'label' => 'Hook',
'default_value' => '',
'format' => '%s',
'mysql_type' => 'VARCHAR',
'mysql_length' => 150,
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'action' => array(
'field' => 'action',
'label' => 'Action',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'VARCHAR',
'mysql_length' => '150',
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'priority' => array(
'field' => 'priority',
'label' => 'Priority',
'default_value' => 10,
'format' => '%d',
'mysql_type' => 'INT',
'mysql_length' => '5',
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'payload' => array(
'field' => 'payload',
'label' => 'Object Data',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'TEXT',
'mysql_length' => '',
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
'type' => 'array',
'encoder' => 'json',
),
'object_type' => array(
'field' => 'object_type',
'label' => 'Object Type',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'VARCHAR',
'mysql_length' => '150',
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'object_id' => array(
'field' => 'object_id',
'label' => 'Object ID',
'default_value' => 0,
'format' => '%d',
'mysql_type' => 'BIGINT',
'mysql_length' => 11,
'mysql_unsigned' => true,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'action_group' => array(
'field' => 'action_group',
'label' => 'Object Type',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'VARCHAR',
'mysql_length' => '150',
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'response' => array(
'field' => 'response',
'label' => 'Response',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'TEXT',
'mysql_length' => '',
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
'type' => 'array',
'encoder' => 'json',
),
'date_created' => array(
'field' => 'date_created',
'label' => 'Date Created',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'DATETIME',
'mysql_length' => '',
'mysql_unsigned' => false,
'mysql_allow_null' => true,
'mysql_extra' => '',
'cache_key' => false,
),
'date_modified' => array(
'field' => 'date_modified',
'label' => 'Date Modified',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'DATETIME',
'mysql_length' => '',
'mysql_unsigned' => false,
'mysql_allow_null' => true,
'mysql_extra' => '',
'cache_key' => false,
),
'date_queued' => array(
'field' => 'date_queued',
'label' => 'Date Queued',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'DATETIME',
'mysql_length' => '',
'mysql_unsigned' => false,
'mysql_allow_null' => true,
'mysql_extra' => '',
'cache_key' => false,
),
'date_processed' => array(
'field' => 'date_processed',
'label' => 'Date Processed',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'DATETIME',
'mysql_length' => '',
'mysql_unsigned' => false,
'mysql_allow_null' => true,
'mysql_extra' => '',
'cache_key' => false,
),
'process_batch_token' => array(
'field' => 'process_batch_token',
'label' => 'Process Batch Token',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'VARCHAR',
'mysql_length' => '50',
'mysql_unsigned' => false,
'mysql_allow_null' => false,
'mysql_extra' => '',
'cache_key' => false,
),
'date_completed' => array(
'field' => 'date_completed',
'label' => 'Date Completed',
'default_value' => false,
'format' => '%s',
'mysql_type' => 'DATETIME',
'mysql_length' => '',
'mysql_unsigned' => false,
'mysql_allow_null' => true,
'mysql_extra' => '',
'cache_key' => false,
),
);
public function get_items_permissions_check( $request ) {
return false;
}
public function get_item_permissions_check( $request ) {
return false;
}
public function create_item_permissions_check( $request ) {
return false;
}
public function update_item_permissions_check( $request ) {
return false;
}
public function delete_item_permissions_check( $request ) {
return false;
}
}