PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 2.2.11
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v2.2.11
4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 3.8.0 All 110 releases
wp-optimize / includes / class-updraft-smush-task.php

class-updraft-smush-task.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 2.2.11, at includes/class-updraft-smush-task.php

326 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * A sample implementation using the Resmush.it API and our tasks library
4 */
5
6 if (!defined('ABSPATH')) die('Access denied.');
7
8 if (!class_exists('Updraft_Task_1_0')) require_once(WPO_PLUGIN_MAIN_PATH . 'vendor/team-updraft/common-libs/src/updraft-tasks/class-updraft-task.php');
9
10 if (!class_exists('Smush_Task')) :
11
12 abstract class Updraft_Smush_Task extends Updraft_Task_1_0 {
13
14 /**
15 * A flag indicating if the operation was succesful
16 *
17 * @var bool
18 */
19 protected $success = false;
20
21 /**
22 * A text descriptor describing the stage of the task
23 *
24 * @var string
25 */
26 protected $stage;
27
28 /**
29 * Initialise the task
30 *
31 * @param Array $options - options to use
32 */
33 public function initialise($options = array()) {
34 parent::initialise($options);
35 $this->set_current_stage('initialised');
36 do_action('ud_task_initialised', $this);
37 }
38
39 /**
40 * Runs the task
41 *
42 * @return bool - true if complete, false otherwise
43 */
44 public function run() {
45
46 do_action('ud_task_started', $this);
47
48 $attachment_id = $this->get_option('attachment_id');
49 $file_path = get_attached_file($attachment_id);
50
51 if (!$this->validate_file($file_path)) return false;
52
53 $this->update_option('original_filesize', filesize($file_path));
54 $this->log($this->get_description());
55
56
57 $post_data = $this->prepare_post_request($file_path);
58 $api_endpoint = $this->get_option('api_endpoint');
59
60 if (false === filter_var($api_endpoint, FILTER_VALIDATE_URL)) {
61 $this->fail("invalid_api_url", "The API endpoint supplied {$api_endpoint} is invalid");
62 }
63
64 $response = $this->post_to_remote_server($api_endpoint, $post_data);
65 $optimised_image = $this->process_server_response($response);
66
67 if ($optimised_image) {
68 $this->save_optimised_image($file_path, $optimised_image);
69 }
70
71 return $this->success;
72 }
73
74 /**
75 * Posts the supplied data to the API url and returns a response
76 *
77 * @param String $api_endpoint - the url to post the form to
78 * @param String $post_data - the post data as specified by the server
79 * @return mixed - the response
80 */
81 public function post_to_remote_server($api_endpoint, $post_data) {
82
83 $this->set_current_stage('connecting');
84 $response = wp_remote_post($api_endpoint, $post_data);
85
86 if (is_wp_error($response)) {
87 $this->fail($response->get_error_code(), $response->get_error_message());
88 return false;
89 }
90
91 return $response;
92 }
93
94 /**
95 * Processes the response recieved from the remote server
96 *
97 * @param mixed $response - the response object
98 * @return mixed - the response
99 */
100 public function process_server_response($response) {
101 $this->set_current_stage('processing_response');
102 return $response;
103 }
104
105 /**
106 * Checks if a file is valid and capable of being smushed
107 *
108 * @param String $file_path - the path of the original image
109 * @return bool - true on success, false otherwise
110 */
111 public function validate_file($file_path) {
112
113 $allowed_file_types = $this->get_option('allowed_file_types');
114
115 if (!file_exists($file_path)) {
116 $this->fail("invalid_file_path", "The linked attachment ID does not have a valid file path");
117 return false;
118 }
119
120 if (filesize($file_path) > $this->get_option('max_filesize')) {
121 $this->fail("exceeded_max_filesize", "$file_path - cannot be optimized, file size is above service provider limit");
122 return false;
123 }
124
125 if (!in_array(pathinfo($file_path, PATHINFO_EXTENSION), $allowed_file_types)) {
126 $this->fail("invalid_file_type", "$file_path - cannot be optimized, it has an invalid file type");
127 return false;
128 }
129
130 return true;
131 }
132
133 /**
134 * Creates a backup of the original image
135 *
136 * @param String $file_path - the path of the original image
137 * @return bool - true on success, false otherwise
138 */
139 public function backup_original_image($file_path) {
140
141 $this->set_current_stage('backup_original');
142
143 $file = pathinfo($file_path);
144 $back_up = $file['dirname'].'/'.basename($file['filename'].$this->get_option('backup_prefix').$file['extension']);
145
146 update_post_meta($this->get_option('attachment_id'), 'original-file', $back_up);
147 $this->log("Backing up the original image - {$back_up}");
148
149 return copy($file_path, $back_up);
150 }
151
152 /**
153 * Creates a backup of the original image
154 *
155 * @param String $file_path - the path of the original image
156 * @param Mixes $optimised_image - the contents of the image
157 * @return bool - true on success, false otherwise
158 */
159 public function save_optimised_image($file_path, $optimised_image) {
160
161 $this->set_current_stage('saving_image');
162
163 if ($this->get_option('keep_original'))
164 $this->backup_original_image($file_path);
165
166 if (false !== file_put_contents($file_path, $optimised_image)) {
167 $this->success = true;
168 } else {
169 $this->success = false;
170 }
171
172 return $this->success;
173 }
174
175 /**
176 * Fires if the task succeds, any clean up code and logging goes here
177 */
178 public function complete() {
179
180 $attachment_id = $this->get_option('attachment_id');
181 $file_path = get_attached_file($attachment_id);
182 $original_size = $this->get_option('original_filesize');
183 $this->set_current_stage('completed');
184
185 clearstatcache(true, $file_path); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.clearstatcache_clear_realpath_cacheFound,PHPCompatibility.FunctionUse.NewFunctionParameters.clearstatcache_filenameFound
186 $saved = round((($original_size - filesize($file_path)) / $original_size * 100), 2);
187 $info = sprintf(__("The file was compressed from %s to %s saving %s percent using WP-Optimize", 'wp-optimize'), $this->format_filesize($original_size), $this->format_filesize(filesize($file_path)), $saved);
188
189 $stats = array(
190 'smushed-with' => $this->label,
191 'original-size' => $original_size,
192 'smushed-size' => filesize($file_path),
193 'savings-percent' => $saved,
194 );
195
196 update_post_meta($attachment_id, 'smush-complete', true);
197 update_post_meta($attachment_id, 'smush-info', $info);
198 update_post_meta($attachment_id, 'smush-stats', $stats);
199
200 $this->log("Successfully optimized the image - {$file_path}." . $info);
201
202 return parent::complete();
203 }
204
205 /**
206 * Fires if the task fails, any clean up code and logging goes here
207 *
208 * @param String $error_code - A code for the failure
209 * @param String $error_message - A description for the failure
210 */
211 public function fail($error_code = "Unknown", $error_message = "Unknown") {
212
213 $attachment_id = $this->get_option('attachment_id');
214
215 $info = sprintf(__("Failed with error code %s - %s", 'wp-optimize'), $error_code, $error_message);
216
217 update_post_meta($attachment_id, 'smush-info', $info);
218 update_post_meta($attachment_id, 'smush-complete', false);
219
220 do_action('ud_smush_task_failed', $this, $error_code, $error_message);
221
222 return parent::fail($error_code, $error_message);
223 }
224
225 /**
226 * Get all the supported task stages.
227 *
228 * @return array - list of task stages.
229 */
230 public function get_allowed_stages() {
231
232 $stages = array(
233 'initialised' => __('Initialised', 'wp-optimize'),
234 'connecting' => __('Connecting to API server', 'wp-optimize'),
235 'processing_response' => __('Processing response', 'wp-optimize'),
236 'backup_original' => __('Backing up original image', 'wp-optimize'),
237 'saving_image' => __('Saving optimized image', 'wp-optimize'),
238 'completed' => __('Successful', 'wp-optimize'),
239 );
240
241 return apply_filters('allowed_task_stages', $stages);
242 }
243
244 /**
245 * Get features available with this service
246 *
247 * @return Array - an array of features
248 */
249 public static function get_features() {
250 return array(
251 'max_filesize' => self::MAX_FILESIZE,
252 'lossy_compression' => true,
253 'preserve_exif' => true,
254 );
255 }
256
257 /**
258 * Retrieve default options for this task.
259 * This method should normally be over-ridden by the child.
260 *
261 * @return Array - an array of options
262 */
263 public function get_default_options() {
264
265 return array(
266 'allowed_file_types' => array('gif', 'png', 'jpg', 'tif', 'jpeg'),
267 'request_timeout' => 15,
268 'image_quality' => 90,
269 'backup_prefix' => '-updraft-pre-smush-original.'
270 );
271 }
272
273 /**
274 * Sets the task stage.
275 *
276 * @param String $stage - the current stage of the task
277 * @return bool - the result of the update
278 */
279 public function set_current_stage($stage) {
280
281 if (array_key_exists($stage, self::get_allowed_stages())) {
282 $this->stage = $stage;
283 return $this->update_option('current_stage', $this->stage);
284 }
285
286 return false;
287 }
288
289 /**
290 * Gets the task stage
291 *
292 * @return String $stage - the current stage of the task
293 */
294 public function get_current_stage() {
295 if (isset($this->stage))
296 return $this->stage;
297 else return $this->get_option('current_stage');
298 }
299
300
301 /**
302 * Helper function to format bytes to a human readable value
303 *
304 * @param int $bytes - the filesize in bytes
305 */
306 public function format_filesize($bytes) {
307
308 if (1073741824 <= $bytes) {
309 $bytes = number_format($bytes / 1073741824, 2) . ' GB';
310 } elseif (1048576 <= $bytes) {
311 $bytes = number_format($bytes / 1048576, 2) . ' MB';
312 } elseif (1024 <= $bytes) {
313 $bytes = number_format($bytes / 1024, 2) . ' KB';
314 } elseif (1 < $bytes) {
315 $bytes = $bytes . ' bytes';
316 } elseif (1 == $bytes) {
317 $bytes = $bytes . ' byte';
318 } else {
319 $bytes = '0 bytes';
320 }
321
322 return $bytes;
323 }
324 }
325 endif;
326