From 52641e26f0342d34181b1dcc80d556cf2cb14640 Mon Sep 17 00:00:00 2001 From: Tung Du Date: Mon, 19 Oct 2020 09:06:27 +0700 Subject: [PATCH 1/5] feat: add crop command --- .../Classifai/Command/ClassifaiCommand.php | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/includes/Classifai/Command/ClassifaiCommand.php b/includes/Classifai/Command/ClassifaiCommand.php index 37f922fb9..8e9e812e4 100644 --- a/includes/Classifai/Command/ClassifaiCommand.php +++ b/includes/Classifai/Command/ClassifaiCommand.php @@ -253,8 +253,13 @@ public function image( $args = [], $opts = [] ) { $limit_total = min( $total, intval( $opts['limit'] ) ); } - $errors = []; - $message = "Classifying $limit_total images ..."; + $errors = []; + $message = "Classifying $limit_total images ..."; + + if ( ! empty( $opts['crop_only'] ) ) { + $message = "Cropping $limit_total images ..."; + } + $progress_bar = \WP_CLI\Utils\make_progress_bar( $message, $limit_total ); for ( $index = 0; $index < $limit_total; $index++ ) { @@ -263,8 +268,9 @@ public function image( $args = [], $opts = [] ) { $progress_bar->tick(); $current_meta = wp_get_attachment_metadata( $attachment_id ); - \WP_CLI::line( 'Processing ' . $attachment_id ); - $classifier->generate_image_alt_tags( $current_meta, $attachment_id ); + if ( empty( $opts['crop_only'] ) ) { + $classifier->generate_image_alt_tags( $current_meta, $attachment_id ); + } $classifier->smart_crop_image( $current_meta, $attachment_id ); } @@ -273,13 +279,45 @@ public function image( $args = [], $opts = [] ) { $total_errors = count( $errors ); $total_success = $total - $total_errors; - \WP_CLI::success( "Classified $total_success images, $total_errors errors." ); + if ( empty( $opts['crop_only'] ) ) { + \WP_CLI::success( "Classified $total_success images, $total_errors errors." ); + } else { + \WP_CLI::success( "Cropped $total_success images, $total_errors errors." ); + } foreach ( $errors as $attachment_id => $error ) { \WP_CLI::log( $attachment_id . ': ' . $error->get_error_code() . ' - ' . $error->get_error_message() ); } } + /** + * Batch crop image(s). + * + * ## Options + * + * [] + * : Comma delimeted Attachment IDs to crop. + * + * [--limit=] + * : Limit classification to N attachments. Default 100. + * + * [--skip=] + * : Skip first N attachments. Default false. + * + * @param array $args Arguments. + * @param array $opts Options. + */ + public function crop( $args = [], $opts = [] ) { + $opts = array_merge( + $opts, + [ + 'force' => true, + 'crop_only' => true, + ] + ); + $this->image( $args, $opts ); + } + /** * Prints the Basic Auth header based on credentials configured in * the plugin. @@ -391,12 +429,12 @@ private function get_attachment_to_classify( $opts = [] ) { ]; } - \WP_CLI::log( 'Fetching images to classify ...' ); + \WP_CLI::log( 'Fetching images ...' ); $query = new \WP_Query( $query_params ); $images = $query->posts; - \WP_CLI::log( 'Fetching images to classify ... DONE (' . count( $images ) . ')' ); + \WP_CLI::log( 'Fetching images ... DONE (' . count( $images ) . ')' ); return $images; } From 006628b049820ec321aa793b3d0b3595a464bc7b Mon Sep 17 00:00:00 2001 From: Tung Du Date: Mon, 19 Oct 2020 17:42:33 +0700 Subject: [PATCH 2/5] refactor: better error reporting for crop command --- .../Classifai/Command/ClassifaiCommand.php | 107 ++++++++++++++---- .../Providers/Azure/SmartCropping.php | 22 +++- 2 files changed, 106 insertions(+), 23 deletions(-) diff --git a/includes/Classifai/Command/ClassifaiCommand.php b/includes/Classifai/Command/ClassifaiCommand.php index 8e9e812e4..843851ec7 100644 --- a/includes/Classifai/Command/ClassifaiCommand.php +++ b/includes/Classifai/Command/ClassifaiCommand.php @@ -7,6 +7,7 @@ use Classifai\Watson\Normalizer; use Classifai\PostClassifier; use Classifai\Providers\Azure\ComputerVision; +use Classifai\Providers\Azure\SmartCropping; /** * ClassifaiCommand is the command line interface of the ClassifAI plugin. @@ -256,10 +257,6 @@ public function image( $args = [], $opts = [] ) { $errors = []; $message = "Classifying $limit_total images ..."; - if ( ! empty( $opts['crop_only'] ) ) { - $message = "Cropping $limit_total images ..."; - } - $progress_bar = \WP_CLI\Utils\make_progress_bar( $message, $limit_total ); for ( $index = 0; $index < $limit_total; $index++ ) { @@ -268,10 +265,7 @@ public function image( $args = [], $opts = [] ) { $progress_bar->tick(); $current_meta = wp_get_attachment_metadata( $attachment_id ); - if ( empty( $opts['crop_only'] ) ) { - $classifier->generate_image_alt_tags( $current_meta, $attachment_id ); - } - $classifier->smart_crop_image( $current_meta, $attachment_id ); + $classifier->generate_image_alt_tags( $current_meta, $attachment_id ); } $progress_bar->finish(); @@ -279,11 +273,7 @@ public function image( $args = [], $opts = [] ) { $total_errors = count( $errors ); $total_success = $total - $total_errors; - if ( empty( $opts['crop_only'] ) ) { - \WP_CLI::success( "Classified $total_success images, $total_errors errors." ); - } else { - \WP_CLI::success( "Cropped $total_success images, $total_errors errors." ); - } + \WP_CLI::success( "Classified $total_success images, $total_errors errors." ); foreach ( $errors as $attachment_id => $error ) { \WP_CLI::log( $attachment_id . ': ' . $error->get_error_code() . ' - ' . $error->get_error_message() ); @@ -308,14 +298,89 @@ public function image( $args = [], $opts = [] ) { * @param array $opts Options. */ public function crop( $args = [], $opts = [] ) { - $opts = array_merge( - $opts, - [ - 'force' => true, - 'crop_only' => true, - ] - ); - $this->image( $args, $opts ); + $classifier = new ComputerVision( false ); + $settings = $classifier->get_settings(); + $smart_cropping = new SmartCropping( $settings ); + + if ( ! isset( $settings['enable_smart_cropping'] ) || '1' !== $settings['enable_smart_cropping'] ) { + \WP_CLI::error( 'Smart Cropping is disabled. Enable it in Image settings to use this command.' ); + } + + $default_opts = [ + 'limit' => false, + ]; + + $opts = wp_parse_args( $opts, $default_opts ); + + if ( ! empty( $args[0] ) ) { + $attachment_ids = explode( ',', $args[0] ); + } else { + $attachment_ids = $this->get_attachment_to_classify( array_merge( $opts, [ 'force' => true ] ) ); + } + + $total = count( $attachment_ids ); + + if ( empty( $total ) ) { + return \WP_CLI::log( 'No images to crop.' ); + } + + $limit_total = $total; + if ( $opts['limit'] ) { + $limit_total = min( $total, intval( $opts['limit'] ) ); + } + + $errors = []; + $message = "Cropping $limit_total images ..."; + + $progress_bar = \WP_CLI\Utils\make_progress_bar( $message, $limit_total ); + + for ( $index = 0; $index < $limit_total; $index++ ) { + $attachment_id = $attachment_ids[ $index ]; + + $progress_bar->tick(); + + $current_meta = wp_get_attachment_metadata( $attachment_id ); + + foreach ( $current_meta['sizes'] as $size => $size_data ) { + if ( ! $smart_cropping->should_crop( $size ) ) { + continue; + } + + $data = [ + 'width' => $size_data['width'], + 'height' => $size_data['height'], + ]; + + $smart_thumbnail = $smart_cropping->get_cropped_thumbnail( $attachment_id, $data ); + + if ( is_wp_error( $smart_thumbnail ) ) { + $errors[ $attachment_id . ':' . $size_data['width'] . 'x' . $size_data['height'] ] = $smart_thumbnail; + } + } + } + + $progress_bar->finish(); + + $total_errors = count( $errors ); + $total_success = $total - $total_errors; + + foreach ( $errors as $attachment_id => $error ) { + \WP_CLI::log( + sprintf( + '%1$s: %2$s (%3$s).', + $attachment_id, + $error->get_error_message(), + $error->get_error_code() + ) + ); + } + + if ( $total_success > 0 ) { + \WP_CLI::success( "Cropped $total_success images, $total_errors errors." ); + } else { + \WP_CLI::error( "Cropped $total_success images, $total_errors errors." ); + } + } /** diff --git a/includes/Classifai/Providers/Azure/SmartCropping.php b/includes/Classifai/Providers/Azure/SmartCropping.php index c70a5ea88..c8d74d2a5 100644 --- a/includes/Classifai/Providers/Azure/SmartCropping.php +++ b/includes/Classifai/Providers/Azure/SmartCropping.php @@ -182,7 +182,8 @@ public function generate_attachment_metadata( $metadata, $attachment_id ) { ]; $better_thumb_filename = $this->get_cropped_thumbnail( $attachment_id, $data ); - if ( ! empty( $better_thumb_filename ) ) { + + if ( ! empty( $better_thumb_filename ) && ! is_wp_error( $better_thumb_filename ) ) { $metadata['sizes'][ $size ]['file'] = basename( $better_thumb_filename ); } } @@ -235,6 +236,11 @@ public function get_cropped_thumbnail( $attachment_id, $size_data ) { $new_thumb_image = $this->request_cropped_thumbnail( $data ); set_transient( 'classifai_azure_computer_vision_smart_cropping_latest_response', $new_thumb_image, DAY_IN_SECONDS * 30 ); + + if ( is_wp_error( $new_thumb_image ) ) { + return $new_thumb_image; + } + if ( empty( $new_thumb_image ) ) { return false; } @@ -334,10 +340,14 @@ public function request_cropped_thumbnail( $data ) { */ do_action( 'classifai_smart_cropping_after_request', $response, $url, $data ); + $response_body = wp_remote_retrieve_body( $response ); + if ( 200 === wp_remote_retrieve_response_code( $response ) ) { - return wp_remote_retrieve_body( $response ); + return $response_body; } + $response_json = json_decode( $response_body ); + /** * Fires when the generateThumbnail smart-cropping API response did not have a 200 status code. * @@ -350,6 +360,14 @@ public function request_cropped_thumbnail( $data ) { */ do_action( 'classifai_smart_cropping_unsuccessful_response', $response, $url, $data ); + if ( ! empty( $response_json->code ) ) { + return new \WP_Error( $response_json->code, $response_json->message ); + } + + if ( ! empty( $response_json->errors ) ) { + return new \WP_Error( 'classifai_smart_cropping_validation_errors', implode( ' ', $response_json->errors->smartCropping ) ); + } + return false; } } From 8b989e68a6fa09c37fee0b8fced08551497a00c9 Mon Sep 17 00:00:00 2001 From: Tung Du Date: Mon, 19 Oct 2020 17:47:58 +0700 Subject: [PATCH 3/5] fix: better error code naming --- includes/Classifai/Providers/Azure/SmartCropping.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Classifai/Providers/Azure/SmartCropping.php b/includes/Classifai/Providers/Azure/SmartCropping.php index c8d74d2a5..0f1bd4eb4 100644 --- a/includes/Classifai/Providers/Azure/SmartCropping.php +++ b/includes/Classifai/Providers/Azure/SmartCropping.php @@ -365,7 +365,7 @@ public function request_cropped_thumbnail( $data ) { } if ( ! empty( $response_json->errors ) ) { - return new \WP_Error( 'classifai_smart_cropping_validation_errors', implode( ' ', $response_json->errors->smartCropping ) ); + return new \WP_Error( 'classifai_smart_cropping_api_validation_errors', implode( ' ', $response_json->errors->smartCropping ) ); } return false; From 807b476d49467dac8a3851ef238ea849c3248b8d Mon Sep 17 00:00:00 2001 From: Jeffrey Paul Date: Mon, 26 Oct 2020 13:09:55 -0500 Subject: [PATCH 4/5] Update ClassifaiCommand.php --- includes/Classifai/Command/ClassifaiCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/Classifai/Command/ClassifaiCommand.php b/includes/Classifai/Command/ClassifaiCommand.php index 843851ec7..fcc842bd4 100644 --- a/includes/Classifai/Command/ClassifaiCommand.php +++ b/includes/Classifai/Command/ClassifaiCommand.php @@ -286,7 +286,7 @@ public function image( $args = [], $opts = [] ) { * ## Options * * [] - * : Comma delimeted Attachment IDs to crop. + * : Comma delimited Attachment IDs to crop. * * [--limit=] * : Limit classification to N attachments. Default 100. From 25bb9c7fab10d764efdb8c6c92a8a687553c60ec Mon Sep 17 00:00:00 2001 From: Tung Du Date: Wed, 28 Oct 2020 23:21:54 +0700 Subject: [PATCH 5/5] fix: keep current behavior of image command --- includes/Classifai/Command/ClassifaiCommand.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/Classifai/Command/ClassifaiCommand.php b/includes/Classifai/Command/ClassifaiCommand.php index fcc842bd4..0f37e7e21 100644 --- a/includes/Classifai/Command/ClassifaiCommand.php +++ b/includes/Classifai/Command/ClassifaiCommand.php @@ -265,7 +265,9 @@ public function image( $args = [], $opts = [] ) { $progress_bar->tick(); $current_meta = wp_get_attachment_metadata( $attachment_id ); + \WP_CLI::line( 'Processing ' . $attachment_id ); $classifier->generate_image_alt_tags( $current_meta, $attachment_id ); + $classifier->smart_crop_image( $current_meta, $attachment_id ); } $progress_bar->finish();