PluginProbe
WP-Stateless – Google Cloud Storage / 3.0.4
WP-Stateless – Google Cloud Storage v3.0.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 3.0.4, at lib/classes/class-ajax.php

436 lines 15.6 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 'stateless_get_bucket_folder'
30 );
31
32 /**
33 * The list of wp_ajax_nopriv_{name} actions
34 *
35 * @var array
36 */
37 var $nopriv_actions = array();
38
39 /**
40 * Init AJAX actions
41 *
42 * @author peshkov@UD
43 */
44 public function __construct(){
45
46 foreach( $this->actions as $action ) {
47 add_action( 'wp_ajax_' . $action, array( $this, 'request' ) );
48 }
49
50 foreach( $this->nopriv_actions as $action ) {
51 add_action( 'wp_ajax_nopriv_' . $action, array( $this, 'request' ) );
52 }
53
54 }
55
56 /**
57 * Handles AJAX request
58 *
59 * @author peshkov@UD
60 */
61 public function request() {
62 global $doing_manual_sync;
63
64 $response = array(
65 'message' => '',
66 'html' => '',
67 );
68
69 try{
70 $doing_manual_sync = true;
71
72 $action = $_REQUEST[ 'action' ];
73
74 /** Determine if the current class has the method to handle request */
75 if( is_callable( array( $this, 'action_'. $action ) ) ) {
76 $response = call_user_func_array( array( $this, 'action_' . $action ), array( $_REQUEST ) );
77 }
78 /** Determine if external function exists to handle request */
79 elseif ( is_callable( 'action_' . $action ) ) {
80 $response = call_user_func_array( $action, array( $_REQUEST ) );
81 }
82 elseif ( is_callable( $action ) ) {
83 $response = call_user_func_array( $action, array( $_REQUEST ) );
84 }
85 /** Oops! */
86 else {
87 throw new \Exception( __( 'Incorrect Request' ) );
88 }
89
90 } catch( \Exception $e ) {
91 wp_send_json_error( $e->getMessage() );
92 }
93
94 wp_send_json_success( $response );
95
96 }
97
98 /**
99 * Update json key to database.
100 */
101 public function action_stateless_wizard_update_settings($data) {
102 $bucket = $data['bucket'];
103 $privateKeyData = base64_decode($data['privateKeyData']);
104 $is_gae = isset($_SERVER["GAE_VERSION"]) ? true : false;
105 $upload_dir = wp_upload_dir();
106 $is_upload_dir_writable = is_writable( $upload_dir['basedir'] );
107
108 if(current_user_can('manage_network_options') && wp_verify_nonce( $data['nonce'], 'network_update_json')){
109 if(get_site_option('sm_mode', 'disabled') == 'disabled')
110 update_site_option( 'sm_mode', 'cdn');
111 /**
112 * If Googl App Engine detected - set Stateless mode
113 * and Google App Engine compatibility by default
114 */
115 if ( $is_gae || !$is_upload_dir_writable ) {
116 update_site_option( 'sm_mode', 'stateless' );
117
118 $modules = get_site_option('stateless-modules', array());
119 if ( $is_gae && empty($modules['google-app-engine']) || $modules['google-app-engine'] != 'true') {
120 $modules['google-app-engine'] = 'true';
121 update_site_option('stateless-modules', $modules, true);
122 }
123 }
124 update_site_option( 'sm_bucket', $bucket);
125 update_site_option( 'sm_key_json', $privateKeyData);
126 }
127 elseif(wp_verify_nonce( $data['nonce'], 'update_json')){
128 if(get_option('sm_mode', 'disabled') == 'disabled')
129 update_option( 'sm_mode', 'cdn');
130
131 /**
132 * If Googl App Engine detected - set Stateless mode
133 * and Google App Engine compatibility by default
134 */
135 if ( $is_gae ) {
136 update_option( 'sm_mode', 'stateless' );
137
138 $modules = get_option('stateless-modules', array());
139 if (empty($modules['google-app-engine']) || $modules['google-app-engine'] != 'true') {
140 $modules['google-app-engine'] = 'true';
141 update_option('stateless-modules', $modules, true);
142 }
143 }
144
145 update_option( 'sm_bucket', $bucket);
146 update_option( 'sm_key_json', $privateKeyData);
147 }
148
149 ud_get_stateless_media()->flush_transients();
150 wp_send_json(array('success' => true));
151 }
152
153
154 /**
155 * Regenerate image sizes.
156 */
157 public function action_stateless_process_image() {
158
159 if(ud_get_stateless_media()->is_connected_to_gs() !== true){
160 throw new \Exception( __( 'Not connected to GCS', ud_get_stateless_media()->domain) );
161 }
162
163 @error_reporting( 0 );
164
165 $use_wildcards = Utility::is_use_wildcards();
166 $id = (int) $_REQUEST['id'];
167 $image = get_post( $id );
168
169 if ( ! $image || 'attachment' != $image->post_type || 'image/' != substr( $image->post_mime_type, 0, 6 ) )
170 throw new \Exception( sprintf( __( 'Failed resize: %s is an invalid image ID.', ud_get_stateless_media()->domain ), esc_html( $_REQUEST['id'] ) ) );
171
172 if ( ! current_user_can( 'manage_options' ) )
173 throw new \Exception( __( "Your user account doesn't have permission to resize images", ud_get_stateless_media()->domain ) );
174
175 $fullsizepath = get_attached_file( $image->ID );
176
177 $upload_dir = wp_upload_dir();
178
179 // If no file found
180 if ( false === $fullsizepath || ! file_exists( $fullsizepath ) ) {
181
182 // Try get it and save
183 $result_code = ud_get_stateless_media()->get_client()->get_media( apply_filters( 'wp_stateless_file_name', $fullsizepath, true, "", "", $use_wildcards), true, $fullsizepath );
184
185 if ( $result_code !== 200 ) {
186 if(!Utility::sync_get_attachment_if_exist($image->ID, $fullsizepath)){ // Save file to local from proxy.
187 Utility::sync_store_failed_attachment( $image->ID, 'images' );
188 throw new \Exception(sprintf(__('Both local and remote files are missing. Unable to resize. (%s)', ud_get_stateless_media()->domain), $image->guid));
189 }
190 }
191 }
192
193 @set_time_limit( -1 );
194
195 //
196 do_action( 'sm:pre::synced::image', $id);
197 $metadata = wp_generate_attachment_metadata( $image->ID, $fullsizepath );
198
199 if(get_post_mime_type($image->ID) !== 'image/svg+xml'){
200 if ( is_wp_error( $metadata ) ) {
201 Utility::sync_store_failed_attachment( $image->ID, 'images' );
202 throw new \Exception($metadata->get_error_message());
203 }
204
205 if ( empty( $metadata ) ) {
206 Utility::sync_store_failed_attachment( $image->ID, 'images' );
207 throw new \Exception(sprintf( __('No metadata generated for %1$s (ID %2$s).', ud_get_stateless_media()->domain), esc_html( get_the_title( $image->ID ) ), $image->ID));
208 }
209 }
210
211 // If this fails, then it just means that nothing was changed (old value == new value)
212 wp_update_attachment_metadata( $image->ID, $metadata );
213
214 Utility::sync_store_current_progress( 'images', $id );
215 Utility::sync_maybe_fix_failed_attachment( 'images', $image->ID );
216 do_action( 'sm:synced::image', $id, $metadata);
217
218 return sprintf( __( '%1$s (ID %2$s) was successfully synced in %3$s seconds.', ud_get_stateless_media()->domain ), esc_html( get_the_title( $image->ID ) ), $image->ID, timer_stop() );
219 }
220
221 /**
222 * @return string
223 * @throws \Exception
224 */
225 public function action_stateless_process_file() {
226 @error_reporting( 0 );
227
228 if(ud_get_stateless_media()->is_connected_to_gs() !== true){
229 throw new \Exception( __( 'Not connected to GCS', ud_get_stateless_media()->domain) );
230 }
231
232 $id = (int) $_REQUEST['id'];
233 $file = get_post( $id );
234
235 if ( ! $file || 'attachment' != $file->post_type )
236 throw new \Exception( sprintf( __( 'Attachment not found: %s is an invalid file ID.', ud_get_stateless_media()->domain ), esc_html( $id ) ) );
237
238 if ( ! current_user_can( 'manage_options' ) )
239 throw new \Exception( __( "You are not allowed to do this.", ud_get_stateless_media()->domain ) );
240
241 $fullsizepath = get_attached_file( $file->ID );
242 $local_file_exists = file_exists( $fullsizepath );
243 $upload_dir = wp_upload_dir();
244
245 if ( false === $fullsizepath || ! $local_file_exists ) {
246
247 // Try get it and save
248 $result_code = ud_get_stateless_media()->get_client()->get_media( str_replace( trailingslashit( $upload_dir[ 'basedir' ] ), '', $fullsizepath ), true, $fullsizepath );
249
250 if ( $result_code !== 200 ) {
251 if(!Utility::sync_get_attachment_if_exist($file->ID, $fullsizepath)){ // Save file to local from proxy.
252 Utility::sync_store_failed_attachment( $file->ID, 'other' );
253 throw new \Exception(sprintf(__('File not found (%s)', ud_get_stateless_media()->domain), $file->guid));
254 }
255 else{
256 $local_file_exists = true;
257 }
258 }
259 else{
260 $local_file_exists = true;
261 }
262 }
263
264 if($local_file_exists){
265
266 if ( !ud_get_stateless_media()->get_client()->media_exists( str_replace( trailingslashit( $upload_dir[ 'basedir' ] ), '', $fullsizepath ) ) ) {
267
268 @set_time_limit( -1 );
269
270 $metadata = wp_generate_attachment_metadata( $file->ID, $fullsizepath );
271
272 if ( is_wp_error( $metadata ) ) {
273 Utility::sync_store_failed_attachment( $file->ID, 'other' );
274 throw new \Exception($metadata->get_error_message());
275 }
276
277 wp_update_attachment_metadata( $file->ID, $metadata );
278 do_action( 'sm:synced::nonImage', $id, $metadata);
279
280 }
281 else{
282 // Ephemeral and Stateless modes: we don't need the local version.
283 if(ud_get_stateless_media()->get( 'sm.mode' ) === 'ephemeral' || ud_get_stateless_media()->get( 'sm.mode' ) === 'stateless'){
284 unlink($fullsizepath);
285 }
286 }
287
288 }
289
290 Utility::sync_store_current_progress( 'other', $id );
291 Utility::sync_maybe_fix_failed_attachment( 'other', $file->ID );
292
293 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() );
294 }
295
296 /**
297 * @return string
298 * @throws \Exception
299 * @todo Show error when file not exist on both local and gcs.
300 */
301 public function action_stateless_process_non_library_file() {
302 @error_reporting( 0 );
303
304 if(ud_get_stateless_media()->is_connected_to_gs() !== true){
305 throw new \Exception( __( 'Not connected to GCS', ud_get_stateless_media()->domain) );
306 }
307
308 $upload_dir = wp_upload_dir();
309 $client = ud_get_stateless_media()->get_client();
310
311 $file_path = trim($_REQUEST['file_path'], '/');
312 $fullsizepath = $upload_dir['basedir'] . '/' . $file_path;
313
314 if ( ! current_user_can( 'manage_options' ) )
315 throw new \Exception( __( "You are not allowed to do this.", ud_get_stateless_media()->domain ) );
316
317
318 do_action( 'sm:sync::syncFile', $file_path, $fullsizepath, true, ['remove_from_queue' => true, 'manual_sync' => true]);
319
320 // $this->store_current_progress( 'other', $file_path );
321 // $this->maybe_fix_failed_attachment( 'other', $file_path );
322
323 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_path ) ), $file_path, timer_stop() );
324 }
325
326 /**
327 * Returns IDs of images media objects
328 */
329 public function action_get_images_media_ids() {
330 global $wpdb;
331
332 if(ud_get_stateless_media()->is_connected_to_gs() !== true){
333 throw new \Exception( __( 'Not connected to GCS', ud_get_stateless_media()->domain) );
334 }
335
336 if ( ! $images = $wpdb->get_results( "SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND post_mime_type LIKE 'image/%' ORDER BY ID DESC" ) ) {
337 throw new \Exception( __('No images media objects found.', ud_get_stateless_media()->domain) );
338 }
339
340 $continue = false;
341 $start_from = 0;
342 if ( isset( $_REQUEST['continue'] ) ) {
343 $continue = (bool) $_REQUEST['continue'];
344 $start_from = isset( $_REQUEST['start_from'] ) ? (int) $_REQUEST['start_from'] : 0;
345 }
346
347 return Utility::sync_get_non_processed_media_ids( 'images', $images, $continue, $start_from );
348 }
349
350 /**
351 * Returns IDs of images media objects
352 */
353 public function action_get_other_media_ids() {
354 global $wpdb;
355
356 if(ud_get_stateless_media()->is_connected_to_gs() !== true){
357 throw new \Exception( __( 'Not connected to GCS', ud_get_stateless_media()->domain) );
358 }
359
360 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" ) ) {
361 throw new \Exception( __('No files found.', ud_get_stateless_media()->domain) );
362 }
363
364 $continue = false;
365 $start_from = 0;
366 if ( isset( $_REQUEST['continue'] ) ) {
367 $continue = (bool) $_REQUEST['continue'];
368 $start_from = isset( $_REQUEST['start_from'] ) ? (int) $_REQUEST['start_from'] : 0;
369 }
370
371 return Utility::sync_get_non_processed_media_ids( 'other', $files, $continue, $start_from );
372 }
373
374 /**
375 * Returns IDs of non media library files
376 * Return files to be manually sync from sync tab.
377 */
378 public function action_get_non_library_files_id() {
379 if(ud_get_stateless_media()->is_connected_to_gs() !== true){
380 throw new \Exception( __( 'Not connected to GCS', ud_get_stateless_media()->domain) );
381 }
382
383 $files = apply_filters( 'sm:sync::nonMediaFiles', array() );
384 if(empty($files)){
385 throw new \Exception( __('', ud_get_stateless_media()->domain) );
386 }
387 return array_values(array_unique($files));
388 }
389
390 /**
391 * Returns current progress storage for all modes (to check whether there is something to continue in JS)
392 */
393 public function action_stateless_get_current_progresses() {
394 return array(
395 'images' => Utility::sync_retrieve_current_progress( 'images' ),
396 'other' => Utility::sync_retrieve_current_progress( 'other' ),
397 );
398 }
399
400 /**
401 * @return array
402 */
403 public function action_stateless_get_all_fails() {
404 return array(
405 'images' => Utility::sync_get_fails( 'images' ),
406 'other' => Utility::sync_get_fails( 'other' )
407 );
408 }
409
410 /**
411 * Resets the current progress for a specific mode.
412 */
413 public function action_stateless_reset_progress() {
414 $mode = 'images';
415 if ( isset( $_REQUEST['mode'] ) && 'other' === $_REQUEST['mode'] ) {
416 $mode = 'other';
417 }
418
419 Utility::sync_reset_current_progress( $mode );
420
421 return true;
422 }
423
424 /**
425 * Returns bucket folder (to check whether there is something to continue in JS)
426 */
427 public function action_stateless_get_bucket_folder() {
428 return array ( 'bucket_folder' =>get_option('sm_root_dir') );
429 }
430
431 }
432
433 }
434
435 }
436