PluginProbe
WP-Stateless – Google Cloud Storage / 3.0.3
WP-Stateless – Google Cloud Storage v3.0.3
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-sync-non-media.php

class-sync-non-media.php in WP-Stateless – Google Cloud Storage 3.0.3, at lib/classes/class-sync-non-media.php

414 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Need to improve workflow.
4 * Maybe add a transient of few days to keep track of synced files.
5 */
6
7 namespace wpCloud\StatelessMedia {
8
9 if (!class_exists('wpCloud\StatelessMedia\SyncNonMedia')) {
10
11 class SyncNonMedia {
12
13 private $registered_dir = array();
14 const table = 'sm_sync';
15 public $table_name;
16
17 public function __construct(){
18 global $wpdb;
19 $this->table_name = $wpdb->prefix . self::table;
20 ud_get_stateless_media()->create_db();
21
22 // Manual sync using sync tab.
23 // called from ajax action_get_non_library_files_id
24 // Return files to be manually sync from sync tab.
25 add_filter( 'sm:sync::nonMediaFiles', array($this, 'sync_non_media_files') );
26 add_filter( 'sm:sync::queue_is_exists', array($this, 'queue_is_exists'), 10, 2 );
27
28 // register a dir to sync from sync tab
29 add_action( 'sm:sync::register_dir', array($this, 'register_dir') );
30 add_action( 'sm:sync::addFile', array($this, 'add_file') );
31 // Sync a file.
32 add_action( 'sm:sync::syncFile', array($this, 'sync_file'), 10, 4 );
33 add_action( 'sm:sync::copyFile', array($this, 'copy_file'), 10, 2 );
34 add_action( 'sm:sync::moveFile', array($this, 'move_file'), 10, 2 );
35 add_action( 'sm:sync::deleteFile', array($this, 'delete_file') );
36 add_action( 'sm:sync::deleteFiles', array($this, 'delete_files') );
37 }
38
39 /**
40 * Register dir to be sync from Sync tab.
41 * @param
42 * $dir: The directory to register
43 */
44 public function register_dir($dir){
45 if(!in_array($dir, $this->registered_dir)){
46 $this->registered_dir[] = $dir;
47 }
48 }
49
50 /**
51 * Add file to list of files to be sync from Sync tab.
52 * Save the file path to database.
53 * @param
54 * $file: The file to register.
55 */
56 public function add_file($file){
57 $this->queue_add_file($file);
58 }
59
60 /**
61 * Sync the file to GCS.
62 * @param $name: Relative path to upload dir.
63 * @param $absolutePath: Full path of the file
64 * @param bool $forced: Type: bool/int; Whether to force to move the file to GCS even it's already exists.
65 * true: Check whether it's already synced or not in database.
66 * 2 (int): Force to overwrite on GCS
67 * @param array $args
68 * @return bool|void $media: Media object returned from client->add_media() method.
69 * @throws: Exception File not found@throws: Exception File not found
70 */
71 public function sync_file($name, $absolutePath, $forced = false, $args = array() ){
72 $sm_mode = ud_get_stateless_media()->get( 'sm.mode' );
73
74 $args = wp_parse_args($args, array(
75 'ephemeral' => true, // whether to delete local file in ephemeral mode.
76 'download' => false, // whether to delete local file in ephemeral mode.
77 'use_root' => 0,
78 'skip_db' => false
79 ));
80
81 if($this->queue_is_exists($name, 'synced') && !$forced){
82 return false;
83 }
84
85 $file_type = Utility::mimetype_from_extension(pathinfo($absolutePath, PATHINFO_EXTENSION));
86 if(empty($this->client)){
87 $this->client = ud_get_stateless_media()->get_client();
88 }
89
90 if( is_wp_error( $this->client ) ) {
91 return;
92 }
93
94 $file_copied_from_gcs = false;
95 $local_file_exists = file_exists( $absolutePath );
96
97 do_action( 'sm::pre::sync::nonMediaFiles', $name, $absolutePath); // , $media
98
99 if ( !$local_file_exists && ( $args['download'] || ud_get_stateless_media()->get( 'sm.mode' ) !== 'ephemeral' || ud_get_stateless_media()->get( 'sm.mode' ) !== 'stateless' ) ) {
100 // Try get it and save
101 $result_code = $this->client->get_media( $name, true, $absolutePath );
102
103 if ( $result_code == 200 ) {
104 $local_file_exists = true;
105 $file_copied_from_gcs = true;
106 }
107 }
108
109 if($local_file_exists && !$file_copied_from_gcs && !$args['download']){
110
111 if ( $sm_mode == 'stateless' && !wp_doing_ajax() ) {
112 global $gs_client;
113
114 $gs_name = apply_filters( 'wp_stateless_file_name', $name, true );
115
116 //Bucket
117 $bucket = ud_get_stateless_media()->get( 'sm.bucket' );
118
119 $bucket = $gs_client->bucket($bucket);
120 $object = $bucket->object($gs_name);
121 $args = wp_parse_args( $args, array(
122 'use_root' => $args['use_root'],
123 'force' => ($forced == 2),
124 'name' => $name,
125 'absolutePath' => $absolutePath,
126 'mimeType' => $file_type,
127 'metadata' => array(
128 'child-of' => dirname($name),
129 'file-hash' => md5( $name ),
130 ),
131 'is_webp' => '',
132 ) );
133 $args = apply_filters('wp_stateless_add_media_args', $args);
134
135 /**
136 * Updating object metadata, ACL, CacheControl and contentDisposition
137 * @return media object
138 */
139 try {
140 $media = $object->update( array( 'metadata' => $args['metadata']) +
141 array('cacheControl' => apply_filters( 'sm:item:cacheControl', 'public, max-age=36000, must-revalidate', $absolutePath),
142 'predefinedAcl' => 'publicRead',
143 'contentDisposition' => apply_filters( 'sm:item:contentDisposition', null, $absolutePath))
144 );
145 } catch (\Throwable $th) {
146 //throw $th;
147 }
148
149
150 } else {
151 $media = $this->client->add_media( array(
152 'use_root' => $args['use_root'],
153 'name' => $name,
154 'force' => ($forced == 2),
155 'absolutePath' => $absolutePath,
156 'cacheControl' => apply_filters( 'sm:item:cacheControl', 'public, max-age=36000, must-revalidate', $absolutePath), //@todo use cacheControl from settings page.
157 'contentDisposition' => apply_filters( 'sm:item:contentDisposition', null, $absolutePath),
158 'mimeType' => $file_type,
159 'metadata' => array(
160 'child-of' => dirname($name),
161 'file-hash' => md5( $name ),
162 ),
163 ));
164 }
165
166 // Addon can hook this function to modify database after manual sync done.
167 do_action( 'sm::synced::nonMediaFiles', $name, $absolutePath, $media); // , $media
168
169 // Ephemeral mode: we don't need the local version.
170 if($args['ephemeral'] == true && ud_get_stateless_media()->get( 'sm.mode' ) === 'ephemeral' ){
171 unlink($absolutePath);
172 }
173
174 if ( !$args['skip_db'] ) {
175 // add file_path to the file list.
176 $this->queue_add_file( $name, 'synced' );
177
178 }
179 return $media;
180 }
181
182 }
183
184 /**
185 * Generate list for manual sync using sync tab. Sync all register files, dir and passed files.
186 * @param array $files - Additional files to sync.
187 * @return array
188 */
189 public function sync_non_media_files($files = array()){
190 $upload_dir = wp_upload_dir();
191 $files = array_merge($files, $this->queue_get_all());
192 foreach ($this->registered_dir as $key => $dir) {
193 $dir = $upload_dir['basedir'] . "/" . trim($dir, '/') . "/";
194 if(is_dir($dir)){
195 // Getting all the files from dir recursively.
196 $_files = $this->get_files( $dir );
197 // validating and adding to the $files array.
198 foreach ($_files as $id => $file) {
199 if(!file_exists($file)){
200 continue;
201 }
202
203 $_file = str_replace(wp_normalize_path($upload_dir['basedir']), '', wp_normalize_path($file));
204 if(!in_array($_file, $files)){
205 $files[] = trim($_file, '/');
206 }
207 }
208 }
209 }
210
211 // $files = array_values(array_unique($files));
212 return $files;
213 }
214
215 /**
216 * Return list of files in a dir.
217 * @param string $dir: Directory path
218 * @return array - Lists of files in the directory and subdirectory.
219 */
220 function get_files($dir) {
221 $return = array();
222 if(is_dir($dir) && $dh = opendir($dir)) {
223 while($file = readdir($dh)){
224 if($file != '.' && $file != '..'){
225 if(is_dir($dir . $file)){
226 // since it is a directory we recursively get files.
227 $arr = $this->get_files($dir . $file . '/');
228 $return = array_merge($return, $arr);
229 }else{
230 $return[] = $dir . $file;
231 }
232 }
233 }
234 closedir($dh);
235 }
236 return $return;
237 }
238
239 /**
240 * Delete a file from GCS.
241 *
242 * @param $file
243 * @param bool $force
244 * @return bool
245 */
246 public function delete_file($file){
247 try{
248 $file = trim($file, '/');
249 if(empty($this->client)){
250 $this->client = ud_get_stateless_media()->get_client();
251 }
252
253 if( is_wp_error( $this->client ) ) {
254 return false;
255 }
256 // Removing file for GCS
257 $this->client->remove_media($file, "", 0);
258 $this->queue_remove_file($file);
259 return true;
260 }
261 catch(\Exception $e){
262 return false;
263 }
264 }
265
266 /**
267 * Remove registered files of specified dir from GCS.
268 *
269 * @param $dir
270 * @return bool|void
271 */
272 public function delete_files($dir){
273 if(empty($this->client)){
274 $this->client = ud_get_stateless_media()->get_client();
275 }
276
277 if( is_wp_error( $this->client ) ) {
278 return;
279 }
280
281 // Removing the files one by one.
282 foreach ($this->queue_get_all($dir) as $key => $file) {
283 if(strpos($file, $dir) !== false){
284 $this->client->remove_media($file, "", 0);
285 $this->queue_remove_file($file);
286 }
287 }
288
289 return true;
290 }
291
292 /**
293 * Return all the files from the database.
294 * @param string $prefix
295 * @return array of files
296 */
297 public function queue_get_all($prefix = ''){
298 global $wpdb;
299 if($prefix){
300 $files = $wpdb->get_col( $wpdb->prepare("SELECT file FROM $this->table_name WHERE file like '%s'", $wpdb->esc_like($prefix) . '%' ) );
301 }
302 else{
303 $files = $wpdb->get_col( "SELECT file FROM $this->table_name" );
304 }
305 if(!empty($files) && is_array($files))
306 return $files;
307 return array();
308 }
309
310 /**
311 * Checks whether a file is exist in database.
312 * @param $file: Path of file relative to upload dir.
313 * @param string $status: optional. queued|synced
314 * @return mixed: non boolean true. number of item found in db.
315 */
316 public function queue_is_exists($file, $status = ''){
317 global $wpdb;
318 if(empty($status)){
319 return $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$this->table_name} WHERE file = '%s';", $file));
320 }
321 else{
322 return $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$this->table_name} WHERE file = '%s' AND status = '%s';", $file, $status));
323 }
324 }
325
326 /**
327 * Add file to the database.
328 * @param $file: Path of file relative to upload dir.
329 * @param string $status: optional. queued|synced
330 * @return bool
331 */
332 public function queue_add_file($file, $status = 'queued'){
333 global $wpdb;
334 if($this->queue_is_exists($file)){
335 return $wpdb->update( $this->table_name, array( 'file' => $file, 'status' => $status ), array('file' => $file), array( '%s', '%s' ), array( '%s' ) );
336 }
337 else{
338 return $wpdb->insert( $this->table_name, array( 'file' => $file, 'status' => $status ), array( '%s', '%s' ) );
339 }
340 return false;
341 }
342
343 /**
344 * Deletes a entry from database.
345 * @param $file: Path of file relative to upload dir.
346 * @return mixed
347 */
348 public function queue_remove_file($file){
349 global $wpdb;
350 return $wpdb->delete( $this->table_name, array( 'file' => $file), array( '%s' ) );
351 }
352
353 /**
354 * Delete a file from GCS.
355 * @param $old_file
356 * @param $new_file
357 * @param bool $force
358 * @param string $status
359 * @return bool
360 */
361 public function copy_file($old_file, $new_file, $force = false, $status = 'copied'){
362 try{
363 if(!$force && $this->queue_is_exists($new_file, $status)){
364 return false;
365 }
366
367 $client = $this->get_gs_client();
368
369 // Removing file for GCS
370 $client->copy_media($old_file, $new_file);
371
372 $this->queue_add_file($new_file, $status);
373 return true;
374 }
375 catch(\Exception $e){
376 return false;
377 }
378 }
379
380 /**
381 * Delete a file from GCS.
382 * @param $old_file
383 * @param $new_file
384 * @return bool
385 */
386 public function move_file($old_file, $new_file){
387 try{
388
389 $this->copy_file($old_file, $new_file, true, 'moved');
390 $this->delete_file($old_file);
391
392 $this->queue_remove_file($old_file);
393 return true;
394 }
395 catch(\Exception $e){
396 return false;
397 }
398 }
399
400 /**
401 * Get GS Client
402 * @return mixed
403 */
404 public function get_gs_client(){
405 if(empty($this->client)){
406 $this->client = ud_get_stateless_media()->get_client();
407 }
408
409 return $this->client;
410 }
411 }
412 }
413 }
414