PluginProbe
ezCache / trunk
ezCache vtrunk
2.6.5 2.6.4 2.6.2 2.6.3 2.6.1 2.6.0 2.5.6 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5 2.2.1 2.2.2 trunk 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.3 1.3.1 1.3.10 1.3.11 All 49 releases
ezcache / includes / WebpApi.php

WebpApi.php in ezCache trunk, at includes/WebpApi.php

119 lines 3.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Upress\EzCache;
3
4 use Upress\EzCache\Utilities\Logger;
5 use WP_Error;
6
7 class WebpApi {
8 protected $domain;
9 protected $license_tail;
10 protected $license_len;
11 protected $api_url = 'https://api.ezcache-wp.com';
12
13 function __construct( $key = '' ) {
14 $this->domain = str_replace( [ 'https://', 'http://' ], '', get_bloginfo( 'wpurl' ) );
15 $this->license_tail = ! empty( $key ) ? substr( $key, -4 ) : '';
16 $this->license_len = strlen( $key );
17 }
18
19 public static function is_available() {
20 return PremiumFeatures::is_premium();
21 }
22
23 public function convert( $image_path ) {
24 if ( ! self::is_available() ) {
25 return new WP_Error( 'premium_required', 'WebP conversion requires a premium license' );
26 }
27
28 wp_raise_memory_limit( 'image' );
29
30 $file = @fopen( $image_path, 'r' );
31 if ( ! $file ) {
32 return new WP_Error( 'invalid_input_file', 'Unable to read source image file' );
33 }
34
35 $file_size = filesize( $image_path );
36 $file_data = fread( $file, $file_size );
37 @fclose( $file );
38
39 if ( false === $file_data || $file_size === 0 ) {
40 return new WP_Error( 'invalid_input_file', 'Unable to read source image file' );
41 }
42
43 $mime = wp_check_filetype( $image_path );
44 $content_type = $mime['type'] ?: 'application/binary';
45
46 $quality = 80;
47 if ( strpos( $content_type, 'png' ) !== false || strpos( $content_type, 'gif' ) !== false ) {
48 $quality = 100;
49 }
50
51 $url = $this->api_url . '/convert?' . http_build_query( [
52 'quality' => $quality,
53 'domain' => $this->domain,
54 'key_len' => $this->license_len,
55 ] );
56
57 $request_args = [
58 'headers' => [
59 'Content-Type' => $content_type,
60 'X-Domain' => $this->domain,
61 'X-License-Tail' => $this->license_tail,
62 'X-Requested-By' => 'wp_remote_request',
63 ],
64 'body' => $file_data,
65 'timeout' => 120,
66 'user-agent' => 'ezCache WebP Converter/2.0',
67 ];
68
69 $max_retries = 3;
70 $retry_delay = 2;
71
72 for ( $attempt = 1; $attempt <= $max_retries; $attempt++ ) {
73 $response = wp_remote_post( $url, $request_args );
74
75 if ( is_wp_error( $response ) ) {
76 Logger::log( 'ezCache WebP API Error (attempt ' . $attempt . '): ' . $response->get_error_message() );
77 if ( $attempt < $max_retries ) {
78 sleep( $retry_delay * $attempt );
79 continue;
80 }
81 return $response;
82 }
83
84 $status_code = wp_remote_retrieve_response_code( $response );
85
86 if ( $status_code === 429 && $attempt < $max_retries ) {
87 Logger::log( 'ezCache WebP API rate limited (attempt ' . $attempt . '), retrying in ' . ($retry_delay * $attempt) . 's' );
88 sleep( $retry_delay * $attempt );
89 continue;
90 }
91
92 break;
93 }
94
95 $info = wp_remote_retrieve_headers( $response );
96 $result = wp_remote_retrieve_body( $response );
97
98 if ( $status_code !== 200 ) {
99 $error_msg = 'WebP API error (HTTP ' . $status_code . ')';
100 if ( strpos( $result, '"error"' ) !== false ) {
101 $json = json_decode( $result, true );
102 if ( isset( $json['error'] ) ) {
103 $error_msg = $json['error'];
104 }
105 }
106 Logger::log( 'ezCache WebP API Error: ' . $error_msg );
107 return new WP_Error( 'api_error', $error_msg );
108 }
109
110 $response_type = wp_remote_retrieve_header( $response, 'content-type' );
111 if ( strpos( $response_type, 'webp' ) === false ) {
112 Logger::log( 'ezCache WebP API Error: response is not WebP (got ' . $response_type . ')' );
113 return new WP_Error( 'invalid_response', 'API did not return a WebP image' );
114 }
115
116 return [ 'info' => $info, 'data' => $result ];
117 }
118 }
119