Skip to content

Commit

Permalink
Wire up the Term Cleanup Feature to use Action Scheduler. Add TODO st…
Browse files Browse the repository at this point in the history
…atements for remaining methods that are needed because of that switch
  • Loading branch information
dkotter committed Oct 9, 2024
1 parent 86311ff commit 1272cea
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 27 deletions.
46 changes: 27 additions & 19 deletions includes/Classifai/Features/TermCleanup.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Classifai\Providers\OpenAI\Embeddings as OpenAIEmbeddings;
use Classifai\Providers\Azure\Embeddings as AzureEmbeddings;
use Classifai\Providers\OpenAI\EmbeddingCalculations;
use Classifai\TermCleanupScheduler;
use WP_Error;

use function Classifai\is_elasticpress_installed;
Expand All @@ -33,7 +34,7 @@ class TermCleanup extends Feature {
/**
* Background process instance.
*
* @var TermCleanupBackgroundProcess
* @var TermCleanupScheduler
*/
private $background_process;

Expand Down Expand Up @@ -84,7 +85,9 @@ public function setup() {
}

$this->setting_page_url = admin_url( 'tools.php?page=classifai-term-cleanup' );
// $this->background_process = new TermCleanupBackgroundProcess(); // TODO: Implement this class.

$this->background_process = new TermCleanupScheduler( 'classifai_schedule_term_cleanup_job' );
$this->background_process->init();
}

/**
Expand Down Expand Up @@ -179,7 +182,7 @@ public function render_settings_page() {
<div class="classifai-content-wrapper">
<h3 class="screen-reader-text"><?php echo esc_html( $all_taxonomies[ $active_tax ] ); ?></h3>
<?php
if ( $this->background_process && $this->background_process->is_queued() ) {
if ( $this->background_process && $this->background_process->in_progress() ) {
$this->render_background_processing_status( $active_tax );
} else {
$plural_label = strtolower( $this->get_taxonomy_label( $active_tax, true ) );
Expand Down Expand Up @@ -439,10 +442,6 @@ public function get_taxonomies(): array {
* Start the term cleanup process.
*/
public function start_term_cleanup_process() {
if ( ! $this->background_process ) {
wp_die( esc_html__( 'Background processing not enabled.', 'classifai' ) );
}

if (
empty( $_POST['classifai_term_cleanup_nonce'] ) ||
! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['classifai_term_cleanup_nonce'] ) ), 'classifai_term_cleanup' )
Expand Down Expand Up @@ -479,8 +478,8 @@ public function start_term_cleanup_process() {
}
}

