PluginProbe
WP-Stateless – Google Cloud Storage / 2.1.4
WP-Stateless – Google Cloud Storage v2.1.4
4.4.3 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 All 62 releases
wp-stateless / lib / classes / class-ajax.php

class-ajax.php in WP-Stateless – Google Cloud Storage 2.1.4, at lib/classes/class-ajax.php

569 lines 18.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * AJAX Handler
4 *
5 * @since 1.0.0
6 */
7 namespace wpCloud\StatelessMedia {
8
9 if( !class_exists( 'wpCloud\StatelessMedia\Ajax' ) ) {
10
11 final class Ajax {
12
13 /**
14 * The list of wp_ajax_{name} actions
15 *
16 * @var array
17 */
18 var $actions = array(
19 'stateless_process_image',
20 'get_images_media_ids',
21 'get_other_media_ids',
22 'get_non_library_files_id',
23 'stateless_process_file',
24 'stateless_process_non_library_file',
25 'stateless_get_current_progresses',
26 'stateless_wizard_update_settings',
27 'stateless_reset_progress',
28 'stateless_get_all_fails'
29 );
30
31 /**
32 * The list of wp_ajax_nopriv_{name} actions
33 *
34 * @var array
35 */
36 var $nopriv_actions = array();
37
38 /**
39 * Init AJAX actions
40 *
41 * @author peshkov@UD
42 */
43 public function __construct(){
44
45 foreach( $this->actions as $action ) {
46 add_action( 'wp_ajax_' . $action, array( $this, 'request' ) );
47 }
48
49 foreach( $this->nopriv_actions as $action ) {
50 add_action( 'wp_ajax_nopriv_' . $action, array( $this, 'request' ) );
51 }
52
53 }
54
55 /**
56 * Handles AJAX request
57 *
58 * @author peshkov@UD
59 */
60 public function request() {
61
62 $response = array(
63 'message' => '',
64 'html' => '',
65 );
66
67 try{
68
69 $action = $_REQUEST[ 'action' ];
70
71 /** Determine if the current class has the method to handle request */
72 if( is_callable( array( $this, 'action_'. $action ) ) ) {
73 $response = call_user_func_array( array( $this, 'action_' . $action ), array( $_REQUEST ) );
74 }
75 /** Determine if external function exists to handle request */
76 elseif ( is_callable( 'action_' . $action ) ) {
77 $response = call_user_func_array( $action, array( $_REQUEST ) );
78 }
79 elseif ( is_callable( $action ) ) {
80 $response = call_user_func_array( $action, array( $_REQUEST ) );
81 }
82 /** Oops! */
83 else {
84 throw new \Exception( __( 'Incorrect Request' ) );
85 }
86
87 } catch( \Exception $e ) {
88 wp_send_json_error( $e->getMessage() );
89 }
90
91 wp_send_json_success( $response );
92
93 }
94
95 /**
96 * Update json key to database.
97 */
98 public function action_stateless_wizard_update_settings($data) {
99 $bucket = $data['bucket'];
100 $privateKeyData = base64_decode($data['privateKeyData']);
101
102 if(is_network_admin()){
103 if(get_site_option('sm_mode', 'disabled') == 'disabled')
104 update_site_option( 'sm_mode', 'cdn');
105 update_site_option( 'sm_bucket', $bucket);
106 update_site_option( 'sm_key_json', $privateKeyData);
107 }
108 else{
109 if(get_option('sm_mode', 'disabled') == 'disabled')
110 update_option( 'sm_mode', 'cdn');
111 update_option( 'sm_bucket', $bucket);
112 update_option( 'sm_key_json', $privateKeyData);
113 }
114
115 ud_get_stateless_media()->flush_transients();
116 wp_send_json(array('success' => true));
117 }
118
119 /**
120 * Fail over to image URL if not found on disk
121 * In case image not available on both local and bucket
122 * try to pull image from image URL in case it is accessible by some sort of proxy.
123 *
124 * @param:
125 * $url (int/string): URL of the image.
126 * $save_to (string): Path where to save the image.
127 *
128 * @return:
129 * boolean (true/false)
130 *
131 */
132 public function get_attachment_if_exist($url, $save_to){
133 if(is_int($url))
134 $url = wp_get_attachment_url($url);
135
136 $response = wp_remote_get( $url );
137 if ( !is_wp_error($response) && is_array( $response ) ) {
138 if(!empty($response['response']['code']) && $response['response']['code'] == 200){
139 try{
140 if(wp_mkdir_p(dirname($save_to))){
141 return file_put_contents($save_to, $response['body']);
142 }
143 }
144 catch(Exception $e){
145 throw $e;
146 }
147 }
148 }
149 return false;
150 }
151
152 /**
153 * Regenerate image sizes.
154 */
155 public function action_stateless_process_image() {
156
157 @error_reporting( 0 );
158
159 $id = (int) $_REQUEST['id'];
160 $image = get_post( $id );
161
162 if ( ! $image || 'attachment' != $image->post_type || 'image/' != substr( $image->post_mime_type, 0, 6 ) )
163 throw new \Exception( sprintf( __( 'Failed resize: %s is an invalid image ID.', ud_get_stateless_media()->domain ), esc_html( $_REQUEST['id'] ) ) );
164
165 if ( ! current_user_can( 'manage_options' ) )
166 throw new \Exception( __( "Your user account doesn't have permission to resize images", ud_get_stateless_media()->domain ) );
167
168 $fullsizepath = get_attached_file( $image->ID );
169
170 // If no file found
171 if ( false === $fullsizepath || ! file_exists( $fullsizepath ) ) {
172 $upload_dir = wp_upload_dir();
173
174 // Try get it and save
175 $result_code = ud_get_stateless_media()->get_client()->get_media( apply_filters( 'wp_stateless_file_name', str_replace( trailingslashit( $upload_dir[ 'basedir' ] ), '', $fullsizepath )), true, $fullsizepath );
176
177 if ( $result_code !== 200 ) {
178 if(!$this->get_attachment_if_exist($image->ID, $fullsizepath)){ // Save file to local from proxy.
179 $this->store_failed_attachment( $image->ID, 'images' );
180 throw new \Exception(sprintf(__('Both local and remote files are missing. Unable to resize. (%s)', ud_get_stateless_media()->domain), $image->guid));
181 }
182 }
183 }
184
185 @set_time_limit( -1 );
186
187 $metadata = wp_generate_attachment_metadata( $image->ID, $fullsizepath );
188
189 if ( is_wp_error( $metadata ) ) {
190 $this->store_failed_attachment( $image->ID, 'images' );
191 throw new \Exception($metadata->get_error_message());
192 }
193 if ( empty( $metadata ) ) {
194 $this->store_failed_attachment( $image->ID, 'images' );
195 throw new \Exception(__('Unknown failure reason.', ud_get_stateless_media()->domain));
196 }
197
198 // If this fails, then it just means that nothing was changed (old value == new value)
199 wp_update_attachment_metadata( $image->ID, $metadata );
200
201 $this->store_current_progress( 'images', $id );
202 $this->maybe_fix_failed_attachment( 'images', $image->ID );
203
204 return sprintf( __( '%1$s (ID %2$s) was successfully resized in %3$s seconds.', ud_get_stateless_media()->domain ), esc_html( get_the_title( $image->ID ) ), $image->ID, timer_stop() );
205 }
206
207 /**
208 * @return string
209 * @throws \Exception
210 */
211 public function action_stateless_process_file() {
212 @error_reporting( 0 );
213
214 $id = (int) $_REQUEST['id'];
215 $file = get_post( $id );
216
217 if ( ! $file || 'attachment' != $file->post_type )
218 throw new \Exception( sprintf( __( 'Attachment not found: %s is an invalid file ID.', ud_get_stateless_media()->domain ), esc_html( $id ) ) );
219
220 if ( ! current_user_can( 'manage_options' ) )
221 throw new \Exception( __( "You are not allowed to do this.", ud_get_stateless_media()->domain ) );
222
223 $fullsizepath = get_attached_file( $file->ID );
224 $local_file_exists = file_exists( $fullsizepath );
225
226 if ( false === $fullsizepath || ! $local_file_exists ) {
227 $upload_dir = wp_upload_dir();
228
229 // Try get it and save
230 $result_code = ud_get_stateless_media()->get_client()->get_media( str_replace( trailingslashit( $upload_dir[ 'basedir' ] ), '', $fullsizepath ), true, $fullsizepath );
231
232 if ( $result_code !== 200 ) {
233 if(!$this->get_attachment_if_exist($file->ID, $fullsizepath)){ // Save file to local from proxy.
234 $this->store_failed_attachment( $file->ID, 'other' );
235 throw new \Exception(sprintf(__('File not found (%s)', ud_get_stateless_media()->domain), $file->guid));
236 }
237 else{
238 $local_file_exists = true;
239 }
240 }
241 else{
242 $local_file_exists = true;
243 }
244 }
245
246 if($local_file_exists){
247 $upload_dir = wp_upload_dir();
248
249 if ( !ud_get_stateless_media()->get_client()->media_exists( str_replace( trailingslashit( $upload_dir[ 'basedir' ] ), '', $fullsizepath ) ) ) {
250
251 @set_time_limit( -1 );
252
253 $metadata = wp_generate_attachment_metadata( $file->ID, $fullsizepath );
254
255 if ( is_wp_error( $metadata ) ) {
256 $this->store_failed_attachment( $file->ID, 'other' );
257 throw new \Exception($metadata->get_error_message());
258 }
259 if ( empty( $metadata ) ) {
260 $this->store_failed_attachment( $file->ID, 'other' );
261 throw new \Exception(__('Unknown failure reason.', ud_get_stateless_media()->domain));
262 }
263
264 wp_update_attachment_metadata( $file->ID, $metadata );
265
266 }
267 else{
268 // Stateless mode: we don't need the local version.
269 if(ud_get_stateless_media()->get( 'sm.mode' ) === 'stateless'){
270 unlink($fullsizepath);
271 }
272 }
273
274 }
275
276 $this->store_current_progress( 'other', $id );
277 $this->maybe_fix_failed_attachment( 'other', $file->ID );
278
279 return sprintf( __( '%1$s (ID %2$s) was successfully synchronised in %3$s seconds.', ud_get_stateless_media()->domain ), esc_html( get_the_title( $file->ID ) ), $file->ID, timer_stop() );
280 }
281
282 /**
283 * @return string
284 * @throws \Exception
285 */
286 public function action_stateless_process_non_library_file() {
287 @error_reporting( 0 );
288 $upload_dir = wp_upload_dir();
289 $client = ud_get_stateless_media()->get_client();
290
291 $file_path = trim($_REQUEST['file_path'], '/');
292 $fullsizepath = $upload_dir['basedir'] . '/' . $file_path;
293
294 if ( ! current_user_can( 'manage_options' ) )
295 throw new \Exception( __( "You are not allowed to do this.", ud_get_stateless_media()->domain ) );
296
297 $local_file_exists = file_exists( $fullsizepath );
298
299 if ( !$local_file_exists ) {
300
301 // Try get it and save
302 $result_code = ud_get_stateless_media()->get_client()->get_media( $fullsizepath, true, $fullsizepath );
303
304 if ( $result_code !== 200 ) {
305 // if(!$this->get_attachment_if_exist($file->ID, $fullsizepath)){ // Save file to local from proxy.
306 $this->store_failed_attachment( $file->ID, 'other' );
307 throw new \Exception(sprintf(__('File not found (%s)', ud_get_stateless_media()->domain), $file->guid));
308 // }
309 // else{
310 // $local_file_exists = true;
311 // }
312 }
313 else{
314 $local_file_exists = true;
315 }
316 }
317
318 if($local_file_exists){
319
320 if ( !ud_get_stateless_media()->get_client()->media_exists( $file_path )) {
321
322 @set_time_limit( -1 );
323 $file_type = wp_check_filetype($fullsizepath);
324 /* Add 'image size' image */
325 $media = $client->add_media( array(
326 'name' => $file_path,
327 'absolutePath' => $fullsizepath,
328 'cacheControl' => apply_filters( 'sm:item:cacheControl', 'public, max-age=36000, must-revalidate', $fullsizepath),
329 'contentDisposition' => apply_filters( 'sm:item:contentDisposition', null, $fullsizepath),
330 'mimeType' => $file_type['type'],
331 'metadata' => array(
332 'child-of' => dirname($file_path),
333 'file-hash' => md5( $file_path ),
334 ),
335 ));
336
337
338
339 }
340 else{
341 // Stateless mode: we don't need the local version.
342 if(ud_get_stateless_media()->get( 'sm.mode' ) === 'stateless'){
343 unlink($fullsizepath);
344 }
345 }
346
347 }
348
349 $this->store_current_progress( 'other', $id );
350 $this->maybe_fix_failed_attachment( 'other', $file->ID );
351
352 return sprintf( __( '%1$s (ID %2$s) was successfully synchronised in %3$s seconds.', ud_get_stateless_media()->domain ), esc_html( get_the_title( $file->ID ) ), $file->ID, timer_stop() );
353 }
354
355 /**
356 * Returns IDs of images media objects
357 */
358 public function action_get_images_media_ids() {
359 global $wpdb;
360
361 if ( ! $images = $wpdb->get_results( "SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' ORDER BY ID DESC" ) ) {
362 throw new \Exception( __('No images media objects found.', ud_get_stateless_media()->domain) );
363 }
364
365 $continue = false;
366 if ( isset( $_REQUEST['continue'] ) ) {
367 $continue = (bool) $_REQUEST['continue'];
368 }
369
370 return $this->get_non_processed_media_ids( 'images', $images, $continue );
371 }
372
373 /**
374 * Returns IDs of images media objects
375 */
376 public function action_get_other_media_ids() {
377 global $wpdb;
378
379 if ( ! $files = $wpdb->get_results( "SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type NOT LIKE 'image/%' ORDER BY ID DESC" ) ) {
380 throw new \Exception( __('No files found.', ud_get_stateless_media()->domain) );
381 }
382
383 $continue = false;
384 if ( isset( $_REQUEST['continue'] ) ) {
385 $continue = (bool) $_REQUEST['continue'];
386 }
387
388 return $this->get_non_processed_media_ids( 'other', $files, $continue );
389 }
390
391 /**
392 * Returns IDs of non media library files
393 */
394 public function action_get_non_library_files_id() {
395 $files = apply_filters( 'sm:sync::nonMediaFiles', array() );
396 return $files;
397 }
398
399 /**
400 * Returns current progress storage for all modes (to check whether there is something to continue in JS)
401 */
402 public function action_stateless_get_current_progresses() {
403 return array(
404 'images' => $this->retrieve_current_progress( 'images' ),
405 'other' => $this->retrieve_current_progress( 'other' ),
406 );
407 }
408
409 /**
410 * @return array
411 */
412 public function action_stateless_get_all_fails() {
413 return array(
414 'images' => $this->get_fails( 'images' ),
415 'other' => $this->get_fails( 'other' )
416 );
417 }
418
419 /**
420 * @param $mode
421 */
422 private function get_fails( $mode ) {
423 if ( $mode !== 'other' ) {
424 $mode = 'images';
425 }
426
427 return get_option( 'wp_stateless_failed_' . $mode );
428 }
429
430 /**
431 * Resets the current progress for a specific mode.
432 */
433 public function action_stateless_reset_progress() {
434 $mode = 'images';
435 if ( isset( $_REQUEST['mode'] ) && 'other' === $_REQUEST['mode'] ) {
436 $mode = 'other';
437 }
438
439 $this->reset_current_progress( $mode );
440
441 return true;
442 }
443
444 /**
445 * @param $mode
446 * @param $files
447 * @param bool $continue
448 * @return array
449 */
450 private function get_non_processed_media_ids( $mode, $files, $continue = false ) {
451 if ( $continue ) {
452 $progress = $this->retrieve_current_progress( $mode );
453 if ( false !== $progress ) {
454 $ids = array();
455 foreach ( $files as $file ) {
456 $id = (int) $file->ID;
457 // only include IDs that have not been processed yet
458 if ( $id > $progress[0] || $id < $progress[1] ) {
459 $ids[] = $id;
460 }
461 }
462 return $ids;
463 }
464 }
465
466 $this->reset_current_progress( $mode );
467
468 $ids = array();
469 foreach ( $files as $file )
470 $ids[] = (int)$file->ID;
471
472 return $ids;
473 }
474
475 /**
476 * @param $mode
477 * @param $id
478 */
479 private function store_current_progress( $mode, $id ) {
480 if ( $mode !== 'other' ) {
481 $mode = 'images';
482 }
483
484 $first_processed = get_option( 'wp_stateless_' . $mode . '_first_processed' );
485 if ( ! $first_processed ) {
486 update_option( 'wp_stateless_' . $mode . '_first_processed', $id );
487 }
488 $last_processed = get_option( 'wp_stateless_' . $mode . '_last_processed' );
489 if ( ! $last_processed || $id < (int) $last_processed ) {
490 update_option( 'wp_stateless_' . $mode . '_last_processed', $id );
491 }
492 }
493
494 /**
495 * @param $attachment_id
496 * @param $mode
497 */
498 private function store_failed_attachment( $attachment_id, $mode ) {
499 if ( $mode !== 'other' ) {
500 $mode = 'images';
501 }
502
503 $fails = get_option( 'wp_stateless_failed_' . $mode );
504 if ( !empty( $fails ) && is_array( $fails ) ) {
505 if ( !in_array( $attachment_id, $fails ) ) {
506 $fails[] = $attachment_id;
507 }
508 } else {
509 $fails = array( $attachment_id );
510 }
511
512 update_option( 'wp_stateless_failed_' . $mode, $fails );
513 }
514
515 /**
516 * @param $mode
517 * @param $attachment_id
518 */
519 private function maybe_fix_failed_attachment( $mode, $attachment_id ) {
520 $fails = get_option( 'wp_stateless_failed_' . $mode );
521
522 if ( !empty( $fails ) && is_array( $fails ) ) {
523 if ( in_array( $attachment_id, $fails ) ) {
524 foreach (array_keys($fails, $attachment_id) as $key) {
525 unset($fails[$key]);
526 }
527 }
528 }
529
530 update_option( 'wp_stateless_failed_' . $mode, $fails );
531 }
532
533 /**
534 * @param $mode
535 * @return array|bool
536 */
537 private function retrieve_current_progress( $mode ) {
538 if ( $mode !== 'other' ) {
539 $mode = 'images';
540 }
541
542 $first_processed = get_option( 'wp_stateless_' . $mode . '_first_processed' );
543 $last_processed = get_option( 'wp_stateless_' . $mode . '_last_processed' );
544
545 if ( ! $first_processed || ! $last_processed ) {
546 return false;
547 }
548
549 return array( (int) $first_processed, (int) $last_processed );
550 }
551
552 /**
553 * @param $mode
554 */
555 private function reset_current_progress( $mode ) {
556 if ( $mode !== 'other' ) {
557 $mode = 'images';
558 }
559
560 delete_option( 'wp_stateless_' . $mode . '_first_processed' );
561 delete_option( 'wp_stateless_' . $mode . '_last_processed' );
562 }
563
564 }
565
566 }
567
568 }
569