PluginProbe
WP-Stateless – Google Cloud Storage / trunk
WP-Stateless – Google Cloud Storage vtrunk
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
← All changes | lib/classes/class-bootstrap.php +808 -596 3.0trunk View file →
@@ -1,19 +1,27 @@
1 1 <?php
2 +
2 3 /**
3 4 * Bootstrap
4 5 *
5 6 * @since 0.2.0
6 7 */
8 +
7 9 namespace wpCloud\StatelessMedia {
8 10
9 11 use Google\Cloud\Storage\StorageClient;
10 12 use Google\Auth\HttpHandler\HttpHandlerFactory;
13 + use wpCloud\StatelessMedia\Sync\FileSync;
14 + use wpCloud\StatelessMedia\Sync\ImageSync;
15 + use wpCloud\StatelessMedia\Sync\NonLibrarySync;
16 + use wpCloud\StatelessMedia\Batch\BatchTaskManager;
11 17
12 - if( !class_exists( 'wpCloud\StatelessMedia\Bootstrap' ) ) {
18 + if (!class_exists('wpCloud\StatelessMedia\Bootstrap')) {
13 19
14 20 final class Bootstrap extends \UsabilityDynamics\WP\Bootstrap_Plugin {
15 21
22 + const REQUIRED_PHP_VERSION = '5.5';
23 +
16 24 /**
17 25 * Google Storage Client
18 26 * Use $this->get_client()
19 27 *
@@ -45,15 +53,24 @@
45 53 * Attention: MUST NOT BE CALLED DIRECTLY! USE get_instance() INSTEAD!
46 54 * @param $args
47 55 * @author peshkov@UD
48 56 */
49 - protected function __construct( $args ) {
50 - parent::__construct( $args );
57 + protected function __construct($args) {
58 + /**
59 + * Need to be loaded before plugin initialization.
60 + */
61 + if ( !(defined('WP_STATELESS_COMPATIBILITY_GAE') && !WP_STATELESS_COMPATIBILITY_GAE) ) {
62 + AppEngine::instance();
63 + }
51 64
65 + parent::__construct($args);
66 +
67 + self::$version = $args['version'] ?? self::$version;
68 +
52 69 /**
53 70 * Add custom args to api ping request
54 71 */
55 - add_filter('ud-api-client-ping-args', function($args, $_, $__) {
72 + add_filter('ud-api-client-ping-args', function ($args, $_, $__) {
56 73 $args['multisite'] = is_multisite();
57 74 $args['stateless_media'] = Utility::get_stateless_media_data_count();
58 75 return $args;
59 76 }, 10, 3);
@@ -58,16 +75,18 @@
58 75 return $args;
59 76 }, 10, 3);
60 77
61 78 //** Define our Admin Notices handler object */
62 - $this->errors = new Errors( array_merge( $args, array(
79 + $this->errors = new Errors(array_merge($args, array(
63 80 'type' => $this->type
64 - ) ) );
81 + )));
65 82
66 83 // Initialize compatibility modules.
67 - add_action( 'plugins_loaded', function(){
84 + add_action('plugins_loaded', function () {
85 + Addons::instance();
68 86 new Module();
69 - });
87 + DynamicImageSupport::instance();
88 + }, 20);
70 89
71 90 /**
72 91 * Define settings and UI.
73 92 *
@@ -79,48 +98,66 @@
79 98 * Manually Update/Add option
80 99 * $this->set( 'sm.client_id', 'zxcvv12adffse' );
81 100 */
82 101 $this->settings = new Settings($this);
102 + Status::instance();
83 103 }
84 104
85 105 /**
86 106 * Prevent loading of textdomain
87 107 */
88 - public function load_textdomain(){}
108 + public function load_textdomain() {
109 + }
89 110
90 111 /**
91 112 * Instantiate class.
92 113 */
93 114 public function init() {
94 - // Parse feature falgs, set constants.
115 + // Parse feature flags, set constants.
95 116 $this->parse_feature_flags();
96 - $sm_mode = $this->get( 'sm.mode' );
117 + $sm_mode = $this->get('sm.mode');
97 118
119 + /**
120 + * Send admin email
121 + */
122 + add_action('wp_stateless_send_admin_email', array($this, 'send_admin_email'), 10, 3);
123 +
124 + // Should be created unconditionally and as early as possible to handle batch migration requests
125 + Migrator::instance();
126 + BatchTaskManager::instance();
127 +
98 128 new SyncNonMedia();
99 129
130 + ImageSync::instance();
131 + FileSync::instance();
132 + NonLibrarySync::instance();
133 +
100 134 // Invoke REST API
101 - add_action( 'rest_api_init', array( $this, 'api_init' ) );
135 + add_action('rest_api_init', array($this, 'api_init'));
102 136
103 137 // Register meta boxes and fields for media edit page
104 - add_filter( 'rwmb_meta_boxes', array( $this, 'attachment_meta_box_callback' ) );
138 + add_filter('rwmb_meta_boxes', array($this, 'attachment_meta_box_callback'));
105 139
106 140 // Register meta boxes and fields for media modal page
107 - add_filter( 'attachment_fields_to_edit', array( $this, 'attachment_modal_meta_box_callback' ), 11, 2 );
141 + add_filter('attachment_fields_to_edit', array($this, 'attachment_modal_meta_box_callback'), 11, 2);
108 142
143 + // Get the REST API root
144 + add_filter('wp_stateless_rest_api_root', array($this, 'get_rest_api_root'));
145 +
109 146 /**
110 147 * Init hook
111 148 */
112 - add_action( 'admin_init', array( $this, 'admin_init' ) );
149 + add_action('admin_init', array($this, 'admin_init'));
113 150
114 151 /**
115 152 * Handle switch blog properly.
116 153 */
117 - add_action( 'switch_blog', array( $this, 'on_switch_blog' ), 10, 2 );
154 + add_action('switch_blog', array($this, 'on_switch_blog'), 10, 2);
118 155
119 156 /**
120 157 * Filter for getting stateless settings
121 158 */
122 - add_filter( 'stateless::get_settings', array( $this, 'get_settings' ), 10);
159 + add_filter('stateless::get_settings', array($this, 'get_settings'), 10);
123 160
124 161 /**
125 162 * Init AJAX jobs
126 163 */
@@ -128,33 +165,47 @@
128 165
129 166 /**
130 167 * Load WP-CLI Commands
131 168 */
132 - if( defined( 'WP_CLI' ) && WP_CLI ) {
169 + if (defined('WP_CLI') && WP_CLI) {
133 170 include_once($this->path('lib/cli/class-sm-cli-command.php', 'dir'));
134 171 }
135 172
136 - $this->is_network_detected();
137 -
138 173 /**
139 174 * Add scripts
140 175 */
141 - add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
176 + add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
142 177
143 178 /**
144 179 * Delete table when blog is deleted.
145 180 */
146 - add_action( 'wp_delete_site', array($this, 'wp_delete_site'));
181 + add_action('wp_delete_site', array($this, 'wp_delete_site'));
147 182
148 183 /**
149 184 * To prevent fatal errors for users who use PHP 5.5 or less.
150 185 */
151 - if( version_compare(PHP_VERSION, '5.5', '<') ) {
152 - $this->errors->add( sprintf( __( 'The plugin requires PHP %s or higher. You current PHP version %s is too old.', ud_get_stateless_media()->domain ), '<b>5.5</b>', '<b>' . PHP_VERSION . '</b>' ) );
186 + if (version_compare(PHP_VERSION, self::REQUIRED_PHP_VERSION, '<')) {
187 + $this->errors->add(sprintf(__('The plugin requires PHP %s or higher. You current PHP version %s is too old.', ud_get_stateless_media()->domain), '<b>' . self::REQUIRED_PHP_VERSION . '</b>', '<b>' . PHP_VERSION . '</b>'));
153 188 }
154 189
190 + /**
191 + * Add the currently processing nag
192 + */
193 + foreach (Utility::get_available_sync_classes() as $process) {
194 + if ($process->is_running()) {
195 + $this->errors->add([
196 + 'title' => __('Media Library Synchronization Underway', ud_get_stateless_media()->domain),
197 + 'message' => __('WP-Stateless is synchronizing your media library in accordance with the Mode setting. You can view progress or stop the process via the WP-Stateless Sync settings area.', ud_get_stateless_media()->domain),
198 + 'button' => __('View Synchronization', ud_get_stateless_media()->domain),
199 + 'button_link' => admin_url('upload.php?page=stateless-settings&tab=stless_sync_tab'),
200 + 'key' => 'processing-in-progress'
201 + ], 'message');
202 + break;
203 + }
204 + }
205 +
155 206 /* Initialize plugin only if Mode is not 'disabled'. */
156 - if ( ($sm_mode !== 'disabled' && $sm_mode !== 'stateless') || ( $sm_mode === 'stateless' && wp_doing_ajax() )) {
207 + if (($sm_mode !== 'disabled' && $sm_mode !== 'stateless') || ($sm_mode === 'stateless' && (wp_doing_ajax() || wp_doing_cron()))) {
157 208
158 209 /**
159 210 * Determine if we have issues with connection to Google Storage Bucket
160 211 * if SM is not disabled.
@@ -160,38 +211,58 @@
160 211 * if SM is not disabled.
161 212 */
162 213 $is_connected = $this->is_connected_to_gs();
163 214
164 - if ( is_wp_error( $is_connected ) ) {
165 - $this->errors->add( $is_connected->get_error_message(), 'warning' );
215 + if (is_wp_error($is_connected)) {
216 + $this->errors->add($is_connected->get_error_message(), 'warning', false);
166 217 }
167 218
168 - if ( $googleSDKVersionConflictError = get_transient( "wp_stateless_google_sdk_conflict" ) ) {
169 - $this->errors->add( $googleSDKVersionConflictError, 'warning' );
219 + if ($googleSDKVersionConflictError = get_transient("wp_stateless_google_sdk_conflict")) {
220 + $this->errors->add($googleSDKVersionConflictError, 'warning', false);
170 221 }
171 222
172 223 /**
173 224 * Carry on only if we do not have errors.
174 225 */
175 - if( !$this->has_errors() ) {
226 + if (!$this->has_errors()) {
176 227
177 - if( in_array( $sm_mode , array( 'cdn', 'ephemeral' ) ) ) {
228 + if (in_array($sm_mode, array('cdn', 'ephemeral', 'stateless'))) {
178 229 /**
179 230 * init main filters
180 231 */
181 - $this->_init_filters( 'main' );
232 + $this->_init_filters('main');
182 233 }
183 234
184 - if( $sm_mode === 'ephemeral' || $sm_mode === 'stateless' ){
235 + if ($sm_mode === 'ephemeral' || $sm_mode === 'stateless') {
185 236 // Store attachment id in a static variable on 'intermediate_image_sizes_advanced' filter.
186 237 // Utility::store_can_delete_attachment();
187 - if(function_exists('is_wp_version_compatible') && is_wp_version_compatible('5.3-RC4-46673')){
188 - add_filter( 'intermediate_image_sizes_advanced', array('wpCloud\StatelessMedia\Utility', 'store_can_delete_attachment'), 10, 3 );
238 + if (function_exists('is_wp_version_compatible') && is_wp_version_compatible('5.3-RC4-46673')) {
239 + add_filter('intermediate_image_sizes_advanced', array('wpCloud\StatelessMedia\Utility', 'store_can_delete_attachment'), 10, 3);
189 240 }
190 241 }
191 242
192 - if ( $this->get( 'sm.delete_remote' ) == 'true' ) {
243 + if ($sm_mode === 'stateless') {
193 244 /**
245 + * Replacing local path to gs:// for using it on StreamWrapper
246 + */
247 + add_filter('upload_dir', array($this, 'filter_upload_dir'), 99);
248 +
249 + /**
250 + * Stateless mode working only with GD library
251 + */
252 + add_filter('wp_image_editors', array($this, 'select_wp_image_editors'));
253 +
254 + /**
255 + * Init GS client
256 + */
257 + global $gs_client;
258 + if ($gs_client = $this->init_gs_client()) {
259 + StreamWrapper::register($gs_client);
260 + }
261 + }
262 +
263 + if ($this->get('sm.delete_remote') == 'true') {
264 + /**
194 265 * On physical file deletion we remove any from GS
195 266 * We need priority grater than default (10) for ShortPixel plugin to work properly.
196 267 */
197 268 add_filter('delete_attachment', array($this, 'remove_media'), 11);
@@ -199,36 +270,57 @@
199 270
200 271 /**
201 272 * init client's filters
202 273 */
203 - $this->_init_filters( 'client' );
274 + $this->_init_filters('client');
204 275 }
205 -
206 - } elseif ( $sm_mode == 'stateless' ) {
276 + } elseif ($sm_mode == 'stateless') {
207 277 /**
208 - * Replacing local path to gs:// for using it on StreamWrapper
278 + * Determine if we have issues with connection to Google Storage Bucket
279 + * if SM is not disabled.
209 280 */
210 - add_filter('upload_dir', array( $this, 'filter_upload_dir' ), 99);
281 + $is_connected = $this->is_connected_to_gs();
211 282
283 + if (is_wp_error($is_connected)) {
284 + $this->errors->add($is_connected->get_error_message(), 'warning', false);
285 + }
286 +
287 + if ($googleSDKVersionConflictError = get_transient("wp_stateless_google_sdk_conflict")) {
288 + $this->errors->add($googleSDKVersionConflictError, 'warning', false);
289 + }
290 +
212 291 /**
213 - * Stateless mode working only with GD library
292 + * Carry on only if we do not have errors.
214 293 */
215 - add_filter( 'wp_image_editors', array($this, 'select_wp_image_editors') );
294 + if (!$this->has_errors()) {
295 + /**
296 + * Replacing local path to gs:// for using it on StreamWrapper
297 + */
298 + add_filter('upload_dir', array($this, 'filter_upload_dir'), 99);
216 299
217 - //init GS client
218 - global $gs_client;
219 - $gs_client = $this->init_gs_client();
220 - StreamWrapper::register($gs_client);
300 + /**
301 + * Stateless mode working only with GD library
302 + */
303 + add_filter('wp_image_editors', array($this, 'select_wp_image_editors'));
221 304
222 - /**
223 - * init client's filters
224 - */
225 - $this->_init_filters( 'client' );
305 + /**
306 + * Init GS client
307 + */
308 + global $gs_client;
309 + if ($gs_client = $this->init_gs_client()) {
310 + StreamWrapper::register($gs_client);
311 + }
226 312
227 - /**
228 - * init main filters
229 - */
230 - $this->_init_filters( 'main' );
313 + /**
314 + * init client's filters
315 + */
316 + $this->_init_filters('client');
317 +
318 + /**
319 + * init main filters
320 + */
321 + $this->_init_filters('main');
322 + }
231 323 }
232 324 }
233 325
234 326 /**
@@ -234,53 +326,50 @@
234 326 /**
235 327 * Init additional filters which uses on all modes
236 328 * @param string $type
237 329 */
238 - private function _init_filters ( $type = '' ) {
239 - switch( $type) {
330 + private function _init_filters($type = '') {
331 + switch ($type) {
240 332 case 'main':
241 - add_filter( 'wp_get_attachment_image_attributes', array( $this, 'wp_get_attachment_image_attributes' ), 20, 3 );
242 - add_filter( 'wp_get_attachment_url', array( $this, 'wp_get_attachment_url' ), 20, 2 );
243 - add_filter( 'get_attached_file', array( $this, 'get_attached_file' ), 9, 2 );
244 - add_filter( 'attachment_url_to_postid', array( $this, 'attachment_url_to_postid' ), 20, 2 );
333 + add_filter('wp_get_attachment_image_attributes', array($this, 'wp_get_attachment_image_attributes'), 20, 3);
334 + add_filter('wp_get_attachment_url', array($this, 'wp_get_attachment_url'), 20, 2);
335 + add_filter('get_attached_file', array($this, 'get_attached_file'), 9, 2);
336 + add_filter('attachment_url_to_postid', array($this, 'attachment_url_to_postid'), 20, 2);
245 337
246 - if( $this->get( 'sm.body_rewrite' ) == 'true' || $this->get( 'sm.body_rewrite' ) == 'enable_editor' ) {
247 - add_filter( 'the_content', array( $this, 'the_content_filter' ), 99 );
338 + if ($this->get('sm.body_rewrite') == 'true' || $this->get('sm.body_rewrite') == 'enable_editor') {
339 + add_filter('the_content', array($this, 'the_content_filter'), 99);
248 340 }
249 341
250 - if( $this->get( 'sm.body_rewrite' ) == 'true' || $this->get( 'sm.body_rewrite' ) == 'enable_meta' ) {
251 - add_filter( 'get_post_metadata', array( $this, 'post_metadata_filter' ), 2, 4 );
342 + if ($this->get('sm.body_rewrite') == 'true' || $this->get('sm.body_rewrite') == 'enable_meta') {
343 + add_filter('get_post_metadata', array($this, 'post_metadata_filter'), 2, 4);
252 344 }
253 345
254 - add_filter( 'wp_stateless_bucket_link', array( $this, 'wp_stateless_bucket_link' ) );
346 + add_filter('wp_stateless_bucket_link', array($this, 'wp_stateless_bucket_link'));
255 347 break;
256 348 case 'client':
257 349 /**
258 350 * Add custom actions to media rows
259 351 */
260 - add_filter( 'media_row_actions', array( $this, 'add_custom_row_actions' ), 10, 3 );
352 + add_filter('media_row_actions', array($this, 'add_custom_row_actions'), 10, 3);
261 353
262 354 /**
263 355 * Hashify file name if option is enabled
264 356 */
265 - if ( $this->get( 'sm.hashify_file_name' ) == 'true' ) {
266 - add_filter('sanitize_file_name', array( 'wpCloud\StatelessMedia\Utility', 'randomize_filename' ), 10);
357 + if ($this->get('sm.hashify_file_name') == 'true') {
358 + add_filter('sanitize_file_name', array('wpCloud\StatelessMedia\Utility', 'randomize_filename'), 10);
267 359 }
268 360
269 361 /**
270 - * Override Cache Control is option is enabled
362 + * Override Cache Control if option is enabled
271 363 */
272 - $cacheControl = trim($this->get( 'sm.cache_control' ));
273 - if ( !empty($cacheControl) ) {
274 - add_filter( 'sm:item:cacheControl', array( $this, 'override_cache_control' ) );
275 - }
364 + add_filter('sm:item:cacheControl', array($this->settings, 'override_cache_control'));
276 365
277 - add_filter( 'wp_stateless_file_name', array( $this, 'handle_root_dir' ), 10, 5 );
366 + add_filter('wp_stateless_file_name', array($this, 'handle_root_dir'), 10, 4);
278 367
279 368 /**
280 369 * Extends metadata by adding GS information.
281 370 */
282 - add_filter( 'wp_get_attachment_metadata', array( $this, 'wp_get_attachment_metadata' ), 10, 2 );
371 + add_filter('wp_get_attachment_metadata', array($this, 'wp_get_attachment_metadata'), 10, 2);
283 372
284 373 /**
285 374 * Add/Edit Media
286 375 *
@@ -286,20 +375,30 @@
286 375 *
287 376 * Once added or edited we can get into Attachment ID then get all image sizes and sync them with GS
288 377 * We can't use this. That's prevent removing this filter.
289 378 */
290 - add_filter( 'wp_update_attachment_metadata', array( 'wpCloud\StatelessMedia\Utility', 'add_media' ), 999, 2 );
379 + add_filter('wp_update_attachment_metadata', array('wpCloud\StatelessMedia\Utility', 'add_media'), 999, 2);
291 380
292 381 /**
382 + * Delete original in the end of generating metadata
383 + * it does not work with PDF
384 + */
385 + // add_filter('wp_generate_attachment_metadata', function ($metadata, $attachment_id, $state) {
386 + // if (!in_array(ud_get_stateless_media()->get('sm.mode'), array('ephemeral'))) return $metadata;
387 + // @unlink(get_attached_file($attachment_id, true));
388 + // return $metadata;
389 + // }, 99, 3);
390 +
391 + /**
293 392 * Rewrite Image URLS
294 393 */
295 - add_filter( 'image_downsize', array( $this, 'image_downsize' ), 99, 3 );
296 - add_filter( 'wp_calculate_image_srcset', array($this, 'wp_calculate_image_srcset'), 10, 5 );
394 + add_filter('image_downsize', array($this, 'image_downsize'), 99, 3);
395 + add_filter('wp_calculate_image_srcset', array($this, 'wp_calculate_image_srcset'), 10, 5);
297 396
298 397 /**
299 398 * Trigger module initialization and registration.
300 399 */
301 - do_action('sm::module::init', $this->get( 'sm' ));
400 + do_action('sm::module::init', $this->get('sm'));
302 401
303 402 break;
304 403 case 'default':
305 404 break;
@@ -312,10 +411,10 @@
312 411 * array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' )
313 412 * @param $editors
314 413 * @return array
315 414 */
316 - public function select_wp_image_editors( $editors ) {
317 - return array( 'WP_Image_Editor_GD' );
415 + public function select_wp_image_editors($editors) {
416 + return array('WP_Image_Editor_GD');
318 417 }
319 418
320 419 /**
321 420 * @param callable|null $httpHandler
@@ -321,12 +420,12 @@
321 420 * @param callable|null $httpHandler
322 421 * @return StorageClient
323 422 * @throws \Exception
324 423 */
325 - public function init_gs_client( callable $httpHandler = null ) {
424 + public function init_gs_client(?callable $httpHandler = null) {
326 425 // May be Loading Google SDK....
327 - if( !class_exists( 'HttpHandlerFactory' ) ) {
328 - include_once( ud_get_stateless_media()->path('lib/Google/vendor/autoload.php', 'dir') );
426 + if (!class_exists('HttpHandlerFactory')) {
427 + include_once(ud_get_stateless_media()->path('lib/Google/vendor/autoload.php', 'dir'));
329 428 }
330 429
331 430 $httpHandler = $httpHandler ? $httpHandler : HttpHandlerFactory::build();
332 431
@@ -331,18 +430,21 @@
331 430 $httpHandler = $httpHandler ? $httpHandler : HttpHandlerFactory::build();
332 431
333 432 $json_key = json_decode($this->settings->get('sm.key_json'), true);
334 433
335 - if ( !empty( $json_key ) ) {
434 + if (!empty($json_key)) {
336 435 return new StorageClient(
337 - [ 'keyFile' => $json_key,
338 - 'httpHandler' => function ( $request, $options ) use ( $httpHandler ) {
339 - $xGoogApiClientHeader = $request->getHeaderLine( 'x-goog-api-client' );
340 - $request = $request->withHeader( 'x-goog-api-client', $xGoogApiClientHeader );
436 + [
437 + 'keyFile' => $json_key,
438 + 'httpHandler' => function ($request, $options) use ($httpHandler) {
439 + $xGoogApiClientHeader = $request->getHeaderLine('x-goog-api-client');
440 + $request = $request->withHeader('x-goog-api-client', $xGoogApiClientHeader);
341 441
342 - return call_user_func_array( $httpHandler, [ $request, $options ] );
442 + return call_user_func_array($httpHandler, [$request, $options]);
343 443 },
344 - 'authHttpHandler' => HttpHandlerFactory::build(), ] );
444 + 'authHttpHandler' => HttpHandlerFactory::build(),
445 + ]
446 + );
345 447 }
346 448 }
347 449
348 450 /**
@@ -349,16 +451,16 @@
349 451 * Replacing root dir with GCS path
350 452 * @param $uploads
351 453 * @return array
352 454 */
353 - public function filter_upload_dir( $uploads ) {
455 + public function filter_upload_dir($uploads) {
354 456 global $default_dir;
355 457 if ($default_dir) return $uploads;
356 458 //Bucket
357 - $bucket = $this->get( 'sm.bucket' );
459 + $bucket = $this->get('sm.bucket');
358 460
359 461 //Bucket folder path
360 - $root_dir = $this->get( 'sm.root_dir' );
462 + $root_dir = $this->get('sm.root_dir');
361 463 $root_dir = apply_filters("wp_stateless_handle_root_dir", $root_dir);
362 464
363 465 /**
364 466 * Subdir not uses on Stateless mode
@@ -365,9 +467,9 @@
365 467 */
366 468 $uploads['subdir'] = '';
367 469
368 470 $basedir = rtrim(sprintf('gs://%s/%s', $bucket, $root_dir), '/');
369 - $baseurl = rtrim(sprintf('https://storage.googleapis.com/%s/%s', $bucket, $root_dir ), '/');
471 + $baseurl = rtrim(sprintf('https://storage.googleapis.com/%s/%s', $bucket, $root_dir), '/');
370 472
371 473 $uploads = array(
372 474 'url' => rtrim($baseurl . $uploads['subdir'], '/'),
373 475 'path' => $basedir . $uploads['subdir'],
@@ -389,24 +491,32 @@
389 491 * @param $image_meta
390 492 * @param $attachment_id
391 493 * @return array
392 494 */
393 - public function wp_calculate_image_srcset($sources, $size_array, $image_src, $image_meta, $attachment_id){
394 - $sm_mode = $this->get( 'sm.mode' );
495 + public function wp_calculate_image_srcset($sources, $size_array, $image_src, $image_meta, $attachment_id) {
496 + $sm_mode = $this->get('sm.mode');
497 +
498 + /**
499 + * In Backup mode using local URL
500 + */
501 + if ("backup" == $sm_mode) {
502 + return $sources;
503 + }
504 +
395 505 if (empty($image_meta['gs_link'])) {
396 506 $image_meta = wp_get_attachment_metadata($attachment_id);
397 507 }
398 508
399 - if(is_array($sources) && !empty( $image_meta['gs_link'] )){
509 + if (is_array($sources) && !empty($image_meta['gs_link'])) {
400 510 $gs_name = $image_meta['gs_name'];
401 511 // getting position of root_dir in gs_name.
402 512 $root_dir_pos = strpos($gs_name, $image_meta['file']);
403 513 // removing rood_dir from gs_name so we can compare to replace url with gs_link.
404 - if($root_dir_pos !== false){
514 + if ($root_dir_pos !== false) {
405 515 $gs_name = substr($gs_name, $root_dir_pos);
406 516 }
407 517
408 - if ( !isset($gs_name) || empty($gs_name) ) {
518 + if (!isset($gs_name) || empty($gs_name)) {
409 519 return [];
410 520 }
411 521
412 522 foreach ($sources as $width => &$image) {
@@ -423,9 +533,9 @@
423 533 }
424 534
425 535 $thumb_gs_name = $meta['gs_name'];
426 536 // removing rood_dir from gs_name
427 - if($root_dir_pos !== false){
537 + if ($root_dir_pos !== false) {
428 538 $thumb_gs_name = substr($thumb_gs_name, $root_dir_pos);
429 539 }
430 540
431 541 if (substr_compare($image['url'], $thumb_gs_name, -strlen($thumb_gs_name)) === 0) {
@@ -435,19 +545,19 @@
435 545 }
436 546 }
437 547
438 548 // if no size found and mode is ephemeral or stateless and nothing to show for srcset item - unset that item
439 - if (!$found && ( $sm_mode === 'ephemeral' || $sm_mode === 'stateless' )) {
549 + if (!$found && ($sm_mode === 'ephemeral' || $sm_mode === 'stateless')) {
440 550 $image = null;
441 551 }
442 552 } else {
443 553 // if mode is stateless and nothing to show for srcset item - unset that item
444 - if ( $sm_mode === 'ephemeral' || $sm_mode === 'stateless' ) {
554 + if ($sm_mode === 'ephemeral' || $sm_mode === 'stateless') {
445 555 $image = null;
446 556 }
447 557 }
448 558 }
449 - } elseif ( is_array( $sources ) && $sm_mode === 'stateless' ) {
559 + } elseif (is_array($sources) && $sm_mode === 'stateless') {
450 560 foreach ($sources as $width => &$image) {
451 561 // Set default src
452 562 $image['url'] = $image_src;
453 563 }
@@ -452,9 +562,9 @@
452 562 $image['url'] = $image_src;
453 563 }
454 564 }
455 565
456 - return array_filter( $sources );
566 + return is_array($sources) ? array_filter($sources) : $sources;
457 567 }
458 568
459 569 /**
460 570 * Return gs host.
@@ -464,9 +574,9 @@
464 574 * @param array $sm
465 575 * @return mixed|void
466 576 */
467 577 public function get_gs_host($sm = array()) {
468 - $sm = $sm?$sm: $this->get( 'sm');
578 + $sm = $sm ? $sm : $this->get('sm');
469 579 $image_host = 'https://storage.googleapis.com/';
470 580 $image_host .= $sm['bucket'];
471 581
472 582 $custom_domain = $sm['custom_domain'];
@@ -476,17 +586,29 @@
476 586
477 587 // checking whether the provided domain is valid.
478 588 // if the custom domain is same as the bucket name
479 589 // or the custom domain is using https.
480 - if ( !empty($sm['bucket']) && !empty($custom_domain) && $custom_domain !== 'storage.googleapis.com' && ( $is_ssl === 0 || $custom_domain == $sm['bucket'] ) ) {
590 + if (!empty($sm['bucket']) && !empty($custom_domain) && $custom_domain !== 'storage.googleapis.com' && ($is_ssl === 0 || $custom_domain == $sm['bucket'])) {
481 591 $image_host = $is_ssl === 0 ? 'https://' : 'http://'; // bucketname will be host
482 592 $image_host .= $custom_domain;
483 593 }
484 594
485 - return apply_filters( 'get_gs_host', $image_host, $image_host, $sm['bucket'], $is_ssl, $sm );
595 + return apply_filters('get_gs_host', $image_host, $image_host, $sm['bucket'], $is_ssl, $sm);
486 596 }
487 597
488 598 /**
599 + * Return gs:// path.
600 + *
601 + * @param array $sm
602 + * @return mixed|void
603 + */
604 + public function get_gs_path() {
605 + $path = 'gs://' . $this->get('sm.bucket');
606 +
607 + return apply_filters('get_gs_path', $path);
608 + }
609 +
610 + /**
489 611 * Filter for wp_stateless_bucket_link if custom domain is set.
490 612 * It's get attachment url and remove "storage.googleapis.com" from url.
491 613 * So that custom url can be used.
492 614 *
@@ -493,20 +615,19 @@
493 615 * @param $fileLink
494 616 * @return mixed|string
495 617 */
496 618 public function wp_stateless_bucket_link($fileLink) {
497 - $bucketname = $this->get( 'sm.bucket' );
498 - $custom_domain = $this->get( 'sm.custom_domain' );
619 + $bucketname = $this->get('sm.bucket');
620 + $custom_domain = $this->get('sm.custom_domain');
499 621 $is_ssl = strpos($custom_domain, 'https://') === 0;
500 622 $fileLink_is_ssl = strpos($fileLink, 'https://') === 0;
501 623 $custom_domain = str_replace(array('http://', 'https://'), '', $custom_domain);
502 624 $custom_domain = trim($custom_domain, '/');
503 625
504 - if ( !empty($bucketname) && $custom_domain !== 'storage.googleapis.com' && $custom_domain == $bucketname && strpos($fileLink, $bucketname) > 8 ) {
626 + if (!empty($bucketname) && $custom_domain !== 'storage.googleapis.com' && $custom_domain == $bucketname && strpos($fileLink, $bucketname) > 8) {
505 627 $fileLink = ($is_ssl ? 'https://' : 'http://') . substr($fileLink, strpos($fileLink, $bucketname));
506 - }
507 - elseif( $custom_domain !== 'storage.googleapis.com' && $custom_domain == $bucketname && $fileLink_is_ssl !== $is_ssl){
508 - if($is_ssl)
628 + } elseif ($custom_domain !== 'storage.googleapis.com' && $custom_domain == $bucketname && $fileLink_is_ssl !== $is_ssl) {
629 + if ($is_ssl)
509 630 $fileLink = str_replace(array('http://', 'https://'), 'https://', $fileLink);
510 631 else
511 632 $fileLink = str_replace(array('http://', 'https://'), 'http://', $fileLink);
512 633 }
@@ -518,19 +639,31 @@
518 639 *
519 640 * @param string $path
520 641 * @return string
521 642 */
522 - public function get_settings_page_url( $path = '' ) {
523 - $url = get_admin_url( get_current_blog_id(), ( is_network_admin() ? 'network/settings.php' : 'upload.php' ) );
643 + public function get_settings_page_url($path = '') {
644 + $url = get_admin_url(get_current_blog_id(), (is_network_admin() ? 'network/settings.php' : 'upload.php'));
524 645 return $url . $path;
525 646 }
526 647
527 648 /**
649 + * Return docs page url.
650 + *
651 + * @param string $path
652 + * @return string
653 + */
654 + public function get_docs_page_url($path = '') {
655 + $path = ltrim($path, '/');
656 +
657 + return 'https://stateless.udx.io/' . $path;
658 + }
659 +
660 + /**
528 661 * Get new blog settings once switched blog.
529 662 * @param $new_blog
530 663 * @param $prev_blog_id
531 664 */
532 - public function on_switch_blog( $new_blog, $prev_blog_id ) {
665 + public function on_switch_blog($new_blog, $prev_blog_id) {
533 666 $this->settings->refresh();
534 667 }
535 668
536 669 /**
@@ -558,21 +691,21 @@
558 691
559 692 foreach ($settings_list as $setting) {
560 693
561 694 /** If setting is already exist, just skip it */
562 - if( isset( $settings[ $setting ] ) ) {
695 + if (isset($settings[$setting])) {
563 696 continue;
564 697 }
565 698
566 - $value = $this->get( 'sm.' . $setting );
699 + $value = $this->get('sm.' . $setting);
567 700
568 701 /** Decode json to array */
569 - if( $value && is_string( $value ) && $setting === 'key_json' ) {
570 - $value = json_decode( $value, true );
702 + if ($value && is_string($value) && $setting === 'key_json') {
703 + $value = json_decode($value, true);
571 704 $setting = 'key';
572 705 }
573 706
574 - $settings[ $setting ] = $value;
707 + $settings[$setting] = $value;
575 708 }
576 709
577 710 return $settings;
578 711 }
@@ -590,26 +723,27 @@
590 723 * @param $post
591 724 * @param $detached
592 725 * @return mixed
593 726 */
594 - public function add_custom_row_actions( $actions, $post, $detached ) {
727 + public function add_custom_row_actions($actions, $post, $detached) {
595 728
596 - if ( !current_user_can( 'upload_files' ) ) return $actions;
729 + if (!current_user_can('upload_files')) return $actions;
597 730
598 - $sm_cloud = get_post_meta( $post->ID, 'sm_cloud', 1 );
599 - $sm_mode = $this->get( 'sm.mode' );
600 - if ( !empty($sm_cloud) && $sm_mode === 'stateless' ) return $actions;
731 + $sm_cloud = apply_filters('wp_stateless_get_file', [], $post->ID);
601 732
602 - if ( $post && 'attachment' == $post->post_type && 'image/' == substr( $post->post_mime_type, 0, 6 ) ) {
603 - $actions['sm_sync'] = '<a href="javascript:;" data-id="'.$post->ID.'" data-type="image" class="sm_inline_sync">' . __('Regenerate and Sync with GCS', ud_get_stateless_media()->domain) . '</a>';
733 +
734 + $sm_mode = $this->get('sm.mode');
735 + if (!empty($sm_cloud) && $sm_mode === 'stateless') return $actions;
736 +
737 + if ($post && 'attachment' == $post->post_type && 'image/' == substr($post->post_mime_type, 0, 6)) {
738 + $actions['sm_sync'] = '<a href="javascript:;" data-id="' . $post->ID . '" data-type="image" class="sm_inline_sync">' . __('Regenerate and Sync with GCS', ud_get_stateless_media()->domain) . '</a>';
604 739 }
605 740
606 - if ( $post && 'attachment' == $post->post_type && 'image/' != substr( $post->post_mime_type, 0, 6 ) ) {
607 - $actions['sm_sync'] = '<a href="javascript:;" data-id="'.$post->ID.'" data-type="other" class="sm_inline_sync">' . __('Sync with GCS', ud_get_stateless_media()->domain) . '</a>';
741 + if ($post && 'attachment' == $post->post_type && 'image/' != substr($post->post_mime_type, 0, 6)) {
742 + $actions['sm_sync'] = '<a href="javascript:;" data-id="' . $post->ID . '" data-type="other" class="sm_inline_sync">' . __('Sync with GCS', ud_get_stateless_media()->domain) . '</a>';
608 743 }
609 744
610 745 return $actions;
611 -
612 746 }
613 747
614 748 /**
615 749 * Define REST API.
@@ -620,28 +754,63 @@
620 754
621 755 $route_namespace = 'wp-stateless/v1';
622 756 $api_namespace = 'wpCloud\StatelessMedia\API';
623 757
624 - register_rest_route( $route_namespace, '/status', array(
758 + register_rest_route($route_namespace, '/status', array(
625 759 'methods' => \WP_REST_Server::READABLE,
626 - 'callback' => array( $api_namespace, 'status' ),
760 + 'callback' => array($api_namespace, 'status'),
627 761 'permission_callback' => '__return_true'
628 - ) );
762 + ));
629 763
630 - register_rest_route( $route_namespace, '/getSettings', array(
764 + register_rest_route($route_namespace, '/getSettings', array(
631 765 'methods' => \WP_REST_Server::READABLE,
632 - 'callback' => array( $api_namespace, 'getSettings' ),
633 - 'permission_callback' => array( $api_namespace, 'authCheck' )
634 - ) );
766 + 'callback' => array($api_namespace, 'getSettings'),
767 + 'permission_callback' => array($api_namespace, 'authCheck')
768 + ));
635 769
636 - register_rest_route( $route_namespace, '/updateSettings', array(
770 + register_rest_route($route_namespace, '/updateSettings', array(
637 771 'methods' => \WP_REST_Server::CREATABLE,
638 - 'callback' => array( $api_namespace, 'updateSettings' ),
639 - 'permission_callback' => array( $api_namespace, 'authCheck' )
640 - ) );
772 + 'callback' => array($api_namespace, 'updateSettings'),
773 + 'permission_callback' => array($api_namespace, 'authCheck')
774 + ));
641 775
642 - }
776 + register_rest_route($route_namespace, '/sync/getProcesses', array(
777 + 'methods' => \WP_REST_Server::READABLE,
778 + 'callback' => array($api_namespace, 'syncGetProcesses'),
779 + 'permission_callback' => array($api_namespace, 'authCheck')
780 + ));
643 781
782 + register_rest_route($route_namespace, '/sync/getProcess/(?P<id>\S+)', array(
783 + 'methods' => \WP_REST_Server::READABLE,
784 + 'callback' => array($api_namespace, 'syncGetProcess'),
785 + 'permission_callback' => array($api_namespace, 'authCheck')
786 + ));
787 +
788 + register_rest_route($route_namespace, '/sync/run', array(
789 + 'methods' => \WP_REST_Server::CREATABLE,
790 + 'callback' => array($api_namespace, 'syncRun'),
791 + 'permission_callback' => array($api_namespace, 'authCheck')
792 + ));
793 +
794 + register_rest_route($route_namespace, '/sync/stop', array(
795 + 'methods' => \WP_REST_Server::CREATABLE,
796 + 'callback' => array($api_namespace, 'syncStop'),
797 + 'permission_callback' => array($api_namespace, 'authCheck')
798 + ));
799 +
800 + register_rest_route($route_namespace, '/batch/state', array(
801 + 'methods' => \WP_REST_Server::READABLE,
802 + 'callback' => array($api_namespace, 'batchState'),
803 + 'permission_callback' => array($api_namespace, 'authCheck')
804 + ));
805 +
806 + register_rest_route($route_namespace, '/batch/action', array(
807 + 'methods' => \WP_REST_Server::CREATABLE,
808 + 'callback' => array($api_namespace, 'batchAction'),
809 + 'permission_callback' => array($api_namespace, 'authCheck')
810 + ));
811 + }
812 +
644 813 /**
645 814 * Metabox for media modal page
646 815 * @param $form_fields
647 816 * @param $post
@@ -646,23 +815,23 @@
646 815 * @param $form_fields
647 816 * @param $post
648 817 * @return array
649 818 */
650 - public function attachment_modal_meta_box_callback ( $form_fields, $post ) {
651 -
652 - //do not show on media edit page, only on modal
653 - if ( isset($_GET['post'])) {
819 + public function attachment_modal_meta_box_callback($form_fields, $post) {
820 + // Do not show on media edit page, only on modal
821 + // Do not show if we are not in Media Library
822 + if ( isset($_GET['post']) || wp_doing_ajax() ) {
654 823 return $form_fields;
655 824 }
656 825
657 826 $link = get_edit_post_link($post->ID);
658 827
659 - $form_field[ 'label' ] = '';
660 - $form_field[ 'input' ] = 'html';
661 - $form_field[ 'html' ] = sprintf("<script>jQuery('.actions').prepend('<a href=\"%s#sm-attachment-metabox\">%s</a> | ')</script>", $link, __("View stateless meta", ud_get_stateless_media()->domain));
662 - $form_field[ 'show_in_modal' ] = true;
828 + $form_field['label'] = '';
829 + $form_field['input'] = 'html';
830 + $form_field['html'] = sprintf("<script>jQuery('.sm_edit_links').remove();jQuery('.actions').prepend('<a class=\"sm_edit_links\" href=\"%s#sm-attachment-metabox\">%s</a> | ')</script>", $link, __("View stateless meta", ud_get_stateless_media()->domain));
831 + $form_field['show_in_modal'] = true;
663 832
664 - $form_fields[ 'sm_html' ] = $form_field;
833 + $form_fields['sm_html'] = $form_field;
665 834 return $form_fields;
666 835 }
667 836
668 837 /**
@@ -669,21 +838,21 @@
669 838 * Metabox for media edit page
670 839 * @param $meta_boxes
671 840 * @return array
672 841 */
673 - public function attachment_meta_box_callback( $meta_boxes ) {
842 + public function attachment_meta_box_callback($meta_boxes) {
674 843 $post_id = false;
675 - if ( isset( $_GET['post'] ) ) {
676 - $post_id = intval( $_GET['post'] );
677 - } elseif ( isset( $_POST['post_ID'] ) ) {
678 - $post_id = intval( $_POST['post_ID'] );
679 - } elseif ( isset( $_GET['item'] ) ) {
680 - $post_id = intval( $_GET['item'] );
681 - } elseif ( isset( $_POST['item'] ) ) {
682 - $post_id = intval( $_POST['item'] );
844 + if (isset($_GET['post'])) {
845 + $post_id = intval($_GET['post']);
846 + } elseif (isset($_POST['post_ID'])) {
847 + $post_id = intval($_POST['post_ID']);
848 + } elseif (isset($_GET['item'])) {
849 + $post_id = intval($_GET['item']);
850 + } elseif (isset($_POST['item'])) {
851 + $post_id = intval($_POST['item']);
683 852 }
684 -
685 - return $this->_prepare_data_for_metabox( $meta_boxes, $post_id );
853 +
854 + return $this->_prepare_data_for_metabox($meta_boxes, $post_id);
686 855 }
687 856
688 857 /**
689 858 * Prepare data for metabox fields
@@ -690,14 +859,14 @@
690 859 * @param $meta_boxes
691 860 * @param $post_id
692 861 * @return array
693 862 */
694 - private function _prepare_data_for_metabox ( $meta_boxes, $post_id ) {
695 - $post = get_post ( $post_id );
696 - $sm_cloud = get_post_meta( $post_id, 'sm_cloud', 1 );
697 - $sm_mode = $this->get( 'sm.mode' );
863 + private function _prepare_data_for_metabox($meta_boxes, $post_id) {
864 + $post = get_post($post_id);
865 + $sm_cloud = apply_filters('wp_stateless_get_file', [], $post_id, true);
866 + $sm_mode = $this->get('sm.mode');
698 867
699 - if ( empty( $post ) ) {
868 + if (empty($post)) {
700 869 return $meta_boxes;
701 870 }
702 871
703 872 $sizes = $this->get_image_sizes();
@@ -703,19 +872,19 @@
703 872 $sizes = $this->get_image_sizes();
704 873
705 874 $fields = array();
706 875
707 - if ( $sm_mode !== 'stateless' || empty( $sm_cloud ) ) {
876 + if ($sm_mode !== 'stateless' || empty($sm_cloud)) {
708 877 $fields[] = array(
709 - 'name' => __( 'Regenerate', ud_get_stateless_media()->domain ),
878 + 'name' => __('Regenerate', ud_get_stateless_media()->domain),
710 879 'id' => 'storage_bucket_url',
711 880 'type' => 'custom_html',
712 - 'std' => $this->_prepare_generate_link( $post, false, '', true, $sm_cloud ),
881 + 'std' => $this->_prepare_generate_link($post, false, '', true, $sm_cloud),
713 882 'tab' => 'thumbnails',
714 883 );
715 884 }
716 885
717 - if ( is_array( $sm_cloud ) && !empty( $sm_cloud[ 'fileLink' ] ) ) {
886 + if (is_array($sm_cloud) && !empty($sm_cloud['fileLink'])) {
718 887
719 888 $fields[] = array(
720 889 'type' => 'heading',
721 890 'name' => 'Files',
@@ -722,58 +891,57 @@
722 891 'tab' => 'thumbnails',
723 892 );
724 893
725 894 $fields[] = array(
726 - 'name' => __( 'Original', ud_get_stateless_media()->domain ),
895 + 'name' => __('Original', ud_get_stateless_media()->domain),
727 896 'id' => 'storage_bucket_url',
728 897 'type' => 'custom_html',
729 898 'media_modal' => true,
730 - 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="'.esc_attr($sm_cloud[ 'fileLink' ]).'" />
731 - <a href="'.$sm_cloud[ 'fileLink' ].'" target="_blank" class="sm-view-link"><i class="dashicons dashicons-external"></i></a>&nbsp;&nbsp;&nbsp;'.$this->_prepare_generate_link( $post, true, '', false, $sm_cloud ).' </label>',
899 + 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="' . esc_attr($sm_cloud['fileLink']) . '" />
900 + <a href="' . $sm_cloud['fileLink'] . '" target="_blank" class="sm-view-link"><i class="dashicons dashicons-external"></i></a>&nbsp;&nbsp;&nbsp;' . $this->_prepare_generate_link($post, true, '', false, $sm_cloud) . ' </label>',
732 901 'tab' => 'thumbnails',
733 902 );
734 903
735 - if ( !empty( $sm_cloud['sizes'] ) && is_array( $sm_cloud['sizes'] ) ) {
736 - foreach( $sm_cloud['sizes'] as $size_label => $size ) {
904 + if (!empty($sm_cloud['sizes']) && is_array($sm_cloud['sizes'])) {
905 + foreach ($sm_cloud['sizes'] as $size_label => $size) {
737 906
738 907 $fields[] = array(
739 - 'name' => __( sprintf( "%s x %s", ($size['width'] ?: $sizes[$size_label]['width']), ($size['height'] ?: $sizes[$size_label]['height']) ), ud_get_stateless_media()->domain ),
740 - 'id' => 'storage_bucket_url'.$size_label,
908 + 'name' => __(sprintf("%s x %s", ($size['width'] ?: $sizes[$size_label]['width']), ($size['height'] ?: $sizes[$size_label]['height'])), ud_get_stateless_media()->domain),
909 + 'id' => 'storage_bucket_url' . $size_label,
741 910 'type' => 'custom_html',
742 911 'media_modal' => true,
743 - 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="'.esc_attr($size[ 'fileLink' ]).'" />
744 - <a href="'.$size[ 'fileLink' ].'" target="_blank" class="sm-view-link"><i class="dashicons dashicons-external"></i></a>&nbsp;&nbsp;&nbsp;'.$this->_prepare_generate_link( $post, true, $size_label, false, $sm_cloud ).' </label>',
912 + 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="' . esc_attr($size['fileLink']) . '" />
913 + <a href="' . $size['fileLink'] . '" target="_blank" class="sm-view-link"><i class="dashicons dashicons-external"></i></a>&nbsp;&nbsp;&nbsp;' . $this->_prepare_generate_link($post, true, $size_label, false, $sm_cloud) . ' </label>',
745 914 'tab' => 'thumbnails',
746 915 );
747 916 }
748 917 }
749 918
750 - if( !empty( $sm_cloud[ 'cacheControl' ] ) ) {
919 + if (!empty($sm_cloud['cacheControl'])) {
751 920 $fields[] = array(
752 - 'name' => __( 'Cache Control', ud_get_stateless_media()->domain ),
921 + 'name' => __('Cache Control', ud_get_stateless_media()->domain),
753 922 'id' => 'cache_control',
754 923 'type' => 'custom_html',
755 - 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="'.$sm_cloud[ 'cacheControl' ].'" /></label>',
924 + 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="' . $sm_cloud['cacheControl'] . '" /></label>',
756 925 'tab' => 'meta',
757 926 );
758 927 }
759 928
760 - if ( !empty( $sm_cloud[ 'bucket' ] ) ) {
929 + if (!empty($sm_cloud['bucket'])) {
761 930 $fields[] = array(
762 - 'name' => __( 'Storage Bucket', ud_get_stateless_media()->domain ),
931 + 'name' => __('Storage Bucket', ud_get_stateless_media()->domain),
763 932 'id' => 'storage_bukcet',
764 933 'type' => 'custom_html',
765 - 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="gs://'.esc_attr($sm_cloud[ 'bucket' ]).'" />
766 - <a href="https://console.cloud.google.com/storage/browser/'.esc_attr($sm_cloud[ 'bucket' ]).'" target="_blank" class="sm-view-link"><i class="dashicons dashicons-external"></i></a></label>',
934 + 'std' => '<label><input type="text" class="widefat urlfield" readonly="readonly" value="gs://' . esc_attr($sm_cloud['bucket']) . '" />
935 + <a href="https://console.cloud.google.com/storage/browser/' . esc_attr($sm_cloud['bucket']) . '" target="_blank" class="sm-view-link"><i class="dashicons dashicons-external"></i></a></label>',
767 936 'tab' => 'meta',
768 937 );
769 938 }
770 -
771 939 }
772 940
773 - $meta_boxes[] = apply_filters( 'sm::attachment::meta', array(
941 + $meta_boxes[] = apply_filters('sm::attachment::meta', array(
774 942 'id' => 'sm-attachment-metabox',
775 - 'title' => __( 'Stateless', ud_get_stateless_media()->domain ),
943 + 'title' => __('Stateless', ud_get_stateless_media()->domain),
776 944 'post_types' => 'attachment',
777 945 //'media_modal' => true,
778 946 //set context `side` for left column
779 947 'context' => 'normal',
@@ -779,13 +947,13 @@
779 947 'context' => 'normal',
780 948 'priority' => 'low',
781 949 'tabs' => array(
782 950 'thumbnails' => array(
783 - 'label' => __( 'Thumbnails', ud_get_stateless_media()->domain ),
951 + 'label' => __('Thumbnails', ud_get_stateless_media()->domain),
784 952 'icon' => 'dashicons-format-gallery',
785 953 ),
786 954 'meta' => array(
787 - 'label' => __( 'Meta', ud_get_stateless_media()->domain ),
955 + 'label' => __('Meta', ud_get_stateless_media()->domain),
788 956 'icon' => 'dashicons-admin-site',
789 957 ),
790 958 ),
791 959 // Tab style: 'default', 'box' or 'left'. Optional
@@ -792,9 +960,9 @@
792 960 'tab_style' => 'left',
793 961 // Show meta box wrapper around tabs? true (default) or false. Optional
794 962 'tab_wrapper' => true,
795 963 'fields' => $fields
796 - ), $post->ID );
964 + ), $post->ID);
797 965
798 966 return $meta_boxes;
799 967 }
800 968
@@ -806,24 +974,24 @@
806 974 * @param bool $button
807 975 * @param array $sm_cloud
808 976 * @return string
809 977 */
810 - private function _prepare_generate_link ( $post, $use_icon = false, $size = '', $button = false, $sm_cloud = array() ) {
978 + private function _prepare_generate_link($post, $use_icon = false, $size = '', $button = false, $sm_cloud = array()) {
811 979 $sync = '';
812 980
813 - $sm_mode = $this->get( 'sm.mode' );
981 + $sm_mode = $this->get('sm.mode');
814 982
815 - if ( current_user_can( 'upload_files' ) && $sm_mode !== 'disabled' && ( $sm_mode !== 'stateless' || empty($sm_cloud) ) ) {
816 - if ( $post && 'attachment' == $post->post_type && 'image/' == substr( $post->post_mime_type, 0, 6 ) ) {
817 - $sync = '<a href="javascript:;" data-type="image" data-id="'.$post->ID.'" data-size="'.$size.'" data-reload_page="'.$button.'"
818 - class="sm_inline_sync '.($button ? 'button button-primary button-large' : '').'">'. ( $use_icon ? "<i class='dashicons dashicons-image-rotate'></i>" : __( 'Regenerate and Sync with GCS', ud_get_stateless_media()->domain )).'</a>';
983 + if (current_user_can('upload_files') && $sm_mode !== 'disabled' && ($sm_mode !== 'stateless' || empty($sm_cloud))) {
984 + if ($post && 'attachment' == $post->post_type && 'image/' == substr($post->post_mime_type, 0, 6)) {
985 + $sync = '<a href="javascript:;" data-type="image" data-id="' . $post->ID . '" data-size="' . $size . '" data-reload_page="' . $button . '"
986 + class="sm_inline_sync ' . ($button ? 'button button-primary button-large' : '') . '">' . ($use_icon ? "<i class='dashicons dashicons-image-rotate'></i>" : __('Regenerate and Sync with GCS', ud_get_stateless_media()->domain)) . '</a>';
819 987 }
820 - if ( $post && 'attachment' == $post->post_type && 'image/' != substr( $post->post_mime_type, 0, 6 ) ) {
821 - $sync = '<a href="javascript:;" data-type="other" data-id="'.$post->ID.'" data-size="'.$size.'" data-reload_page="'.$button.'"
822 - class="sm_inline_sync '.($button ? 'button button-primary button-large' : '').'">'. ($use_icon ? "<i class='dashicons dashicons-image-rotate'></i>" : __( 'Sync with GCS', ud_get_stateless_media()->domain )).'</a>';
988 + if ($post && 'attachment' == $post->post_type && 'image/' != substr($post->post_mime_type, 0, 6)) {
989 + $sync = '<a href="javascript:;" data-type="other" data-id="' . $post->ID . '" data-size="' . $size . '" data-reload_page="' . $button . '"
990 + class="sm_inline_sync ' . ($button ? 'button button-primary button-large' : '') . '">' . ($use_icon ? "<i class='dashicons dashicons-image-rotate'></i>" : __('Sync with GCS', ud_get_stateless_media()->domain)) . '</a>';
823 991 }
824 - } elseif ( $button && $sm_mode !== 'stateless' ) {
825 - $sync = __('You do not have access to sync or Stateless mode is Disabled', ud_get_stateless_media()->domain );
992 + } elseif ($button && $sm_mode !== 'stateless') {
993 + $sync = __('You do not have access to sync or Stateless mode is Disabled', ud_get_stateless_media()->domain);
826 994 }
827 995 return $sync;
828 996 }
829 997
@@ -833,63 +1001,58 @@
833 1001 * 0 will be passed from various compatibilities so that the root dir is not used.
834 1002 * false will passed from some compatibilities to use the value as local path.
835 1003 * @param $attachment_id
836 1004 * @param $size
837 - * @param $use_wildcards
838 1005 * @return string
839 1006 */
840 - public function handle_root_dir( $current_path, $use_root = true, $attachment_id = '', $size = '', $use_wildcards = false ) {
841 - global $wpdb;
1007 + public function handle_root_dir($current_path, $use_root = true, $attachment_id = '', $size = '') {
1008 + //non media files
1009 + if ($use_root === 0) {
1010 + $non_media = ud_stateless_db()->get_non_library_file_name($current_path);
842 1011
843 - //for existing media
844 - $cloud_meta = get_post_meta( $attachment_id, 'sm_cloud', true );
845 -
846 - if ( !$use_wildcards && $cloud_meta ) {
847 - if ( ( !$size || $size === '__full' ) && !empty( $cloud_meta['name'] ) ) {
848 - return $cloud_meta['name'];
849 - } else {
850 - if ( !empty( $cloud_meta['sizes'] ) && isset( $cloud_meta['sizes'][$size] ) ) {
851 - return !empty( $cloud_meta['sizes'][$size]['name'] ) ? $cloud_meta['sizes'][$size]['name'] : $current_path;
852 - }
853 - }
854 - }
855 -
856 - //non media files
857 - if($use_root === 0){
858 - $table_name = $wpdb->prefix . 'sm_sync';
859 - $non_media = $wpdb->get_var($wpdb->prepare("SELECT file FROM {$table_name} WHERE file like '%%%s';", $current_path));
860 - if ( $non_media ) {
1012 + if ($non_media) {
861 1013 return $non_media;
862 1014 }
863 1015 }
864 1016
865 -
866 - $root_dir = $this->get( 'sm.root_dir' );
1017 + $root_dir = $this->get('sm.root_dir');
867 1018 $root_dir_regex = '~^' . apply_filters("wp_stateless_handle_root_dir", $root_dir, true) . '/~';
868 1019 /**
869 1020 * Retrieve Y/M and other tags from current path
870 1021 */
871 - $path_elements = apply_filters( 'wp_stateless_unhandle_root_dir', $current_path );
1022 + $path_elements = apply_filters('wp_stateless_unhandle_root_dir', $current_path);
872 1023 $root_dir = apply_filters("wp_stateless_handle_root_dir", $root_dir, false, $path_elements);
873 1024
874 1025 $upload_dir = wp_upload_dir();
875 - $current_path = str_replace( wp_normalize_path( trailingslashit( $upload_dir[ 'basedir' ] ) ), '', wp_normalize_path( $current_path ) );
876 - $current_path = str_replace( wp_normalize_path( trailingslashit( $upload_dir[ 'baseurl' ] ) ), '', wp_normalize_path( $current_path ) );
877 - $current_path = str_replace( trailingslashit( $this->get_gs_host() ), '', $current_path );
1026 + $current_path = str_replace(wp_normalize_path(trailingslashit($upload_dir['basedir'])), '', wp_normalize_path($current_path));
1027 + $current_path = str_replace(wp_normalize_path(trailingslashit($upload_dir['baseurl'])), '', wp_normalize_path($current_path));
1028 + $current_path = str_replace(trailingslashit($this->get_gs_host()), '', $current_path);
878 1029
879 1030 /**
880 1031 * Using only filename. Other parts of path included to $root_dir.
1032 + * excluding compatibility.
881 1033 */
882 - $current_path = basename($current_path);
1034 + if ($use_root) {
1035 + $current_path = basename($current_path);
1036 + }
883 1037
884 - if(!$use_root){
885 - // removing the root dir if already exists in the begaining.
886 - return preg_replace($root_dir_regex, '', $current_path);
1038 + if (!$use_root) {
1039 + // removing the root dir if already exists in the beginning.
1040 + $raw_name = preg_replace($root_dir_regex, '', $current_path);
1041 +
1042 + if ($raw_name && is_multisite() && ($blog_id = get_current_blog_id()) != 1) {
1043 + $folder = "sites/{$blog_id}/";
1044 + if (strpos($raw_name, $folder) === 0) return $raw_name;
1045 +
1046 + return "$folder$raw_name";
1047 + }
1048 +
1049 + return $raw_name;
887 1050 }
888 1051
889 1052 // skip adding root dir if it's already added.
890 - if ( !empty( $root_dir ) && !preg_match($root_dir_regex, $current_path) ) {
891 - return $root_dir . '/' . trim( $current_path, '/ ' );
1053 + if (!empty($root_dir) && !preg_match($root_dir_regex, $current_path)) {
1054 + return $root_dir . '/' . trim($current_path, '/ ');
892 1055 }
893 1056
894 1057 return $current_path;
895 1058 }
@@ -897,22 +1060,25 @@
897 1060 /**
898 1061 * @param $content
899 1062 * @return mixed
900 1063 */
901 - public function the_content_filter( $content ) {
1064 + public function the_content_filter($content) {
902 1065
903 - if ( $upload_data = wp_upload_dir() ) {
1066 + if ($upload_data = wp_upload_dir()) {
904 1067
905 - if ( !empty( $upload_data['url'] ) && !empty( $content ) ) {
906 - $url = preg_replace('/https?:\/\//','',$upload_data['url']);
1068 + if (!empty($upload_data['url']) && !empty($content)) {
1069 + $url = preg_replace('/https?:\/\//', '', $upload_data['url']);
907 1070
908 - $root_dir = trim( $this->get( 'sm.root_dir' ), '/ ' ); // Remove any forward slash and empty space.
1071 + $root_dir = trim($this->get('sm.root_dir'), '/ '); // Remove any forward slash and empty space.
909 1072 $root_dir = apply_filters("wp_stateless_handle_root_dir", $root_dir);
910 - $root_dir = !empty( $root_dir ) ? $root_dir . '/' : false;
1073 + $root_dir = !empty($root_dir) ? $root_dir . '/' : false;
911 1074 $image_host = $this->get_gs_host();
912 1075 $file_ext = $this->replaceable_file_types();
913 - $content = preg_replace( '/(href|src)=(\'|")(https?:\/\/'.str_replace('/', '\/', $url).')\/(.+?)('.$file_ext.')(\'|")/i',
914 - '$1=$2'.$image_host.'/'.($root_dir?$root_dir:'').'$4$5$6', $content);
1076 + $content = preg_replace(
1077 + '/(href|src)=(\'|")(https?:\/\/' . str_replace('/', '\/', $url) . ')\/(.+?)(' . $file_ext . ')(\'|")/i',
1078 + '$1=$2' . $image_host . '/' . ($root_dir ? $root_dir : '') . '$4$5$6',
1079 + $content
1080 + );
915 1081 }
916 1082 }
917 1083
918 1084 return $content;
@@ -921,9 +1087,9 @@
921 1087 /**
922 1088 * Return file types supported by File URL Replacement.
923 1089 * @return string
924 1090 */
925 - public function replaceable_file_types(){
1091 + public function replaceable_file_types() {
926 1092 $types = $this->get('sm.body_rewrite_types');
927 1093
928 1094 // Removing extra space.
929 1095 $types = trim($types);
@@ -941,23 +1107,23 @@
941 1107 * @param $meta_key
942 1108 * @param $single
943 1109 * @return mixed
944 1110 */
945 - public function post_metadata_filter($value, $object_id, $meta_key, $single){
946 - if(empty($value)){
1111 + public function post_metadata_filter($value, $object_id, $meta_key, $single) {
1112 + if (empty($value)) {
947 1113 $meta_type = 'post';
948 1114 $transient_key = "stateless_{$meta_type}_meta";
949 1115
950 1116 $meta_cache = wp_cache_get($object_id, $transient_key);
951 - if(empty($meta_cache)){
1117 + if (empty($meta_cache)) {
952 1118 $meta_cache = wp_cache_get($object_id, $meta_type . '_meta');
953 1119
954 - if ( !$meta_cache ) {
955 - $meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
1120 + if (!$meta_cache) {
1121 + $meta_cache = update_meta_cache($meta_type, array($object_id));
956 1122 $meta_cache = $meta_cache[$object_id];
957 1123 }
958 1124
959 - foreach($meta_cache as $key => $meta){
1125 + foreach ($meta_cache as $key => $meta) {
960 1126 $meta_cache[$key] = array_map('maybe_unserialize', $meta_cache[$key]);
961 1127 }
962 1128
963 1129 $meta_cache = $this->convert_to_gs_link($meta_cache);
@@ -963,13 +1129,13 @@
963 1129 $meta_cache = $this->convert_to_gs_link($meta_cache);
964 1130 wp_cache_set($object_id, $meta_cache, $transient_key);
965 1131 }
966 1132
967 - if ( ! $meta_key ) {
1133 + if (!$meta_key) {
968 1134 return $meta_cache;
969 1135 }
970 1136
971 - if ( isset($meta_cache[$meta_key]) ) {
1137 + if (isset($meta_cache[$meta_key])) {
972 1138 return $meta_cache[$meta_key];
973 1139 }
974 1140
975 1141 // in case no metadata is found return what was passed in $value.
@@ -977,9 +1143,8 @@
977 1143 return $value;
978 1144 }
979 1145
980 1146 return $this->convert_to_gs_link($value);
981 -
982 1147 }
983 1148
984 1149 /**
985 1150 * Replace all image link with gs link and return only if meta modified.
@@ -987,23 +1152,23 @@
987 1152 * @param $meta
988 1153 * @param $return
989 1154 * @return mixed or null when not changed.
990 1155 */
991 - public function convert_to_gs_link($meta, $return = false){
1156 + public function convert_to_gs_link($meta, $return = false) {
992 1157 $updated = $meta;
993 - if ( $meta && $upload_data = wp_upload_dir() ) {
994 - if ( !empty( $upload_data['url'] ) && !empty( $meta ) ) {
995 - $url = preg_replace('/https?:\/\//','',$upload_data['url']);
996 - $root_dir = trim( $this->get( 'sm.root_dir' ), '/ ' ); // Remove any forward slash and empty space.
1158 + if ($meta && $upload_data = wp_upload_dir()) {
1159 + if (!empty($upload_data['url']) && !empty($meta)) {
1160 + $url = preg_replace('/https?:\/\//', '', $upload_data['url']);
1161 + $root_dir = trim($this->get('sm.root_dir'), '/ '); // Remove any forward slash and empty space.
997 1162 $root_dir = apply_filters("wp_stateless_handle_root_dir", $root_dir);
998 - $root_dir = !empty( $root_dir ) ? $root_dir . '/': false;
999 - $image_host = $this->get_gs_host().'/'.($root_dir?$root_dir:'');
1163 + $root_dir = !empty($root_dir) ? $root_dir . '/' : false;
1164 + $image_host = $this->get_gs_host() . '/' . ($root_dir ? $root_dir : '');
1000 1165 $file_ext = $this->replaceable_file_types();
1001 1166 $updated = $this->_convert_to_gs_link($meta, $image_host, $url, $file_ext);
1002 1167 }
1003 1168 }
1004 1169
1005 - if($updated == $meta && !$return){
1170 + if ($updated == $meta && !$return) {
1006 1171 return null; // Not changed.
1007 1172 }
1008 1173 return $updated;
1009 1174 }
@@ -1016,21 +1181,21 @@
1016 1181 * @param $url
1017 1182 * @param $file_ext
1018 1183 * @return array|null|string|string[]
1019 1184 */
1020 - public function _convert_to_gs_link($meta, $image_host, $url, $file_ext){
1021 - if(is_array($meta)){
1185 + public function _convert_to_gs_link($meta, $image_host, $url, $file_ext) {
1186 + if (is_array($meta)) {
1022 1187 foreach ($meta as $key => $value) {
1023 1188 $meta[$key] = $this->_convert_to_gs_link($value, $image_host, $url, $file_ext);
1024 1189 }
1025 1190 return $meta;
1026 - } elseif (is_object($meta) && $meta instanceof \stdClass ) {
1191 + } elseif (is_object($meta) && $meta instanceof \stdClass) {
1027 1192 foreach (get_object_vars($meta) as $key => $value) {
1028 1193 $meta->{$key} = $this->_convert_to_gs_link($value, $image_host, $url, $file_ext);
1029 1194 }
1030 1195 return $meta;
1031 - } elseif(is_string($meta)){
1032 - return preg_replace( '/(https?:\/\/'.str_replace('/', '\/', $url).')\/(.+?)(' . $file_ext . ')/i', $image_host.'$2$3', $meta);
1196 + } elseif (is_string($meta)) {
1197 + return preg_replace('/(https?:\/\/' . str_replace('/', '\/', $url) . ')\/(.+?)(' . $file_ext . ')/i', $image_host . '$2$3', $meta);
1033 1198 }
1034 1199
1035 1200 return $meta;
1036 1201 }
@@ -1035,28 +1200,8 @@
1035 1200 return $meta;
1036 1201 }
1037 1202
1038 1203 /**
1039 - * @param $links
1040 - * @param $file
1041 - * @return mixed
1042 - */
1043 - public function plugin_action_links( $links, $file ) {
1044 -
1045 - if ($file == plugin_basename( dirname( __DIR__ ) . '/wp-stateless-media.php' ) ) {
1046 - $settings_link = '<a href="'. '' .'">'.__( 'Settings' , 'ssd').'</a>';
1047 - array_unshift( $links, $settings_link );
1048 - }
1049 -
1050 - if ($file == plugin_basename( dirname( __DIR__ ) . '/wp-stateless.php' ) ) {
1051 - $settings_link = '<a href="'. '' .'">'.__( 'Settings' , 'ssd').'</a>';
1052 - array_unshift( $links, $settings_link );
1053 - }
1054 -
1055 - return $links;
1056 - }
1057 -
1058 - /**
1059 1204 * Determines if plugin is loaded via mu-plugins
1060 1205 * or Network Enabled.
1061 1206 *
1062 1207 * @param bool $is_multisite
@@ -1065,20 +1210,20 @@
1065 1210 */
1066 1211 public function is_network_detected($is_multisite = false) {
1067 1212 /* Plugin is loaded via mu-plugins. */
1068 1213
1069 - if( strpos( Utility::normalize_path( $this->root_path ), Utility::normalize_path( WPMU_PLUGIN_DIR ) ) !== false ) {
1214 + if (strpos(Utility::normalize_path($this->root_path), Utility::normalize_path(WPMU_PLUGIN_DIR)) !== false) {
1070 1215 return true;
1071 1216 }
1072 1217
1073 - if( is_multisite() ) {
1074 - if($is_multisite) return true;
1218 + if (is_multisite()) {
1219 + if ($is_multisite) return true;
1075 1220 /* Looks through network enabled plugins to see if our one is there. */
1076 1221 foreach (wp_get_active_network_plugins() as $path) {
1077 1222 // Trying again using readlink in case it's a symlink file.
1078 1223 // boot_file is already solved.
1079 1224 // wp_normalize_path is helpfull in windows.
1080 - if (wp_normalize_path($this->boot_file) == wp_normalize_path($path) || (is_link($path) AND $this->boot_file == readlink($path))) {
1225 + if (wp_normalize_path($this->boot_file) == wp_normalize_path($path) || (is_link($path) && $this->boot_file == readlink($path))) {
1081 1226 return true;
1082 1227 }
1083 1228 }
1084 1229 }
@@ -1090,43 +1235,47 @@
1090 1235 * Register scripts and styles
1091 1236 */
1092 1237 public function admin_init() {
1093 1238 $this->show_notice_stateless_cache_busting();
1094 - wp_register_style( 'wp-stateless', $this->path( 'static/styles/wp-stateless.css', 'url' ), array(), self::$version );
1239 + wp_register_style('wp-stateless', $this->path('static/styles/wp-stateless.css', 'url'), array(), self::$version);
1095 1240
1096 1241 /**
1097 1242 * select2 styles
1098 1243 */
1099 - wp_register_style( 'wp-stateless-select2', $this->path( 'static/styles/select2.min.css', 'url' ), array(), self::$version );
1244 + wp_register_style('wp-stateless-select2', $this->path('static/styles/select2.min.css', 'url'), array(), self::$version);
1100 1245
1101 1246 /* Attachment or upload page */
1102 - wp_register_script( 'wp-stateless-uploads-js', $this->path( 'static/scripts/wp-stateless-uploads.js', 'url' ), array( 'jquery' ), self::$version );
1247 + wp_register_script('wp-stateless-uploads-js', $this->path('static/scripts/wp-stateless-uploads.js', 'url'), array('jquery'), self::$version);
1248 + wp_localize_script('wp-stateless-uploads-js', 'stateless_upload', [
1249 + 'inline_sync_nonce' => wp_create_nonce('sm_inline_sync'),
1250 + ]);
1103 1251
1104 1252 /* Setup wizard styles. */
1105 - wp_register_style( 'wp-stateless-setup-wizard', $this->path( 'static/styles/wp-stateless-setup-wizard.css', 'url' ), array(), self::$version );
1253 + // #152
1254 + // wp_register_style('wp-stateless-setup-wizard', $this->path('static/styles/wp-stateless-setup-wizard.css', 'url'), array(), self::$version);
1106 1255
1107 - wp_register_script( 'wp-stateless-select2', ud_get_stateless_media()->path( 'static/scripts/select2.min.js', 'url' ), array( 'jquery' ), self::$version, true );
1256 + wp_register_script('wp-stateless-select2', ud_get_stateless_media()->path('static/scripts/select2.min.js', 'url'), array('jquery'), self::$version, true);
1108 1257
1109 1258 /* Stateless settings page */
1110 - wp_register_script( 'wp-stateless-settings', ud_get_stateless_media()->path( 'static/scripts/wp-stateless-settings.js', 'url' ), array(), self::$version );
1111 - wp_localize_script( 'wp-stateless-settings', 'stateless_l10n', $this->get_l10n_data() );
1259 + wp_register_script('wp-stateless-settings', ud_get_stateless_media()->path('static/scripts/wp-stateless-settings.js', 'url'), array('clipboard'), self::$version);
1260 + wp_localize_script('wp-stateless-settings', 'stateless_l10n', $this->get_l10n_data());
1112 1261
1113 - wp_register_style( 'wp-stateless-settings', $this->path( 'static/styles/wp-stateless-settings.css', 'url' ), array(), self::$version );
1262 + wp_register_style('wp-stateless-settings', $this->path('static/styles/wp-stateless-settings.css', 'url'), array(), self::$version);
1263 + wp_register_style('wp-stateless-addons', $this->path('static/styles/wp-stateless-addons.css', 'url'), array(), self::$version);
1264 + wp_register_style('wp-stateless-status', $this->path('static/styles/wp-stateless-status.css', 'url'), array(), self::$version);
1114 1265
1115 1266 // Sync tab
1116 - if ( wp_script_is( 'jquery-ui-widget', 'registered' ) ){
1117 - wp_register_script( 'jquery-ui-progressbar', ud_get_stateless_media()->path('static/scripts/jquery-ui/jquery.ui.progressbar.min.js', 'url'), array( 'jquery-ui-core', 'jquery-ui-widget' ), '1.8.6' );
1118 - }
1119 - else{
1120 - wp_register_script( 'jquery-ui-progressbar', ud_get_stateless_media()->path( 'static/scripts/jquery-ui/jquery.ui.progressbar.min.1.7.2.js', 'url' ), array( 'jquery-ui-core' ), '1.7.2' );
1121 - }
1122 - wp_register_script( 'wp-stateless-angular', ud_get_stateless_media()->path( 'static/scripts/angular.min.js', 'url' ), array(), '1.5.0', true );
1123 - wp_register_script( 'wp-stateless-angular-sanitize', ud_get_stateless_media()->path( 'static/scripts/angular-sanitize.min.js', 'url' ), array('wp-stateless-angular'), '1.5.0', true );
1124 - wp_register_script( 'wp-stateless', ud_get_stateless_media()->path( 'static/scripts/wp-stateless.js', 'url' ), array( 'jquery-ui-core', 'wp-stateless-settings' ), self::$version, true );
1267 + wp_register_script('wp-stateless', ud_get_stateless_media()->path('static/scripts/wp-stateless.js', 'url'), array('jquery-ui-core', 'wp-stateless-settings', 'wp-api-request'), self::$version, true);
1125 1268
1126 - wp_localize_script( 'wp-stateless', 'stateless_l10n', $this->get_l10n_data() );
1269 + wp_localize_script('wp-stateless', 'stateless_l10n', $this->get_l10n_data());
1127 1270 wp_localize_script('wp-stateless', 'wp_stateless_configs', array(
1128 1271 'WP_DEBUG' => defined('WP_DEBUG') ? WP_DEBUG : false,
1272 + 'REST_API_TOKEN' => Utility::generate_jwt_token(['user_id' => get_current_user_id()], DAY_IN_SECONDS),
1273 + 'api_root' => apply_filters( 'wp_stateless_rest_api_root', '' ),
1274 + 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1275 + 'stateless_check_ajax_nonce' => wp_create_nonce('stateless_check_ajax'),
1276 + 'text_ok' => __('Ok', ud_get_stateless_media()->domain),
1277 + 'text_fail' => __('Fail', ud_get_stateless_media()->domain),
1129 1278 ));
1130 1279
1131 1280 $settings = ud_get_stateless_media()->get('sm');
1132 1281 $settings['wildcards'] = $this->settings->wildcards;
@@ -1131,15 +1280,20 @@
1131 1280 $settings = ud_get_stateless_media()->get('sm');
1132 1281 $settings['wildcards'] = $this->settings->wildcards;
1133 1282 $settings['network_admin'] = is_network_admin();
1134 1283 $settings['is_multisite'] = is_multisite();
1135 - if(defined('WP_STATELESS_MEDIA_JSON_KEY') && WP_STATELESS_MEDIA_JSON_KEY){
1284 + if (defined('WP_STATELESS_MEDIA_JSON_KEY') && WP_STATELESS_MEDIA_JSON_KEY) {
1136 1285 $settings['key_json'] = "Currently configured via a constant.";
1137 1286 }
1138 1287 wp_localize_script('wp-stateless', 'wp_stateless_settings', $settings);
1139 - wp_localize_script('wp-stateless', 'wp_stateless_compatibility', Module::get_modules());
1140 - wp_register_style( 'jquery-ui-regenthumbs', ud_get_stateless_media()->path( 'static/scripts/jquery-ui/redmond/jquery-ui-1.7.2.custom.css', 'url' ), array(), '1.7.2' );
1141 1288
1289 + // Batch processes tab
1290 + wp_register_script('wp-stateless-batch', ud_get_stateless_media()->path('static/scripts/wp-stateless-batch.js', 'url'), array('wp-api-request'), self::$version, true);
1291 + wp_localize_script('wp-stateless-batch', 'wp_stateless_batch', array(
1292 + 'REST_API_TOKEN' => Utility::generate_jwt_token(['user_id' => get_current_user_id()], DAY_IN_SECONDS),
1293 + 'is_running' => BatchTaskManager::instance()->is_running(),
1294 + 'api_root' => apply_filters( 'wp_stateless_rest_api_root', '' ),
1295 + ));
1142 1296 }
1143 1297
1144 1298 /**
1145 1299 * Get_l10n_data
@@ -1146,10 +1300,10 @@
1146 1300 *
1147 1301 * @param string $value
1148 1302 * @return mixed
1149 1303 */
1150 - public function get_l10n_data($value=''){
1151 - include ud_get_stateless_media()->path( 'l10n.php', 'dir');
1304 + public function get_l10n_data($value = '') {
1305 + include ud_get_stateless_media()->path('l10n.php', 'dir');
1152 1306 return $l10n;
1153 1307 }
1154 1308
1155 1309 /**
@@ -1156,19 +1310,19 @@
1156 1310 * Admin Scripts
1157 1311 *
1158 1312 * @param $hook
1159 1313 */
1160 - public function admin_enqueue_scripts( $hook ) {
1314 + public function admin_enqueue_scripts($hook) {
1161 1315
1162 - switch( $hook ) {
1316 + switch ($hook) {
1163 1317
1164 1318 case 'options-media.php':
1165 - wp_enqueue_style( 'wp-stateless');
1319 + wp_enqueue_style('wp-stateless');
1166 1320 break;
1167 1321
1168 1322 case 'upload.php':
1169 - wp_enqueue_style( 'wp-stateless');
1170 - wp_enqueue_script( 'wp-stateless-uploads-js' );
1323 + wp_enqueue_style('wp-stateless');
1324 + wp_enqueue_script('wp-stateless-uploads-js');
1171 1325
1172 1326 break;
1173 1327
1174 1328 case 'post.php':
@@ -1174,51 +1328,60 @@
1174 1328 case 'post.php':
1175 1329
1176 1330 global $post;
1177 1331
1178 - if ( $post->post_type == 'attachment' ) {
1179 - wp_enqueue_style( 'wp-stateless');
1180 - wp_enqueue_script( 'wp-stateless-uploads-js' );
1332 + if ($post->post_type == 'attachment') {
1333 + wp_enqueue_style('wp-stateless');
1334 + wp_enqueue_script('wp-stateless-uploads-js');
1181 1335 }
1182 1336
1183 1337 break;
1184 1338
1185 - case 'media_page_stateless-setup':
1339 + // #152
1340 + // case 'media_page_stateless-setup':
1186 1341 case 'settings_page_stateless-setup':
1187 - wp_enqueue_style( 'wp-stateless');
1188 - wp_enqueue_style( 'wp-stateless-setup-wizard' );
1342 + wp_enqueue_style('wp-stateless');
1343 + // #152
1344 + // wp_enqueue_style('wp-stateless-setup-wizard');
1189 1345 break;
1190 1346 case 'media_page_stateless-settings':
1191 1347 case 'settings_page_stateless-settings':
1192 - wp_enqueue_style( 'wp-stateless');
1193 - wp_enqueue_style( 'wp-stateless-select2');
1194 - wp_enqueue_script( 'wp-stateless-settings' );
1195 - wp_enqueue_script( 'wp-stateless-select2' );
1196 - wp_enqueue_style( 'wp-stateless-settings' );
1348 + wp_enqueue_style('wp-stateless');
1349 + wp_enqueue_style('wp-stateless-select2');
1350 + wp_enqueue_script('wp-stateless-settings');
1351 + wp_enqueue_script('wp-stateless-select2');
1352 + wp_enqueue_style('wp-stateless-settings');
1353 + wp_enqueue_style('wp-stateless-addons');
1354 + wp_enqueue_style('wp-stateless-status');
1355 + wp_enqueue_style( 'media-views' );
1197 1356
1198 1357 // Sync tab
1199 - wp_enqueue_script( 'jquery-ui-progressbar' );
1200 - wp_enqueue_script( 'wp-stateless-angular' );
1201 - wp_enqueue_script( 'wp-stateless-angular-sanitize' );
1202 - wp_enqueue_script( 'wp-stateless' );
1203 - wp_enqueue_style( 'jquery-ui-regenthumbs' );
1358 + wp_enqueue_script('wp-stateless');
1204 1359
1360 + // Data updates
1361 + wp_enqueue_script('jquery-ui-dialog');
1362 + wp_enqueue_style('wp-jquery-ui-dialog');
1363 + wp_enqueue_script('wp-stateless-batch');
1364 +
1365 + wp_enqueue_style('wp-pointer');
1366 + wp_enqueue_script('wp-pointer');
1367 +
1205 1368 $data = array(
1206 1369 'key' => 'stateless-cache-busting',
1207 1370 'class' => 'notice',
1208 - 'title' => sprintf( __( "Stateless and Ephemeral modes enables and requires the Cache-Busting option.", ud_get_stateless_media()->domain ) ),
1209 - 'message' => sprintf( __("WordPress looks at local files to prevent files with the same filenames.
1210 - Since Stateless mode bypasses this check, there is a potential for files to be stored with the same file name. We enforce the Cache-Busting option to prevent this.
1211 - Override with the <a href='%s' target='_blank'>%s</a> constant.", ud_get_stateless_media()->domain),"https://wp-stateless.github.io/docs/constants/#wp_stateless_media_cache_busting", "WP_STATELESS_MEDIA_CACHE_BUSTING" ),
1371 + 'title' => sprintf(__("Stateless and Ephemeral modes enables and requires the Cache-Busting option.", ud_get_stateless_media()->domain)),
1372 + 'message' => sprintf(__("WordPress looks at local files to prevent files with the same filenames.
1373 + Since Stateless mode bypasses this check, there is a potential for files to be stored with the same file name. We enforce the Cache-Busting option to prevent this.
1374 + Override with the <a href='%s' target='_blank'>%s</a> constant.", ud_get_stateless_media()->domain), ud_get_stateless_media()->get_docs_page_url('docs/constants/#wpstatelessmediacachebusting'), "WP_STATELESS_MEDIA_CACHE_BUSTING"),
1212 1375 );
1213 1376 echo "<script id='template-stateless-cache-busting' type='text/html'>";
1214 - include ud_get_stateless_media()->path( '/static/views/error-notice.php', 'dir' );
1377 + include ud_get_stateless_media()->path('/static/views/error-notice.php', 'dir');
1215 1378 echo "</script>";
1216 1379
1217 1380 break;
1218 - default: break;
1381 + default:
1382 + break;
1219 1383 }
1220 -
1221 1384 }
1222 1385
1223 1386 /**
1224 1387 * Add Attributes to media HTML
@@ -1228,20 +1391,19 @@
1228 1391 * @param $attachment
1229 1392 * @param $size
1230 1393 * @return mixed
1231 1394 */
1232 - public function wp_get_attachment_image_attributes( $attr, $attachment, $size = null ) {
1233 -
1234 - $sm_cloud = get_post_meta( $attachment->ID, 'sm_cloud', true );
1235 - if( is_array( $sm_cloud ) && !empty( $sm_cloud[ 'name' ] ) ) {
1236 - $attr[ 'class' ] = $attr[ 'class' ] . ' wp-stateless-item';
1237 - $attr[ 'data-image-size' ] = is_array( $size ) ? implode( 'x', $size ) : $size;
1238 - $attr[ 'data-stateless-media-bucket' ] = isset( $sm_cloud[ 'bucket' ] ) ? $sm_cloud[ 'bucket' ] : false;
1239 - $attr[ 'data-stateless-media-name' ] = $sm_cloud[ 'name' ];
1395 + public function wp_get_attachment_image_attributes($attr, $attachment, $size = null) {
1396 +
1397 + $sm_cloud = apply_filters('wp_stateless_get_file', [], $attachment->ID);
1398 + if (is_array($sm_cloud) && !empty($sm_cloud['name'])) {
1399 + $attr['class'] = $attr['class'] . ' wp-stateless-item';
1400 + $attr['data-image-size'] = is_array($size) ? implode('x', $size) : $size;
1401 + $attr['data-stateless-media-bucket'] = isset($sm_cloud['bucket']) ? $sm_cloud['bucket'] : false;
1402 + $attr['data-stateless-media-name'] = $sm_cloud['name'];
1240 1403 }
1241 1404
1242 1405 return $attr;
1243 -
1244 1406 }
1245 1407
1246 1408 /**
1247 1409 * Adds filter link to Media Library table.
@@ -1248,10 +1410,10 @@
1248 1410 *
1249 1411 * @param $views
1250 1412 * @return mixed
1251 1413 */
1252 - public function views_upload( $views ) {
1253 - $views['stateless'] = '<a href="#">' . __( 'Stateless Media' ) . '</a>';
1414 + public function views_upload($views) {
1415 + $views['stateless'] = '<a href="#">' . __('Stateless Media') . '</a>';
1254 1416 return $views;
1255 1417 }
1256 1418
1257 1419 /**
@@ -1261,11 +1423,11 @@
1261 1423 * @param integer $id
1262 1424 * @param string $size
1263 1425 * @return mixed $false
1264 1426 */
1265 - public function image_downsize( $false = false, $id, $size ) {
1427 + public function image_downsize($false, $id, $size) {
1266 1428
1267 - if ( (!isset( $this->client ) || !$this->client || is_wp_error( $this->client )) && $this->get( 'sm.mode' ) !== 'stateless' ) {
1429 + if ((!isset($this->client) || !$this->client || is_wp_error($this->client)) && $this->get('sm.mode') !== 'stateless') {
1268 1430 return $false;
1269 1431 }
1270 1432
1271 1433 /**
@@ -1270,9 +1432,9 @@
1270 1432
1271 1433 /**
1272 1434 * Check if enabled
1273 1435 */
1274 - if ( !in_array( $this->get( 'sm.mode' ), array( 'cdn', 'stateless', 'ephemeral' ) )) {
1436 + if (!in_array($this->get('sm.mode'), array('cdn', 'stateless', 'ephemeral'))) {
1275 1437 return $false;
1276 1438 }
1277 1439
1278 1440 /** Start determine remote file */
@@ -1281,16 +1443,14 @@
1281 1443 $width = $height = 0;
1282 1444 $is_intermediate = false;
1283 1445
1284 1446 //** try for a new style intermediate size */
1285 - if ( $intermediate = image_get_intermediate_size( $id, $size ) ) {
1286 - if(!empty( $intermediate['gs_link'] )){
1447 + if ($intermediate = image_get_intermediate_size($id, $size)) {
1448 + if (!empty($intermediate['gs_link'])) {
1287 1449 $img_url = $intermediate['gs_link'];
1288 - }
1289 - else if(!empty( $intermediate['url'] )){
1450 + } else if (!empty($intermediate['url'])) {
1290 1451 $img_url = $intermediate['url'];
1291 - }
1292 - else{
1452 + } else {
1293 1453 $img_url = dirname($img_url) . $intermediate['file'];
1294 1454 }
1295 1455
1296 1456 $width = $intermediate['width'];
@@ -1302,18 +1462,18 @@
1302 1462 * maybe try to get images info from sm_cloud
1303 1463 * this case may happen when no local files
1304 1464 * @author korotkov@ud
1305 1465 */
1306 - if ( !$width && !$height ) {
1307 - $sm_cloud = get_post_meta( $id, 'sm_cloud', true );
1308 - if ( is_string($size) && !empty( $sm_cloud['sizes'] ) && !empty( $sm_cloud['sizes'][$size] ) ) {
1466 + if (!$width && !$height) {
1467 + $sm_cloud = apply_filters('wp_stateless_get_file', [], $id, true);
1468 + if (is_string($size) && !empty($sm_cloud['sizes']) && !empty($sm_cloud['sizes'][$size])) {
1309 1469 global $_wp_additional_image_sizes;
1310 1470
1311 - $img_url = !empty( $sm_cloud['sizes'][$size]['fileLink'] ) ? $sm_cloud['sizes'][$size]['fileLink'] : $img_url;
1471 + $img_url = !empty($sm_cloud['sizes'][$size]['fileLink']) ? $sm_cloud['sizes'][$size]['fileLink'] : $img_url;
1312 1472
1313 - if ( !empty( $_wp_additional_image_sizes[ $size ] ) ) {
1314 - $width = !empty( $_wp_additional_image_sizes[ $size ]['width'] ) ? $_wp_additional_image_sizes[ $size ]['width'] : $width;
1315 - $height = !empty( $_wp_additional_image_sizes[ $size ]['height'] ) ? $_wp_additional_image_sizes[ $size ]['height'] : $height;
1473 + if (!empty($_wp_additional_image_sizes[$size])) {
1474 + $width = !empty($_wp_additional_image_sizes[$size]['width']) ? $_wp_additional_image_sizes[$size]['width'] : $width;
1475 + $height = !empty($_wp_additional_image_sizes[$size]['height']) ? $_wp_additional_image_sizes[$size]['height'] : $height;
1316 1476 }
1317 1477
1318 1478 $is_intermediate = true;
1319 1479 }
@@ -1318,9 +1478,9 @@
1318 1478 $is_intermediate = true;
1319 1479 }
1320 1480 }
1321 1481
1322 - if ( !$width && !$height && isset( $meta['width'], $meta['height'] ) ) {
1482 + if (!$width && !$height && isset($meta['width'], $meta['height'])) {
1323 1483
1324 1484 //** any other type: use the real image */
1325 1485 $width = $meta['width'];
1326 1486 $height = $meta['height'];
@@ -1326,14 +1486,14 @@
1326 1486 $height = $meta['height'];
1327 1487 }
1328 1488
1329 1489
1330 - if ( $img_url) {
1490 + if ($img_url) {
1331 1491
1332 1492 //** we have the actual image size, but might need to further constrain it if content_width is narrower */
1333 - list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
1493 + list($width, $height) = image_constrain_size_for_editor($width, $height, $size);
1334 1494 $img_url = apply_filters('wp_stateless_bucket_link', $img_url);
1335 - return array( $img_url, $width, $height, $is_intermediate );
1495 + return array($img_url, $width, $height, $is_intermediate);
1336 1496 }
1337 1497
1338 1498
1339 1499 /**
@@ -1339,9 +1499,8 @@
1339 1499 /**
1340 1500 * All other cases work as usually
1341 1501 */
1342 1502 return $false;
1343 -
1344 1503 }
1345 1504
1346 1505 /**
1347 1506 * Extends metadata by adding GS information.
@@ -1350,61 +1509,61 @@
1350 1509 * @param $metadata
1351 1510 * @param $attachment_id
1352 1511 * @return array|mixed
1353 1512 */
1354 - public function wp_get_attachment_metadata( $metadata, $attachment_id ) {
1513 + public function wp_get_attachment_metadata($metadata, $attachment_id) {
1355 1514 global $default_dir;
1356 1515 $default_dir = false;
1357 1516 /* Determine if the media file has GS data at all. */
1358 - $sm_cloud = get_post_meta( $attachment_id, 'sm_cloud', true );
1517 + $sm_cloud = apply_filters('wp_stateless_get_file', [], $attachment_id, true);
1359 1518 // If metadata not passed the get metadata from post meta.
1360 - if(empty($metadata)){
1361 - $metadata = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
1519 + if (empty($metadata)) {
1520 + $metadata = get_post_meta($attachment_id, '_wp_attachment_metadata', true);
1362 1521 }
1363 1522
1364 - if(empty($metadata)){
1523 + if (empty($metadata)) {
1365 1524 $metadata = [];
1366 1525 }
1367 1526
1368 - if( is_array( $metadata ) && is_array( $sm_cloud ) && !empty( $sm_cloud[ 'fileLink' ] ) ) {
1369 - $metadata[ 'gs_link' ] = apply_filters('wp_stateless_bucket_link', $sm_cloud[ 'fileLink' ]);
1370 - $metadata[ 'gs_name' ] = isset( $sm_cloud[ 'name' ] ) ? $sm_cloud[ 'name' ] : false;
1371 - $metadata[ 'gs_bucket' ] = isset( $sm_cloud[ 'bucket' ] ) ? $sm_cloud[ 'bucket' ] : false;
1372 - if( !empty( $metadata[ 'sizes' ] ) && is_array( $metadata[ 'sizes' ] ) ) {
1373 - foreach( $metadata[ 'sizes' ] as $k => $v ) {
1374 - if( !empty( $sm_cloud[ 'sizes' ][ $k ][ 'name' ] ) ) {
1375 - $metadata['sizes'][$k]['gs_name'] = $sm_cloud[ 'sizes' ][ $k ][ 'name' ];
1376 - $metadata['sizes'][$k]['gs_link'] = apply_filters('wp_stateless_bucket_link', $sm_cloud[ 'sizes' ][ $k ][ 'fileLink' ]);
1527 + if (is_array($metadata) && is_array($sm_cloud) && !empty($sm_cloud['fileLink'])) {
1528 + $metadata['gs_link'] = apply_filters('wp_stateless_bucket_link', $sm_cloud['fileLink']);
1529 + $metadata['gs_name'] = isset($sm_cloud['name']) ? $sm_cloud['name'] : false;
1530 + $metadata['gs_bucket'] = isset($sm_cloud['bucket']) ? $sm_cloud['bucket'] : false;
1531 + if (!empty($metadata['sizes']) && is_array($metadata['sizes'])) {
1532 + foreach ($metadata['sizes'] as $k => $v) {
1533 + if (!empty($sm_cloud['sizes'][$k]['name'])) {
1534 + $metadata['sizes'][$k]['gs_name'] = $sm_cloud['sizes'][$k]['name'];
1535 + $metadata['sizes'][$k]['gs_link'] = apply_filters('wp_stateless_bucket_link', $sm_cloud['sizes'][$k]['fileLink']);
1377 1536 }
1378 1537 }
1379 1538 }
1380 1539 }
1381 - if(is_multisite() && !empty($metadata['file'])){
1382 - if ( $this->get('sm.mode') == 'stateless' ) {
1540 + if (is_multisite() && !empty($metadata['file'])) {
1541 + if ($this->get('sm.mode') == 'stateless') {
1383 1542 $default_dir = true;
1384 1543 $uploads = wp_get_upload_dir();
1385 1544 $default_dir = false;
1386 1545
1387 1546 $file_path_fix = $uploads['basedir'] . "/{$metadata['file']}";
1388 - if(file_exists($file_path_fix)) {
1389 - $metadata[ 'file' ] = "{$metadata['file']}";
1547 + if (file_exists($file_path_fix)) {
1548 + $metadata['file'] = "{$metadata['file']}";
1390 1549 }
1391 1550 } else {
1392 1551 $uploads = wp_get_upload_dir();
1393 1552 $blog_id = get_current_blog_id();
1394 - $file_path_fix = $uploads[ 'basedir' ] . "/sites/$blog_id/{$metadata['file']}";
1395 - if( file_exists( $file_path_fix ) ) {
1396 - $metadata[ 'file' ] = "sites/$blog_id/{$metadata['file']}";
1553 + $file_path_fix = $uploads['basedir'] . "/sites/$blog_id/{$metadata['file']}";
1554 + if (file_exists($file_path_fix)) {
1555 + $metadata['file'] = "sites/$blog_id/{$metadata['file']}";
1397 1556 }
1398 1557 }
1399 - } elseif ( empty($sm_cloud) && $this->get('sm.mode') == 'stateless' ) {
1558 + } elseif ( empty($sm_cloud) && $this->get('sm.mode') == 'stateless' && isset($metadata['file']) ) {
1400 1559 $default_dir = true;
1401 1560 $uploads = wp_get_upload_dir();
1402 1561 $default_dir = false;
1403 1562
1404 1563 $file_path_fix = $uploads['basedir'] . "/{$metadata['file']}";
1405 - if(file_exists($file_path_fix)) {
1406 - $metadata[ 'file' ] = "{$metadata['file']}";
1564 + if (file_exists($file_path_fix)) {
1565 + $metadata['file'] = "{$metadata['file']}";
1407 1566 }
1408 1567 }
1409 1568
1410 1569 return $metadata;
@@ -1415,33 +1574,31 @@
1415 1574 * @param $file
1416 1575 * @param $attachment_id
1417 1576 * @return string
1418 1577 */
1419 - public function get_attached_file($file, $attachment_id){
1578 + public function get_attached_file($file, $attachment_id) {
1420 1579 global $default_dir;
1421 - $sm_cloud = get_post_meta( $attachment_id, 'sm_cloud', 1 );
1580 +
1581 + $sm_cloud = apply_filters('wp_stateless_get_file', [], $attachment_id);
1582 + $_file = get_post_meta($attachment_id, '_wp_attached_file', true);
1583 +
1422 1584 /* Determine if the media file has GS data at all. */
1423 - if(is_multisite()){
1424 - $sm_cloud = get_post_meta( $attachment_id, 'sm_cloud', true );
1425 - $_file = get_post_meta( $attachment_id, '_wp_attached_file', true );
1426 - if($_file){
1427 - $blog_id = get_current_blog_id();
1428 - $uploads = wp_get_upload_dir();
1429 - $_file = apply_filters( 'wp_stateless_file_name', $_file, false);
1430 - $file_path_fix = $uploads['basedir'] . "/sites/$blog_id/$_file";
1431 - if(file_exists($file_path_fix)){
1432 - $file = $file_path_fix;
1433 - }
1585 + if (is_multisite() && $_file) {
1586 + $blog_id = get_current_blog_id();
1587 + $uploads = wp_get_upload_dir();
1588 + $_file = apply_filters('wp_stateless_file_name', $_file, false);
1589 + $file_path_fix = $uploads['basedir'] . "/sites/$blog_id/$_file";
1590 +
1591 + if (file_exists($file_path_fix)) {
1592 + return $file_path_fix;
1434 1593 }
1435 - } elseif ( empty($sm_cloud) && $this->get('sm.mode') == 'stateless' ) {
1436 - $_file = get_post_meta( $attachment_id, '_wp_attached_file', true );
1437 - if( $_file ) {
1438 - $default_dir = true;
1439 - $uploads = wp_get_upload_dir();
1440 - $default_dir = false;
1441 - return $uploads[ 'basedir' ] . '/' . $_file;
1442 - }
1594 + } elseif (empty($sm_cloud) && $this->get('sm.mode') == 'stateless' && $_file) {
1595 + $default_dir = true;
1596 + $uploads = wp_get_upload_dir();
1597 + $default_dir = false;
1598 + return $uploads['basedir'] . '/' . $_file;
1443 1599 }
1600 +
1444 1601 return $file;
1445 1602 }
1446 1603
1447 1604 /**
@@ -1452,24 +1609,23 @@
1452 1609 * @return object $this->client. \wpCloud\StatelessMedia\GS_Client or \WP_Error
1453 1610 */
1454 1611 public function get_client() {
1455 1612
1456 - if( null === $this->client ) {
1613 + if (null === $this->client) {
1457 1614
1458 - $key_json = $this->get( 'sm.key_json' );
1459 - if ( empty($key_json) ) {
1460 - $key_json = get_site_option( 'sm_key_json' );
1615 + $key_json = $this->get('sm.key_json');
1616 + if (empty($key_json)) {
1617 + $key_json = get_site_option('sm_key_json');
1461 1618 }
1462 1619
1463 1620 /* Try to initialize GS Client */
1464 - $this->client = GS_Client::get_instance( array(
1465 - 'bucket' => $this->get( 'sm.bucket' ),
1621 + $this->client = GS_Client::get_instance(array(
1622 + 'bucket' => $this->get('sm.bucket'),
1466 1623 'key_json' => $key_json
1467 - ) );
1624 + ));
1468 1625 }
1469 1626
1470 1627 return $this->client;
1471 -
1472 1628 }
1473 1629
1474 1630 /**
1475 1631 * Determines if we can connect to Google Storage Bucket.
@@ -1476,47 +1632,46 @@
1476 1632 *
1477 1633 * @author peshkov@UD
1478 1634 */
1479 1635 public function is_connected_to_gs() {
1636 + $trnst = get_transient('sm::is_connected_to_gs');
1480 1637
1481 - $trnst = get_transient( 'sm::is_connected_to_gs' );
1482 -
1483 - if ( empty($trnst) || false === $trnst || !isset( $trnst[ 'hash' ] ) || $trnst[ 'hash' ] != md5( serialize( $this->get( 'sm' ) ) ) ) {
1638 + if (empty($trnst) || false === $trnst || !isset($trnst['hash']) || $trnst['hash'] != md5(serialize($this->get('sm')))) {
1484 1639 $trnst = array(
1485 1640 'success' => 'true',
1486 1641 'error' => '',
1487 - 'hash' => md5( serialize( $this->get( 'sm' ) ) ),
1642 + 'hash' => md5(serialize($this->get('sm'))),
1488 1643 );
1489 1644 $client = $this->get_client();
1490 1645
1491 - if ( is_wp_error( $client ) ) {
1492 - $trnst[ 'success' ] = 'false';
1493 - $trnst[ 'error' ] = $client->get_error_message();
1646 + if (is_wp_error($client)) {
1647 + $trnst['success'] = 'false';
1648 + $trnst['error'] = $client->get_error_message();
1494 1649 } else {
1495 1650 $connected = $client->is_connected();
1496 - if( $connected !== true ) {
1497 - $trnst[ 'success' ] = 'false';
1498 - $trnst[ 'error' ] = sprintf( __( 'Could not connect to Google Storage bucket. Please, be sure that bucket with name <b>%s</b> exists.', $this->domain ), $this->get( 'sm.bucket' ) );
1651 + if ($connected !== true) {
1652 + $trnst['success'] = 'false';
1653 + $trnst['error'] = sprintf('Could not connect to Google Storage bucket. Please be sure that bucket with name <b>%s</b> exists and the access credentials are correct.', esc_html($this->get('sm.bucket')));
1499 1654
1500 - if( is_callable(array($connected, 'getHandlerContext')) && $handlerContext = $connected->getHandlerContext() ){
1501 - if(!empty($handlerContext['error'])){
1655 + if (is_callable(array($connected, 'getHandlerContext')) && $handlerContext = $connected->getHandlerContext()) {
1656 + if (!empty($handlerContext['error'])) {
1502 1657 $handlerContext['error'];
1503 - $trnst[ 'error' ] = "Could not connect to Google Storage bucket. " . make_clickable($handlerContext['error']);
1658 + $trnst['error'] = "Could not connect to Google Storage bucket. " . make_clickable($handlerContext['error']);
1504 1659 }
1505 1660 }
1506 1661
1507 - if( is_callable(array($connected, 'getErrors')) && $error = $connected->getErrors() ){
1662 + if (is_callable(array($connected, 'getErrors')) && $error = $connected->getErrors()) {
1508 1663 $error = reset($error);
1509 - if($error['reason'] == 'accessNotConfigured')
1510 - $trnst[ 'error' ] = "Could not connect to Google Storage bucket. " . make_clickable($error['message']);
1664 + if ($error['reason'] == 'accessNotConfigured')
1665 + $trnst['error'] = "Could not connect to Google Storage bucket. " . make_clickable($error['message']);
1511 1666 }
1512 1667 }
1513 1668 }
1514 - set_transient( 'sm::is_connected_to_gs', $trnst, 4 * HOUR_IN_SECONDS );
1669 + set_transient('sm::is_connected_to_gs', $trnst, 4 * HOUR_IN_SECONDS);
1515 1670 }
1516 1671
1517 - if( isset( $trnst[ 'success' ] ) && $trnst[ 'success' ] == 'false' ) {
1518 - return new \WP_Error( 'error', ( !empty( $trnst[ 'error' ] ) ? $trnst[ 'error' ] : __( 'There is an Error on connection to Google Storage.', $this->domain ) ) );
1672 + if (isset($trnst['success']) && $trnst['success'] == 'false') {
1673 + return new \WP_Error('error', (!empty($trnst['error']) ? $trnst['error'] : 'There is an Error on connection to Google Storage.'));
1519 1674 }
1520 1675
1521 1676 return true;
1522 1677 }
@@ -1525,9 +1680,9 @@
1525 1680 * Flush all plugin transients
1526 1681 *
1527 1682 */
1528 1683 public function flush_transients() {
1529 - delete_transient( 'sm::is_connected_to_gs' );
1684 + delete_transient('sm::is_connected_to_gs');
1530 1685 }
1531 1686
1532 1687 /**
1533 1688 * Plugin Activation
@@ -1533,9 +1688,9 @@
1533 1688 * Plugin Activation
1534 1689 *
1535 1690 */
1536 1691 public function activate() {
1537 - add_action( 'activated_plugin', array($this, 'redirect_to_splash'), 99 );
1692 + add_action('activated_plugin', array($this, 'redirect_to_splash'), 99);
1538 1693 $this->run_upgrade_process();
1539 1694 }
1540 1695
1541 1696 /**
@@ -1544,10 +1699,9 @@
1544 1699 * Works on even manual plugin update.
1545 1700 *
1546 1701 * @author alim@UD
1547 1702 */
1548 - public function run_install_process()
1549 - {
1703 + public function run_install_process() {
1550 1704 // calling the upgrade function because it's same as this point for fresh install or updates.
1551 1705 $this->run_upgrade_process();
1552 1706 }
1553 1707
@@ -1557,61 +1711,27 @@
1557 1711 * Works on even manual plugin update.
1558 1712 *
1559 1713 * @author alim@UD
1560 1714 */
1561 - public function run_upgrade_process()
1562 - {
1715 + public function run_upgrade_process() {
1563 1716 // Creating database on new installation.
1564 - $this->create_db();
1717 + ud_stateless_db()->create_db();
1718 +
1719 + Migrator::instance()->migrate();
1720 +
1565 1721 /**
1566 1722 * Maybe Upgrade current Version
1567 1723 */
1568 - Upgrader::call( $this->args[ 'version' ] );
1724 + Upgrader::call($this->args['version']);
1569 1725 }
1570 1726
1571 1727 /**
1572 - * Create database on plugin activation.
1573 - * @param boolean $force - whether to create db even if option exists. For debug purpose only.
1574 - */
1575 - public function create_db($force = false) {
1576 - global $wpdb;
1577 - $sm_sync_db_version = get_option( 'sm_sync_db_version' );
1578 -
1579 - if( $sm_sync_db_version && $force == false ) {
1580 - return;
1581 - }
1582 -
1583 - $table_name = $wpdb->prefix . 'sm_sync';
1584 - $charset_collate = $wpdb->get_charset_collate();
1585 -
1586 - // `expire` timestamp NULL DEFAULT NULL,
1587 - $sql = "CREATE TABLE $table_name (
1588 - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT ,
1589 - `file` varchar(255) NOT NULL ,
1590 - `status` varchar(10) NOT NULL ,
1591 - PRIMARY KEY (`id`)
1592 - ) $charset_collate;";
1593 -
1594 - require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
1595 - dbDelta( $sql );
1596 -
1597 - add_option( 'sm_sync_db_version', $this->args[ 'version' ] );
1598 - }
1599 -
1600 - /**
1601 1728 * Delete table when blog is deleted.
1602 1729 *
1603 1730 * @param $old_site
1604 1731 */
1605 - public function wp_delete_site($old_site){
1606 - global $wpdb;
1607 -
1608 - switch_to_blog( $old_site->id );
1609 - $table_name = $wpdb->prefix . 'sm_sync';
1610 -
1611 - $sql = "DROP TABLE IF EXISTS $table_name";
1612 - $wpdb->query($sql);
1613 - restore_current_blog();
1732 + public function wp_delete_site($old_site) {
1733 + ud_stateless_db()->clear_db($old_site->id);
1614 1734 }
1615 1735
1616 1736 /**
1617 1737 * Redirect_to_splash
@@ -1617,16 +1737,16 @@
1617 1737 * Redirect_to_splash
1618 1738 *
1619 1739 * @param string $plugin
1620 1740 */
1621 - public function redirect_to_splash($plugin =''){
1741 + public function redirect_to_splash($plugin = '') {
1622 1742 // $this->settings = new Settings();
1623 1743
1624 - if(defined( 'WP_CLI' ) || $this->settings->get('sm.key_json') || isset($_POST['checked']) && count($_POST['checked']) > 1){
1744 + if (defined('WP_CLI') || $this->settings->get('sm.key_json') || isset($_POST['checked']) && count($_POST['checked']) > 1) {
1625 1745 return;
1626 1746 }
1627 1747
1628 - if(
1748 + if (
1629 1749 !$this->settings->get('sm.key_json') &&
1630 1750 defined('WP_STATELESS_MEDIA_HIDE_SETUP_ASSISTANT') && WP_STATELESS_MEDIA_HIDE_SETUP_ASSISTANT == true &&
1631 1751 defined('WP_STATELESS_MEDIA_HIDE_SETTINGS_PANEL') && WP_STATELESS_MEDIA_HIDE_SETTINGS_PANEL == true
1632 1752 ) {
@@ -1632,19 +1752,23 @@
1632 1752 ) {
1633 1753 return;
1634 1754 }
1635 1755
1636 - if( !$this->settings->get('sm.key_json') && defined('WP_STATELESS_MEDIA_HIDE_SETUP_ASSISTANT') && WP_STATELESS_MEDIA_HIDE_SETUP_ASSISTANT == true ) {
1756 + if (!$this->settings->get('sm.key_json') && defined('WP_STATELESS_MEDIA_HIDE_SETUP_ASSISTANT') && WP_STATELESS_MEDIA_HIDE_SETUP_ASSISTANT == true) {
1637 1757 $url = $this->get_settings_page_url('?page=stateless-settings');
1638 - exit( wp_redirect($url));
1758 + exit(wp_redirect($url));
1639 1759 }
1640 1760
1641 - if( $plugin == plugin_basename( $this->boot_file ) ) {
1642 - $url = $this->get_settings_page_url('?page=stateless-setup&step=splash-screen');
1643 - if(json_decode($this->settings->get('sm.key_json'))){
1761 + if ($plugin == plugin_basename($this->boot_file)) {
1762 + // #152
1763 + // $url = $this->get_settings_page_url('?page=stateless-setup&step=splash-screen');
1764 + $url = $this->get_settings_page_url('?page=stateless-settings');
1765 +
1766 + if (json_decode($this->settings->get('sm.key_json'))) {
1644 1767 $url = $this->get_settings_page_url('?page=stateless-settings');
1645 1768 }
1646 - exit( wp_redirect($url));
1769 +
1770 + exit( wp_redirect($url) );
1647 1771 }
1648 1772 }
1649 1773
1650 1774 /**
@@ -1650,24 +1774,25 @@
1650 1774 /**
1651 1775 * Plugin Deactivation
1652 1776 *
1653 1777 */
1654 - public function deactivate() {}
1778 + public function deactivate() {
1779 + }
1655 1780
1656 1781 /**
1657 1782 * Show_notice_stateless_cache_busting
1658 1783 *
1659 1784 */
1660 - public function show_notice_stateless_cache_busting(){
1661 - $this->errors->add( array(
1785 + public function show_notice_stateless_cache_busting() {
1786 + $this->errors->add(array(
1662 1787 'key' => 'stateless_cache_busting',
1663 1788 'button' => 'View Settings',
1664 1789 'button_link' => admin_url('upload.php?page=stateless-settings'),
1665 - 'title' => sprintf( __( "Stateless mode now requires the Cache-Busting option.", ud_get_stateless_media()->domain ) ),
1666 - 'message' => sprintf( __("WordPress looks at local files to prevent files with the same filenames.
1667 - Since Stateless mode bypasses this check, there is a potential for files to be stored with the same file name. We enforce the Cache-Busting option to prevent this.
1668 - Override with the <a href='%s' target='_blank'>%s</a> constant.", ud_get_stateless_media()->domain),"https://wp-stateless.github.io/docs/constants/#wp_stateless_media_cache_busting", "WP_STATELESS_MEDIA_CACHE_BUSTING" ),
1669 - ), 'notice' );
1790 + 'title' => sprintf(__("Stateless mode now requires the Cache-Busting option.", ud_get_stateless_media()->domain)),
1791 + 'message' => sprintf(__("WordPress looks at local files to prevent files with the same filenames.
1792 + Since Stateless mode bypasses this check, there is a potential for files to be stored with the same file name. We enforce the Cache-Busting option to prevent this.
1793 + Override with the <a href='%s' target='_blank'>%s</a> constant.", ud_get_stateless_media()->domain), ud_get_stateless_media()->get_docs_page_url('docs/constants/#wpstatelessmediacachebusting'), "WP_STATELESS_MEDIA_CACHE_BUSTING"),
1794 + ), 'notice');
1670 1795 }
1671 1796
1672 1797 /**
1673 1798 * Filter for wp_get_attachment_url();
@@ -1674,47 +1799,47 @@
1674 1799 * @param string $url
1675 1800 * @param string $post_id
1676 1801 * @return mixed|null|string
1677 1802 */
1678 - public function wp_get_attachment_url( $url = '', $post_id = '' ) {
1803 + public function wp_get_attachment_url($url = '', $post_id = '') {
1679 1804 global $default_dir;
1680 - $sm_cloud = get_post_meta( $post_id, 'sm_cloud', 1 );
1681 - if( is_array( $sm_cloud ) && !empty( $sm_cloud[ 'fileLink' ] ) ) {
1682 - $_url = parse_url($sm_cloud[ 'fileLink' ]);
1683 - $url = !isset($_url['scheme']) ? ( 'https:' . $sm_cloud[ 'fileLink' ] ) : $sm_cloud[ 'fileLink' ];
1684 - return apply_filters('wp_stateless_bucket_link', $url);
1685 - }
1686 - elseif(is_multisite() && empty($sm_cloud)){
1687 - $_file = get_post_meta( $post_id, '_wp_attached_file', true );
1688 - if($_file){
1689 - if ( $this->get('sm.mode') == 'stateless' ) {
1805 + $sm_cloud = apply_filters('wp_stateless_get_file', [], $post_id);
1806 + if (is_array($sm_cloud) && !empty($sm_cloud['fileLink'])) {
1807 + $_url = parse_url($sm_cloud['fileLink']);
1808 + $url = !isset($_url['scheme']) ? ('https:' . $sm_cloud['fileLink']) : $sm_cloud['fileLink'];
1809 + $url = apply_filters('wp_stateless_bucket_link', $url);
1810 + } elseif (is_multisite() && empty($sm_cloud)) {
1811 + $_file = get_post_meta($post_id, '_wp_attached_file', true);
1812 + if ($_file) {
1813 + if ($this->get('sm.mode') == 'stateless') {
1690 1814 $default_dir = true;
1691 1815 $uploads = wp_get_upload_dir();
1692 1816 $default_dir = false;
1693 - return $uploads['baseurl'].'/'.$_file;
1817 + $url = $uploads['baseurl'] . '/' . $_file;
1694 1818 } else {
1695 1819 $uploads = wp_get_upload_dir();
1696 1820 $default_dir = false;
1697 - $_file = apply_filters( 'wp_stateless_file_name', $_file, false );
1821 + $_file = apply_filters('wp_stateless_file_name', $_file, false);
1698 1822 $blog_id = get_current_blog_id();
1699 - $file_path_fix = $uploads[ 'basedir' ] . "/sites/$blog_id/$_file";
1823 + $file_path_fix = $uploads['basedir'] . "/sites/$blog_id/$_file";
1700 1824
1701 - if( file_exists( $file_path_fix ) ) {
1702 - $url = $uploads[ 'baseurl' ] . "/sites/$blog_id/$_file";
1825 + if (file_exists($file_path_fix)) {
1826 + $url = $uploads['baseurl'] . "/sites/$blog_id/$_file";
1703 1827 }
1704 1828 }
1705 1829 }
1706 - } elseif ( empty($sm_cloud) && $this->get('sm.mode') == 'stateless' ) {
1707 - $_file = get_post_meta( $post_id, '_wp_attached_file', true );
1708 - if($_file){
1830 + } elseif (empty($sm_cloud) && $this->get('sm.mode') == 'stateless') {
1831 + $_file = get_post_meta($post_id, '_wp_attached_file', true);
1832 + if ($_file) {
1709 1833 $default_dir = true;
1710 1834 $uploads = wp_get_upload_dir();
1711 1835 $default_dir = false;
1712 1836
1713 - return $uploads['baseurl'].'/'.$_file;
1837 + $url = $uploads['baseurl'] . '/' . $_file;
1714 1838 }
1715 1839 }
1716 - return $url;
1840 +
1841 + return apply_filters('wp_stateless_attachment_url', $url, $post_id);
1717 1842 }
1718 1843
1719 1844 /**
1720 1845 * Filter for attachment_url_to_postid()
@@ -1722,22 +1847,29 @@
1722 1847 * @param int|false $post_id originally found post ID (or false if not found)
1723 1848 * @param string $url the URL to find the post ID for
1724 1849 * @return int|false found post ID from cloud storage URL
1725 1850 */
1726 - public function attachment_url_to_postid( $post_id, $url ) {
1851 + public function attachment_url_to_postid($post_id, $url) {
1727 1852 global $wpdb;
1728 1853
1729 - if ( ! $post_id ) {
1854 + if (!$post_id) {
1730 1855 $post_id = get_transient("stateless_url_to_postid_" . md5($url));
1731 1856
1732 - if(defined('WP_STATELESS_LEGACY_URL_TO_POSTID')){
1857 + if (defined('WP_STATELESS_LEGACY_URL_TO_POSTID')) {
1733 1858 // User can use this constant if they change the Bucket Folder (root_dir) after uploading image.
1734 1859 // This can be little slow at first run.
1735 - if(empty($post_id)){
1736 - $query = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'sm_cloud' AND meta_value LIKE '%s'";
1737 - $post_id = $wpdb->get_var( $wpdb->prepare( $query, '%' . $url . '%' ) );
1860 + if (empty($post_id)) {
1861 + if ( !$this->get('sm.use_postmeta') ) {
1862 + $query = 'SELECT post_id FROM ' . ud_stateless_db()->files . ' WHERE file_link = %s';
1863 + $post_id = $wpdb->get_var($wpdb->prepare($query, $url));
1864 + }
1865 +
1866 + if (empty($post_id)) {
1867 + $query = "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'sm_cloud' AND meta_value LIKE '%s'";
1868 + $post_id = $wpdb->get_var($wpdb->prepare($query, '%' . $url . '%'));
1869 + }
1738 1870
1739 - if($post_id){
1871 + if ($post_id) {
1740 1872 set_transient("stateless_url_to_postid_" . md5($url), $post_id);
1741 1873 }
1742 1874 }
1743 1875 return $post_id;
@@ -1742,28 +1874,27 @@
1742 1874 }
1743 1875 return $post_id;
1744 1876 }
1745 1877
1746 - if(empty($post_id)){
1878 + if (empty($post_id)) {
1747 1879 $gs_base_url = $this->get_gs_host();
1748 - $root_dir = $this->get( 'sm.root_dir' );
1749 - $path_elements = apply_filters( 'wp_stateless_unhandle_root_dir', $url );
1880 + $root_dir = $this->get('sm.root_dir');
1881 + $path_elements = apply_filters('wp_stateless_unhandle_root_dir', $url);
1750 1882 $root_dir = apply_filters("wp_stateless_handle_root_dir", $root_dir, false, $path_elements);
1751 1883 $gs_url = $this->get_gs_host() . '/' . $root_dir;
1752 1884 $site_url = parse_url($gs_url);
1753 - $image_path = parse_url( $url );
1885 + $image_path = parse_url($url);
1754 1886
1755 1887 //force the protocols to match if needed
1756 - if( isset( $image_path['scheme'] ) && ( $image_path['scheme'] !== $site_url['scheme'] ) ) {
1757 - $url = str_replace( $image_path['scheme'], $site_url['scheme'], $url );
1888 + if (isset($image_path['scheme']) && ($image_path['scheme'] !== $site_url['scheme'])) {
1889 + $url = str_replace($image_path['scheme'], $site_url['scheme'], $url);
1758 1890 }
1759 1891
1760 - if( 0 === strpos( $url, $gs_url . '/' ) ) {
1761 - $url = substr( $url, strlen( $gs_url . '/' ) );
1762 - }
1763 - else if( 0 === strpos( $url, $gs_base_url . '/' ) ) {
1892 + if (0 === strpos($url, $gs_url . '/')) {
1893 + $url = substr($url, strlen($gs_url . '/'));
1894 + } else if (0 === strpos($url, $gs_base_url . '/')) {
1764 1895 // In case user added Bucket Folder (root_dir) after uploading image.
1765 - $url = substr( $url, strlen( $gs_base_url . '/' ) );
1896 + $url = substr($url, strlen($gs_base_url . '/'));
1766 1897 }
1767 1898
1768 1899 /**
1769 1900 * If `uploads_use_yearmonth_folders` is set - adding year and month to url
@@ -1769,10 +1900,10 @@
1769 1900 * If `uploads_use_yearmonth_folders` is set - adding year and month to url
1770 1901 */
1771 1902 $organize_media = get_option('uploads_use_yearmonth_folders');
1772 1903 $path = '';
1773 - if ( $organize_media == '1' && isset ($path_elements['%date_year/date_month%']) ) {
1774 - $path .= $path_elements['%date_year/date_month%'].'/';
1904 + if ($organize_media == '1' && isset($path_elements['%date_year/date_month%'])) {
1905 + $path .= $path_elements['%date_year/date_month%'] . '/';
1775 1906 }
1776 1907 $url = $path . $url;
1777 1908
1778 1909 $sql = $wpdb->prepare(
@@ -1778,11 +1909,11 @@
1778 1909 $sql = $wpdb->prepare(
1779 1910 "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = %s",
1780 1911 $url
1781 1912 );
1782 - $post_id = $wpdb->get_var( $sql );
1913 + $post_id = $wpdb->get_var($sql);
1783 1914
1784 - if($post_id){
1915 + if ($post_id) {
1785 1916 set_transient("stateless_url_to_postid_" . md5($url), $post_id);
1786 1917 }
1787 1918 }
1788 1919 }
@@ -1795,15 +1926,14 @@
1795 1926 *
1796 1927 * @param $data
1797 1928 * @return mixed
1798 1929 */
1799 - public function upload_dir( $data ) {
1800 - $data[ 'basedir' ] = $this->get_gs_host();
1801 - $data[ 'baseurl' ] = $this->get_gs_host();
1802 - $data[ 'url' ] = $data[ 'baseurl' ] . $data[ 'subdir' ];
1930 + public function upload_dir($data) {
1931 + $data['basedir'] = $this->get_gs_host();
1932 + $data['baseurl'] = $this->get_gs_host();
1933 + $data['url'] = $data['baseurl'] . $data['subdir'];
1803 1934
1804 1935 return $data;
1805 -
1806 1936 }
1807 1937
1808 1938 /**
1809 1939 * Set Feature Flag constants by parsing composer.json
@@ -1812,42 +1942,39 @@
1812 1942 *
1813 1943 * @author potanin@UD
1814 1944 * @return array|mixed|null|object
1815 1945 */
1816 - public function parse_feature_flags( ) {
1946 + public function parse_feature_flags() {
1817 1947
1818 1948 try {
1819 1949
1820 - $_raw = file_get_contents( Utility::normalize_path( $this->root_path ) . 'composer.json' );
1950 + $_raw = file_get_contents(Utility::normalize_path($this->root_path) . 'composer.json');
1821 1951
1822 - $_parsed = json_decode( $_raw );
1952 + $_parsed = json_decode($_raw);
1823 1953
1824 1954 // @todo Catch poorly formatted JSON.
1825 - if( !is_object( $_parsed ) ) {
1955 + if (!is_object($_parsed)) {
1826 1956 // throw new Error( "unable to parse." );
1827 1957 }
1828 1958
1829 - foreach( (array) $_parsed->extra->featureFlags as $_feature ) {
1959 + foreach ((array) $_parsed->extra->featureFlags as $_feature) {
1830 1960
1831 - if( !defined( $_feature->constant ) ) {
1832 - define( $_feature->constant, $_feature->enabled );
1961 + if (!defined($_feature->constant)) {
1962 + define($_feature->constant, $_feature->enabled);
1833 1963
1834 - if( $_feature->enabled ) {
1835 - Utility::log( 'Feature flag ' . $_feature->name . ', [' . $_feature->constant . '] enabled.' );
1964 + if ($_feature->enabled) {
1965 + Utility::log('Feature flag ' . $_feature->name . ', [' . $_feature->constant . '] enabled.');
1836 1966 } else {
1837 - Utility::log( 'Feature flag ' . $_feature->name . ', [' . $_feature->constant . '] disabled.' );
1967 + Utility::log('Feature flag ' . $_feature->name . ', [' . $_feature->constant . '] disabled.');
1838 1968 }
1839 1969 }
1840 -
1841 1970 }
1842 -
1843 - } catch ( \Exception $e ) {
1844 - Utility::log( 'Unable to parse [composer.json] feature flags. Error: [' . $e->getMessage() . ']' );
1971 + } catch (\Exception $e) {
1972 + Utility::log('Unable to parse [composer.json] feature flags. Error: [' . $e->getMessage() . ']');
1845 1973 // echo 'Caught exception: ', $e->getMessage(), "\n";
1846 1974 }
1847 1975
1848 - return isset( $_parsed ) ? $_parsed : null;
1849 -
1976 + return isset($_parsed) ? $_parsed : null;
1850 1977 }
1851 1978
1852 1979 /**
1853 1980 * Determine if Utility class contains missed function
@@ -1857,11 +1984,11 @@
1857 1984 * @param $name
1858 1985 * @param $arguments
1859 1986 * @return mixed|null
1860 1987 */
1861 - public function __call( $name, $arguments ) {
1862 - if( is_callable( array( "wpCloud\\StatelessMedia\\Utility", $name ) ) ) {
1863 - return call_user_func_array( array( "wpCloud\\StatelessMedia\\Utility", $name ), $arguments );
1988 + public function __call($name, $arguments) {
1989 + if (is_callable(array("wpCloud\\StatelessMedia\\Utility", $name))) {
1990 + return call_user_func_array(array("wpCloud\\StatelessMedia\\Utility", $name), $arguments);
1864 1991 } else {
1865 1992 return NULL;
1866 1993 }
1867 1994 }
@@ -1874,35 +2001,120 @@
1874 2001 *
1875 2002 * @param boolean [$unset_disabled = true]
1876 2003 * @return array
1877 2004 */
1878 - function get_image_sizes( $unset_disabled = true ) {
1879 - $wais = & $GLOBALS['_wp_additional_image_sizes'];
2005 + function get_image_sizes($unset_disabled = true) {
2006 + $wais = &$GLOBALS['_wp_additional_image_sizes'];
1880 2007
1881 2008 $sizes = array();
1882 2009
1883 - foreach ( get_intermediate_image_sizes() as $_size ) {
1884 - if ( in_array( $_size, array('thumbnail', 'medium', 'medium_large', 'large') ) ) {
1885 - $sizes[ $_size ] = array(
1886 - 'width' => get_option( "{$_size}_size_w" ),
1887 - 'height' => get_option( "{$_size}_size_h" ),
1888 - 'crop' => (bool) get_option( "{$_size}_crop" ),
2010 + foreach (get_intermediate_image_sizes() as $_size) {
2011 + if (in_array($_size, array('thumbnail', 'medium', 'medium_large', 'large'))) {
2012 + $sizes[$_size] = array(
2013 + 'width' => get_option("{$_size}_size_w"),
2014 + 'height' => get_option("{$_size}_size_h"),
2015 + 'crop' => (bool) get_option("{$_size}_crop"),
1889 2016 );
1890 - }
1891 - elseif ( isset( $wais[$_size] ) ) {
1892 - $sizes[ $_size ] = array(
1893 - 'width' => $wais[ $_size ]['width'],
1894 - 'height' => $wais[ $_size ]['height'],
1895 - 'crop' => $wais[ $_size ]['crop'],
2017 + } elseif (isset($wais[$_size])) {
2018 + $sizes[$_size] = array(
2019 + 'width' => $wais[$_size]['width'],
2020 + 'height' => $wais[$_size]['height'],
2021 + 'crop' => $wais[$_size]['crop'],
1896 2022 );
1897 2023 }
1898 2024
1899 2025 // size registered, but has 0 width and height
1900 - if( $unset_disabled && ($sizes[ $_size ]['width'] == 0) && ($sizes[ $_size ]['height'] == 0) )
1901 - unset( $sizes[ $_size ] );
2026 + if ($unset_disabled && ($sizes[$_size]['width'] == 0) && ($sizes[$_size]['height'] == 0))
2027 + unset($sizes[$_size]);
1902 2028 }
1903 2029
1904 2030 return $sizes;
2031 + }
2032 +
2033 + /**
2034 + * Get the email for notifications
2035 + *
2036 + * @return string
2037 + */
2038 + public function get_notification_email() {
2039 + $type = $this->get( 'sm.status_email_type' );
2040 +
2041 + switch ($type) {
2042 + case 'true':
2043 + // Emails to Admin
2044 + return get_site_option('admin_email');
2045 + case 'custom':
2046 + // Emails to Custom Email
2047 + return $this->get( 'sm.status_email_address' );
2048 + }
2049 +
2050 + // Emails disabled
2051 + return '';
2052 + }
2053 +
2054 + /**
2055 + * Send admin email
2056 + *
2057 + * @param string $subject
2058 + * @param string $message
2059 + * @param string $email
2060 + */
2061 + public function send_admin_email($subject, $message, $email = '') {
2062 + $admin_email = empty($email) ? $this->get_notification_email() : $email;
2063 +
2064 + $admin_email = explode(',', $admin_email);
2065 + $admin_email = array_map( function($item) {
2066 + return strip_tags( trim($item) );
2067 + }, $admin_email);
2068 +
2069 + if ( empty($admin_email) || empty($subject) || empty($message) ) {
2070 + return;
2071 + }
2072 +
2073 + wp_mail( $admin_email, $subject, $message);
2074 + }
2075 +
2076 + /**
2077 + * Check if we are in specific mode
2078 + *
2079 + * @param string|array $mode
2080 + * @return bool
2081 + */
2082 + public function is_mode($mode) {
2083 + if ( !is_array($mode) ) {
2084 + $mode = [$mode];
2085 + }
2086 +
2087 + return in_array($this->get('sm.mode'), $mode);
2088 + }
2089 +
2090 + /**
2091 + * Get default cache control value
2092 + *
2093 + * @return string
2094 + */
2095 + public function get_default_cache_control() {
2096 + return Settings::DEFAULT_CACHE_CONTROL;
2097 + }
2098 +
2099 + /**
2100 + * Override REST API root for headless CMS
2101 + *
2102 + * @return string
2103 + */
2104 + public function get_rest_api_root($rest_api_root) {
2105 + $rest_api_root = sanitize_url( get_rest_url() );
2106 + $rest_api_root .= 'wp-stateless/v1/';
2107 +
2108 + if ( $this->get('sm.use_api_siteurl') == 'WP_SITEURL' ) {
2109 + $home = get_home_url();
2110 + $site = get_site_url();
2111 +
2112 + return str_replace( $home, $site, $rest_api_root );
2113 + }
2114 +
2115 +
2116 + return $rest_api_root;
1905 2117 }
1906 2118 }
1907 2119 }
1908 2120 }