Skip to content

Commit

Permalink
Merge branch 'develop' into fix/92-update-php-message
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffpaul committed Feb 19, 2020
2 parents 253d005 + baccd42 commit d2cd9a4
Show file tree
Hide file tree
Showing 13 changed files with 856 additions and 99 deletions.
4 changes: 4 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ Describe the actions you performed (e.g., commands you ran, text you typed, butt
### Applicable Issues

<!-- Enter any applicable Issues here -->

### Changelog Entry

<!-- Add sample CHANGELOG.md entry for this PR, noting whether this is something being Added / Changed / Deprecated / Removed / Fixed / or Security related. -->
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ release
/vendor/*
phpunit.xml
/dist
coverage

debug.log

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
* Classify your content using [IBM Watson's Natural Language Understanding API](https://www.ibm.com/watson/services/natural-language-understanding/) and [Microsoft Azure's Computer Vision API](https://azure.microsoft.com/en-us/services/cognitive-services/computer-vision/)
* Supports Watson's [Categories](https://console.bluemix.net/docs/services/natural-language-understanding/index.html#categories), [Keywords](https://console.bluemix.net/docs/services/natural-language-understanding/index.html#keywords), [Concepts](https://console.bluemix.net/docs/services/natural-language-understanding/index.html#concepts) & [Entities](https://console.bluemix.net/docs/services/natural-language-understanding/index.html#entities) and Azure's [Describe Image](https://westus.dev.cognitive.microsoft.com/docs/services/5adf991815e1060e6355ad44/operations/56f91f2e778daf14a499e1fe)
* Automatically classify content and images on save
* [Smartly crop images](https://docs.microsoft.com/en-us/rest/api/cognitiveservices/computervision/generatethumbnail) around a region of interest identified by Computer Vision
* Bulk classify content with [WP-CLI](https://wp-cli.org/)

## Requirements

* PHP 7.0+
* [WordPress](http://wordpress.org) 5.0+
* To utilize the Lanaguage Processing functionality, you will need an active [IBM Watson](https://cloud.ibm.com/registration) account.
* To utilize the Language Processing functionality, you will need an active [IBM Watson](https://cloud.ibm.com/registration) account.
* To utilize the Image Processing functionality, you will need an active [Microsoft Azure](https://signup.azure.com/signup) account.

## Installation
Expand Down Expand Up @@ -61,13 +62,13 @@

#### 3. Configure Post Types to classify and IBM Watson Features to enable under ClassifAI > Language Processing
- Choose which public post types to classify when saved.
- Chose whether to assign category, keyword, entity, and concept as well as the taxonomies used for each.
- Choose whether to assign category, keyword, entity, and concept as well as the taxonomies used for each.

#### 4. Save Post or run WP CLI command to batch classify posts

## Set Up Image Processing (via Microsoft Azure)

Note that [Computer Vision](https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/home#image-requirements) can analyze images that meet the following requirements:
Note that [Computer Vision](https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/home#image-requirements) can analyze and crop images that meet the following requirements:
- The image must be presented in JPEG, PNG, GIF, or BMP format
- The file size of the image must be less than 4 megabytes (MB)
- The dimensions of the image must be greater than 50 x 50 pixels
Expand Down
2 changes: 1 addition & 1 deletion includes/Classifai/Admin/Notifications.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function maybe_render_notices() {
if ( $needs_setup ) {
printf(
'<div class="notice notice-warning"><p><a href="%s">' . esc_html__( 'ClassifAI requires setup', 'classifai' ) . '</a></p></div>',
esc_url( admin_url( 'options-general.php?page=classifai_settings' ) )
esc_url( admin_url( 'admin.php?page=classifai_settings' ) )
);
delete_transient( 'classifai_activation_notice' );
}
Expand Down
67 changes: 67 additions & 0 deletions includes/Classifai/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,70 @@ function get_feature_taxonomy( $feature ) {
*/
return apply_filters( 'classifai_taxonomy_for_feature', $taxonomy, $feature );
}

/**
* Provides the max filesize for the Computer Vision service.
*
* @since 1.4.0
*
* @return int
*/
function computer_vision_max_filesize() {
/**
* Filters the Computer Vision maximum allowed filesize.
*
* @param int Default 4MB.
*/
return apply_filters( 'classifai_computer_vision_max_filesize', 4 * MB_IN_BYTES ); // 4MB default.
}