$this->background_process->push_to_queue(
array(
$job_args = [
[
'taxonomy' => $taxonomy,
'thresold' => $thresold,
'action' => 'term_cleanup',
Expand All @@ -489,16 +488,16 @@ public function start_term_cleanup_process() {
'term_id' => 0,
'offset' => 0,
'started_by' => get_current_user_id(),
)
);
],
];

$this->background_process->schedule( $job_args );

$this->add_notice(
__( 'Process for finding similar terms has started.', 'classifai' ),
'info'
);

$this->background_process->save()->dispatch();

// Redirect back to the settings page.
wp_safe_redirect( add_query_arg( 'tax', $taxonomy, $this->setting_page_url ) );
exit;
Expand All @@ -508,6 +507,7 @@ public function start_term_cleanup_process() {
* Cancel the term cleanup process.
*/
public function cancel_term_cleanup_process() {
// TODO
if ( ! $this->background_process ) {
wp_die( esc_html__( 'Background processing not enabled.', 'classifai' ) );
}
Expand Down Expand Up @@ -549,9 +549,9 @@ public function get_max_terms(): int {
* Generate embeddings for the terms.
*
* @param string $taxonomy Taxonomy to process.
* @return bool True if embeddings were generated, false otherwise.
* @return bool|WP_Error True if embeddings were generated, false otherwise.
*/
public function generate_embeddings( string $taxonomy ): bool {
public function generate_embeddings( string $taxonomy ) {
$exclude = [];

// Exclude the uncategorized term.
Expand Down Expand Up @@ -586,7 +586,11 @@ public function generate_embeddings( string $taxonomy ): bool {

// Generate embedding data for each term.
foreach ( $terms as $term_id ) {
$provider->generate_embeddings_for_term( $term_id, false, $this );
$result = $provider->generate_embeddings_for_term( $term_id, false, $this );

if ( is_wp_error( $result ) ) {
return $result;
}
}

return true;
Expand All @@ -598,7 +602,7 @@ public function generate_embeddings( string $taxonomy ): bool {
* @param string $taxonomy Taxonomy to process.
* @param int $thresold Thresold to consider terms as duplicates.
* @param array $args Additional arguments.
* @return array|bool
* @return array|bool|WP_Error
*/
public function get_similar_terms( string $taxonomy, int $thresold, array $args = [] ) {
if ( class_exists( '\\ElasticPress\\Feature' ) && '1' === $this->get_settings( 'use_ep' ) ) {
Expand Down Expand Up @@ -827,7 +831,9 @@ public function get_background_processing_status( string $taxonomy ): array {
return [];
}

$batches = $this->background_process->get_batches();
// TODO

Check warning on line 834 in includes/Classifai/Features/TermCleanup.php

View workflow job for this annotation

GitHub Actions / vipcs

This comment is 54% valid code; is this commented out code?
// $batches = $this->background_process->get_batches();
$batches = [];

if ( ! empty( $batches ) ) {

Check failure on line 838 in includes/Classifai/Features/TermCleanup.php

View workflow job for this annotation

GitHub Actions / PHPStan

Variable $batches in empty() always exists and is always falsy.
foreach ( $batches as $batch ) {
Expand All @@ -848,6 +854,7 @@ public function get_background_processing_status( string $taxonomy ): array {
* @param string $taxonomy Taxonomy to process.
*/
public function render_background_processing_status( $taxonomy ) {
// TODO
$status = $this->get_background_processing_status( $taxonomy );

if ( empty( $status ) ) {
Expand Down Expand Up @@ -998,6 +1005,7 @@ public function get_taxonomy_label( $taxonomy, $plural = false ): string {
* Ajax handler for refresh compare status.
*/
public function get_term_cleanup_status() {
// TODO
if ( ! $this->background_process ) {
wp_send_json_error( [ 'error' => __( 'Background processing not enabled.', 'classifai' ) ] );
}
Expand All @@ -1016,7 +1024,7 @@ public function get_term_cleanup_status() {
wp_send_json_error( $data );
}

if ( $this->background_process->is_queued() ) {
if ( $this->background_process->in_progress() ) {
$data['is_running'] = true;
ob_start();
$this->render_background_processing_status( $taxonomy );
Expand Down
18 changes: 10 additions & 8 deletions includes/Classifai/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -240,18 +240,20 @@ public function filter_plugin_action_links( $links ): array {
* Load the Action Scheduler library.
*/
public function load_action_scheduler() {
$feature = new \Classifai\Features\Classification();
$features = [ new \Classifai\Features\Classification(), new \Classifai\Features\TermCleanup() ];
$is_feature_being_enabled = false;

if ( isset( $_POST['classifai_feature_classification'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
$is_feature_being_enabled = sanitize_text_field( wp_unslash( $_POST['classifai_feature_classification']['status'] ?? false ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}
foreach ( $features as $feature ) {
if ( isset( $_POST['classifai_feature_classification'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
$is_feature_being_enabled = sanitize_text_field( wp_unslash( $_POST['classifai_feature_classification']['status'] ?? false ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}

if ( ! ( $feature->is_enabled() || '1' === $is_feature_being_enabled ) ) {
return;
}
if ( ! ( $feature->is_enabled() || '1' === $is_feature_being_enabled ) ) {
continue;
}

require_once CLASSIFAI_PLUGIN_DIR . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
require_once CLASSIFAI_PLUGIN_DIR . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
}
}

/**
Expand Down
166 changes: 166 additions & 0 deletions includes/Classifai/TermCleanupScheduler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?php

namespace Classifai;

use Classifai\Features\TermCleanup;
use ActionScheduler_Store;

use function as_enqueue_async_action;

Check failure on line 8 in includes/Classifai/TermCleanupScheduler.php

View workflow job for this annotation

GitHub Actions / PHPStan

Used function as_enqueue_async_action not found.

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( 'classifai_schedule_term_cleanup_job', [ $this, 'run' ] );
// add_filter( 'heartbeat_send', [ $this, 'check_embedding_generation_status' ] );

Check warning on line 33 in includes/Classifai/TermCleanupScheduler.php

View workflow job for this annotation

GitHub Actions / vipcs

This comment is 56% valid code; is this commented out code?
// add_action( 'classifai_before_feature_nav', [ $this, 'render_embeddings_generation_status' ] );
}

/**
* 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 );

// 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 );

// 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( 'classifai_schedule_term_cleanup_job', $args );
}
}

/**
* Check if job is in progress.
*
* @return bool
*/
public function in_progress(): bool {
if ( ! class_exists( 'ActionScheduler_Store' ) ) {
return false;
}

$store = ActionScheduler_Store::instance();

$action_id = $store->find_action(
$this->job_name,
array(
'status' => ActionScheduler_Store::STATUS_PENDING,
)
);

return ! empty( $action_id );
}
}

0 comments on commit 1272cea

Please sign in to comment.