<?php
namespace Classifai;
use Classifai\Features\TermCleanup;
use ActionScheduler_Store;
class TermCleanupScheduler {
/**
* The name of the job.
*
* @var string
*/
private $job_name = '';
/**
* TermCleanupScheduler constructor.
*
* @param string $job_name The name of the job.
*/
public function __construct( string $job_name = '' ) {
$this->job_name = $job_name;
}
/**
* Initialize the class.
*/
public function init() {
add_action( $this->job_name, [ $this, 'run' ] );
}
/**
* Run the term cleanup job.
*
* @param array $item Item details to process.
*/
public function run( array $item = [] ) {
$action = $item['action'];
if ( ! $action ) {
return;
}
switch ( $action ) {
case 'term_cleanup':
$started_by = absint( $item['started_by'] );
$taxonomy = $item['taxonomy'];
$thresold = $item['thresold'];
$term_cleanup = new TermCleanup();
$embeddings_generated = (bool) $item['embeddings_generated'];
$original_user_id = get_current_user_id();
// Set the user to the one who started the process, to avoid permission issues.
wp_set_current_user( (int) $started_by );
// Check if cancel request is made.
if ( isset( $item['job_id'] ) && get_transient( 'classifai_cancel_term_cleanup_process' ) === $item['job_id'] ) {
delete_transient( 'classifai_cancel_term_cleanup_process' );
return;
}
// Generate embeddings if not already generated.
if ( ! $embeddings_generated ) {
$results = $term_cleanup->generate_embeddings( $taxonomy );
if ( is_wp_error( $results ) ) {
$term_cleanup->add_notice(
// translators: %s: error message.
sprintf( esc_html__( 'Error in generating embeddings: %s', 'classifai' ), $results->get_error_message() ),
'error'
);
return;
}
// If get we false, then there are no further terms to process.
if ( false === $results ) {
$item['embeddings_generated'] = true;
$this->schedule( [ $item ] );
return;
}
$this->schedule( [ $item ] );
return;
}
// Find similar terms.
$args = array(
'processed' => $item['processed'] ?? 0,
'term_id' => $item['term_id'] ?? 0,
'offset' => $item['offset'] ?? 0,
);
$res = $term_cleanup->get_similar_terms( $taxonomy, $thresold, $args );
/**
* Fires when a batch of similar terms are calculated.
*
* @since x.x.x
* @hook classifai_feature_term_cleanup_get_similar_terms
*
* @param {array|bool|WP_Error} $res Response from the get_similar_terms method.
* @param {string} $taxonomy Taxonomy of terms we are comparing.
* @param {array} $args Arguments used for getting similar terms.
*/
do_action( 'classifai_feature_term_cleanup_get_similar_terms', $res, $taxonomy, $args );
// Restore original user.
wp_set_current_user( $original_user_id );
if ( is_wp_error( $res ) ) {
$term_cleanup->add_notice(
// translators: %s: error message.
sprintf( esc_html__( 'Error in finding similar terms: %s', 'classifai' ), $res->get_error_message() ),
'error'
);
return;
}
if ( false === $res ) {
$label = strtolower( $term_cleanup->get_taxonomy_label( $taxonomy, true ) );
// Show notice to user.
$term_cleanup->add_notice(
// translators: %s: taxonomy label.
sprintf( __( 'Process for finding similar %s has been completed.', 'classifai' ), $label ),
'success'
);
// No more terms to process.
return;
}
// Update item.
$item['processed'] = $res['processed'];
$item['term_id'] = $res['term_id'];
$item['offset'] = $res['offset'];
$this->schedule( [ $item ] );
return;
default:
return;
}
}
/**
* Schedule the term cleanup job.
*
* @param array $args Arguments to pass to the job.
*/
public function schedule( array $args = [] ) {
if ( function_exists( 'as_enqueue_async_action' ) ) {
as_enqueue_async_action( $this->job_name, $args );
}
}
/**
* Unschedule the term cleanup job.
*
* @return bool
*/
public function unschedule() {
if ( function_exists( 'as_unschedule_all_actions' ) ) {
as_unschedule_all_actions( $this->job_name );
if ( ! class_exists( 'ActionScheduler_Store' ) ) {
return false;
}
$store = ActionScheduler_Store::instance();
// Check if the job is still in progress.
$action_id = $store->find_action(
$this->job_name,
array(
'status' => ActionScheduler_Store::STATUS_RUNNING,
)
);
// If no action running, return true.
if ( empty( $action_id ) ) {
return true;
}
$action = $store->fetch_action( $action_id );
$args = $action->get_args();
if ( ! empty( $args ) && isset( $args[0]['job_id'] ) ) {
set_transient( 'classifai_cancel_term_cleanup_process', $args[0]['job_id'], 300 );
}
return true;
}
return false;
}
/**
* Check if job is in progress.
*
* @return bool
*/
public function in_progress(): bool {
if ( function_exists( 'as_has_scheduled_action' ) ) {
return as_has_scheduled_action( $this->job_name );
}
return false;
}
/**
* Get the arguments for the current job.
*
* @return array|bool
*/
public function get_args() {
if ( ! class_exists( 'ActionScheduler_Store' ) ) {
return false;
}
$store = ActionScheduler_Store::instance();
$running_action_id = $store->find_action(
$this->job_name,
array(
'status' => ActionScheduler_Store::STATUS_RUNNING,
)
);
$pending_action_id = $store->find_action(
$this->job_name,
array(
'status' => ActionScheduler_Store::STATUS_PENDING,
)
);
if ( empty( $running_action_id ) && empty( $pending_action_id ) ) {
return false;
}
$action_id = ! empty( $running_action_id ) ? $running_action_id : $pending_action_id;
$action = $store->fetch_action( $action_id );
$args = $action->get_args();
return $args;
}
}