/**
* Callback for sorting images by width plus height, descending.
*
* @since 1.5.0
*
* @param array $size_1 Associative array containing width and height values.
* @param array $size_2 Associative array containing width and height values.
* @return int Returns -1 if $size_1 is larger, 1 if $size_2 is larger, and 0 if they are equal.
*/
function sort_images_by_size_cb( $size_1, $size_2 ) {
$size_1_total = $size_1['width'] + $size_1['height'];
$size_2_total = $size_2['width'] + $size_2['height'];

if ( $size_1_total === $size_2_total ) {
return 0;
}

return $size_1_total > $size_2_total ? -1 : 1;
}

/**
* Retrieves the URL of the largest version of an attachment image lower than a specified max size.
*
* @since 1.4.0
*
* @param string $full_image The path to the full-sized image source file.
* @param string $full_url The URL of the full-sized image.
* @param array $sizes Intermediate size data from attachment meta.
* @param int $max The maximum acceptable size.
* @return string|null The image URL, or null if no acceptable image found.
*/
function get_largest_acceptable_image_url( $full_image, $full_url, $sizes, $max = MB_IN_BYTES ) {
$file_size = @filesize( $full_image ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
if ( $file_size && $max >= $file_size ) {
return $full_url;
}

usort( $sizes, __NAMESPACE__ . '\sort_images_by_size_cb' );

foreach ( $sizes as $size ) {
$sized_file = str_replace( basename( $full_image ), $size['file'], $full_image );
$file_size = @filesize( $sized_file ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged

if ( $file_size && $max >= $file_size ) {
return str_replace( basename( $full_url ), $size['file'], $full_url );
}
}

return null;
}
5 changes: 3 additions & 2 deletions includes/Classifai/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ public function init() {
$post_type,
'_classifai_error',
[
'show_in_rest' => true,
'single' => true,
'show_in_rest' => true,
'single' => true,
'auth_callback' => '__return_true',
]
);
}
Expand Down
119 changes: 65 additions & 54 deletions includes/Classifai/Providers/Azure/ComputerVision.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

use Classifai\Providers\Provider;

use function Classifai\computer_vision_max_filesize;
use function Classifai\get_largest_acceptable_image_url;

class ComputerVision extends Provider {

/**
Expand Down Expand Up @@ -48,32 +51,60 @@ public function can_register() {
if ( empty( $options ) ) {
return false;
}

return true;
}

/**
* Register the functionality.
*/
public function register() {
add_filter( 'wp_generate_attachment_metadata', [ $this, 'process_image' ], 10, 2 );
add_filter( 'wp_generate_attachment_metadata', [ $this, 'smart_crop_image' ], 8, 2 );
add_filter( 'wp_generate_attachment_metadata', [ $this, 'generate_image_alt_tags' ], 8, 2 );
add_filter( 'posts_clauses', [ $this, 'filter_attachment_query_keywords' ], 10, 1 );
}


/**
* Provides the max filesize for the ComputerVision service.
* Adds smart-cropped image thumbnails to the attachment metadata.
*
* @return int
* @since 1.5.0
* @filter wp_generate_attachment_metadata
*
* @since 1.4.0
* @param array $metadata Attachment metadata.
* @param int $attachment_id Attachment ID.
* @return array Filtered attachment metadata.
*/
public function get_max_filesize() {
public function smart_crop_image( $metadata, $attachment_id ) {
$settings = $this->get_settings();

if ( ! is_array( $metadata ) || ! is_array( $settings ) ) {
return $metadata;
}

$should_smart_crop = isset( $settings['enable_smart_cropping'] ) && '1' === $settings['enable_smart_cropping'];

/**
* Filters the ComputerVision maximum allowed filesize.
* Filters whether to apply smart cropping to the current image.
*
* @param int Default 4MB.
* @since 1.5.0
*
* @param boolean Whether to apply smart cropping. The default value is set in ComputerVision settings.
* @param array Image metadata.
* @param int The attachment ID.
*/
return apply_filters( 'classifai_computervision_max_filesize', 4 * MB_IN_BYTES ); // 4MB default.
if ( ! apply_filters( 'classifai_should_smart_crop_image', $should_smart_crop, $metadata, $attachment_id ) ) {
return $metadata;
}

// Direct file system access is required for the current implementation of this feature.
$access_type = get_filesystem_method();
if ( 'direct' !== $access_type || ! WP_Filesystem() ) {
return $metadata;
}

$smart_cropping = new SmartCropping( $settings );

return $smart_cropping->generate_attachment_metadata( $metadata, intval( $attachment_id ) );
}

/**
Expand All @@ -84,18 +115,19 @@ public function get_max_filesize() {
*
* @return mixed
*/
public function process_image( $metadata, $attachment_id ) {
public function generate_image_alt_tags( $metadata, $attachment_id ) {

$settings = $this->get_settings();
if (
'no' !== $settings['enable_image_tagging'] ||
'no' !== $settings['enable_image_captions']
) {
if ( isset( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ) {
$image_url = $this->get_largest_acceptable_image_url(
$image_url = get_largest_acceptable_image_url(
get_attached_file( $attachment_id ),
wp_get_attachment_url( $attachment_id, 'full' ),
$metadata['sizes']
$metadata['sizes'],
computer_vision_max_filesize()
);
} else {
$image_url = wp_get_attachment_url( $attachment_id, 'full' );
Expand All @@ -121,48 +153,6 @@ public function process_image( $metadata, $attachment_id ) {
return $metadata;
}

/**
* Retrieves the URL of the largest version of an attachment image accepted by the ComputerVision service.
*
* @param string $full_image The path to the full-sized image source file.
* @param string $full_url The URL of the full-sized image.
* @param array $sizes Intermediate size data from attachment meta.
* @return string|null The image URL, or null if no acceptable image found.
*
* @since 1.4.0
*/
public function get_largest_acceptable_image_url( $full_image, $full_url, $sizes ) {
$file_size = @filesize( $full_image ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
if ( $file_size && $this->get_max_filesize() >= $file_size ) {
return $full_url;
}

// Sort the image sizes in order of total width + height, descending.
$sort_sizes = function( $size_1, $size_2 ) {
$size_1_total = $size_1['width'] + $size_1['height'];
$size_2_total = $size_2['width'] + $size_2['height'];

if ( $size_1_total === $size_2_total ) {
return 0;
}

return $size_1_total > $size_2_total ? -1 : 1;
};

usort( $sizes, $sort_sizes );

foreach ( $sizes as $size ) {
$sized_file = str_replace( basename( $full_image ), $size['file'], $full_image );
$file_size = @filesize( $sized_file ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged

if ( $file_size && $this->get_max_filesize() >= $file_size ) {
return str_replace( basename( $full_url ), $size['file'], $full_url );
}
}

return null;
}

/**
* Scan the image and return the captions.
*
Expand Down Expand Up @@ -396,6 +386,23 @@ public function setup_fields_sections() {
'options' => $options,
]
);

add_settings_field(
'enable-smart-cropping',
esc_html__( 'Enable smart cropping', 'classifai' ),
[ $this, 'render_input' ],
$this->get_option_name(),
$this->get_option_name(),
[
'label_for' => 'enable_smart_cropping',
'input_type' => 'checkbox',
'default_value' => false,
'description' => __(
'Crop images around a region of interest identified by ComputerVision',
'classifai'
),
]
);
}

/**
Expand Down Expand Up @@ -457,6 +464,9 @@ public function sanitize_settings( $settings ) {
$new_settings['image_tag_taxonomy'] = $settings['image_tag_taxonomy'];
}

$smart_cropping_enabled = isset( $settings['enable_smart_cropping'] ) ? '1' : 'no';
$new_settings['enable_smart_cropping'] = $smart_cropping_enabled;

return $new_settings;
}

Expand Down Expand Up @@ -497,6 +507,7 @@ protected function authenticate_credentials( $url, $api_key ) {
* Provides debug information related to the provider.
*
* @param null|array $settings Settings array. If empty, settings will be retrieved.
* @return array Keyed array of debug information.
* @since 1.4.0
*/
public function get_provider_debug_information( $settings = null ) {
Expand Down
Loading

0 comments on commit d2cd9a4

Please sign in to comment.