Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVIF settings update #775

Merged
merged 6 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions classes/Avif/Avif.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
namespace Imagify\Avif;

use Imagify\Traits\InstanceGetterTrait;

/**
* AVIF image
*/
class Avif {
use InstanceGetterTrait;

/**
* Class init: launch hooks.
*
* @since 2.2
*/
public function init() {
}
}
119 changes: 108 additions & 11 deletions classes/Bulk/Bulk.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ class Bulk {
*/
public function init() {
add_action( 'imagify_optimize_media', [ $this, 'optimize_media' ], 10, 3 );
add_action( 'imagify_convert_webp', [ $this, 'generate_webp_versions' ], 10, 2 );
add_action( 'imagify_convert_next_gen', [ $this, 'generate_next_gen_versions' ], 10, 2 );
add_action( 'imagify_convert_webp_finished', [ $this, 'clear_webp_transients' ], 10, 2 );
add_action( 'wp_ajax_imagify_bulk_optimize', [ $this, 'bulk_optimize_callback' ] );
add_action( 'imagify_bulk_optimize', [ $this, 'bulk_optimize' ], 10, 2 );
add_action( 'wp_ajax_imagify_missing_webp_generation', [ $this, 'missing_webp_callback' ] );
add_action( 'wp_ajax_imagify_get_folder_type_data', [ $this, 'get_folder_type_data_callback' ] );
add_action( 'wp_ajax_imagify_bulk_info_seen', [ $this, 'bulk_info_seen_callback' ] );
add_action( 'wp_ajax_imagify_bulk_get_stats', [ $this, 'bulk_get_stats_callback' ] );
add_action( 'imagify_after_optimize', [ $this, 'check_optimization_status' ], 10, 2 );
add_action( 'imagify_deactivation', [ $this, 'delete_transients_data' ] );
add_action( 'update_option_imagify_settings', [ $this, 'maybe_bulk_optimize_callback' ] );
}

/**
Expand Down Expand Up @@ -266,10 +268,11 @@ public function run_generate_webp( array $contexts ) {
foreach ( $media_ids as $media_id ) {
try {
as_enqueue_async_action(
'imagify_convert_webp',
'imagify_convert_next_gen',
[
'id' => $media_id,
'context' => $context,
'format' => static::,
],
"imagify-{$context}-convert-webp"
);
Expand Down Expand Up @@ -310,13 +313,13 @@ private function get_bulk_class_name( string $context ): string {
}

/**
* Filter the name of the class to use for bulk process.
*
* @since 1.9
*
* @param int $class_name The class name.
* @param string $context The context name.
*/
* Filter the name of the class to use for bulk process.
*
* @since 1.9
*
* @param int $class_name The class name.
* @param string $context The context name.
*/
$class_name = apply_filters( 'imagify_bulk_class_name', $class_name, $context );

return '\\' . ltrim( $class_name, '\\' );
Expand Down Expand Up @@ -383,12 +386,29 @@ private function force_optimize( int $media_id, string $context, int $level ) {
*
* @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
*/
public function generate_webp_versions( int $media_id, string $context ) {
public function generate_next_gen_versions( int $media_id, string $context ) {
if ( ! $this->can_optimize() ) {
return false;
}

return imagify_get_optimization_process( $media_id, $context )->generate_webp_versions();
return imagify_get_optimization_process( $media_id, $context )->generate_next_gen_versions();
}
/**
* Generate AVIF images if they are missing.
*
* @since 2.2
*
* @param int $media_id Media ID.
* @param string $context Current context.
*
* @return bool|WP_Error True if successfully launched. A \WP_Error instance on failure.
*/
public function generate_avif_versions( int $media_id, string $context ) {
if ( ! $this->can_optimize() ) {
return false;
}

return imagify_get_optimization_process( $media_id, $context )->generate_avif_versions();
}

/**
Expand Down Expand Up @@ -455,6 +475,16 @@ public function get_optimization_level( $method = 'GET', $parameter = 'optimizat
/** BULK OPTIMIZATION CALLBACKS ============================================================= */
/** ----------------------------------------------------------------------------------------- */

/**
* Launch the bulk optimization without going through AJAX.
*
* @param string $context Current context (WP/Custom folders).
* @param int $level Optimization level.
* @return void
*/
public function bulk_optimize( $context, $level ) {
$this->run_optimize( $context, $level );
}
/**
* Launch the bulk optimization action
*
Expand Down Expand Up @@ -575,4 +605,71 @@ public function bulk_get_stats_callback() {

wp_send_json_success( imagify_get_bulk_stats( array_flip( $folder_types ) ) );
}

/**
* Update Options callback to start bulk optimization.
*
* @since 2.2
*
* @return void
*/
public function maybe_bulk_optimize_callback() {
$level = \Imagify_Options::get_instance()->get( 'optimization_level' );
$contexts = $this->get_contexts();
foreach ( $contexts as $context ) {
do_action( 'imagify_bulk_optimize', $context, $level );
}
}

/**
* Get the context for the bulk optimization page.
*
* @since 2.2
*
* @return array The array of unique contexts ('wp' or 'custom-folders').
*/
public function get_contexts() {
$contexts = [];
$types = [];

// Library: in each site.
if ( ! is_network_admin() ) {
$types['library|wp'] = 1;
}

// Custom folders: in network admin only if network activated, in each site otherwise.
if ( imagify_can_optimize_custom_folders() && ( imagify_is_active_for_network() && is_network_admin() || ! imagify_is_active_for_network() ) ) {
$types['custom-folders|custom-folders'] = 1;
}

/**
* Filter the types to display in the bulk optimization page.
*
* @since 1.7.1
*
* @param array $types The folder types displayed on the page. If a folder type is "library", the context should be suffixed after a pipe character. They are passed as array keys.
*/
$types = apply_filters( 'imagify_bulk_page_types', $types );
$types = array_filter( (array) $types );

if ( isset( $types['library|wp'] ) && ! in_array( 'wp', $contexts, true ) ) {
$contexts[] = 'wp';
}

if ( isset( $types['custom-folders|custom-folders'] ) ) {
$folders_instance = \Imagify_Folders_DB::get_instance();

if ( ! $folders_instance->has_items() ) {
// New Feature!
if ( ! in_array( 'wp', $contexts, true ) ) {
$contexts[] = 'wp';
}
} elseif ( $folders_instance->has_active_folders() && ! in_array( 'custom-folders', $contexts, true ) ) {
$contexts[] = 'custom-folders';
}
}

return $contexts;
}

}
2 changes: 1 addition & 1 deletion classes/Job/MediaOptimization.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ private function task_optimize( $item ) {

} elseif ( 'already_optimized' === $data['status'] ) {
// Status is "already_optimized", try to create WebP versions only.
$item['sizes'] = array_filter( $item['sizes'], [ $this->optimization_process, 'is_size_webp' ] );
$item['sizes'] = array_filter( $item['sizes'], [ $this->optimization_process, 'is_size_next_gen' ] );

} elseif ( 'success' !== $data['status'] ) {
// Don't go further if the full size has not the "success" status.
Expand Down
63 changes: 50 additions & 13 deletions classes/Optimization/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public function can_be_processed() {
return new \WP_Error(
'not_exists',
sprintf(
/* translators: %s is a file path. */
/* translators: %s is a file path. */
__( 'The file %s does not seem to exist.', 'imagify' ),
'<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
)
Expand All @@ -124,7 +124,7 @@ public function can_be_processed() {
return new \WP_Error(
'not_a_file',
sprintf(
/* translators: %s is a file path. */
/* translators: %s is a file path. */
__( 'This does not seem to be a file: %s.', 'imagify' ),
'<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
)
Expand All @@ -135,7 +135,7 @@ public function can_be_processed() {
return new \WP_Error(
'not_writable',
sprintf(
/* translators: %s is a file path. */
/* translators: %s is a file path. */
__( 'The file %s does not seem to be writable.', 'imagify' ),
'<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
)
Expand All @@ -148,7 +148,7 @@ public function can_be_processed() {
return new \WP_Error(
'folder_not_writable',
sprintf(
/* translators: %s is a file path. */
/* translators: %s is a file path. */
__( 'The folder %s does not seem to be writable.', 'imagify' ),
'<code>' . esc_html( $this->filesystem->make_path_relative( $parent_folder ) ) . '</code>'
)
Expand Down Expand Up @@ -197,7 +197,7 @@ public function resize( $dimensions = [], $max_width = 0 ) {
return new \WP_Error(
'not_an_image',
sprintf(
/* translators: %s is a file path. */
/* translators: %s is a file path. */
__( 'The file %s does not seem to be an image, and cannot be resized.', 'imagify' ),
'<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
)
Expand Down Expand Up @@ -321,7 +321,7 @@ public function create_thumbnail( $destination ) {
return new \WP_Error(
'not_an_image',
sprintf(
/* translators: %s is a file path. */
/* translators: %s is a file path. */
__( 'The file %s does not seem to be an image, and cannot be resized.', 'imagify' ),
'<code>' . esc_html( $this->filesystem->make_path_relative( $this->path ) ) . '</code>'
)
Expand Down Expand Up @@ -474,7 +474,7 @@ public function optimize( $args = [] ) {
*
* @param string $path Absolute path to the media file.
* @param array $args Arguments passed to the method.
*/
*/
do_action( 'imagify_before_optimize_file', $this->path, $args );

/**
Expand All @@ -485,7 +485,7 @@ public function optimize( $args = [] ) {
*
* @param string $path Absolute path to the image file.
* @param bool $backup True if a backup will be make.
*/
*/
do_action_deprecated( 'before_do_imagify', [ $this->path, $args['backup'] ], '1.9', 'imagify_before_optimize_file' );

if ( $args['backup'] ) {
Expand All @@ -509,6 +509,7 @@ public function optimize( $args = [] ) {

if ( $args['convert'] ) {
$data['convert'] = $args['convert'];
$format = $args['convert'];
}

$response = upload_imagify_image( [
Expand All @@ -534,8 +535,12 @@ public function optimize( $args = [] ) {
$args['convert'] = '';
}

if ( 'webp' === $args['convert'] ) {
$destination_path = $this->get_path_to_webp();
$formats = [
'webp',
'avif',
];
if ( in_array( $args['convert'], $formats, true ) ) {
$destination_path = $this->get_path_to_next_gen( $args['convert'] );
$this->path = $destination_path;
$this->file_type = null;
$this->editor = null;
Expand All @@ -557,7 +562,7 @@ public function optimize( $args = [] ) {
*
* @param string $path Absolute path to the image file.
* @param bool $backup True if a backup has been made.
*/
*/
do_action_deprecated( 'after_do_imagify', [ $this->path, $args['backup'] ], '1.9', 'imagify_before_optimize_file' );

/**
Expand All @@ -568,7 +573,7 @@ public function optimize( $args = [] ) {
*
* @param string $path Absolute path to the media file.
* @param array $args Arguments passed to the method.
*/
*/
do_action( 'imagify_after_optimize_file', $this->path, $args );

return $response;
Expand Down Expand Up @@ -603,7 +608,7 @@ protected function get_editor() {
$this->editor = new \WP_Error(
'image_editor',
sprintf(
/* translators: %1$s is an error message, %2$s is a "More info?" link. */
/* translators: %1$s is an error message, %2$s is a "More info?" link. */
__( 'No php extensions are available to edit images on the server. ImageMagick or GD is required. The internal error is: %1$s. %2$s', 'imagify' ),
$this->editor->get_error_message(),
'<a href="' . esc_url( imagify_get_external_url( 'documentation-imagick-gd' ) ) . '" target="_blank">' . __( 'More info?', 'imagify' ) . '</a>'
Expand Down Expand Up @@ -765,6 +770,26 @@ public function get_path_to_webp() {
return imagify_path_to_webp( $this->path );
}

/**
* Replace the file extension by its next-gen format extension.
*
* @since 2.2
*
* @param string $format the format we are targeting.
* @return string|bool The file path on success. False if not an image or on failure.
*/
public function get_path_to_next_gen( string $format ) {
if ( ! $this->is_image() ) {
return false;
}

if ( $this->is_webp() || $this->is_avif() ) {
return false;
}

return imagify_path_to_next_gen( $this->path, $format );
}

/**
* Tell if the file is a WebP image.
* Rejects "path/to/.webp" files.
Expand All @@ -778,6 +803,18 @@ public function is_webp() {
return preg_match( '@(?!^|/|\\\)\.webp$@i', $this->path );
}

/**
* Tell if the file is an AVIF image.
* Rejects "path/to/.avif" files.
*
* @since 2.2
*
* @return bool
*/
public function is_avif() {
return preg_match( '@(?!^|/|\\\)\.avif$@i', $this->path );
}

/**
* Get the file mime type + file extension.
*
Expand Down
Loading