| Current File : /home/digitaw/www/wp-content/plugins/webp-converter-for-media/src/Service/MediaStatusViewer.php |
<?php
namespace WebpConverter\Service;
use WebpConverter\Conversion\AttachmentPathsGenerator;
use WebpConverter\Conversion\Endpoint\RegenerateAttachmentEndpoint;
use WebpConverter\Conversion\Format\AvifFormat;
use WebpConverter\Conversion\Format\FormatFactory;
use WebpConverter\Conversion\Format\WebpFormat;
use WebpConverter\Conversion\LargerFilesOperator;
use WebpConverter\Conversion\OutputPathGenerator;
use WebpConverter\HookableInterface;
use WebpConverter\Model\Token;
use WebpConverter\PluginData;
use WebpConverter\Repository\TokenRepository;
use WebpConverter\Settings\Option\MediaStatsOption;
use WebpConverter\Settings\Page\PageIntegrator;
/**
* Generates information about conversion status in Media Library.
*/
class MediaStatusViewer implements HookableInterface {
/**
* @var PluginData
*/
private $plugin_data;
/**
* @var TokenRepository
*/
private $token_repository;
/**
* @var OutputPathGenerator
*/
private $output_path;
/**
* @var AttachmentPathsGenerator|null
*/
private $attachment = null;
/**
* @var Token|null
*/
private $token = null;
public function __construct(
PluginData $plugin_data,
TokenRepository $token_repository,
FormatFactory $format_factory,
?OutputPathGenerator $output_path = null
) {
$this->plugin_data = $plugin_data;
$this->token_repository = $token_repository;
$this->output_path = $output_path ?: new OutputPathGenerator( $format_factory );
}
/**
* {@inheritdoc}
*/
public function init_hooks() {
add_action( 'admin_init', [ $this, 'init_hooks_after_setup' ] );
add_filter( 'webpc_attachment_stats', [ $this, 'get_conversion_stats_for_attachment' ], 10, 3 );
}
/**
* @return void
* @internal
*/
public function init_hooks_after_setup() {
$plugin_settings = $this->plugin_data->get_plugin_settings();
if ( ! $plugin_settings[ MediaStatsOption::OPTION_NAME ] ) {
return;
}
add_filter( 'manage_media_columns', [ $this, 'add_custom_table_column' ] );
add_action( 'manage_media_custom_column', [ $this, 'print_table_column_value' ], 10, 2 );
add_action( 'attachment_submitbox_misc_actions', [ $this, 'print_attachment_sidebar_value' ], 20 );
add_filter( 'wp_prepare_attachment_for_js', [ $this, 'add_status_for_attachment_data' ], 10, 2 );
}
/**
* @param string $current_value .
* @param int $post_id .
* @param int|null $strategy_level .
*
* @return string|null
* @internal
*/
public function get_conversion_stats_for_attachment( string $current_value, int $post_id, ?int $strategy_level = null ): ?string {
$conversion_status = $this->get_conversion_status( $post_id, $strategy_level );
if ( $conversion_status === null ) {
return null;
}
return wp_kses( implode( PHP_EOL, $conversion_status ), $this->get_allowed_html_tags() );
}
/**
* @param string[] $columns .
*
* @return string[]
* @internal
*/
public function add_custom_table_column( array $columns ): array {
$columns['webpc_status'] = 'Converter for Media';
return $columns;
}
/**
* @param string $column_name .
* @param int $post_id .
*
* @return void
* @internal
*/
public function print_table_column_value( string $column_name, int $post_id ) {
if ( ( $column_name !== 'webpc_status' ) || ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
$conversion_stats = $this->get_conversion_stats_for_attachment( '', $post_id );
if ( $conversion_stats === null ) {
return;
}
printf(
'<div id="webpc-attachment-trigger-%1$s-wrapper">%2$s</div>',
esc_attr( (string) $post_id ),
wp_kses( $conversion_stats, $this->get_allowed_html_tags() )
);
}
/**
* @param \WP_Post $post .
*
* @return void
* @internal
*/
public function print_attachment_sidebar_value( \WP_Post $post ) {
$conversion_stats = $this->get_conversion_stats_for_attachment( '', $post->ID );
if ( $conversion_stats === null ) {
return;
}
?>
<div class="misc-pub-section misc-pub-webpc">
<div id="webpc-attachment-trigger-<?php echo esc_attr( (string) $post->ID ); ?>-wrapper">
<?php echo wp_kses( $conversion_stats, $this->get_allowed_html_tags() ); ?>
</div>
<small>
<?php
echo wp_kses_post(
sprintf(
/* translators: %s: plugin name */
__( 'Optimized by: %s', 'webp-converter-for-media' ),
sprintf( '<a href="%1$s">%2$s</a>', esc_attr( PageIntegrator::get_settings_page_url() ), 'Converter for Media' )
)
);
?>
</small>
</div>
<?php
}
/**
* @param mixed[] $response .
* @param \WP_Post $attachment .
*
* @return mixed[]
* @internal
*/
public function add_status_for_attachment_data( array $response, \WP_Post $attachment ): array {
$source_post_id = (string) ( $_REQUEST['post_id'] ?? '' ); // phpcs:ignore WordPress.Security
if ( $source_post_id !== '0' ) {
return $response;
}
$conversion_stats = $this->get_conversion_stats_for_attachment( '', $attachment->ID );
if ( $conversion_stats === null ) {
return $response;
}
$response['compat'] = $response['compat'] ?? [];
$response['compat']['meta'] = $response['compat']['meta'] ?? '';
$response['compat']['meta'] .= sprintf(
'<br><div id="webpc-attachment-trigger-%1$s-wrapper">%2$s</div><small>%3$s</small>',
$attachment->ID,
$conversion_stats,
wp_kses_post(
sprintf(
/* translators: %s: plugin name */
__( 'Optimized by: %s', 'webp-converter-for-media' ),
sprintf( '<a href="%1$s">%2$s</a>', esc_attr( PageIntegrator::get_settings_page_url() ), 'Converter for Media' )
)
)
);
return $response;
}
/**
* @param int $post_id .
* @param int|null $strategy_level .
*
* @return string[]|null
*/
private function get_conversion_status( int $post_id, ?int $strategy_level = null ): ?array {
$this->attachment = $this->attachment ?: new AttachmentPathsGenerator( $this->plugin_data );
$this->token = $this->token ?: $this->token_repository->get_token();
$source_paths = $this->attachment->get_attachment_paths( $post_id );
if ( ! $source_paths ) {
return null;
}
$images_stats = $this->get_images_stats( $source_paths, $post_id );
if ( ! $images_stats ) {
return null;
}
$percent_values = array_filter(
array_column( $images_stats, 'optimized_percent' ),
function ( $value ) {
return ! is_null( $value );
}
);
$percent_average = ( $percent_values )
? -( 100 - round( array_sum( $percent_values ) / count( $percent_values ) ) )
: null;
$rows = [
sprintf(
/* translators: %s: percent value */
__( 'Average image size reduction: %s', 'webp-converter-for-media' ),
( $percent_average !== null )
?
sprintf(
'<abbr title="%1$s">%2$s</abbr>',
esc_html__( 'File size reduction of all thumbnails compared to the original ones.', 'webp-converter-for-media' ),
( '<strong>' . ( ( $percent_average > 0 ) ? ( '+' . $percent_average ) : $percent_average ) . '%</strong>' )
)
: '<strong>—</strong>'
),
'<br>',
'<div class="webpcMediaStat">',
sprintf(
'<input type="checkbox" class="webpcMediaStat__button" id="stats-webp-converter-for-media-attachment-%s">',
$post_id
),
sprintf(
'<label for="stats-webp-converter-for-media-attachment-%1$s" class="webpcMediaStat__buttonLabel webpcMediaStat__buttonLabel--unchecked button button-small">%2$s</label>',
$post_id,
sprintf(
/* translators: %s: files count */
__( 'Show stats for all thumbnails (%s)', 'webp-converter-for-media' ),
count( $images_stats )
)
),
sprintf(
'<label for="stats-webp-converter-for-media-attachment-%1$s" class="webpcMediaStat__buttonLabel webpcMediaStat__buttonLabel--checked button button-small">%2$s</label>',
$post_id,
__( 'Hide stats', 'webp-converter-for-media' )
),
'<div class="webpcMediaStat__wrapper">',
];
if ( ! $this->token->get_valid_status() ) {
$rows[] = '<div class="webpcMediaStat__notice">';
$rows[] = sprintf(
/* translators: %1$s: call to action, %2$s: format name, %3$s: percent value, %4$s: format name */
__( '%1$s and convert your images to the %2$s format, making them weigh about %3$s less than images converted only to the %4$s format.', 'webp-converter-for-media' ),
sprintf(
/* translators: %1$s: open anchor tag, %2$s: close anchor tag */
__( '%1$sUpgrade to PRO%2$s', 'webp-converter-for-media' ),
'<a href="https://url.mattplugins.com/converter-media-stats-notice-upgrade" target="_blank">',
' </a>'
),
'AVIF',
'50%',
'WebP'
);
$rows[] = '</div>';
}
foreach ( $images_stats as $images_stat ) {
$percent_value = -( 100 - $images_stat['optimized_percent'] );
$rows[] = sprintf(
'<div class="webpcMediaStat__item">
<div class="webpcMediaStat__itemProgress">
<div class="webpcMediaStat__itemProgressInner" style="width: %5$s%%;"></div>
</div>
<a href="%1$s" target="_blank" class="webpcMediaStat__itemLink">%2$s</a>
<br>
%3$s
<br>
%4$s
</div>',
$images_stat['file_url'],
basename( $images_stat['file_url'] ),
sprintf(
/* translators: %s: file size */
__( 'Original file size: %s', 'webp-converter-for-media' ),
sprintf( '<strong>%s</strong>', size_format( $images_stat['original_size'] ) )
),
( $images_stat['output_format'] )
?
sprintf(
/* translators: %1$s: format name, %2$s: file size */
__( 'Optimized file size in the %1$s format: %2$s', 'webp-converter-for-media' ),
$images_stat['output_format'],
sprintf(
'<strong>%1$s <abbr title="%2$s">(%3$s)</abbr></strong>',
size_format( $images_stat['optimized_size'] ),
sprintf(
/* translators: %s: format name */
__( 'Image size reduction after conversion to the %s format compared to the original one.', 'webp-converter-for-media' ),
$images_stat['output_format']
),
( $percent_value > 0 )
? sprintf( '+%s%%', $percent_value )
: sprintf( '%s%%', $percent_value )
)
)
:
sprintf(
/* translators: %s: file size */
__( 'Optimized file size: %s', 'webp-converter-for-media' ),
'<strong>-</strong>'
),
( $images_stat['output_format'] )
? $images_stat['optimized_percent']
: 0
);
}
$rows[] = '</div>';
$rows[] = '</div>';
$quality_levels = apply_filters( 'webpc_option_quality_levels', [ 75, 80, 85, 90, 95 ] );
$quality_levels = [
intval( $quality_levels[0] ?? 75 ),
intval( $quality_levels[1] ?? 80 ),
intval( $quality_levels[2] ?? 85 ),
intval( $quality_levels[3] ?? 90 ),
intval( $quality_levels[4] ?? 95 ),
0,
];
$rows[] = '<br>';
$rows[] = sprintf(
'<select id="webpc-attachment-trigger-%1$s" onchange="webpcConvertAttachment(this,%1$s);" data-api-path="%2$s|%3$s">%4$s</select><span id="webpc-attachment-trigger-%1$s-spinner" class="spinner no-float" hidden></span>',
$post_id,
RegenerateAttachmentEndpoint::get_route_url(),
RegenerateAttachmentEndpoint::get_route_nonce(),
implode(
'',
[
sprintf(
'<option value="%1$s" %2$s disabled>%3$s</option>',
'',
( $strategy_level === null ) ? 'selected' : '',
( $percent_average !== null )
? __( 'Re-optimize Now', 'webp-converter-for-media' )
: __( 'Optimize Now', 'webp-converter-for-media' )
),
sprintf(
'<option value="%1$s" %2$s>%3$s</option>',
$quality_levels[0],
( $strategy_level === $quality_levels[0] ) ? 'selected' : '',
sprintf(
/* translators: %s: strategy level */
'— ' . __( 'using Strategy %s', 'webp-converter-for-media' ),
sprintf( '%1$s (%2$s)', '#1', __( 'Lossy', 'webp-converter-for-media' ) )
)
),
sprintf(
'<option value="%1$s" %2$s>%3$s</option>',
$quality_levels[1],
( $strategy_level === $quality_levels[1] ) ? 'selected' : '',
sprintf(
/* translators: %s: strategy level */
'— ' . __( 'using Strategy %s', 'webp-converter-for-media' ),
'#2'
)
),
sprintf(
'<option value="%1$s" %2$s>%3$s</option>',
$quality_levels[2],
( $strategy_level === $quality_levels[2] ) ? 'selected' : '',
sprintf(
/* translators: %s: strategy level */
'— ' . __( 'using Strategy %s', 'webp-converter-for-media' ),
sprintf( '%1$s (%2$s)', '#3', __( 'Optimal', 'webp-converter-for-media' ) )
)
),
sprintf(
'<option value="%1$s" %2$s>%3$s</option>',
$quality_levels[3],
( $strategy_level === $quality_levels[3] ) ? 'selected' : '',
sprintf(
/* translators: %s: strategy level */
'— ' . __( 'using Strategy %s', 'webp-converter-for-media' ),
'#4'
)
),
sprintf(
'<option value="%1$s" %2$s>%3$s</option>',
$quality_levels[4],
( $strategy_level === $quality_levels[4] ) ? 'selected' : '',
sprintf(
/* translators: %s: strategy level */
'— ' . __( 'using Strategy %s', 'webp-converter-for-media' ),
sprintf( '%1$s (%2$s)', '#5', __( 'Lossless', 'webp-converter-for-media' ) )
)
),
( $percent_average !== null )
?
sprintf(
'<option value="%1$s" %2$s>%3$s</option>',
$quality_levels[5],
( $strategy_level === $quality_levels[5] ) ? 'selected' : '',
__( 'Restore Originals', 'webp-converter-for-media' )
)
: '',
]
)
);
return $rows;
}
/**
* @param string[] $source_paths .
* @param int $attachment_id .
*
* @return mixed[] {
* @type int $original_size .
* @type int|null $optimized_size .
* @type int|null $optimized_percent Size of optimized file compared to the original one (from >0 to <=100).
* @type string|null $output_format .
* @type string $file_url .
* }
*/
private function get_images_stats( array $source_paths, int $attachment_id ): array {
$file_url = wp_get_attachment_url( $attachment_id ) ?: null;
if ( $file_url ) {
$file_url = dirname( $file_url );
}
$items = [];
foreach ( $source_paths as $source_path ) {
$filesize_original = ( file_exists( $source_path ) ) ? ( filesize( $source_path ) ?: null ) : null;
if ( $filesize_original === null ) {
continue;
}
$output_path_webp = $this->output_path->get_path( $source_path, false, WebpFormat::FORMAT_EXTENSION );
$output_path_avif = $this->output_path->get_path( $source_path, false, AvifFormat::FORMAT_EXTENSION );
$filesize_avif = ( $output_path_avif )
? ( ( file_exists( $output_path_avif ) ) ? ( filesize( $output_path_avif ) ?: null ) : null )
: null;
$filesize_webp = ( $output_path_webp )
? ( ( file_exists( $output_path_webp ) ) ? ( filesize( $output_path_webp ) ?: null ) : null )
: null;
$status_avif = ( ( $filesize_avif !== null ) || file_exists( $output_path_avif . '.' . LargerFilesOperator::DELETED_FILE_EXTENSION ) );
$status_webp = ( ( $filesize_webp !== null ) || file_exists( $output_path_webp . '.' . LargerFilesOperator::DELETED_FILE_EXTENSION ) );
$items[] = [
'original_size' => $filesize_original,
'optimized_size' => ( $filesize_avif !== null )
? $filesize_avif
: ( ( $filesize_webp !== null )
? $filesize_webp
: ( ( $status_avif || $status_webp ) ? $filesize_original : null )
),
'optimized_percent' => ( $filesize_avif !== null )
? round( $filesize_avif / $filesize_original * 100 )
: ( ( $filesize_webp !== null )
? round( $filesize_webp / $filesize_original * 100 )
: ( ( $status_avif || $status_webp ) ? 100 : null )
),
'output_format' => ( $filesize_avif !== null )
? 'AVIF'
: ( ( ( $filesize_webp !== null ) || $status_webp )
? 'WebP'
: null
),
'file_url' => sprintf( '%1$s/%2$s', $file_url, basename( $source_path ) ),
];
}
return $items;
}
/**
* @return mixed[]
*/
private function get_allowed_html_tags(): array {
return [
'a' => [
'href' => [],
'class' => [],
'target' => [],
],
'abbr' => [
'title' => [],
],
'br' => [],
'div' => [
'id' => [],
'class' => [],
'style' => [],
],
'input' => [
'id' => [],
'type' => [],
'class' => [],
],
'label' => [
'for' => [],
'class' => [],
],
'option' => [
'value' => [],
'selected' => [],
'disabled' => [],
],
'select' => [
'id' => [],
'onchange' => [],
'data-api-path' => [],
],
'span' => [
'id' => [],
'class' => [],
'hidden' => [],
],
'strong' => [
'class' => [],
'titleyik mnb ' => [],
],
];
}
}