PluginProbe ʕ •ᴥ•ʔ
TinyPNG – JPEG, PNG & WebP image compression / 3.8.0
TinyPNG – JPEG, PNG & WebP image compression v3.8.0
3.8.0 3.7.0 3.6.14 trunk 1.0.0 1.1.0 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.4.0 1.5.0 1.6.0 1.7.0 1.7.1 1.7.2 2.0.0 2.0.1 2.0.2 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.0.0 3.0.1 3.1.0 3.2.0 3.2.1 3.3 3.4 3.4.1 3.4.2 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.6.0 3.6.1 3.6.10 3.6.11 3.6.12 3.6.13 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9
tiny-compress-images / src / class-tiny-image-size.php
tiny-compress-images / src Last commit date
compatibility 2 months ago config 2 months ago css 7 months ago data 4 years ago images 4 years ago js 1 week ago vendor 6 months ago views 1 week ago class-tiny-apache-rewrite.php 2 months ago class-tiny-bulk-optimization.php 2 months ago class-tiny-cli.php 2 months ago class-tiny-compress-client.php 1 week ago class-tiny-compress-fopen.php 2 months ago class-tiny-compress.php 1 week ago class-tiny-conversion.php 4 months ago class-tiny-diagnostics.php 7 months ago class-tiny-exception.php 7 months ago class-tiny-helpers.php 2 months ago class-tiny-image-size.php 1 week ago class-tiny-image.php 1 week ago class-tiny-logger.php 2 months ago class-tiny-migrate.php 2 months ago class-tiny-notices.php 2 months ago class-tiny-php.php 2 months ago class-tiny-picture.php 2 months ago class-tiny-plugin.php 1 week ago class-tiny-settings.php 1 week ago class-tiny-source-base.php 1 week ago class-tiny-source-image.php 7 months ago class-tiny-source-picture.php 7 months ago class-tiny-wp-base.php 2 months ago
class-tiny-image-size.php
309 lines
1 <?php
2 /*
3 * Tiny Compress Images - WordPress plugin.
4 * Copyright (C) 2015-2018 Tinify B.V.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc., 51
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 class Tiny_Image_Size {
22 public $filename;
23 public $meta = array();
24
25 /**
26 * Whether the file exists on disk.
27 *
28 * @var bool|null $exists
29 */
30 private $exists;
31
32 /**
33 * File size in bytes.
34 *
35 * @var int|null $file_size
36 */
37 private $file_size;
38
39 /**
40 * MIME type of the file.
41 *
42 * @var string|null $mime_type
43 */
44 private $mime_type;
45
46 private $duplicate = false;
47
48 private $duplicate_of_size = '';
49
50 public function __construct( $filename = null ) {
51 $this->filename = $filename;
52 }
53
54 public function end_time() {
55 if ( isset( $this->meta['end'] ) ) {
56 return $this->meta['end'];
57 } elseif ( isset( $this->meta['timestamp'] ) ) {
58 return $this->meta['timestamp'];
59 } else {
60 return null;
61 }
62 }
63
64 public function add_tiny_meta_start() {
65 $this->meta = array(
66 'start' => time(),
67 );
68 }
69
70 public function add_tiny_meta( $response ) {
71 if ( isset( $this->meta['start'] ) ) {
72 $this->meta = $response;
73 $this->meta['end'] = time();
74 $this->clear_memoized_filesystem();
75 }
76 }
77
78 /**
79 * Clears the memoized exists/file_size/mime_type values.
80 *
81 * Must be called whenever the file on disk changed after those were
82 * memoized, e.g. after compression overwrites it, so the next read
83 * reflects the new file instead of the stale cached one.
84 *
85 * @return void
86 */
87 private function clear_memoized_filesystem() {
88 clearstatcache( true, $this->filename );
89 $this->exists = null;
90 $this->file_size = null;
91 $this->mime_type = null;
92 }
93
94 public function add_tiny_meta_error( $exception ) {
95 if ( isset( $this->meta['start'] ) ) {
96 $this->meta = array(
97 'error' => $exception->get_type(),
98 'message' => $exception->get_message(),
99 'timestamp' => time(),
100 );
101 }
102 }
103
104 /**
105 * Marks the image size as compressed without actually processing it.
106 *
107 * This method simulates the compression process by creating metadata that
108 * indicates the image has been processed, while keeping the original file
109 * size and format unchanged. Useful for marking images as compressed when
110 * they don't need actual compression or have been processed externally.
111 *
112 * @since 3.0.0
113 *
114 * @param bool $include_conversion Optional. Whether to include conversion metadata.
115 * When true, adds conversion data with current
116 * file information. Default false.
117 * @return void
118 */
119 public function mark_as_compressed( $include_conversion = false ) {
120
121 if ( ! $this->has_been_compressed() ) {
122 $this->add_tiny_meta_start();
123 $tiny_image_size_meta = array(
124 'input' => array(
125 'size' => $this->filesize(),
126 ),
127 'output' => array(
128 'size' => $this->filesize(),
129 'type' => $this->mimetype(),
130 ),
131 );
132 $this->add_tiny_meta( $tiny_image_size_meta );
133 }
134
135 if ( ! $this->has_been_converted() && $include_conversion ) {
136 $this->meta['convert'] = array(
137 'size' => $this->filesize(),
138 'type' => $this->mimetype(),
139 'path' => $this->filename,
140 );
141 }
142 }
143
144 public function has_been_compressed() {
145 return isset( $this->meta['output'] );
146 }
147
148 public function has_been_converted() {
149 return isset( $this->meta['convert'] );
150 }
151
152 public function never_compressed() {
153 return ! $this->has_been_compressed();
154 }
155
156 public function filesize() {
157 if ( is_null( $this->file_size ) ) {
158 if ( $this->exists() ) {
159 $this->file_size = filesize( $this->filename );
160 } else {
161 $this->file_size = 0;
162 }
163 }
164 return $this->file_size;
165 }
166
167 public function mimetype() {
168 if ( is_null( $this->mime_type ) ) {
169 if ( $this->exists() ) {
170 $file = file_get_contents( $this->filename );
171 $this->mime_type = Tiny_Helpers::get_mimetype( $file );
172 } else {
173 $this->mime_type = 'application/octet-stream';
174 }
175 }
176 return $this->mime_type;
177 }
178
179 public function exists() {
180 if ( is_null( $this->exists ) ) {
181 $this->exists = $this->filename && file_exists( $this->filename );
182 }
183 return $this->exists;
184 }
185
186 private function same_size() {
187 return ( $this->filesize() == $this->meta['output']['size'] );
188 }
189
190 public function still_exists() {
191 return $this->has_been_compressed() && $this->exists();
192 }
193
194 public function missing() {
195 return $this->has_been_compressed() && ! $this->exists();
196 }
197
198 /**
199 * Checks wether the image has been processed for conversion.
200 * Will still return true if conversion was not needed.
201 *
202 * @return bool true if image is processed for conversion
203 */
204 public function converted() {
205 return isset( $this->meta['convert'] );
206 }
207
208 /**
209 * Checks wether the image is applicable for conversion and has
210 * not been converted yet.
211 *
212 * @return bool true if image can be converted and has not been converted
213 */
214 public function unconverted() {
215 return ! $this->converted() && $this->exists();
216 }
217
218 /**
219 * Checks if the converted image size exists
220 *
221 * @return boolean true if the image size has a optimized alternative format
222 */
223 public function converted_image_exists() {
224 if ( ! $this->converted() ) {
225 return false;
226 }
227 return file_exists( $this->meta['convert']['path'] );
228 }
229
230 public function conversion_text() {
231 if ( ! $this->converted() ) {
232 return esc_html__( 'Not converted', 'tiny-compress-images' );
233 }
234 $conversion_text = $this->meta['convert']['type'] . ' (' .
235 size_format( $this->meta['convert']['size'], 1 ) . ')';
236 return $conversion_text;
237 }
238
239 public function compressed() {
240 return $this->still_exists() && $this->same_size();
241 }
242
243 public function modified() {
244 return $this->still_exists() && ! $this->same_size();
245 }
246
247 public function uncompressed() {
248 return $this->exists() &&
249 ! $this->is_duplicate() &&
250 ! ( isset( $this->meta['output'] ) && $this->same_size() );
251 }
252
253 public function in_progress() {
254 return $this->recently_started() && ! isset( $this->meta['output'] );
255 }
256
257 public function resized() {
258 return (
259 isset( $this->meta['output'] ) &&
260 isset( $this->meta['output']['resized'] ) &&
261 $this->meta['output']['resized']
262 );
263 }
264
265 public function mark_duplicate( $duplicate_size_name ) {
266 $this->duplicate = true;
267 $this->duplicate_of_size = $duplicate_size_name;
268 }
269 public function is_duplicate() {
270 return $this->duplicate;
271 }
272
273 public function duplicate_of_size() {
274 return $this->duplicate_of_size;
275 }
276
277 /**
278 * Deletes the converted image file for this image size.
279 *
280 * @return void
281 */
282 public function delete_converted_image_size() {
283 if ( ! $this->converted_image_exists() ) {
284 return;
285 }
286 $upload_dir = wp_upload_dir();
287 $convert_real_path = realpath( $this->meta['convert']['path'] );
288 $real_basedir = realpath( $upload_dir['basedir'] );
289
290 if (
291 $convert_real_path &&
292 Tiny_Helpers::str_starts_with(
293 $convert_real_path,
294 trailingslashit( $real_basedir )
295 )
296 ) {
297 unlink( $convert_real_path );
298 }
299 }
300
301 private function recently_started() {
302 $thirty_minutes_ago = gmdate( 'U' ) - ( 60 * 30 );
303 return (
304 isset( $this->meta['start'] ) &&
305 $this->meta['start'] > $thirty_minutes_ago
306 );
307 }
308 }
309