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

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

405 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Helper Functions List
4 *
5 * Can be called via Singleton. Since Singleton uses magic method __call().
6 * Example:
7 *
8 * Add Media to GS storage:
9 * ud_get_stateless_media()->add_media( false, $post_id );
10 *
11 * @class Utility
12 */
13 namespace wpCloud\StatelessMedia {
14
15 if( !class_exists( 'wpCloud\StatelessMedia\Utility' ) ) {
16
17 class Utility {
18
19 /**
20 * ChromeLogger
21 *
22 * @author potanin@UD
23 * @param $data
24 */
25 static public function log( $data ) {
26
27 if( !class_exists( 'wpCloud\StatelessMedia\Logger' )) {
28 include_once( __DIR__ . '/class-logger.php' );
29 }
30
31 if( !class_exists( 'wpCloud\StatelessMedia\Logger' )) {
32 return;
33 }
34
35 if( defined( 'WP_STATELESS_CONSOLE_LOG' ) && WP_STATELESS_CONSOLE_LOG ) {
36 Logger::log( '[wp-stateless]', $data );
37 }
38
39 }
40
41 /**
42 * Override Cache Control
43 * @param $cacheControl
44 * @return mixed
45 */
46 public static function override_cache_control( $cacheControl ) {
47 return ud_get_stateless_media()->get( 'sm.cache_control' );
48 }
49
50 /**
51 * wp_normalize_path was added in 3.9.0
52 *
53 * @param $path
54 * @return mixed|string
55 *
56 */
57 public static function normalize_path( $path ) {
58
59 if( function_exists( 'wp_normalize_path' ) ) {
60 return wp_normalize_path( $path );
61 }
62
63 $path = str_replace( '\\', '/', $path );
64 $path = preg_replace( '|/+|','/', $path );
65 return $path;
66
67 }
68
69 /**
70 * Randomize file name
71 * @param $filename
72 * @return string
73 */
74 public static function randomize_filename( $filename ) {
75 $return = apply_filters('stateless_skip_cache_busting', null, $filename);
76 if($return){
77 return $return;
78 }
79 $info = pathinfo($filename);
80 $ext = empty($info['extension']) ? '' : '' . $info['extension'];
81 $_parts = array();
82 $rand = substr(md5(time()), 0, 8);
83
84 $body_rewrite_types = ud_get_stateless_media()->get( 'sm.body_rewrite_types' );
85 if(empty($info['extension']) || strpos($body_rewrite_types, $info['extension']) === false){
86 return $filename;
87 }
88
89 if(strpos($filename, $rand) !== false){
90 return $filename;
91 }
92
93 if (strpos($info['filename'], '@')) {
94 $_cleanName = explode('@', $info['filename'])[0];
95 $_retna = explode('@', $info['filename'])[1];
96 $_parts[] = $rand;
97 $_parts[] = '-';
98 $_parts[] = strtolower($_cleanName);
99 $_parts[] = '@' . strtolower($_retna);
100 } else {
101 $_parts[] = $rand;
102 $_parts[] = '-';
103 $_parts[] = strtolower($info['filename']);
104 }
105
106 $filename = join('', $_parts);
107 if(!empty($ext)){
108 $filename .= '.' . $ext;
109 }
110
111 return $filename;
112 }
113
114 /**
115 * Get Media Item Content Disposition
116 *
117 * @param null $attachment_id
118 * @param array $metadata
119 * @param array $data
120 * @return string
121 */
122 public static function getContentDisposition( $attachment_id = null, $metadata = array(), $data = array() ) {
123 // return 'Content-Disposition: attachment; filename=some-file.sql';
124
125 return apply_filters( 'sm:item:contentDisposition', null, array( 'attachment_id' => $attachment_id, 'mime_type' => get_post_mime_type( $attachment_id ), 'metadata' => $metadata, 'data' => $data ) );
126
127 }
128
129 /**
130 * @param null $attachment_id
131 * @param array $metadata
132 * @param array $data
133 * @return string
134 */
135 public static function getCacheControl( $attachment_id = null, $metadata = array(), $data = array() ) {
136
137 if( !$attachment_id ) {
138 return apply_filters( 'sm:item:cacheControl', 'private, no-cache, no-store', $attachment_id, array( 'attachment_id' => null, 'mime_type' => null, 'metadata' => $metadata, 'data' => $data ) );
139 }
140
141 $_mime_type = get_post_mime_type( $attachment_id );
142
143 // Treat images as public.
144 if( strpos( $_mime_type, 'image/' ) !== false ) {
145 return apply_filters( 'sm:item:cacheControl', 'public, max-age=36000, must-revalidate', array( 'attachment_id' => $attachment_id, 'mime_type' => null, 'metadata' => $metadata, 'data' => $data ) );
146 }
147
148 // Treat images as public.
149 if( strpos( $_mime_type, 'sql' ) !== false ) {
150 return apply_filters( 'sm:item:cacheControl', 'private, no-cache, no-store', array( 'attachment_id' => $attachment_id, 'mime_type' => null, 'metadata' => $metadata, 'data' => $data ) );
151 }
152
153 return apply_filters( 'sm:item:cacheControl', 'public, max-age=30, no-store, must-revalidate', array( 'attachment_id' => $attachment_id, 'mime_type' => null, 'metadata' => $metadata, 'data' => $data ) );
154
155 }
156
157 /**
158 * Add/Update Media to Bucket
159 * Fired for every action with image add or update
160 *
161 * $force and $args params will no be passed on media library uploads.
162 * This two will be passed on by compatibility.
163 *
164 * @action wp_generate_attachment_metadata
165 * @author peshkov@UD
166 * @param $metadata
167 * @param $attachment_id
168 * @param $force Whether to force the upload incase of it's already exists.
169 * @param $args Whether to only sync the full size image.
170 * @return bool|string
171 */
172 public static function add_media( $metadata, $attachment_id, $force = false, $args = array() ) {
173 global $stateless_synced_full_size;
174 $file = '';
175 $upload_dir = wp_upload_dir();
176 $args = wp_parse_args($args, array(
177 'no_thumb' => false,
178 ));
179
180 /* Get metadata in case if method is called directly. */
181 if( current_filter() !== 'wp_generate_attachment_metadata' && current_filter() !== 'wp_update_attachment_metadata' ) {
182 $metadata = wp_get_attachment_metadata( $attachment_id );
183 }
184
185 /**
186 * To skip the sync process.
187 *
188 * Returning a non-null value
189 * will effectively short-circuit the function.
190 *
191 * $force and $args params will no be passed on media library uploads.
192 * This two will be passed on by compatibility.
193 *
194 * @since 2.2.4
195 *
196 * @param bool $value This should return true if want to skip the sync.
197 * @param int $metadata Metadata for the attachment.
198 * @param string $attachment_id Attachment ID.
199 * @param bool $force Whether to force the sync even the file already exist in GCS.
200 * @param bool $args Whether to only sync the full size image.
201 */
202 $check = apply_filters('wp_stateless_skip_add_media', null, $metadata, $attachment_id, $force, $args);
203
204 $client = ud_get_stateless_media()->get_client();
205
206 if( !is_wp_error( $client ) && !$check ) {
207
208 $fullsizepath = wp_normalize_path( get_attached_file( $attachment_id ) );
209 // Make non-images uploadable.
210 if( empty( $metadata['file'] ) && $attachment_id ) {
211 $file = str_replace( wp_normalize_path(trailingslashit( $upload_dir[ 'basedir' ] )), '', $fullsizepath );
212 if(empty($metadata)){
213 $metadata = array();
214 }
215 $mime_type = get_post_mime_type( $attachment_id );
216 if($mime_type != "application/pdf"){
217 $metadata["file"] = $file;
218 }
219 }
220
221 $file = wp_normalize_path( !empty($metadata[ 'file' ])?$metadata[ 'file' ]:$file );
222
223 $image_host = ud_get_stateless_media()->get_gs_host();
224 $bucketLink = apply_filters('wp_stateless_bucket_link', $image_host);
225
226 $_metadata = array(
227 "width" => isset( $metadata[ 'width' ] ) ? $metadata[ 'width' ] : null,
228 "height" => isset( $metadata[ 'height' ] ) ? $metadata[ 'height' ] : null,
229 'object-id' => $attachment_id,
230 'source-id' => md5( $attachment_id.ud_get_stateless_media()->get( 'sm.bucket' ) ),
231 'file-hash' => md5( $file )
232 );
233
234 if($attachment_id && !empty($metadata) && !$force){
235 $db_metadata = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
236 if($db_metadata != $metadata){
237 $force = true;
238 }
239 }
240
241 /* Add default image */
242 $media = $client->add_media( $_mediaOptions = array_filter( array(
243 'force' => $force && $stateless_synced_full_size != $attachment_id,
244 'name' => $file,
245 'absolutePath' => wp_normalize_path( get_attached_file( $attachment_id ) ),
246 'cacheControl' => $_cacheControl = self::getCacheControl( $attachment_id, $metadata, null ),
247 'contentDisposition' => $_contentDisposition = self::getContentDisposition( $attachment_id, $metadata, null ),
248 'mimeType' => get_post_mime_type( $attachment_id ),
249 'metadata' => $_metadata
250 ) ));
251
252 // Break if we have errors.
253 // @note Errors could be due to key being invalid or now having sufficient permissions in which case should notify user.
254 if( is_wp_error( $media ) ) {
255 return $metadata;
256 }
257
258 /* Add Google Storage metadata to our attachment */
259 $fileLink = $bucketLink . '/' . ( !empty($media['name']) ? $media['name'] : $file );
260
261 $cloud_meta = array(
262 'id' => $media[ 'id' ],
263 'name' => !empty($media['name']) ? $media['name'] : $file,
264 'fileLink' => $fileLink,
265 'storageClass' => $media[ 'storageClass' ],
266 'mediaLink' => $media[ 'mediaLink' ],
267 'selfLink' => $media[ 'selfLink' ],
268 'bucket' => ud_get_stateless_media()->get( 'sm.bucket' ),
269 'object' => $media,
270 'sizes' => array(),
271 );
272
273 if( isset( $_cacheControl ) && $_cacheControl ) {
274 //update_post_meta( $attachment_id, 'sm_cloud:cacheControl', $_cacheControl );
275 $cloud_meta[ 'cacheControl' ] = $_cacheControl;
276 }
277
278 if( isset( $_contentDisposition ) && $_contentDisposition ) {
279 //update_post_meta( $attachment_id, 'sm_cloud:contentDisposition', $_contentDisposition );
280 $cloud_meta[ 'contentDisposition' ] = $_contentDisposition;
281 }
282
283 if( empty( $metadata[ 'sizes' ] ) ) {
284 // @note This could happen if WordPress does not have any wp_get_image_editor(), e.g. Imagemagic not installed.
285 }
286
287 /* Now we go through all available image sizes and upload them to Google Storage */
288 if( !empty( $metadata[ 'sizes' ] ) && is_array( $metadata[ 'sizes' ] ) && $args['no_thumb'] != true ) {
289
290 $path = wp_normalize_path( dirname( get_attached_file( $attachment_id ) ) );
291 $mediaPath = wp_normalize_path( trim( dirname( $file ), '\/\\' ) );
292
293 /**
294 * @see https://github.com/wpCloud/wp-stateless/issues/343
295 **/
296 $mediaPath = $mediaPath === '.' ? '' : $mediaPath;
297
298 foreach( (array) $metadata[ 'sizes' ] as $image_size => $data ) {
299
300 $absolutePath = wp_normalize_path( $path . '/' . $data[ 'file' ] );
301
302 /* Add 'image size' image */
303 $media = $client->add_media( array(
304 'force' => $force,
305 'name' => $file_path = trim($mediaPath . '/' . $data[ 'file' ], '/'),
306 'absolutePath' => $absolutePath,
307 'cacheControl' => $_cacheControl,
308 'contentDisposition' => $_contentDisposition,
309 'mimeType' => $data[ 'mime-type' ],
310 'metadata' => array_merge( $_metadata, array(
311 'width' => $data['width'],
312 'height' => $data['height'],
313 'child-of' => $attachment_id,
314 'file-hash' => md5( $data[ 'file' ] )
315 ))
316 ));
317
318 /* Break if we have errors. */
319 if( !is_wp_error( $media ) ) {
320
321 $fileLink = $bucketLink . '/' . (!empty($media['name']) ? $media['name'] : $file_path);
322
323 // @note We don't add storageClass because it's same as parent...
324 $cloud_meta[ 'sizes' ][ $image_size ] = array(
325 'id' => $mediaPath . '/' . $media[ 'id' ],
326 'name' => !empty($media['name']) ? $media['name'] : $file_path,
327 'fileLink' => $fileLink,
328 'mediaLink' => $media[ 'mediaLink' ],
329 'selfLink' => $media[ 'selfLink' ]
330 );
331
332 // Stateless mode: we don't need the local version.
333 if(ud_get_stateless_media()->get( 'sm.mode' ) === 'stateless'){
334 unlink($absolutePath);
335 }
336 }
337
338
339 }
340
341 }
342
343 // Stateless mode: we don't need the local version.
344 if(ud_get_stateless_media()->get( 'sm.mode' ) === 'stateless' && $args['no_thumb'] != true){
345 unlink($fullsizepath);
346 }
347
348 update_post_meta( $attachment_id, 'sm_cloud', $cloud_meta );
349
350 if($args['no_thumb'] == true){
351 $stateless_synced_full_size = $attachment_id;
352 }
353 }
354
355 return $metadata;
356 }
357
358 /**
359 * Remove Media from Bucket by post ID
360 * Fired on calling function wp_delete_attachment()
361 *
362 * @todo: add error logging. peshkov@UD
363 * @see wp_delete_attachment()
364 * @action delete_attachment
365 * @author peshkov@UD
366 * @param $post_id
367 */
368 public static function remove_media( $post_id ) {
369 /* Get attachments metadata */
370 $metadata = wp_get_attachment_metadata( $post_id );
371
372 /* Be sure we have the same bucket in settings and have GS object's name before proceed. */
373 if(
374 isset( $metadata[ 'gs_name' ] ) &&
375 isset( $metadata[ 'gs_bucket' ] ) &&
376 $metadata[ 'gs_bucket' ] == ud_get_stateless_media()->get( 'sm.bucket' )
377 ) {
378
379 $client = ud_get_stateless_media()->get_client();
380 if( !is_wp_error( $client ) ) {
381
382 /* Remove default image */
383 $client->remove_media( $metadata[ 'gs_name' ] );
384
385 /* Now, go through all sizes and remove 'image sizes' images from Bucket too. */
386 if( !empty( $metadata[ 'sizes' ] ) && is_array( $metadata[ 'sizes' ] ) ) {
387 foreach( $metadata[ 'sizes' ] as $k => $v ) {
388 if( !empty( $v[ 'gs_name' ] ) ) {
389 $client->remove_media( $v[ 'gs_name' ] );
390 }
391 }
392 }
393
394 }
395
396 }
397
398 }
399
400 }
401
402 }
403
404 }
405