Making background processes and importers store progress #62

This commit is contained in:
Leo Germani 2018-06-19 13:18:58 -03:00
parent b94a39689a
commit 9eec2bb4b2
7 changed files with 170 additions and 7 deletions

View File

@ -105,14 +105,17 @@ abstract class Background_Process extends \WP_Background_Process {
*
* @return $this
*/
public function update( $key, $data ) {
public function update( $key, $batch ) {
$data = $batch->data;
if ( ! empty( $data ) ) {
global $wpdb;
$wpdb->update(
$this->table,
[
'data' => maybe_serialize($data),
'processed_last' => date('Y-m-d H:i:s')
'processed_last' => date('Y-m-d H:i:s'),
'progress_label' => $batch->progress_label,
'progress_value' => $batch->progress_value
],
['ID' => $key]
);
@ -221,7 +224,7 @@ abstract class Background_Process extends \WP_Background_Process {
// TODO: find a way to catch and log PHP errors as
try {
$task = $this->task( $batch->data, $batch->key );
$task = $this->task( $batch );
} catch (\Exception $e) {
// TODO: Add Stacktrace
$this->write_error_log($batch->key, ['Fatal Error: ' . $e->getMessage()]);

View File

@ -500,7 +500,7 @@ if ( ! class_exists( 'WP_Background_Process' ) ) {
*
* @return mixed
*/
abstract protected function task( $item, $key );
abstract protected function task( $item );
}
}

View File

@ -9,8 +9,11 @@ class Background_Importer extends Background_Process {
*/
protected $action = 'import';
function task($data, $key) {
function task($batch) {
$data = $batch->data;
$key = $batch->key;
$className = $data['class_name'];
if (class_exists($className)) {
$object = new $className($data);
@ -26,7 +29,13 @@ class Background_Importer extends Background_Process {
if (false === $runned) {
return false;
}
return $object->_to_Array();
$batch->progress_label = $object->get_progress_label();
$batch->progress_value = $object->get_progress_value();
$batch->data = $object->_to_Array(true);
return $batch;
}
return false;

View File

@ -22,6 +22,12 @@ class Importer_Handler {
'slug' => 'csv',
'class_name' => '\Tainacan\Importer\CSV'
]);
$this->register_importer([
'name' => 'Test Importer',
'description' => __('Create 2 test colletions with random items', 'tainacan'),
'slug' => 'test',
'class_name' => '\Tainacan\Importer\Test_Importer'
]);
do_action('tainacan_register_importers');

View File

@ -108,6 +108,7 @@ abstract class Importer {
protected $steps = [
[
'name' => 'Import Items',
'progress_label' => 'Importing Items',
'callback' => 'process_collections'
]
];
@ -516,6 +517,131 @@ abstract class Importer {
return $this->abort;
}
/**
* Gets the current label to be displayed below the progress bar to give
* feedback to the user.
*
* It automatically gets the attribute progress_label from the current step running.
*
* Importers may change this label whenever they want
*
* @return string
*/
public function get_progress_label() {
$current_step = $this->get_current_step();
$steps = $this->get_current_step();
$label = '';
if ( isset($steps[$current_step]) ) {
$step = $steps[$current_step];
if ( isset($step['progress_label']) ) {
$label = $step['progress_label'];
} elseif ( isset($step['name']) ) {
$label = $step['name'];
}
}
if ( sizeof($steps) > 1 ) {
$preLabel = sprintf( __('Step %d of %d', 'tainacan'), $current_step + 1, sizeof($steps) );
$label = $preLabel . ': ' . $label;
}
if ( empty($label) ) {
$label = __('Running Importer', 'tainacan');
}
return $label;
}
/**
* Gets the current value to build the progress bar and give feedback to the user
* on the background process that is running the importer.
*
* It does so by comparing the "size" attribute with the $in_step_count class attribute
* where size indicates the total size of iterations the step will take and $this->in_step_count
* is the current iteration.
*
* For the step with "process_items" as a callback, this method will look for the the $this->collections array
* and sum the value of all "total_items" attributes of each collection. Then it will look for
* $this->get_current_collection and $this->set_current_collection_item to calculate the progress.
*
* The value must be from 0 to 100
*
* If a negative value is passed, it is assumed that the progress is unknown
*/
public function get_progress_value() {
$current_step = $this->get_current_step();
$steps = $this->get_current_step();
$value = -1;
if ( isset($steps[$current_step]) ) {
$step = $steps[$current_step];
if ($step['callback'] == 'process_items') {
$totalItems = 0;
$currentItem = $this->get_current_collection_item();
$current_collection = $this->get_current_collection();
$collections = $this->get_collections();
foreach ($collections as $i => $col) {
if ( isset($col['total_items']) && is_integer($col['total_items']) ) {
$totalItems += $col['total_items'];
if ($i < $current_collection) {
$currentItem += $col['total_items'];
}
}
}
if ($totalItems > 0) {
$value = round( ($currentItem/$totalItems) * 100 );
}
} else {
if ( isset($step['total']) && is_integer($step['total']) && $step['total'] > 0 ) {
$current = $this->get_in_step_count();
$value = round( ($current/$step['total']) * 100 );
}
}
}
return $value;
}
/**
* Sets the total attribute for the current step
*
* The "total" attribute of a step indicates the number of iterations this step will take to complete.
*
* The iteration is counted using $this->in_step_count attribute, and comparing the two values gives us
* the current progress of the process.
*
*/
protected function set_current_step_total(int $value) {
$this->set_step_total($this->get_current_step(), $value);
}
/**
* Sets the total attribute for a given step
*
* The "total" attribute of a step indicates the number of iterations this step will take to complete.
*
* The iteration is counted using $this->in_step_count attribute, and comparing the two values gives us
* the current progress of the process.
*
*/
protected function set_step_total(int $step, int $value) {
$steps = $this->get_steps();
if (isset($steps[$step]) && is_array($steps[$step])) {
$steps[$step]['total'] = $value;
$this->set_steps($steps);
}
}
///////////////////////////////
// Abstract methods

View File

@ -35,23 +35,29 @@ class Test_Importer extends Importer {
[
'name' => 'Create Taxonomies',
'progress_label' => 'Creating taxonomies',
'callback' => 'create_taxonomies'
],
[
'name' => 'Create Collections',
'progress_label' => 'Creating Collections',
'callback' => 'create_collections'
],
[
'name' => 'Import Items',
'progress_label' => 'Importing items',
'callback' => 'process_collections'
],
[
'name' => 'Post-configure taxonomies',
'progress_label' => 'post processing taxonomies',
'callback' => 'close_taxonomies'
],
[
'name' => 'Finalize',
'callback' => 'finish_processing'
'progress_label' => 'Finalizing',
'callback' => 'finish_processing',
'total' => 5
]
];

View File

@ -15,12 +15,25 @@ function tainacan_create_bd_process_db() {
data longtext NOT NULL,
action text NOT NULL,
done boolean not null default 0,
progress_label text,
progress_value int,
PRIMARY KEY (ID),
KEY user_id (user_id),
KEY action (action($max_index_length))
) $charset_collate;\n";
$wpdb->query($query);
$column_exists = $wpdb->get_results( "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'wp_t' AND column_name = 'progress_label'" );
if(empty($column_exists)) {
$wpdb->query("
ALTER TABLE {$wpdb->prefix}tnc_bg_process
ADD progress_label text,
ADD progress_value int
");
}
}