Media Cleaner - Version 4.8.4

Version Description

  • Fix: Issue with ACF Repeater.
  • Fix: Trash and Ignore features resulted in a weird behavior when used together.
  • Add: Now can delete the results of a search.
  • Update: Many UI improvements.
  • Info: Please help this plugin survive by giving me a nice review, here: https://wordpress.org/support/plugin/meow-lightbox/reviews/?rate=5#new-post. Thank you :)
Download this release

Release Info

Developer TigrouMeow
Plugin Icon 128x128 Media Cleaner
Version 4.8.4
Comparing to
See all releases

Code changes from version 4.8.0 to 4.8.4

Files changed (13) hide show
  1. admin.php +12 -0
  2. core.php +30 -775
  3. media-cleaner.css +13 -0
  4. media-cleaner.js +491 -108
  5. media-cleaner.php +6 -2
  6. readme.txt +8 -3
  7. scan.php +78 -47
  8. ui.php +470 -0
  9. views/menu-screen.php +335 -0
  10. wpmc_admin.php +0 -365
  11. wpmc_checkers.php +0 -211
  12. wpmc_custom_checkers.php +0 -20
  13. wpmc_scan.php +0 -189
admin.php CHANGED
@@ -84,6 +84,9 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
84
  add_settings_field( 'wpmc_hide_warning', "Warning Message",
85
  array( $this, 'admin_hide_warning_callback' ),
86
  'wpmc_ui_settings-menu', 'wpmc_ui_settings' );
 
 
 
87
 
88
  // SUBMENU > Settings > Advanced
89
  add_settings_section( 'wpmc_advanced_settings', null, null, 'wpmc_advanced_settings-menu' );
@@ -115,6 +118,7 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
115
 
116
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_thumbnails' );
117
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_warning' );
 
118
 
119
  register_setting( 'wpmc_advanced_settings', 'wpmc_medias_buffer' );
120
  register_setting( 'wpmc_advanced_settings', 'wpmc_posts_buffer' );
@@ -361,6 +365,14 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
361
  echo $html;
362
  }
363
 
 
 
 
 
 
 
 
 
364
  function admin_thumbnails_only_callback( $args ) {
365
  $value = get_option( 'wpmc_thumbnails_only', false );
366
  $html = '<input type="checkbox" id="wpmc_thumbnails_only" name="wpmc_thumbnails_only" value="1" ' .
84
  add_settings_field( 'wpmc_hide_warning', "Warning Message",
85
  array( $this, 'admin_hide_warning_callback' ),
86
  'wpmc_ui_settings-menu', 'wpmc_ui_settings' );
87
+ add_settings_field( 'wpmc_results_per_page', "Results Per Page",
88
+ array( $this, 'admin_results_per_page' ),
89
+ 'wpmc_ui_settings-menu', 'wpmc_ui_settings' );
90
 
91
  // SUBMENU > Settings > Advanced
92
  add_settings_section( 'wpmc_advanced_settings', null, null, 'wpmc_advanced_settings-menu' );
118
 
119
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_thumbnails' );
120
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_warning' );
121
+ register_setting( 'wpmc_ui_settings', 'wpmc_results_per_page' );
122
 
123
  register_setting( 'wpmc_advanced_settings', 'wpmc_medias_buffer' );
124
  register_setting( 'wpmc_advanced_settings', 'wpmc_posts_buffer' );
365
  echo $html;
366
  }
367
 
368
+ function admin_results_per_page( $args ) {
369
+ $value = get_option( 'wpmc_results_per_page', 20 );
370
+ $html = <<< HTML
371
+ <input step="1" min="1" max="999" name="wpmc_results_per_page" id="wpmc_results_per_page" maxlength="3" value="{$value}" type="number">
372
+ HTML;
373
+ echo $html;
374
+ }
375
+
376
  function admin_thumbnails_only_callback( $args ) {
377
  $value = get_option( 'wpmc_thumbnails_only', false );
378
  $html = '<input type="checkbox" id="wpmc_thumbnails_only" name="wpmc_thumbnails_only" value="1" ' .
core.php CHANGED
@@ -12,20 +12,8 @@ class Meow_WPMC_Core {
12
 
13
  public function __construct( $admin ) {
14
  $this->admin = $admin;
15
- add_action( 'admin_init', array( $this, 'admin_init' ) );
16
- add_action( 'admin_menu', array( $this, 'admin_menu' ) );
17
- add_action( 'admin_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
18
- add_action( 'admin_print_scripts', array( $this, 'admin_inline_js' ) );
19
- add_action( 'wp_ajax_wpmc_scan', array( $this, 'wp_ajax_wpmc_scan' ) );
20
- add_action( 'wp_ajax_wpmc_get_all_issues', array( $this, 'wp_ajax_wpmc_get_all_issues' ) );
21
- add_action( 'wp_ajax_wpmc_get_all_deleted', array( $this, 'wp_ajax_wpmc_get_all_deleted' ) );
22
- add_action( 'wp_ajax_wpmc_scan_do', array( $this, 'wp_ajax_wpmc_scan_do' ) );
23
- add_action( 'wp_ajax_wpmc_prepare_do', array( $this, 'wp_ajax_wpmc_prepare_do' ) );
24
- add_action( 'wp_ajax_wpmc_delete_do', array( $this, 'wp_ajax_wpmc_delete_do' ) );
25
- add_action( 'wp_ajax_wpmc_ignore_do', array( $this, 'wp_ajax_wpmc_ignore_do' ) );
26
- add_action( 'wp_ajax_wpmc_recover_do', array( $this, 'wp_ajax_wpmc_recover_do' ) );
27
- add_filter( 'media_row_actions', array( $this, 'media_row_actions' ), 10, 2 );
28
- add_action( 'add_meta_boxes', array( $this, 'add_metabox' ) );
29
  }
30
 
31
  function admin_init() {
@@ -38,122 +26,6 @@ class Meow_WPMC_Core {
38
  $this->checkers = new Meow_WPMC_Checkers( $this );
39
  }
40
 
41
- /*******************************************************************************
42
- * METABOX FOR USAGE
43
- ******************************************************************************/
44
-
45
- function add_metabox() {
46
- add_meta_box( 'mfrh_media_usage_box', 'Media Cleaner', array( $this, 'display_metabox' ), 'attachment', 'side', 'default' );
47
- }
48
-
49
- function display_metabox( $post ) {
50
- $this->log( "Media Edit > Checking Media #{$post->ID}" );
51
- $success = $this->wpmc_check_media( $post->ID, true );
52
- $this->log( "Success $success\n" );
53
- if ( $success ) {
54
- if ( $this->last_analysis == "CONTENT" ) {
55
- echo "Found in content.";
56
- }
57
- else if ( $this->last_analysis == "CONTENT (ID)" ) {
58
- echo "Found in content (as an ID).";
59
- }
60
- else if ( $this->last_analysis == "CONTENT (URL)" ) {
61
- echo "Found in content (as an URL).";
62
- }
63
- else if ( $this->last_analysis == "THEME" ) {
64
- echo "Found in theme.";
65
- }
66
- else if ( $this->last_analysis == "PAGE BUILDER" ) {
67
- echo "Found in Page Builder.";
68
- }
69
- else if ( $this->last_analysis == "GALLERY" ) {
70
- echo "Found in gallery.";
71
- }
72
- else if ( $this->last_analysis == "META" ) {
73
- echo "Found in meta.";
74
- }
75
- else if ( $this->last_analysis == "META (ID)" ) {
76
- echo "Found in meta (as an ID).";
77
- }
78
- else if ( $this->last_analysis == "META (URL)" ) {
79
- echo "Found in meta (as an URL).";
80
- }
81
- else if ( $this->last_analysis == "META ACF (ID)" ) {
82
- echo "Found in ACF meta (as an ID).";
83
- }
84
- else if ( $this->last_analysis == "META ACF (URL)" ) {
85
- echo "Found in ACF meta (as an URL).";
86
- }
87
- else if ( $this->last_analysis == "WIDGET" ) {
88
- echo "Found in widget.";
89
- }
90
- else {
91
- echo "It seems to be used as: " . $this->last_analysis;
92
- }
93
- }
94
- else {
95
- echo "Doesn't seem to be used.";
96
- }
97
- }
98
-
99
- /*******************************************************************************
100
- * ASYNCHRONOUS AJAX FUNCTIONS
101
- ******************************************************************************/
102
-
103
- function wp_ajax_wpmc_delete_do () {
104
- ob_start();
105
- $data = $_POST['data'];
106
- $success = 0;
107
- foreach ( $data as $piece ) {
108
- $success += ( $this->wpmc_delete( $piece ) ? 1 : 0 );
109
- }
110
- ob_end_clean();
111
- echo json_encode(
112
- array(
113
- 'success' => true,
114
- 'result' => array( 'data' => $data, 'success' => $success ),
115
- 'message' => __( "Status unknown.", 'media-cleaner' )
116
- )
117
- );
118
- die();
119
- }
120
-
121
- function wp_ajax_wpmc_ignore_do () {
122
- ob_start();
123
- $data = $_POST['data'];
124
- $success = 0;
125
- foreach ( $data as $piece ) {
126
- $success += ( $this->wpmc_ignore( $piece ) ? 1 : 0 );
127
- }
128
- ob_end_clean();
129
- echo json_encode(
130
- array(
131
- 'success' => true,
132
- 'result' => array( 'data' => $data, 'success' => $success ),
133
- 'message' => __( "Status unknown.", 'media-cleaner' )
134
- )
135
- );
136
- die();
137
- }
138
-
139
- function wp_ajax_wpmc_recover_do () {
140
- ob_start();
141
- $data = $_POST['data'];
142
- $success = 0;
143
- foreach ( $data as $piece ) {
144
- $success += ( $this->wpmc_recover( $piece ) ? 1 : 0 );
145
- }
146
- ob_end_clean();
147
- echo json_encode(
148
- array(
149
- 'success' => true,
150
- 'result' => array( 'data' => $data, 'success' => $success ),
151
- 'message' => __( "Status unknown.", 'media-cleaner' )
152
- )
153
- );
154
- die();
155
- }
156
-
157
  function deepsleep( $seconds ) {
158
  $start_time = time();
159
  while( true ) {
@@ -172,12 +44,21 @@ class Meow_WPMC_Core {
172
  private $items_checked = 0;
173
  private $items_count = 0;
174
 
 
 
 
 
 
 
 
 
 
 
 
175
  function timeout_check_start( $count ) {
176
  $this->start_time = time();
177
  $this->items_count = $count;
178
- $this->max_execution_time = ini_get( "max_execution_time" );
179
- if ( empty( $this->max_execution_time ) )
180
- $this->max_execution_time = 30;
181
  }
182
 
183
  function timeout_check() {
@@ -202,214 +83,6 @@ class Meow_WPMC_Core {
202
  $this->item_scan_avg_time = ceil( ( $this->time_elapsed / $this->items_checked ) * 10 ) / 10;
203
  }
204
 
205
- function wp_ajax_wpmc_prepare_do() {
206
- $limit = isset( $_POST['limit'] ) ? $_POST['limit'] : 0;
207
- $limitsize = get_option( 'wpmc_posts_buffer', 5 );
208
- if ( empty( $limit ) )
209
- $this->wpmc_reset_issues();
210
-
211
- $method = get_option( 'wpmc_method', 'media' );
212
- $check_library = get_option(' wpmc_media_library', true );
213
- $check_postmeta = get_option( 'wpmc_postmeta', false );
214
- $check_posts = get_option( 'wpmc_posts', false );
215
- $check_widgets = get_option( 'wpmc_widgets', false );
216
- if ( $method == 'media' && !$check_posts && !$check_postmeta && !$check_widgets ) {
217
- echo json_encode( array(
218
- 'results' => array(),
219
- 'success' => true,
220
- 'finished' => true,
221
- 'message' => __( "Posts, Meta and Widgets analysis are all off. Done.", 'media-cleaner' )
222
- ) );
223
- die();
224
- }
225
- if ( $method == 'files' && $check_library && !$check_posts && !$check_postmeta && !$check_widgets ) {
226
- echo json_encode( array(
227
- 'results' => array(),
228
- 'success' => true,
229
- 'finished' => true,
230
- 'message' => __( "Posts, Meta and Widgets analysis are all off. Done.", 'media-cleaner' )
231
- ) );
232
- die();
233
- }
234
-
235
- global $wpdb;
236
- // Maybe we could avoid to check more post_types.
237
- // SELECT post_type, COUNT(*) FROM `wp_posts` GROUP BY post_type
238
- $posts = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p
239
- WHERE p.post_status != 'inherit'
240
- AND p.post_status != 'trash'
241
- AND p.post_type != 'attachment'
242
- AND p.post_type != 'shop_order'
243
- AND p.post_type != 'shop_order_refund'
244
- AND p.post_type != 'nav_menu_item'
245
- AND p.post_type != 'revision'
246
- AND p.post_type != 'auto-draft'
247
- AND p.post_type != 'wphb_minify_group'
248
- AND p.post_type != 'customize_changeset'
249
- AND p.post_type != 'oembed_cache'
250
- AND p.post_type NOT LIKE '%acf-%'
251
- AND p.post_type NOT LIKE '%edd_%'
252
- LIMIT %d, %d", $limit, $limitsize
253
- )
254
- );
255
-
256
- $found = array();
257
-
258
- // Only at the beginning
259
- if ( empty( $limit ) ) {
260
-
261
- $this->log( "Analyzing for references:" );
262
-
263
- $theme_ids = array();
264
- $theme_urls = array();
265
- $this->get_images_from_themes( $theme_ids, $theme_urls );
266
- $this->add_reference_id( $theme_ids, 'THEME' );
267
- $this->add_reference_url( $theme_urls, 'THEME' );
268
-
269
- // Only on Start: Analyze Widgets
270
- if ( get_option( 'wpmc_widgets', false ) ) {
271
- $widgets_ids = array();
272
- $widgets_urls = array();
273
- $this->get_images_from_widgets( $widgets_ids, $widgets_urls );
274
- $this->add_reference_id( $widgets_ids, 'WIDGET' );
275
- $this->add_reference_url( $widgets_urls, 'WIDGET' );
276
- }
277
-
278
- // Only on Start: Analyze WooCommerce Categories Images
279
- if ( class_exists( 'WooCommerce' ) ) {
280
- $metas = $wpdb->get_col( "SELECT meta_value
281
- FROM $wpdb->termmeta
282
- WHERE meta_key LIKE '%thumbnail_id%'"
283
- );
284
- if ( count( $metas ) > 0 ) {
285
- $postmeta_images_ids = array();
286
- foreach ( $metas as $meta )
287
- if ( is_numeric( $meta ) && $meta > 0 )
288
- array_push( $postmeta_images_ids, $meta );
289
- $this->add_reference_id( $postmeta_images_ids, 'META (ID)' );
290
- }
291
- }
292
- }
293
-
294
- $this->timeout_check_start( count( $posts ) );
295
-
296
- foreach ( $posts as $post ) {
297
- $this->timeout_check();
298
- // Run the scanners
299
- if ( $check_postmeta )
300
- do_action( 'wpmc_scan_postmeta', $post );
301
- if ( $check_posts ) {
302
- // Get HTML for this post
303
- $html = get_post_field( 'post_content', $post );
304
- // Scan on the raw TML content
305
- do_action( 'wpmc_scan_post', $html, $post );
306
- $html = do_shortcode( $html );
307
- $html = wp_make_content_images_responsive( $html );
308
- // Scan with shortcodes resolved and src-set
309
- do_action( 'wpmc_scan_post', $html, $post );
310
- }
311
- $this->timeout_check_additem();
312
- }
313
- // Write the references cached by the scanners
314
- $this->write_references();
315
-
316
- $finished = count( $posts ) < $limitsize;
317
- if ( $finished ) {
318
- $found = array();
319
- // Optimize DB (but that takes too long!)
320
- //$table_name = $wpdb->prefix . "mclean_refs";
321
- // $wpdb->query ("DELETE a FROM $table_name as a, $table_name as b
322
- // WHERE (a.mediaId = b.mediaId OR a.mediaId IS NULL AND b.mediaId IS NULL)
323
- // AND (a.mediaUrl = b.mediaUrl OR a.mediaUrl IS NULL AND b.mediaUrl IS NULL)
324
- // AND (a.originType = b.originType OR a.originType IS NULL AND b.originType IS NULL)
325
- // AND (a.origin = b.origin OR a.origin IS NULL AND b.origin IS NULL)
326
- // AND a.ID < b.ID;" );
327
- // $wpdb->query ("DELETE a FROM $table_name as a, $table_name as b WHERE a.mediaId = b.mediaId AND a.mediaId > 0 AND a.ID < b.ID;" );
328
- // $wpdb->query ("DELETE a FROM $table_name as a, $table_name as b WHERE a.mediaUrl = b.mediaUrl AND LENGTH(a.mediaUrl) > 1 AND a.ID < b.ID;" );
329
- }
330
- if ( $finished && get_option( 'wpmc_debuglogs', false ) ) {
331
- //$this->log( print_r( $found, true ) );
332
- }
333
- echo json_encode(
334
- array(
335
- 'success' => true,
336
- 'finished' => $finished,
337
- 'limit' => $limit + $limitsize,
338
- 'message' => __( "Posts checked.", 'media-cleaner' ) )
339
- );
340
- die();
341
- }
342
-
343
- function wp_ajax_wpmc_scan_do () {
344
- // For debug, to pretend there is a timeout
345
- //$this->deepsleep(10);
346
- //header("HTTP/1.0 408 Request Timeout");
347
- //exit;
348
-
349
- ob_start();
350
- $type = $_POST['type'];
351
- $data = $_POST['data'];
352
- $this->timeout_check_start( count( $data ) );
353
- $success = 0;
354
- foreach ( $data as $piece ) {
355
- $this->timeout_check();
356
- if ( $type == 'file' ) {
357
- $this->log( "Check File: {$piece}" );
358
- $result = ( apply_filters( 'wpmc_check_file', true, $piece ) ? 1 : 0 );
359
- $this->log( "Success " . $result . "\n" );
360
- $success += $result;
361
- }
362
- else if ( $type == 'media' ) {
363
- $this->log( "Checking Media #{$piece}" );
364
- $result = ( $this->wpmc_check_media( $piece ) ? 1 : 0 );
365
- $this->log( "Success " . $result . "\n" );
366
- $success += $result;
367
- }
368
- $this->timeout_check_additem();
369
- }
370
- ob_end_clean();
371
- echo json_encode(
372
- array(
373
- 'success' => true,
374
- 'result' => array( 'type' => $type, 'data' => $data, 'success' => $success ),
375
- 'message' => __( "Items checked.", 'media-cleaner' )
376
- )
377
- );
378
- die();
379
- }
380
-
381
- function wp_ajax_wpmc_get_all_deleted () {
382
- global $wpdb;
383
- $table_name = $wpdb->prefix . "mclean_scan";
384
- $ids = $wpdb->get_col( "SELECT id FROM $table_name WHERE ignored = 0 AND deleted = 1" );
385
- echo json_encode(
386
- array(
387
- 'results' => array( 'ids' => $ids ),
388
- 'success' => true,
389
- 'message' => __( "List generated.", 'media-cleaner' )
390
- )
391
- );
392
- die;
393
- }
394
-
395
- function wp_ajax_wpmc_get_all_issues () {
396
- global $wpdb;
397
- $isTrash = ( isset( $_POST['isTrash'] ) && $_POST['isTrash'] == 1 ) ? true : false;
398
- $table_name = $wpdb->prefix . "mclean_scan";
399
- if ( $isTrash )
400
- $ids = $wpdb->get_col( "SELECT id FROM $table_name WHERE ignored = 0 AND deleted = 1" );
401
- else
402
- $ids = $wpdb->get_col( "SELECT id FROM $table_name WHERE ignored = 0 AND deleted = 0" );
403
- echo json_encode(
404
- array(
405
- 'results' => array( 'ids' => $ids ),
406
- 'success' => true,
407
- 'message' => __( "List generated.", 'media-cleaner' )
408
- )
409
- );
410
- die;
411
- }
412
-
413
  function array_to_ids_or_urls( &$meta, &$ids, &$urls ) {
414
  foreach ( $meta as $k => $m ) {
415
  if ( is_numeric( $m ) ) {
@@ -504,7 +177,7 @@ class Meow_WPMC_Core {
504
  preg_match_all( "/((https?:\/\/)?[^\\&\#\[\] \"\?]+\.pdf)/", $html, $res );
505
  if ( !empty( $res ) && isset( $res[1] ) && count( $res[1] ) > 0 ) {
506
  foreach ( $res[1] as $url ) {
507
- error_log(print_r($url, 1));
508
  array_push( $results, $this->wpmc_clean_url( $url ) );
509
  }
510
  }
@@ -578,49 +251,6 @@ class Meow_WPMC_Core {
578
  return true;
579
  }
580
 
581
- function wp_ajax_wpmc_scan() {
582
- global $wpdb;
583
-
584
- $method = get_option( 'wpmc_method', 'media' );
585
- if ( !$this->admin->is_registered() )
586
- $method = 'media';
587
- $path = isset( $_POST['path'] ) ? $_POST['path'] : null;
588
- $limit = isset( $_POST['limit'] ) ? $_POST['limit'] : 0;
589
- $limitsize = get_option( 'wpmc_medias_buffer', 100 );
590
-
591
- if ( $method == 'files' ) {
592
- $output = apply_filters( 'wpmc_list_uploaded_files', array(
593
- 'results' => array(), 'success' => false, 'message' => __( "Unavailable.", 'media-cleaner' )
594
- ), $path );
595
- echo json_encode( $output );
596
- die();
597
- }
598
-
599
- if ( $method == 'media' ) {
600
- // Prevent double scanning by removing filesystem entries that we have DB entries for
601
- $results = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p
602
- WHERE p.post_status = 'inherit'
603
- AND p.post_type = 'attachment'
604
- LIMIT %d, %d", $limit, $limitsize
605
- )
606
- );
607
- $finished = count( $results ) < $limitsize;
608
- echo json_encode(
609
- array(
610
- 'results' => $results,
611
- 'success' => true,
612
- 'finished' => $finished,
613
- 'limit' => $limit + $limitsize,
614
- 'message' => __( "Medias retrieved.", 'media-cleaner' ) )
615
- );
616
- die();
617
- }
618
-
619
- // No task.
620
- echo json_encode( array( 'success' => false, 'message' => __( "No task.", 'media-cleaner' ) ) );
621
- die();
622
- }
623
-
624
  /**
625
  *
626
  * HELPERS
@@ -749,11 +379,14 @@ class Meow_WPMC_Core {
749
  function wpmc_ignore( $id ) {
750
  global $wpdb;
751
  $table_name = $wpdb->prefix . "mclean_scan";
752
- $has = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $table_name WHERE id = %d AND ignored = 1", $id ) );
753
- if ( $has > 0 )
754
  $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET ignored = 0 WHERE id = %d", $id ) );
755
- else
 
 
756
  $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET ignored = 1 WHERE id = %d", $id ) );
 
757
  return true;
758
  }
759
 
@@ -798,7 +431,7 @@ class Meow_WPMC_Core {
798
  if ( $issue->deleted == 0 ) {
799
  // Move file to the trash
800
  if ( $this->wpmc_trash_file( $issue->path ) )
801
- $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET deleted = 1 WHERE id = %d", $id ) );
802
  return true;
803
  }
804
  else {
@@ -848,7 +481,7 @@ class Meow_WPMC_Core {
848
  }
849
  }
850
  wp_delete_attachment( $issue->postId, false );
851
- $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET deleted = 1 WHERE id = %d", $id ) );
852
  return true;
853
  }
854
  else {
@@ -1148,23 +781,6 @@ class Meow_WPMC_Core {
1148
  delete_transient( "wpmc_galleries_images_urls" );
1149
  }
1150
 
1151
- /**
1152
- *
1153
- * DASHBOARD
1154
- *
1155
- */
1156
-
1157
- function admin_inline_js() {
1158
- echo "<script type='text/javascript'>\n";
1159
- echo 'var wpmc_cfg = {
1160
- delay: ' . get_option( 'wpmc_delay', 100 ) . ',
1161
- analysisBuffer: ' . get_option( 'wpmc_analysis_buffer', 50 ) . ',
1162
- isPro: ' . ( $this->admin->is_registered() ? '1' : '0') . ',
1163
- scanFiles: ' . ( ( get_option( 'wpmc_method', 'media' ) == 'files' && $this->admin->is_registered() ) ? '1' : '0' ) . ',
1164
- scanMedia: ' . ( get_option( 'wpmc_method', 'media' ) == 'media' ? '1' : '0' ) . ' };';
1165
- echo "\n</script>";
1166
- }
1167
-
1168
  function echo_issue( $issue ) {
1169
  if ( $issue == 'NO_CONTENT' ) {
1170
  _e( "Seems not in use.", 'media-cleaner' );
@@ -1182,369 +798,6 @@ class Meow_WPMC_Core {
1182
  echo $issue;
1183
  }
1184
  }
1185
-
1186
- function media_row_actions( $actions, $post ) {
1187
- global $current_screen;
1188
- if ( 'upload' != $current_screen->id )
1189
- return $actions;
1190
- global $wpdb;
1191
- $table_name = $wpdb->prefix . "mclean_scan";
1192
- $res = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE postId = %d", $post->ID ) );
1193
- if ( !empty( $res ) && isset( $actions['delete'] ) )
1194
- $actions['delete'] = "<a href='?page=media-cleaner&view=deleted'>" .
1195
- __( 'Delete with Media Cleaner', 'media-cleaner' ) . "</a>";
1196
- if ( !empty( $res ) && isset( $actions['trash'] ) )
1197
- $actions['trash'] = "<a href='?page=media-cleaner'>" .
1198
- __( 'Trash with Media Cleaner', 'media-cleaner' ) . "</a>";
1199
- if ( !empty( $res ) && isset( $actions['untrash'] ) ) {
1200
- $actions['untrash'] = "<a href='?page=media-cleaner&view=deleted'>" .
1201
- __( 'Restore with Media Cleaner', 'media-cleaner' ) . "</a>";
1202
- }
1203
- return $actions;
1204
- }
1205
-
1206
- function wpmc_screen() {
1207
- global $wplr;
1208
- ?>
1209
- <div class='wrap'>
1210
-
1211
- <?php
1212
- echo $this->admin->display_title( "Media Cleaner" );
1213
- global $wpdb;
1214
- $posts_per_page = get_user_meta( get_current_user_id(), 'upload_per_page', true );
1215
- if ( empty( $posts_per_page ) )
1216
- $posts_per_page = 20;
1217
- $view = isset ( $_GET[ 'view' ] ) ? sanitize_text_field( $_GET[ 'view' ] ) : "issues";
1218
- $paged = isset ( $_GET[ 'paged' ] ) ? sanitize_text_field( $_GET[ 'paged' ] ) : 1;
1219
- $reset = isset ( $_GET[ 'reset' ] ) ? $_GET[ 'reset' ] : 0;
1220
- if ( $reset ) {
1221
- wpmc_reset();
1222
- $this->wpmc_reset_issues();
1223
- }
1224
- $s = isset ( $_GET[ 's' ] ) ? sanitize_text_field( $_GET[ 's' ] ) : null;
1225
- $table_name = $wpdb->prefix . "mclean_scan";
1226
- $issues_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE ignored = 0 AND deleted = 0" );
1227
- $total_size = $wpdb->get_var( "SELECT SUM(size) FROM $table_name WHERE ignored = 0 AND deleted = 0" );
1228
- $trash_total_size = $wpdb->get_var( "SELECT SUM(size) FROM $table_name WHERE ignored = 0 AND deleted = 1" );
1229
- $ignored_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE ignored = 1" );
1230
- $deleted_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE deleted = 1" );
1231
-
1232
- if ( $view == 'deleted' ) {
1233
- $items_count = $deleted_count;
1234
- $items = $wpdb->get_results( $wpdb->prepare( "SELECT id, type, postId, path, size, ignored, deleted, issue
1235
- FROM $table_name WHERE ignored = 0 AND deleted = 1 AND path LIKE %s
1236
- ORDER BY time
1237
- DESC LIMIT %d, %d", '%' . $s . '%', ( $paged - 1 ) * $posts_per_page, $posts_per_page ), OBJECT );
1238
- }
1239
- else if ( $view == 'ignored' ) {
1240
- $items_count = $ignored_count;
1241
- $items = $wpdb->get_results( $wpdb->prepare( "SELECT id, type, postId, path, size, ignored, deleted, issue
1242
- FROM $table_name
1243
- WHERE ignored = 1 AND deleted = 0 AND path LIKE %s
1244
- ORDER BY time
1245
- DESC LIMIT %d, %d", '%' . $s . '%', ( $paged - 1 ) * $posts_per_page, $posts_per_page ), OBJECT );
1246
- }
1247
- else {
1248
- $items_count = $issues_count;
1249
- $items = $wpdb->get_results( $wpdb->prepare( "SELECT id, type, postId, path, size, ignored, deleted, issue
1250
- FROM $table_name
1251
- WHERE ignored = 0 AND deleted = 0 AND path LIKE %s
1252
- ORDER BY time
1253
- DESC LIMIT %d, %d", '%' . $s . '%', ( $paged - 1 ) * $posts_per_page, $posts_per_page ), OBJECT );
1254
- }
1255
- ?>
1256
-
1257
- <style>
1258
- #wpmc-pages {
1259
- float: right;
1260
- position: relative;
1261
- top: 12px;
1262
- }
1263
-
1264
- #wpmc-pages a {
1265
- text-decoration: none;
1266
- border: 1px solid black;
1267
- padding: 2px 5px;
1268
- border-radius: 4px;
1269
- background: #E9E9E9;
1270
- color: lightslategrey;
1271
- border-color: #BEBEBE;
1272
- }
1273
-
1274
- #wpmc-pages .current {
1275
- font-weight: bold;
1276
- }
1277
- </style>
1278
-
1279
- <div style='margin-top: 0px; background: #FFF; padding: 5px; border-radius: 4px; height: 28px; box-shadow: 0px 0px 6px #C2C2C2;'>
1280
-
1281
- <!-- SCAN -->
1282
- <?php if ( $view != 'deleted' ) { ?>
1283
- <a id='wpmc_scan' onclick='wpmc_scan()' class='button-primary' style='float: left;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-search"></span><?php _e("Start Scan", 'media-cleaner'); ?></a>
1284
- <?php } ?>
1285
-
1286
- <!-- PAUSE -->
1287
- <?php if ( $view != 'deleted' ) { ?>
1288
- <a id='wpmc_pause' onclick='wpmc_pause()' class='button' style='float: left; margin-left: 5px; display: none;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-pause"></span><?php _e("Pause", 'media-cleaner'); ?></a>
1289
- <?php } ?>
1290
-
1291
- <!-- DELETE SELECTED -->
1292
- <a id='wpmc_delete' onclick='wpmc_delete()' class='button' style='float: left; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-no"></span><?php _e("Delete", 'media-cleaner'); ?></a>
1293
- <?php if ( $view == 'deleted' ) { ?>
1294
- <a id='wpmc_recover' onclick='wpmc_recover()' class='button-secondary' style='float: left; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-repeat"></span><?php _e( "Recover", 'media-cleaner' ); ?></a>
1295
- <?php } ?>
1296
-
1297
- <!-- IGNORE SELECTED -->
1298
- <a id='wpmc_ignore' onclick='wpmc_ignore()' class='button' style='float: left; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-yes"></span><?php
1299
- if ( $view == 'ignored' )
1300
- _e( "Mark as Issue", 'media-cleaner' );
1301
- else
1302
- _e( "Ignore", 'media-cleaner' );
1303
- ?>
1304
- </a>
1305
-
1306
- <!-- RESET -->
1307
- <?php if ( $view != 'deleted' ) { ?>
1308
- <a id='wpmc_reset' href='?page=media-cleaner&reset=1' class='button-primary' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-sos"></span><?php _e("Reset", 'media-cleaner'); ?></a>
1309
- <?php } ?>
1310
-
1311
- <!-- DELETE ALL -->
1312
- <?php if ( $view == 'deleted' ) { ?>
1313
- <a id='wpmc_recover_all' onclick='wpmc_recover_all()' class='button-primary' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-repeat"></span><?php _e("Recover all", 'media-cleaner'); ?></a>
1314
- <a id='wpmc_delete_all' onclick='wpmc_delete_all(true)' class='button button-red' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-trash"></span><?php _e("Empty trash", 'media-cleaner'); ?></a>
1315
- <?php } else { ?>
1316
- <a id='wpmc_delete_all' onclick='wpmc_delete_all()' class='button button-red' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-trash"></span><?php _e("Delete all", 'media-cleaner'); ?></a>
1317
- <?php } ?>
1318
-
1319
- <form id="posts-filter" action="upload.php" method="get" style='float: right;'>
1320
- <p class="search-box" style='margin-left: 5px; float: left;'>
1321
- <input type="search" name="s" style="width: 120px;" value="<?php echo $s ? $s : ""; ?>">
1322
- <input type="hidden" name="page" value="media-cleaner">
1323
- <input type="hidden" name="view" value="<?php echo $view; ?>">
1324
- <input type="hidden" name="paged" value="1">
1325
- <input type="submit" class="button" value="<?php _e( 'Search', 'media-cleaner' ) ?>"><span style='border-right: #A2A2A2 solid 1px; margin-left: 5px; margin-right: 3px;'>&nbsp;</span>
1326
- </p>
1327
- </form>
1328
-
1329
- <!-- PROGRESS -->
1330
- <span style='margin-left: 12px; font-size: 15px; top: 5px; position: relative; color: #747474;' id='wpmc_progression'></span>
1331
-
1332
- </div>
1333
-
1334
- <p>
1335
- <?php
1336
-
1337
- $table_scan = $wpdb->prefix . "mclean_scan";
1338
- $table_refs = $wpdb->prefix . "mclean_refs";
1339
- if ( $wpdb->get_var("SHOW TABLES LIKE '$table_scan'") != $table_scan ||
1340
- $wpdb->get_var("SHOW TABLES LIKE '$table_refs'") != $table_refs ) {
1341
- _e( "<div class='notice notice-error'><p><b>The database is not ready for Media Cleaner. The scan will not work.</b> Click on the <b>Reset</b> button, it re-creates the tables required by Media Cleaner. If this message still appear, contact the support.</p></div>", 'media-cleaner' );
1342
- }
1343
- else {
1344
- $method = get_option( 'wpmc_method', 'media' );
1345
- if ( !$this->admin->is_registered() )
1346
- $method = 'media';
1347
-
1348
- $hide_warning = get_option( 'wpmc_hide_warning', false );
1349
-
1350
- if ( !$hide_warning ) {
1351
- _e( "<div class='notice notice-warning'><p><b style='color: red;'>Important.</b> <b>Backup your DB and your /uploads directory before using Media Cleaner. </b> The deleted files will be temporarily moved to the <b>uploads/wpmc-trash</b> directory. After testing your website, you can check the <a href='?page=media-cleaner&s&view=deleted'>trash</a> to either empty it or recover the media and files. The Media Cleaner does its best to be safe to use. However, WordPress being a very dynamic and pluggable system, it is impossible to predict all the situations in which your files are used. <b style='color: red;'>Again, please backup!</b> If you don't know how, give a try to this: <a href='https://updraftplus.com/?afref=460' target='_blank'>UpdraftPlus</a>. <br /><br /><b style='color: red;'>Be thoughtful.</b> Don't blame Media Cleaner if it deleted too many or not enough of your files. It makes cleaning possible and this task is only possible this way; don't post a bad review because it broke your install. <b>If you have a proper backup, there is no risk</b>. Sorry for the lengthy message, but better be safe than sorry. You can disable this big warning in the options if you have a Pro license. Make sure you read this warning twice. Media Cleaner is awesome and always getting better so I hope you will enjoy it. Thank you :)</p></div>", 'media-cleaner' );
1352
- }
1353
-
1354
- if ( !MEDIA_TRASH ) {
1355
- _e( "<div class='notice notice-warning'><p>The trash for the Media Library is disabled. Any media removed by the plugin will be <b>permanently deleted</b>. To enable it, modify your wp-config.php file and add this line (preferably at the top):<br /><b>define( 'MEDIA_TRASH', true );</b></p></div>", 'media-cleaner' );
1356
- }
1357
- }
1358
-
1359
- if ( !$this->admin->is_registered() ) {
1360
- echo "<div class='notice notice-info'><p>";
1361
- _e( "<b>This version is not Pro.</b> This plugin is a lot of work so please consider <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a> in order to receive support and to contribute in the evolution of it. Also, <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a> version will also give you the option <b>to scan the physical files in your /uploads folder</b> and extra checks for the common Page Builders.", 'media-cleaner' );
1362
- echo "</p></div>";
1363
-
1364
- if ( function_exists( '_et_core_find_latest' ) ) {
1365
- echo "<div class='notice notice-warning'><p>";
1366
- _e( "<b>Divi has been detected</b>. The free version might detect the files used by Divi correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
1367
- echo "</p></div>";
1368
- }
1369
-
1370
- if ( class_exists( 'Vc_Manager' ) ) {
1371
- echo "<div class='notice notice-warning'><p>";
1372
- _e( "<b>Visual Composer has been detected</b>. The free version might detect the files used by Visual Composer correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
1373
- echo "</p></div>";
1374
- }
1375
-
1376
- if ( function_exists( 'fusion_builder_map' ) ) {
1377
- echo "<div class='notice notice-warning'><p>";
1378
- _e( "<b>Fusion Builder has been detected</b>. The free version might detect the files used by Fusion Builder correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
1379
- echo "</p></div>";
1380
- }
1381
-
1382
- if ( class_exists( 'FLBuilderModel' ) ) {
1383
- echo "<div class='notice notice-warning'><p>";
1384
- _e( "<b>Beaver Builder has been detected</b>. The free version might detect the files used by Beaver Builder correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
1385
- echo "</p></div>";
1386
- }
1387
-
1388
- if ( function_exists( 'elementor_load_plugin_textdomain' ) ) {
1389
- echo "<div class='notice notice-warning'><p>";
1390
- _e( "<b>Elementor has been detected</b>. The free version might detect the files used by Elementor correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
1391
- echo "</p></div>";
1392
- }
1393
-
1394
- if ( class_exists( 'SiteOrigin_Panels' ) ) {
1395
- echo "<div class='notice notice-warning'><p>";
1396
- _e( "<b>SiteOrigin Page Builder has been detected</b>. The free version might detect the files used by SiteOrigin Page Builder correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
1397
- echo "</p></div>";
1398
- }
1399
-
1400
- }
1401
-
1402
- $anychecks = get_option( 'wpmc_posts', false ) || get_option( 'wpmc_postmeta', false ) || get_option( 'wpmc_widgets', false );
1403
- $check_library = get_option(' wpmc_media_library', true );
1404
-
1405
- if ( $method == 'media' ) {
1406
- if ( !$anychecks )
1407
- _e( "<div class='error'><p>Media Cleaner will analyze your Media Library. However, There is <b>NOTHING MARKED TO BE CHECKED</b> in the Settings. Media Cleaner will therefore run a special scan: <b>only the broken medias will be detected as issues.</b></p></div>", 'media-cleaner' );
1408
- else
1409
- _e( "<div class='notice notice-success'><p>Media Cleaner will analyze your Media Library.</p></div>", 'media-cleaner' );
1410
- }
1411
- else if ( $method == 'files' ) {
1412
- if ( !$anychecks && !$check_library )
1413
- _e( "<div class='error'><p>Media Cleaner will analyze your Filesystem. However, There is <b>NOTHING MARKED TO BE CHECKED</b> in the Settings. If you scan now, all the files will be detected as <b>NOT USED</b>.</p></div>", 'media-cleaner' );
1414
- else
1415
- _e( "<div class='notice notice-success'><p>Media Cleaner will analyze your Filesystem.</p></div>", 'media-cleaner' );
1416
- }
1417
-
1418
- echo sprintf( __( 'There are <b>%s issue(s)</b> with your files, accounting for <b>%s MB</b>. Your trash contains <b>%s MB.</b>', 'media-cleaner' ), number_format( $issues_count, 0 ), number_format( $total_size / 1000000, 2 ), number_format( $trash_total_size / 1000000, 2 ) );
1419
- ?>
1420
- </p>
1421
-
1422
- <div id='wpmc-pages'>
1423
- <?php
1424
- echo paginate_links(array(
1425
- 'base' => '?page=media-cleaner&s=' . urlencode($s) . '&view=' . $view . '%_%',
1426
- 'current' => $paged,
1427
- 'format' => '&paged=%#%',
1428
- 'total' => ceil( $items_count / $posts_per_page ),
1429
- 'prev_next' => false
1430
- ));
1431
- ?>
1432
- </div>
1433
-
1434
- <ul class="subsubsub">
1435
- <li class="all"><a <?php if ( $view == 'issues' ) echo "class='current'"; ?> href='?page=media-cleaner&s=<?php echo $s; ?>&view=issues'><?php _e( "Issues", 'media-cleaner' ); ?></a><span class="count">(<?php echo $issues_count; ?>)</span></li> |
1436
- <li class="all"><a <?php if ( $view == 'ignored' ) echo "class='current'"; ?> href='?page=media-cleaner&s=<?php echo $s; ?>&view=ignored'><?php _e( "Ignored", 'media-cleaner' ); ?></a><span class="count">(<?php echo $ignored_count; ?>)</span></li> |
1437
- <li class="all"><a <?php if ( $view == 'deleted' ) echo "class='current'"; ?> href='?page=media-cleaner&s=<?php echo $s; ?>&view=deleted'><?php _e( "Trash", 'media-cleaner' ); ?></a><span class="count">(<?php echo $deleted_count; ?>)</span></li>
1438
- </ul>
1439
-
1440
- <table id='wpmc-table' class='wp-list-table widefat fixed media'>
1441
-
1442
- <thead>
1443
- <tr>
1444
- <th scope="col" id="cb" class="manage-column column-cb check-column"><input id="wpmc-cb-select-all" type="checkbox"></th>
1445
- <?php if ( !get_option( 'wpmc_hide_thumbnails', false ) ): ?>
1446
- <th style='width: 64px;'><?php _e( 'Thumb', 'media-cleaner' ) ?></th>
1447
- <?php endif; ?>
1448
- <th style='width: 50px;'><?php _e( 'Type', 'media-cleaner' ) ?></th>
1449
- <th style='width: 80px;'><?php _e( 'Origin', 'media-cleaner' ) ?></th>
1450
-
1451
- <?php if ( !empty( $wplr ) ): ?>
1452
- <th style='width: 70px;'><?php _e( 'LR ID', 'media-cleaner' ) ?></th>
1453
- <?php endif; ?>
1454
-
1455
- <th><?php _e( 'Path', 'media-cleaner' ) ?></th>
1456
- <th style='width: 220px;'><?php _e( 'Issue', 'media-cleaner' ) ?></th>
1457
- <th style='width: 80px; text-align: right;'><?php _e( 'Size', 'media-cleaner' ) ?></th>
1458
- </tr>
1459
- </thead>
1460
-
1461
- <tbody>
1462
- <?php
1463
- foreach ( $items as $issue ) {
1464
- $regex = "^(.*)(\\s\\(\\+.*)$";
1465
- $issue->path = preg_replace( '/' .$regex . '/i', '$1', $issue->path );
1466
- ?>
1467
- <tr>
1468
- <td><input type="checkbox" name="id" value="<?php echo $issue->id ?>"></td>
1469
- <?php if ( !get_option( 'wpmc_hide_thumbnails', false ) ): ?>
1470
- <td>
1471
- <?php
1472
- if ( $issue->deleted == 0 ) {
1473
- if ( $issue ->type == 0 ) {
1474
- // FILE
1475
- $upload_dir = wp_upload_dir();
1476
- $url = htmlspecialchars( $upload_dir['baseurl'] . '/' . $issue->path, ENT_QUOTES );
1477
- echo "<a target='_blank' href='" . $url .
1478
- "'><img style='max-width: 48px; max-height: 48px;' src='" . $url . "' /></a>";
1479
- }
1480
- else {
1481
- // MEDIA
1482
- $file = get_attached_file( $issue->postId );
1483
- if ( file_exists( $file ) ) {
1484
- $attachmentsrc = wp_get_attachment_image_src( $issue->postId, 'thumbnail' );
1485
- if ( empty( $attachmentsrc ) )
1486
- echo '<span class="dashicons dashicons-no-alt"></span>';
1487
- else {
1488
- $attachmentsrc_clean = htmlspecialchars( $attachmentsrc[0], ENT_QUOTES );
1489
- echo "<a target='_blank' href='" . $attachmentsrc_clean .
1490
- "'><img style='max-width: 48px; max-height: 48px;' src='" .
1491
- $attachmentsrc_clean . "' />";
1492
- }
1493
- }
1494
- else {
1495
- echo '<span class="dashicons dashicons-no-alt"></span>';
1496
- }
1497
- }
1498
- }
1499
- if ( $issue->deleted == 1 ) {
1500
- $upload_dir = wp_upload_dir();
1501
- $url = htmlspecialchars( $upload_dir['baseurl'] . '/wpmc-trash/' . $issue->path, ENT_QUOTES );
1502
- echo "<a target='_blank' href='" . $url .
1503
- "'><img style='max-width: 48px; max-height: 48px;' src='" . $url . "' /></a>";
1504
- }
1505
- ?>
1506
- </td>
1507
- <?php endif; ?>
1508
- <td><?php echo $issue->type == 0 ? 'FILE' : 'MEDIA'; ?></td>
1509
- <td><?php echo $issue->type == 0 ? 'Filesystem' : ("<a href='post.php?post=" .
1510
- $issue->postId . "&action=edit'>ID " . $issue->postId . "</a>"); ?></td>
1511
- <?php if ( !empty( $wplr ) ) { $info = $wplr->get_sync_info( $issue->postId ); ?>
1512
- <td style='width: 70px;'><?php echo ( !empty( $info ) && $info->lr_id ? $info->lr_id : "" ); ?></td>
1513
- <?php } ?>
1514
- <td><?php echo stripslashes( $issue->path ); ?></td>
1515
- <td><?php $this->echo_issue( $issue->issue ); ?></td>
1516
- <td style='text-align: right;'><?php echo number_format( $issue->size / 1000, 2 ); ?> KB</td>
1517
- </tr>
1518
- <?php } ?>
1519
- </tbody>
1520
-
1521
- <tfoot>
1522
- <tr><th></th>
1523
- <?php if ( !get_option( 'hide_thumbnails', false ) ): ?>
1524
- <th></th>
1525
- <?php endif; ?>
1526
- <th><?php _e( 'Type', 'media-cleaner' ) ?></th><th><?php _e( 'Origin', 'media-cleaner' ) ?></th>
1527
- <?php if ( !empty( $wplr ) ): ?>
1528
- <th style='width: 70px;'><?php _e( 'LR ID', 'media-cleaner' ) ?></th>
1529
- <?php endif; ?>
1530
- <th><?php _e( 'Path', 'media-cleaner' ) ?></th><th><?php _e( 'Issue', 'media-cleaner' ) ?></th><th style='width: 80px; text-align: right;'><?php _e( 'Size', 'media-cleaner' ) ?></th></tr>
1531
- </tfoot>
1532
-
1533
- </table>
1534
- </wrap>
1535
-
1536
- <?php
1537
- }
1538
-
1539
- function admin_menu() {
1540
- //load_plugin_textdomain( 'media-cleaner', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
1541
- add_media_page( 'Media Cleaner', 'Cleaner', 'manage_options', 'media-cleaner', array( $this, 'wpmc_screen' ) );
1542
- }
1543
-
1544
- function wp_enqueue_scripts () {
1545
- wp_enqueue_style( 'media-cleaner-css', plugins_url( '/media-cleaner.css', __FILE__ ) );
1546
- wp_enqueue_script( 'media-cleaner', plugins_url( '/media-cleaner.js', __FILE__ ), array( 'jquery' ), "3.7.0", true );
1547
- }
1548
  }
1549
 
1550
 
@@ -1552,9 +805,11 @@ class Meow_WPMC_Core {
1552
  INSTALL / UNINSTALL
1553
  */
1554
 
1555
- register_activation_hook( __FILE__, 'wpmc_reset' );
1556
- register_deactivation_hook( __FILE__, 'wpmc_uninstall' );
1557
- register_uninstall_hook( __FILE__, 'wpmc_uninstall' );
 
 
1558
 
1559
  function wpmc_reset () {
1560
  wpmc_uninstall();
@@ -1592,8 +847,8 @@ function wpmc_install() {
1592
  $sql = "CREATE TABLE $table_name (
1593
  id BIGINT(20) NOT NULL AUTO_INCREMENT,
1594
  mediaId BIGINT(20) NULL,
1595
- mediaUrl VARCHAR(256) NULL,
1596
- originType VARCHAR(32) NOT NULL,
1597
  PRIMARY KEY (id)
1598
  ) " . $charset_collate . ";";
1599
  require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
12
 
13
  public function __construct( $admin ) {
14
  $this->admin = $admin;
15
+ if ( is_admin() )
16
+ $this->admin_init();
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
  function admin_init() {
26
  $this->checkers = new Meow_WPMC_Checkers( $this );
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  function deepsleep( $seconds ) {
30
  $start_time = time();
31
  while( true ) {
44
  private $items_checked = 0;
45
  private $items_count = 0;
46
 
47
+ function get_max_execution_time() {
48
+ if ( isset( $this->max_execution_time ) )
49
+ return $this->max_execution_time;
50
+
51
+ $this->max_execution_time = ini_get( "max_execution_time" );
52
+ if ( empty( $this->max_execution_time ) || $this->max_execution_time < 5 )
53
+ $this->max_execution_time = 30;
54
+
55
+ return $this->max_execution_time;
56
+ }
57
+
58
  function timeout_check_start( $count ) {
59
  $this->start_time = time();
60
  $this->items_count = $count;
61
+ $this->get_max_execution_time();
 
 
62
  }
63
 
64
  function timeout_check() {
83
  $this->item_scan_avg_time = ceil( ( $this->time_elapsed / $this->items_checked ) * 10 ) / 10;
84
  }
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  function array_to_ids_or_urls( &$meta, &$ids, &$urls ) {
87
  foreach ( $meta as $k => $m ) {
88
  if ( is_numeric( $m ) ) {
177
  preg_match_all( "/((https?:\/\/)?[^\\&\#\[\] \"\?]+\.pdf)/", $html, $res );
178
  if ( !empty( $res ) && isset( $res[1] ) && count( $res[1] ) > 0 ) {
179
  foreach ( $res[1] as $url ) {
180
+ //error_log(print_r($url, 1));
181
  array_push( $results, $this->wpmc_clean_url( $url ) );
182
  }
183
  }
251
  return true;
252
  }
253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  /**
255
  *
256
  * HELPERS
379
  function wpmc_ignore( $id ) {
380
  global $wpdb;
381
  $table_name = $wpdb->prefix . "mclean_scan";
382
+ $issue = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE id = %d", $id ), OBJECT );
383
+ if ( (int) $issue->ignored )
384
  $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET ignored = 0 WHERE id = %d", $id ) );
385
+ else {
386
+ if ( (int) $issue->deleted ) // If it is in trash, recover it
387
+ $this->wpmc_recover( $id );
388
  $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET ignored = 1 WHERE id = %d", $id ) );
389
+ }
390
  return true;
391
  }
392
 
431
  if ( $issue->deleted == 0 ) {
432
  // Move file to the trash
433
  if ( $this->wpmc_trash_file( $issue->path ) )
434
+ $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET deleted = 1, ignored = 0 WHERE id = %d", $id ) );
435
  return true;
436
  }
437
  else {
481
  }
482
  }
483
  wp_delete_attachment( $issue->postId, false );
484
+ $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET deleted = 1, ignored = 0 WHERE id = %d", $id ) );
485
  return true;
486
  }
487
  else {
781
  delete_transient( "wpmc_galleries_images_urls" );
782
  }
783
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784
  function echo_issue( $issue ) {
785
  if ( $issue == 'NO_CONTENT' ) {
786
  _e( "Seems not in use.", 'media-cleaner' );
798
  echo $issue;
799
  }
800
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
801
  }
802
 
803
 
805
  INSTALL / UNINSTALL
806
  */
807
 
808
+ function wpmc_init( $mainfile ) {
809
+ register_activation_hook( $mainfile, 'wpmc_reset' );
810
+ register_deactivation_hook( $mainfile, 'wpmc_uninstall' );
811
+ register_uninstall_hook( $mainfile, 'wpmc_uninstall' );
812
+ }
813
 
814
  function wpmc_reset () {
815
  wpmc_uninstall();
847
  $sql = "CREATE TABLE $table_name (
848
  id BIGINT(20) NOT NULL AUTO_INCREMENT,
849
  mediaId BIGINT(20) NULL,
850
+ mediaUrl VARBINARY(256) NULL,
851
+ originType VARBINARY(32) NOT NULL,
852
  PRIMARY KEY (id)
853
  ) " . $charset_collate . ";";
854
  require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
media-cleaner.css CHANGED
@@ -70,3 +70,16 @@
70
  text-shadow: 0 -1px 0 rgba(0,0,0,0.1) !important;
71
  cursor: default;
72
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  text-shadow: 0 -1px 0 rgba(0,0,0,0.1) !important;
71
  cursor: default;
72
  }
73
+
74
+ /**
75
+ * Dialog
76
+ */
77
+ #wpmc-dialog {
78
+ text-align: center;
79
+ }
80
+ #wpmc-dialog .prompt {
81
+ margin-top: 16px;
82
+ }
83
+ #wpmc-dialog .prompt .button + .button {
84
+ margin-left: 16px;
85
+ }
media-cleaner.js CHANGED
@@ -88,9 +88,14 @@ function wpmc_delete() {
88
  wpmc_delete_do(items, items.length);
89
  }
90
 
91
- function wpmc_delete_all(isTrash) {
92
  var items = [];
93
- var data = { action: 'wpmc_get_all_issues', isTrash: isTrash ? 1 : 0 };
 
 
 
 
 
94
  jQuery.post(ajaxurl, data, function (response) {
95
  reply = jQuery.parseJSON(response);
96
  if ( !reply.success ) {
@@ -154,15 +159,122 @@ function wpmc_ignore_do(items, totalcount) {
154
  *
155
  */
156
 
157
- var wpmc = {
158
- dirs: [],
159
- files: [],
160
- medias: [],
161
- total: 0,
162
- issues: 0,
163
- isPause: false,
164
- isPendingPause: false
165
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
  // WPMC GET INITIAL INFO
168
 
@@ -174,28 +286,58 @@ function wpmc_scan_type_next(type, path) {
174
 
175
  }
176
 
177
- function wpmc_prepare(limit = 0) {
178
- var data = { action: 'wpmc_prepare_do', limit: limit };
 
 
 
 
179
  setTimeout(
180
  function() {
181
- jQuery('#wpmc_progression').html('<span class="dashicons dashicons-portfolio"></span> Preparing posts (' + limit + ' posts)...');
182
- jQuery.post(ajaxurl, data, function (response) {
183
- reply = jQuery.parseJSON(response);
184
- if ( !reply.success ) {
185
- alert( reply.message );
186
- return;
187
- }
188
- if (!reply.finished)
189
- return wpmc_prepare(reply.limit);
190
- else
191
- return wpmc_scan_start();
192
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  }, wpmc_cfg.delay
194
  );
195
  }
196
 
197
  function wpmc_scan_type(type, path = null, limit = 0) {
198
- var data = { action: 'wpmc_scan', medias: type === 'medias', files: type === 'files', path: path, limit: limit };
 
 
 
 
199
  if (path) {
200
  elpath = path.replace(/^.*[\\\/]/, '');
201
  jQuery('#wpmc_progression').html('<span class="dashicons dashicons-portfolio"></span> Preparing files (' + elpath + ')...');
@@ -207,12 +349,26 @@ function wpmc_scan_type(type, path = null, limit = 0) {
207
 
208
  setTimeout(
209
  function() {
210
- jQuery.post(ajaxurl, data, function (response) {
211
- reply = jQuery.parseJSON(response);
212
- if ( !reply.success ) {
213
- alert( reply.message );
214
- return;
215
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
  // Store results
218
  for (var i = 0, len = reply.results.length; i < len; i++) {
@@ -233,28 +389,37 @@ function wpmc_scan_type(type, path = null, limit = 0) {
233
 
234
  // Next query
235
  if (type === 'medias') {
236
- if (wpmc_cfg.scanFiles || !reply.finished)
237
- return wpmc_scan_type('medias', null, reply.limit);
 
 
238
  else
239
- return wpmc_scan_do();
240
  }
241
  else if (type === 'files') {
242
  var dir = wpmc.dirs.pop();
243
- if (dir)
244
- return wpmc_scan_type('files', dir);
 
 
245
  else
246
- return wpmc_scan_do();
247
  }
 
 
 
 
248
  });
 
249
  }, wpmc_cfg.delay
250
  );
251
  }
252
 
253
  function wpmc_pause() {
254
- if (wpmc.isPause) {
255
  jQuery('#wpmc_pause').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-pause"></span>Pause');
256
  wpmc.isPause = false;
257
- wpmc_scan_do();
258
  }
259
  else if (wpmc.isPendingPause) {
260
  wpmc.isPendingPause = false;
@@ -265,36 +430,61 @@ function wpmc_pause() {
265
  }
266
  }
267
 
268
- function wpmc_scan() {
269
- if (!wpmc.isPause)
270
- wpmc_prepare();
271
- else
272
- wpmc_scan_start();
273
- }
274
-
275
- function wpmc_scan_start() {
276
- wpmc = { dirs: [], files: [], medias: [], total: 0, issues: 0, isPause: false, isPendingPause: false };
277
- jQuery('#wpmc_pause').hide();
278
- jQuery('#wpmc_pause').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-pause"></span>Pause');
279
- if (wpmc_cfg.scanMedia)
280
- wpmc_scan_type('medias', null);
281
- else if (wpmc_cfg.scanFiles)
282
- wpmc_scan_type('files', null);
283
- }
284
-
285
  function wpmc_update_to_pause() {
286
  if (wpmc.isPendingPause) {
287
- var current = wpmc.total - (wpmc.files.length + wpmc.medias.length);
288
- var totalcount = wpmc.total;
289
- jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at ' + current + "/" + totalcount + " (" + Math.round(current / totalcount * 100) + "%)");
290
  jQuery('#wpmc_pause').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-play"></span>Continue');
291
  wpmc.isPendingPause = false;
292
  wpmc.isPause = true;
293
- return;
294
  }
295
  }
296
 
297
- function wpmc_update_to_error(error) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  var current = wpmc.total - (wpmc.files.length + wpmc.medias.length);
299
  var totalcount = wpmc.total;
300
  jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Error at ' + current + "/" + totalcount + " (" + Math.round(current / totalcount * 100) + "%): " + error);
@@ -304,79 +494,272 @@ function wpmc_update_to_error(error) {
304
  }
305
 
306
  function wpmc_scan_do() {
 
 
307
  if (wpmc.isPendingPause)
308
  return wpmc_update_to_pause();
309
- else
310
- jQuery('#wpmc_pause').show();
311
- var newFiles = null;
312
- var newMedias = null;
313
  wpmc_update_progress(wpmc.total - (wpmc.files.length + wpmc.medias.length), wpmc.total);
314
  var data = {};
315
  var expectedSuccess = 0;
316
  if (wpmc.files.length > 0) {
317
- newFiles = wpmc_pop_array(wpmc.files, wpmc_cfg.analysisBuffer);
318
- expectedSuccess = newFiles.length;
319
- data = { action: 'wpmc_scan_do', type: 'file', data: newFiles };
320
  }
321
  else if (wpmc.medias.length > 0) {
322
- newMedias = wpmc_pop_array(wpmc.medias, wpmc_cfg.analysisBuffer);
323
- expectedSuccess = newMedias.length;
324
- data = { action: 'wpmc_scan_do', type: 'media', data: newMedias };
325
  }
326
  else {
327
  jQuery('#wpmc_progression').html(wpmc.issues + " issue(s) found. <a href='?page=media-cleaner'></span>Refresh</a>.");
 
 
 
 
 
328
  return;
329
  }
330
 
331
  setTimeout(
332
  function () {
333
  jQuery.ajax({
334
- type: "POST",
335
  url: ajaxurl,
 
336
  data: data,
337
- success: function (response) {
338
- try {
339
- reply = jQuery.parseJSON(response);
340
- }
341
- catch (e) {
342
- reply = null;
343
- }
344
- if (!reply) {
345
- reply = { success: false, message: "The reply from the server is broken. The reply will be displayed in your Javascript console. You should also check your PHP Error Logs." };
346
- console.debug( "Media File Cleaner got this reply from the server: " + response);
347
- }
348
- if (!reply.success) {
349
- wpmc_update_to_error(reply.message);
350
- console.debug("Media Cleaner got an error from server.", reply.message);
351
- }
352
- if (reply.result) {
353
- wpmc.issues += expectedSuccess - reply.result.success;
354
- }
355
- wpmc_scan_do();
356
- },
357
- error: function(request, status, err) {
358
- if (newFiles) {
359
- while (newFiles.length > 0)
360
- wpmc.files.push(newFiles.pop());
361
- }
362
- if (newMedias) {
363
- while (newMedias.length > 0)
364
- wpmc.medias.push(newMedias.pop());
365
- }
366
- wpmc_update_to_error(err);
367
- console.debug("Media Cleaner got an error from server.", status, err);
368
- }
369
  });
 
370
  }, wpmc_cfg.delay
371
  );
372
  }
373
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  /**
375
  *
376
  * INIT
377
  *
378
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
379
 
380
- jQuery('#wpmc-cb-select-all').on('change', function (cb) {
381
- jQuery('#wpmc-table input').prop('checked', cb.target.checked);
382
- });
88
  wpmc_delete_do(items, items.length);
89
  }
90
 
91
+ function wpmc_delete_all(isTrash, filter = '') {
92
  var items = [];
93
+ var data = {
94
+ action: 'wpmc_get_all_issues',
95
+ isTrash: isTrash ? 1 : 0,
96
+ s: filter
97
+ };
98
+
99
  jQuery.post(ajaxurl, data, function (response) {
100
  reply = jQuery.parseJSON(response);
101
  if ( !reply.success ) {
159
  *
160
  */
161
 
162
+ var wpmc = wpmc_new_context();
163
+
164
+ /**
165
+ * Creates a context object that preserves various states and variables for scanning
166
+ * @return {object}
167
+ */
168
+ function wpmc_new_context() {
169
+ return {
170
+ dirs: [],
171
+ files: [],
172
+ medias: [],
173
+ current: 0,
174
+ total: 0,
175
+ issues: 0,
176
+ isPause: false,
177
+ isPendingPause: false,
178
+ currentPhase: null,
179
+
180
+ phases: {
181
+ preparePosts: {
182
+ init: function () {
183
+ this.progress = 0; // Scanned posts count
184
+ this.progressPrev = 0;
185
+ return this;
186
+ },
187
+ run: function () {
188
+ wpmc_prepare();
189
+ },
190
+ pause: function () {
191
+ jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at preparing posts (' + this.progress + ' posts)');
192
+ },
193
+ skip: function () {
194
+ this.progress += wpmc_cfg.postsBuffer;
195
+ },
196
+ nextPhase: function () {
197
+ if (wpmc_cfg.scanMedia)
198
+ return wpmc.phases.prepareMedia;
199
+ if (wpmc_cfg.scanFiles)
200
+ return wpmc.phases.prepareFiles;
201
+ console.error('Configuration Error'); // This shouldn't happen
202
+ }
203
+ },
204
+ prepareFiles: {
205
+ init: function () {
206
+ this.progress = null; // The last scanned directory
207
+ this.progressPrev = null;
208
+ return this;
209
+ },
210
+ run: function () {
211
+ wpmc_scan_type('files', this.progress);
212
+ },
213
+ pause: function () {
214
+ jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at preparing files (' + this.progress + ')');
215
+ },
216
+ skip: function () {
217
+ var dir = wpmc.dirs.pop();
218
+ if (dir) {
219
+ wpmc.currentPhase.progressPrev = wpmc.currentPhase.progress;
220
+ wpmc.currentPhase.progress = dir;
221
+ }
222
+ else
223
+ wpmc.currentPhase = this.nextPhase().init();
224
+ },
225
+ nextPhase: function () {
226
+ return wpmc.phases.analyze;
227
+ }
228
+ },
229
+ prepareMedia: {
230
+ init: function () {
231
+ this.progress = 0; // Scanned media count
232
+ this.progressPrev = 0;
233
+ return this;
234
+ },
235
+ run: function () {
236
+ wpmc_scan_type('medias', null, this.progress);
237
+ },
238
+ pause: function () {
239
+ jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at preparing media (' + this.progress + ' media)');
240
+ },
241
+ skip: function () {
242
+ this.progress += wpmc_cfg.mediasBuffer;
243
+ },
244
+ nextPhase: function () {
245
+ return wpmc.phases.analyze;
246
+ }
247
+ },
248
+ analyze: {
249
+ init: function () {
250
+ this.currentFiles = [];
251
+ this.currentMedia = [];
252
+ return this;
253
+ },
254
+ run: function () {
255
+ wpmc_scan_do();
256
+ },
257
+ pause: function () {
258
+ var current = wpmc.total - (wpmc.files.length + wpmc.medias.length);
259
+ var totalcount = wpmc.total;
260
+ jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at ' + current + "/" + totalcount + " (" + Math.round(current / totalcount * 100) + "%)");
261
+ },
262
+ skip: function () {
263
+ if (wpmc.files.length)
264
+ this.currentFiles = wpmc_pop_array(wpmc.files, wpmc_cfg.analysisBuffer);
265
+ if (wpmc.medias.lenght)
266
+ this.currentMedia = wpmc_pop_array(wpmc.medias, wpmc_cfg.analysisBuffer);
267
+ },
268
+ rollback: function () {
269
+ wpmc.files = wpmc.files.concat(this.currentFiles.reverse()); // @see wpmc_pop_array
270
+ this.currentFiles = [];
271
+ wpmc.medias = wpmc.medias.concat(this.currentMedia.reverse()); // @see wpmc_pop_array
272
+ this.currentMedia = [];
273
+ }
274
+ }
275
+ }
276
+ };
277
+ }
278
 
279
  // WPMC GET INITIAL INFO
280
 
286
 
287
  }
288
 
289
+ function wpmc_prepare() {
290
+ if (!wpmc.currentPhase) return; // Aborted
291
+
292
+ if (wpmc.isPendingPause)
293
+ return wpmc_update_to_pause();
294
+
295
  setTimeout(
296
  function() {
297
+ if (!wpmc.currentPhase) return; // Aborted
298
+
299
+ jQuery('#wpmc_progression').html('<span class="dashicons dashicons-portfolio"></span> Preparing posts (' + wpmc.currentPhase.progress + ' posts)...');
300
+
301
+ jQuery.ajax({
302
+ type: 'POST',
303
+ url: ajaxurl,
304
+ dataType: 'text',
305
+ data: {
306
+ action: 'wpmc_prepare_do',
307
+ limit: wpmc.currentPhase.progress
308
+ },
309
+ timeout: wpmc_cfg.timeout + 5000 // Extra 5sec for fail-safe
310
+
311
+ }).done(function (response) {
312
+ if (!wpmc.currentPhase) return; // Aborted
313
+
314
+ var reply = wpmc_parse_response(response);
315
+
316
+ if (!reply.success)
317
+ return wpmc_handle_error(reply.message);
318
+
319
+ if (!reply.finished) {
320
+ wpmc.currentPhase.progressPrev = wpmc.currentPhase.progress;
321
+ wpmc.currentPhase.progress = reply.limit;
322
+ }
323
+ else wpmc.currentPhase = wpmc.currentPhase.nextPhase().init();
324
+
325
+ return wpmc.currentPhase.run();
326
+
327
+ }).fail(function (e) { // Server Error
328
+ wpmc_handle_error(e.statusText, e.status);
329
+ });
330
+
331
  }, wpmc_cfg.delay
332
  );
333
  }
334
 
335
  function wpmc_scan_type(type, path = null, limit = 0) {
336
+ if (!wpmc.currentPhase) return; // Aborted
337
+
338
+ if (wpmc.isPendingPause)
339
+ return wpmc_update_to_pause();
340
+
341
  if (path) {
342
  elpath = path.replace(/^.*[\\\/]/, '');
343
  jQuery('#wpmc_progression').html('<span class="dashicons dashicons-portfolio"></span> Preparing files (' + elpath + ')...');
349
 
350
  setTimeout(
351
  function() {
352
+ jQuery.ajax({
353
+ type: 'POST',
354
+ url: ajaxurl,
355
+ dataType: 'text',
356
+ data: {
357
+ action: 'wpmc_scan',
358
+ medias: type === 'medias',
359
+ files: type === 'files',
360
+ path: path,
361
+ limit: limit
362
+ },
363
+ timeout: wpmc_cfg.timeout + 5000 // Extra 5sec for fail-safe
364
+
365
+ }).done(function (response) {
366
+ if (!wpmc.currentPhase) return; // Aborted
367
+
368
+ var reply = wpmc_parse_response(response);
369
+
370
+ if (!reply.success)
371
+ return wpmc_handle_error(reply.message);
372
 
373
  // Store results
374
  for (var i = 0, len = reply.results.length; i < len; i++) {
389
 
390
  // Next query
391
  if (type === 'medias') {
392
+ if (wpmc_cfg.scanFiles || !reply.finished) {
393
+ wpmc.currentPhase.progressPrev = wpmc.currentPhase.progress;
394
+ wpmc.currentPhase.progress = reply.limit;
395
+ }
396
  else
397
+ wpmc.currentPhase = wpmc.currentPhase.nextPhase().init();
398
  }
399
  else if (type === 'files') {
400
  var dir = wpmc.dirs.pop();
401
+ if (dir) {
402
+ wpmc.currentPhase.progressPrev = wpmc.currentPhase.progress;
403
+ wpmc.currentPhase.progress = dir;
404
+ }
405
  else
406
+ wpmc.currentPhase = wpmc.currentPhase.nextPhase().init();
407
  }
408
+ wpmc.currentPhase.run();
409
+
410
+ }).fail(function (e) { // Server Error
411
+ wpmc_handle_error(e.statusText, e.status);
412
  });
413
+
414
  }, wpmc_cfg.delay
415
  );
416
  }
417
 
418
  function wpmc_pause() {
419
+ if (wpmc.isPause) { // Resume
420
  jQuery('#wpmc_pause').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-pause"></span>Pause');
421
  wpmc.isPause = false;
422
+ wpmc.currentPhase.run();
423
  }
424
  else if (wpmc.isPendingPause) {
425
  wpmc.isPendingPause = false;
430
  }
431
  }
432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
  function wpmc_update_to_pause() {
434
  if (wpmc.isPendingPause) {
435
+ wpmc.currentPhase.pause();
436
+
 
437
  jQuery('#wpmc_pause').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-play"></span>Continue');
438
  wpmc.isPendingPause = false;
439
  wpmc.isPause = true;
 
440
  }
441
  }
442
 
443
+ /**
444
+ * Parses a Ajax response into a valid JSON
445
+ * @param {string} response The response content to parse
446
+ * @return {object} The parsed result
447
+ */
448
+ function wpmc_parse_response(response) {
449
+ if (typeof response == 'object') return response;
450
+
451
+ var r;
452
+ try {
453
+ r = jQuery.parseJSON(response);
454
+ } catch (e) {
455
+ r = null;
456
+ }
457
+ if (!r) { // Couldn't parse as a valid JSON
458
+ r = {
459
+ success: false,
460
+ message: 'The reply from the server is broken. The reply will be displayed in your Javascript console. You should also check your PHP Error Logs.'
461
+ };
462
+ console.error('Media File Cleaner got a broken reply from the server:', response);
463
+ }
464
+ return r;
465
+ }
466
+
467
+ /**
468
+ * Pauses the scan and Displays an error dialog
469
+ * @param {string} msg=null The error message
470
+ * @param {int} status=null The actual status code that the server responded
471
+ */
472
+ function wpmc_handle_error(msg = null, status = null) {
473
+ wpmc.isPendingPause = true;
474
+ wpmc_update_to_pause();
475
+
476
+ var errDialog = jQuery('#wpmc-error-dialog');
477
+ if (!msg) msg = 'An error happened'; // Default error message
478
+ if (status) {
479
+ console.error('Media Cleaner got an error from server:', status + ' ' + msg);
480
+ msg = '<span class="error-status">' + status + '</span> ' + msg;
481
+ } else
482
+ console.error(msg);
483
+ errDialog.find('h3').html(msg);
484
+ errDialog.dialog('open');
485
+ }
486
+
487
+ function wpmc_update_to_error() {
488
  var current = wpmc.total - (wpmc.files.length + wpmc.medias.length);
489
  var totalcount = wpmc.total;
490
  jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Error at ' + current + "/" + totalcount + " (" + Math.round(current / totalcount * 100) + "%): " + error);
494
  }
495
 
496
  function wpmc_scan_do() {
497
+ if (!wpmc.currentPhase) return; // Aborted
498
+
499
  if (wpmc.isPendingPause)
500
  return wpmc_update_to_pause();
501
+
 
 
 
502
  wpmc_update_progress(wpmc.total - (wpmc.files.length + wpmc.medias.length), wpmc.total);
503
  var data = {};
504
  var expectedSuccess = 0;
505
  if (wpmc.files.length > 0) {
506
+ wpmc.currentPhase.currentFiles = wpmc_pop_array(wpmc.files, wpmc_cfg.analysisBuffer);
507
+ expectedSuccess = wpmc.currentPhase.currentFiles.length;
508
+ data = { action: 'wpmc_scan_do', type: 'file', data: wpmc.currentPhase.currentFiles };
509
  }
510
  else if (wpmc.medias.length > 0) {
511
+ wpmc.currentPhase.currentMedia = wpmc_pop_array(wpmc.medias, wpmc_cfg.analysisBuffer);
512
+ expectedSuccess = wpmc.currentPhase.currentMedia.length;
513
+ data = { action: 'wpmc_scan_do', type: 'media', data: wpmc.currentPhase.currentMedia };
514
  }
515
  else {
516
  jQuery('#wpmc_progression').html(wpmc.issues + " issue(s) found. <a href='?page=media-cleaner'></span>Refresh</a>.");
517
+
518
+ wpmc = wpmc_new_context(); // Reset the context
519
+ jQuery('#wpmc_pause').hide();
520
+ jQuery('#wpmc_scan').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-search"></span>Start Scan');
521
+ jQuery('#wpmc_actions').trigger('idle');
522
  return;
523
  }
524
 
525
  setTimeout(
526
  function () {
527
  jQuery.ajax({
528
+ type: 'POST',
529
  url: ajaxurl,
530
+ dataType: 'text',
531
  data: data,
532
+ timeout: wpmc_cfg.timeout + 5000 // Extra 5sec for fail-safe
533
+
534
+ }).done(function (response) {
535
+ var reply = wpmc_parse_response(response);
536
+
537
+ if (!reply.success)
538
+ return wpmc_handle_error(reply.message);
539
+
540
+ if (reply.result)
541
+ wpmc.issues += expectedSuccess - reply.result.success;
542
+
543
+ wpmc_scan_do();
544
+
545
+ }).fail(function (e) { // Server Error
546
+ wpmc_handle_error(e.statusText, e.status);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  });
548
+
549
  }, wpmc_cfg.delay
550
  );
551
  }
552
 
553
+ /**
554
+ * Opens a dialog
555
+ * @param {object} content
556
+ * @param {string} content.title=null The title of the dialog
557
+ * @param {string} content.head=null The heading
558
+ * @param {string} content.body=null The body
559
+ * @param {jQuery} content.prepend=null Additional element to prepend
560
+ * @param {jQuery} content.append=null Additional element to append
561
+ * @return {jQuery} The dialog element
562
+ */
563
+ function wpmc_open_dialog(content) {
564
+ var dialog = jQuery('#wpmc-dialog');
565
+ dialog.html('');
566
+ if (content.title)
567
+ dialog.dialog('option', 'title', content.title);
568
+ if (content.head)
569
+ dialog.append('<h3 class="head">' + content.head + '</h3>');
570
+ if (content.body)
571
+ dialog.append('<div class="body">' + content.body + '</div>');
572
+ if (content.prepend)
573
+ dialog.prepend(content.prepend);
574
+ if (content.append)
575
+ dialog.append(content.append);
576
+ dialog.dialog('open');
577
+ return dialog;
578
+ }
579
+
580
  /**
581
  *
582
  * INIT
583
  *
584
  */
585
+ (function ($) {
586
+
587
+ // Bulk Selection
588
+ $('#wpmc-cb-select-all').on('change', function (cb) {
589
+ $('#wpmc-table input').prop('checked', cb.target.checked);
590
+ });
591
+
592
+ // Actions
593
+ (function () {
594
+ var wrap = $('#wpmc_actions');
595
+
596
+ // Events: Busy, Idle
597
+ wrap.on('busy', function () {
598
+ wrap.addClass('busy');
599
+ wrap.find('a.exclusive').addClass('disabled');
600
+ wrap.find('input.exclusive').attr('disabled', true);
601
+
602
+ }).on('idle', function () {
603
+ wrap.find('a.exclusive').removeClass('disabled');
604
+ wrap.find('input.exclusive').attr('disabled', false);
605
+ wrap.removeClass('busy');
606
+ });
607
+
608
+ // Scan Button
609
+ wrap.find('#wpmc_scan').on('click', function (ev) {
610
+ ev.preventDefault();
611
+ if (wpmc.currentPhase) { // Abort scan
612
+ wpmc = wpmc_new_context(); // Reset the current context
613
+ $('#wpmc_pause').hide();
614
+ $('#wpmc_pause').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-pause"></span>Pause');
615
+ $('#wpmc_progression').text('');
616
+ $('#wpmc_scan').html('<span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-search"></span>Start Scan');
617
+ wrap.trigger('idle');
618
+ return;
619
+ }
620
+ wrap.trigger('busy');
621
+ $('#wpmc_scan').html('Stop Scan');
622
+ $('#wpmc_pause').show();
623
+ wpmc.currentPhase = wpmc.phases.preparePosts.init();
624
+ wpmc.currentPhase.run();
625
+ });
626
+
627
+ // Delete Button
628
+ wrap.find('#wpmc_delete').on('click', function (ev) {
629
+ ev.preventDefault();
630
+ if ($(this).hasClass('disabled')) return;
631
+ wpmc_delete();
632
+ });
633
+
634
+ // Delete All (Search Results) Button
635
+ wrap.find('#wpmc_delete_all').on('click', function (ev) {
636
+ ev.preventDefault();
637
+ var $this = $(this);
638
+ if ($this.hasClass('disabled')) return;
639
+ var filter = $this.data('filter') || '';
640
+ if (filter && filter != wrap.find('.search-box input[name="s"]').val()) {
641
+ var dialog = wpmc_open_dialog({
642
+ title: 'Continue?',
643
+ body: 'You have modified the search terms and did not click on "Search".<br>The <b>current</b> results will be deleted. Do you want to continue?',
644
+ append: $('<div class="prompt">')
645
+ .append(
646
+ // Cancel Button
647
+ $('<a class="button cancel" href="#">Cancel</a>').on('click', function (ev) {
648
+ ev.preventDefault();
649
+ dialog.dialog('close');
650
+ })
651
+ ).append(
652
+ // Continue Button
653
+ $('<a class="button button-primary continue" href="#">Continue</a>').on('click', function (ev) {
654
+ ev.preventDefault();
655
+ dialog.dialog('close');
656
+ wpmc_delete_all(false, filter);
657
+ })
658
+ )
659
+ });
660
+ return;
661
+ }
662
+ wpmc_delete_all(false, filter);
663
+ });
664
+
665
+ // Ignore Button
666
+ wrap.find('#wpmc_ignore').on('click', function (ev) {
667
+ ev.preventDefault();
668
+ if ($(this).hasClass('disabled')) return;
669
+ wpmc_ignore();
670
+ });
671
+
672
+ // Recover All Button
673
+ wrap.find('#wpmc_recover_all').on('click', function (ev) {
674
+ ev.preventDefault();
675
+ if ($(this).hasClass('disabled')) return;
676
+ wpmc_recover_all();
677
+ });
678
+
679
+ // Empty Trash Button
680
+ wrap.find('#wpmc_empty_trash').on('click', function (ev) {
681
+ ev.preventDefault();
682
+ if ($(this).hasClass('disabled')) return;
683
+ wpmc_delete_all(true);
684
+ });
685
+ })();
686
+
687
+ // Dialog
688
+ (function () {
689
+ var dialog = $('#wpmc-dialog');
690
+
691
+ dialog.dialog({
692
+ dialogClass: 'wp-dialog',
693
+ autoOpen: false,
694
+ draggable: true,
695
+ width: 'auto',
696
+ modal: true,
697
+ resizable: false,
698
+ closeOnEscape: true,
699
+ position: {
700
+ my: "center",
701
+ at: "center",
702
+ of: window
703
+ },
704
+ open: function () {
705
+ // Close dialog by clicking the overlay behind it
706
+ $('.ui-widget-overlay').on('click', function () {
707
+ dialog.dialog('close');
708
+ });
709
+ },
710
+ create: function () {
711
+ // Style fix for WordPress admin
712
+ $('.ui-dialog-titlebar-close').addClass('ui-button');
713
+ }
714
+ });
715
+ })();
716
+
717
+ // Error Dialog
718
+ (function () {
719
+ var errDialog = $('#wpmc-error-dialog');
720
+
721
+ errDialog.dialog({
722
+ title: 'ERROR',
723
+ dialogClass: 'wp-dialog',
724
+ autoOpen: false,
725
+ draggable: true,
726
+ width: 'auto',
727
+ modal: true,
728
+ resizable: false,
729
+ closeOnEscape: true,
730
+ position: {
731
+ my: "center",
732
+ at: "center",
733
+ of: window
734
+ },
735
+ open: function () {
736
+ $('.ui-widget-overlay').on('click', function () {
737
+ errDialog.dialog('close');
738
+ });
739
+ },
740
+ create: function () {
741
+ $('.ui-dialog-titlebar-close').addClass('ui-button');
742
+ }
743
+ });
744
+
745
+ // Retry
746
+ errDialog.find('a.retry').on('click', function (ev) {
747
+ ev.preventDefault();
748
+
749
+ wpmc_pause(); // Resume
750
+ errDialog.dialog('close');
751
+ });
752
+
753
+ // Skip (Ignore error)
754
+ errDialog.find('a.skip').on('click', function (ev) {
755
+ ev.preventDefault();
756
+
757
+ wpmc.currentPhase.skip();
758
+ console.warn('1 error is ignored by you');
759
+
760
+ wpmc_pause(); // Resume
761
+ errDialog.dialog('close');
762
+ });
763
+ })();
764
 
765
+ })(jQuery);
 
 
media-cleaner.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Media Cleaner
4
  Plugin URI: https://meowapps.com
5
  Description: Clean your Media Library, many options, trash system.
6
- Version: 4.8.0
7
  Author: Jordy Meow
8
  Author URI: https://meowapps.com
9
  Text Domain: media-cleaner
@@ -24,7 +24,7 @@ if ( class_exists( 'Meow_WPMC_Core' ) ) {
24
  if ( is_admin() ) {
25
 
26
  global $wpmc_version;
27
- $wpmc_version = '4.8.0';
28
 
29
  // Admin
30
  require __DIR__ . '/admin.php';
@@ -35,6 +35,10 @@ if ( is_admin() ) {
35
  $wpmc_core = new Meow_WPMC_Core( $wpmc_admin );
36
  $wpmc_admin->core = $wpmc_core;
37
 
 
 
 
 
38
  /*******************************************************************************
39
  * TODO: OLD PRO, THIS FUNCTION SHOULD BE REMOVED IN THE FUTURE
40
  ******************************************************************************/
3
  Plugin Name: Media Cleaner
4
  Plugin URI: https://meowapps.com
5
  Description: Clean your Media Library, many options, trash system.
6
+ Version: 4.8.4
7
  Author: Jordy Meow
8
  Author URI: https://meowapps.com
9
  Text Domain: media-cleaner
24
  if ( is_admin() ) {
25
 
26
  global $wpmc_version;
27
+ $wpmc_version = '4.8.4';
28
 
29
  // Admin
30
  require __DIR__ . '/admin.php';
35
  $wpmc_core = new Meow_WPMC_Core( $wpmc_admin );
36
  $wpmc_admin->core = $wpmc_core;
37
 
38
+ // UI
39
+ require __DIR__ . '/ui.php';
40
+ new Meow_WPMC_UI( $wpmc_core, $wpmc_admin );
41
+
42
  /*******************************************************************************
43
  * TODO: OLD PRO, THIS FUNCTION SHOULD BE REMOVED IN THE FUTURE
44
  ******************************************************************************/
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: TigrouMeow, amekusa
3
  Tags: clean, delete, file, files, images, image, media, library, upload, clean, acf
4
  Requires at least: 4.2
5
  Tested up to: 4.9.4
6
- Stable tag: 4.8.0
7
 
8
  Clean your WordPress (broken media, unused media, files). It has its own trash and recovery features. Please read the description.
9
 
@@ -42,17 +42,22 @@ The official FAQ is [here](https://meowapps.com/wplr-sync/faq/).
42
 
43
  == Changelog ==
44
 
 
 
 
 
 
 
 
45
  = 4.8.0 =
46
  * Update: Many parts of the UI were rewritten for a better experience. Buttons have a nicer logic.
47
  * Add: Enhanced error control. From now, when an error occurs during the scan, a popup will appear (asking to try again, or to skip the current item), and errors will be logged to the console.
48
- * Info: Please help this plugin survive by giving me a nice review, here: https://wordpress.org/support/plugin/meow-lightbox/reviews/?rate=5#new-post. Thank you :)
49
 
50
  = 4.6.3 =
51
  * Add: Added an option to only scan the thumbnails and ignore the base files.
52
  * Add: ACF Repeater support.
53
  * Update: Improved the code and the performance. Scan is now done differently, using the DB.
54
  * Fix: Debug logs weren't logging (and enhanced them a bit).
55
- * Notice: That's a big release :) Please help me by giving me a nice review, here: https://wordpress.org/support/plugin/meow-lightbox/reviews/?rate=5#new-post.
56
 
57
  = 4.5.5 =
58
  * Fix: Doesn't remove the Media entry if the files cannot be deleted.
3
  Tags: clean, delete, file, files, images, image, media, library, upload, clean, acf
4
  Requires at least: 4.2
5
  Tested up to: 4.9.4
6
+ Stable tag: 4.8.4
7
 
8
  Clean your WordPress (broken media, unused media, files). It has its own trash and recovery features. Please read the description.
9
 
42
 
43
  == Changelog ==
44
 
45
+ = 4.8.4 =
46
+ * Fix: Issue with ACF Repeater.
47
+ * Fix: Trash and Ignore features resulted in a weird behavior when used together.
48
+ * Add: Now can delete the results of a search.
49
+ * Update: Many UI improvements.
50
+ * Info: Please help this plugin survive by giving me a nice review, here: https://wordpress.org/support/plugin/meow-lightbox/reviews/?rate=5#new-post. Thank you :)
51
+
52
  = 4.8.0 =
53
  * Update: Many parts of the UI were rewritten for a better experience. Buttons have a nicer logic.
54
  * Add: Enhanced error control. From now, when an error occurs during the scan, a popup will appear (asking to try again, or to skip the current item), and errors will be logged to the console.
 
55
 
56
  = 4.6.3 =
57
  * Add: Added an option to only scan the thumbnails and ignore the base files.
58
  * Add: ACF Repeater support.
59
  * Update: Improved the code and the performance. Scan is now done differently, using the DB.
60
  * Fix: Debug logs weren't logging (and enhanced them a bit).
 
61
 
62
  = 4.5.5 =
63
  * Fix: Doesn't remove the Media entry if the files cannot be deleted.
scan.php CHANGED
@@ -110,58 +110,89 @@ class MeowApps_WPMC_Scan {
110
  }
111
 
112
  public function scan_postmeta_acf( $id ) {
113
- $postmeta_images_acf_ids = array();
114
- $postmeta_images_acf_urls = array();
115
  $fields = get_field_objects( $id );
116
  if ( is_array( $fields ) ) {
117
- foreach ( $fields as $field ) {
118
- $format = "";
119
- if ( isset( $field['return_format'] ) )
120
- $format = $field['return_format'];
121
- else if ( isset( $field['save_format'] ) )
122
- $format = $field['save_format'];
123
-
124
- // ACF Repeater
125
- if ( $field['type'] == 'repeater' ) {
126
- if ( !empty( $field['value'] ) ) {
127
- foreach ( $field['value'] as $subfields ) {
128
- foreach ( $subfields as $subfield ) {
129
- if ( $subfield['type'] == 'image' ) {
130
- if ( !empty( $subfield['id'] ) )
131
- array_push( $postmeta_images_acf_ids, $subfield['id'] );
132
- if ( !empty( $subfield['url'] ) )
133
- array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $subfield['url'] ) );
134
- }
135
- }
136
- }
137
- }
138
- }
139
- // ACF Image ID and URL
140
- else if ( $field['type'] == 'image' && ( $format == 'array' || $format == 'object' ) ) {
141
- if ( !empty( $field['value']['id'] ) )
142
- array_push( $postmeta_images_acf_ids, $field['value']['id'] );
143
- if ( !empty( $field['value']['url'] ) )
144
- array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $field['value']['url'] ) );
145
- }
146
- // ACF Image ID
147
- else if ( $field['type'] == 'image' && $format == 'id' && !empty( $field['value'] ) ) {
148
- array_push( $postmeta_images_acf_ids, $field['value'] );
149
- }
150
- // ACF Image URL
151
- else if ( $field['type'] == 'image' && $format == 'url' && !empty( $field['value'] ) ) {
152
- array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $field['value'] ) );
153
- }
154
- // ACF Gallery
155
- else if ( $field['type'] == 'gallery' && !empty( $field['value'] ) ) {
156
- foreach ( $field['value'] as $media ) {
157
- if ( !empty( $media['id'] ) )
158
- array_push( $postmeta_images_acf_ids, $media['id'] );
159
  }
 
160
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
- $this->core->add_reference_id( $postmeta_images_acf_ids, 'ACF (ID)' );
163
- $this->core->add_reference_url( $postmeta_images_acf_urls, 'ACF (URL)' );
164
  }
 
 
165
  }
166
-
167
  }
110
  }
111
 
112
  public function scan_postmeta_acf( $id ) {
 
 
113
  $fields = get_field_objects( $id );
114
  if ( is_array( $fields ) ) {
115
+ foreach ( $fields as $field )
116
+ $this->scan_postmeta_acf_field( $field, $id, 8 );
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Scans a single ACF field object.
122
+ * If the specified field is a repeater or a flexible content,
123
+ * scans each subfield recursively.
124
+ *
125
+ * @param array $field
126
+ * An associative array replesenting a single ACF field.
127
+ * The actual array must be structured like this:
128
+ * array (
129
+ * 'name' => The name of the field
130
+ * 'type' => The field type i.e. 'text', 'object', 'repeater'
131
+ * 'value' => The value
132
+ * ...
133
+ * )
134
+ * @param int $id The post ID
135
+ * @param int $recursion_limit The max recursion depth. Negative number means unlimited
136
+ *
137
+ * @since ACF 5.6.10
138
+ */
139
+ public function scan_postmeta_acf_field( $field, $id, $recursion_limit = -1 ) {
140
+ if ( !isset( $field['type'] ) ) return;
141
+
142
+ /** Multiple Fields (Repeater or Flexible Content) **/
143
+ static $recursives = array ( // Possibly Recursive Types
144
+ 'repeater',
145
+ 'flexible_content'
146
+ );
147
+ if ( in_array( $field['type'], $recursives ) && have_rows( $field['name'], $id ) ) {
148
+ if ( $recursion_limit == 0 ) return; // Too much recursion
149
+ do { // Iterate over rows
150
+ $row = the_row( true );
151
+ foreach ( $row as $col => $value ) { // Iterate over columns (subfields)
152
+ $subfield = get_sub_field_object( $col, true, true );
153
+ if ( !is_array( $subfield ) ) continue;
154
+ if ( WP_DEBUG ) { // XXX Debug
155
+ if ( !isset( $subfield['value'] ) ) trigger_error( 'Unexpected Situation: $subfield[value] is not set', E_USER_ERROR );
156
+ if ( $subfield['value'] != $value ) trigger_error( 'Unexpected Situation: $subfield[value] has unexpected value', E_USER_ERROR );
157
  }
158
+ $this->scan_postmeta_acf_field( $subfield, $id, $recursion_limit - 1 ); // Recursion
159
  }
160
+ } while ( have_rows( $field['name'], $id ) );
161
+ return;
162
+ }
163
+ /** Singular Field **/
164
+ $postmeta_images_acf_ids = array();
165
+ $postmeta_images_acf_urls = array();
166
+
167
+ $format = "";
168
+ if ( isset( $field['return_format'] ) )
169
+ $format = $field['return_format'];
170
+ else if ( isset( $field['save_format'] ) )
171
+ $format = $field['save_format'];
172
+
173
+ // ACF Image ID and URL
174
+ if ( $field['type'] == 'image' && ( $format == 'array' || $format == 'object' ) ) {
175
+ if ( !empty( $field['value']['id'] ) )
176
+ array_push( $postmeta_images_acf_ids, $field['value']['id'] );
177
+ if ( !empty( $field['value']['url'] ) )
178
+ array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $field['value']['url'] ) );
179
+ }
180
+ // ACF Image ID
181
+ else if ( $field['type'] == 'image' && $format == 'id' && !empty( $field['value'] ) ) {
182
+ array_push( $postmeta_images_acf_ids, $field['value'] );
183
+ }
184
+ // ACF Image URL
185
+ else if ( $field['type'] == 'image' && $format == 'url' && !empty( $field['value'] ) ) {
186
+ array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $field['value'] ) );
187
+ }
188
+ // ACF Gallery
189
+ else if ( $field['type'] == 'gallery' && !empty( $field['value'] ) ) {
190
+ foreach ( $field['value'] as $media ) {
191
+ if ( !empty( $media['id'] ) )
192
+ array_push( $postmeta_images_acf_ids, $media['id'] );
193
  }
 
 
194
  }
195
+ $this->core->add_reference_id( $postmeta_images_acf_ids, 'ACF (ID)' );
196
+ $this->core->add_reference_url( $postmeta_images_acf_urls, 'ACF (URL)' );
197
  }
 
198
  }
ui.php ADDED
@@ -0,0 +1,470 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Meow_WPMC_UI {
4
+ private $core = null;
5
+ private $admin = null;
6
+
7
+ function __construct( $core, $admin ) {
8
+ $this->core = $core;
9
+ $this->admin = $admin;
10
+ add_action( 'admin_menu', array( $this, 'admin_menu' ) );
11
+ add_action( 'admin_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
12
+ add_action( 'admin_print_scripts', array( $this, 'admin_inline_js' ) );
13
+ add_action( 'add_meta_boxes', array( $this, 'add_metabox' ) );
14
+ add_action( 'wp_ajax_wpmc_prepare_do', array( $this, 'wp_ajax_wpmc_prepare_do' ) );
15
+ add_action( 'wp_ajax_wpmc_scan', array( $this, 'wp_ajax_wpmc_scan' ) );
16
+ add_action( 'wp_ajax_wpmc_scan_do', array( $this, 'wp_ajax_wpmc_scan_do' ) );
17
+ add_action( 'wp_ajax_wpmc_get_all_issues', array( $this, 'wp_ajax_wpmc_get_all_issues' ) );
18
+ add_action( 'wp_ajax_wpmc_get_all_deleted', array( $this, 'wp_ajax_wpmc_get_all_deleted' ) );
19
+ add_action( 'wp_ajax_wpmc_delete_do', array( $this, 'wp_ajax_wpmc_delete_do' ) );
20
+ add_action( 'wp_ajax_wpmc_ignore_do', array( $this, 'wp_ajax_wpmc_ignore_do' ) );
21
+ add_action( 'wp_ajax_wpmc_recover_do', array( $this, 'wp_ajax_wpmc_recover_do' ) );
22
+ add_filter( 'media_row_actions', array( $this, 'media_row_actions' ), 10, 2 );
23
+ }
24
+
25
+ /**
26
+ * Renders a view within the views directory.
27
+ * @param string $view The name of the view to render
28
+ * @param array $data
29
+ * An associative array of variables to bind to the view.
30
+ * Each key turns into a variable name.
31
+ * @return string Rendered view
32
+ */
33
+ function render_view( $view, $data = null ) {
34
+ ob_start();
35
+ if ( is_array( $data ) ) extract( $data );
36
+ include( __DIR__ . "/views/$view.php" );
37
+ return ob_get_clean();
38
+ }
39
+
40
+ function admin_menu() {
41
+ //load_plugin_textdomain( 'media-cleaner', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
42
+ add_media_page( 'Media Cleaner', 'Cleaner', 'manage_options', 'media-cleaner', array( $this, 'wpmc_screen' ) );
43
+ }
44
+
45
+ function wpmc_screen() {
46
+ global $wpdb, $wplr;
47
+ echo $this->render_view( 'menu-screen', array(
48
+ 'wpdb' => $wpdb,
49
+ 'wplr' => $wplr,
50
+ 'ui' => $this,
51
+ 'core' => $this->core,
52
+ 'admin' => $this->admin
53
+ ) );
54
+ }
55
+
56
+ function wp_enqueue_scripts() {
57
+ wp_enqueue_style( 'wp-jquery-ui-dialog' );
58
+ wp_enqueue_script( 'jquery-ui-dialog' );
59
+ wp_enqueue_style( 'media-cleaner-css', plugins_url( '/media-cleaner.css', __FILE__ ) );
60
+ wp_enqueue_script( 'media-cleaner', plugins_url( '/media-cleaner.js', __FILE__ ), array( 'jquery', 'jquery-ui-dialog' ), "3.7.0", true );
61
+ }
62
+
63
+ /**
64
+ *
65
+ * DASHBOARD
66
+ *
67
+ */
68
+
69
+ function admin_inline_js() {
70
+ echo "<script type='text/javascript'>\n";
71
+ echo 'var wpmc_cfg = {
72
+ timeout: ' . ( (int) $this->core->get_max_execution_time() ) * 1000 . ',
73
+ delay: ' . get_option( 'wpmc_delay', 100 ) . ',
74
+ postsBuffer:' . get_option( 'wpmc_posts_buffer', 5 ) . ',
75
+ mediasBuffer:' . get_option( 'wpmc_medias_buffer', 100 ) . ',
76
+ analysisBuffer: ' . get_option( 'wpmc_analysis_buffer', 50 ) . ',
77
+ isPro: ' . ( $this->admin->is_registered() ? '1' : '0') . ',
78
+ scanFiles: ' . ( ( get_option( 'wpmc_method', 'media' ) == 'files' && $this->admin->is_registered() ) ? '1' : '0' ) . ',
79
+ scanMedia: ' . ( get_option( 'wpmc_method', 'media' ) == 'media' ? '1' : '0' ) . ' };';
80
+ echo "\n</script>";
81
+ }
82
+
83
+ /*******************************************************************************
84
+ * METABOX FOR USAGE
85
+ ******************************************************************************/
86
+
87
+ function add_metabox() {
88
+ add_meta_box( 'mfrh_media_usage_box', 'Media Cleaner', array( $this, 'display_metabox' ), 'attachment', 'side', 'default' );
89
+ }
90
+
91
+ function display_metabox( $post ) {
92
+ $this->core->log( "Media Edit > Checking Media #{$post->ID}" );
93
+ $success = $this->core->wpmc_check_media( $post->ID, true );
94
+ $this->core->log( "Success $success\n" );
95
+ if ( $success ) {
96
+ if ( $this->core->last_analysis == "CONTENT" ) {
97
+ echo "Found in content.";
98
+ }
99
+ else if ( $this->core->last_analysis == "CONTENT (ID)" ) {
100
+ echo "Found in content (as an ID).";
101
+ }
102
+ else if ( $this->core->last_analysis == "CONTENT (URL)" ) {
103
+ echo "Found in content (as an URL).";
104
+ }
105
+ else if ( $this->core->last_analysis == "THEME" ) {
106
+ echo "Found in theme.";
107
+ }
108
+ else if ( $this->core->last_analysis == "PAGE BUILDER" ) {
109
+ echo "Found in Page Builder.";
110
+ }
111
+ else if ( $this->core->last_analysis == "GALLERY" ) {
112
+ echo "Found in gallery.";
113
+ }
114
+ else if ( $this->core->last_analysis == "META" ) {
115
+ echo "Found in meta.";
116
+ }
117
+ else if ( $this->core->last_analysis == "META (ID)" ) {
118
+ echo "Found in meta (as an ID).";
119
+ }
120
+ else if ( $this->core->last_analysis == "META (URL)" ) {
121
+ echo "Found in meta (as an URL).";
122
+ }
123
+ else if ( $this->core->last_analysis == "META ACF (ID)" ) {
124
+ echo "Found in ACF meta (as an ID).";
125
+ }
126
+ else if ( $this->core->last_analysis == "META ACF (URL)" ) {
127
+ echo "Found in ACF meta (as an URL).";
128
+ }
129
+ else if ( $this->core->last_analysis == "WIDGET" ) {
130
+ echo "Found in widget.";
131
+ }
132
+ else {
133
+ echo "It seems to be used as: " . $this->core->last_analysis;
134
+ }
135
+ }
136
+ else {
137
+ echo "Doesn't seem to be used.";
138
+ }
139
+ }
140
+
141
+ function media_row_actions( $actions, $post ) {
142
+ global $current_screen;
143
+ if ( 'upload' != $current_screen->id )
144
+ return $actions;
145
+ global $wpdb;
146
+ $table_name = $wpdb->prefix . "mclean_scan";
147
+ $res = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table_name WHERE postId = %d", $post->ID ) );
148
+ if ( !empty( $res ) && isset( $actions['delete'] ) )
149
+ $actions['delete'] = "<a href='?page=media-cleaner&view=deleted'>" .
150
+ __( 'Delete with Media Cleaner', 'media-cleaner' ) . "</a>";
151
+ if ( !empty( $res ) && isset( $actions['trash'] ) )
152
+ $actions['trash'] = "<a href='?page=media-cleaner'>" .
153
+ __( 'Trash with Media Cleaner', 'media-cleaner' ) . "</a>";
154
+ if ( !empty( $res ) && isset( $actions['untrash'] ) ) {
155
+ $actions['untrash'] = "<a href='?page=media-cleaner&view=deleted'>" .
156
+ __( 'Restore with Media Cleaner', 'media-cleaner' ) . "</a>";
157
+ }
158
+ return $actions;
159
+ }
160
+
161
+ /*******************************************************************************
162
+ * ASYNCHRONOUS AJAX FUNCTIONS
163
+ ******************************************************************************/
164
+
165
+ function wp_ajax_wpmc_prepare_do() {
166
+ $limit = isset( $_POST['limit'] ) ? $_POST['limit'] : 0;
167
+ $limitsize = get_option( 'wpmc_posts_buffer', 5 );
168
+ if ( empty( $limit ) )
169
+ $this->core->wpmc_reset_issues();
170
+
171
+ $method = get_option( 'wpmc_method', 'media' );
172
+ $check_library = get_option(' wpmc_media_library', true );
173
+ $check_postmeta = get_option( 'wpmc_postmeta', false );
174
+ $check_posts = get_option( 'wpmc_posts', false );
175
+ $check_widgets = get_option( 'wpmc_widgets', false );
176
+ if ( $method == 'media' && !$check_posts && !$check_postmeta && !$check_widgets ) {
177
+ echo json_encode( array(
178
+ 'results' => array(),
179
+ 'success' => true,
180
+ 'finished' => true,
181
+ 'message' => __( "Posts, Meta and Widgets analysis are all off. Done.", 'media-cleaner' )
182
+ ) );
183
+ die();
184
+ }
185
+ if ( $method == 'files' && $check_library && !$check_posts && !$check_postmeta && !$check_widgets ) {
186
+ echo json_encode( array(
187
+ 'results' => array(),
188
+ 'success' => true,
189
+ 'finished' => true,
190
+ 'message' => __( "Posts, Meta and Widgets analysis are all off. Done.", 'media-cleaner' )
191
+ ) );
192
+ die();
193
+ }
194
+
195
+ global $wpdb;
196
+ // Maybe we could avoid to check more post_types.
197
+ // SELECT post_type, COUNT(*) FROM `wp_posts` GROUP BY post_type
198
+ $posts = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p
199
+ WHERE p.post_status != 'inherit'
200
+ AND p.post_status != 'trash'
201
+ AND p.post_type != 'attachment'
202
+ AND p.post_type != 'shop_order'
203
+ AND p.post_type != 'shop_order_refund'
204
+ AND p.post_type != 'nav_menu_item'
205
+ AND p.post_type != 'revision'
206
+ AND p.post_type != 'auto-draft'
207
+ AND p.post_type != 'wphb_minify_group'
208
+ AND p.post_type != 'customize_changeset'
209
+ AND p.post_type != 'oembed_cache'
210
+ AND p.post_type NOT LIKE '%acf-%'
211
+ AND p.post_type NOT LIKE '%edd_%'
212
+ LIMIT %d, %d", $limit, $limitsize
213
+ )
214
+ );
215
+
216
+ $found = array();
217
+
218
+ // Only at the beginning
219
+ if ( empty( $limit ) ) {
220
+
221
+ $this->core->log( "Analyzing for references:" );
222
+
223
+ $theme_ids = array();
224
+ $theme_urls = array();
225
+ $this->core->get_images_from_themes( $theme_ids, $theme_urls );
226
+ $this->core->add_reference_id( $theme_ids, 'THEME' );
227
+ $this->core->add_reference_url( $theme_urls, 'THEME' );
228
+
229
+ // Only on Start: Analyze Widgets
230
+ if ( get_option( 'wpmc_widgets', false ) ) {
231
+ $widgets_ids = array();
232
+ $widgets_urls = array();
233
+ $this->core->get_images_from_widgets( $widgets_ids, $widgets_urls );
234
+ $this->core->add_reference_id( $widgets_ids, 'WIDGET' );
235
+ $this->core->add_reference_url( $widgets_urls, 'WIDGET' );
236
+ }
237
+
238
+ // Only on Start: Analyze WooCommerce Categories Images
239
+ if ( class_exists( 'WooCommerce' ) ) {
240
+ $metas = $wpdb->get_col( "SELECT meta_value
241
+ FROM $wpdb->termmeta
242
+ WHERE meta_key LIKE '%thumbnail_id%'"
243
+ );
244
+ if ( count( $metas ) > 0 ) {
245
+ $postmeta_images_ids = array();
246
+ foreach ( $metas as $meta )
247
+ if ( is_numeric( $meta ) && $meta > 0 )
248
+ array_push( $postmeta_images_ids, $meta );
249
+ $this->core->add_reference_id( $postmeta_images_ids, 'META (ID)' );
250
+ }
251
+ }
252
+ }
253
+
254
+ $this->core->timeout_check_start( count( $posts ) );
255
+
256
+ foreach ( $posts as $post ) {
257
+ $this->core->timeout_check();
258
+ // Run the scanners
259
+ if ( $check_postmeta )
260
+ do_action( 'wpmc_scan_postmeta', $post );
261
+ if ( $check_posts ) {
262
+ // Get HTML for this post
263
+ $html = get_post_field( 'post_content', $post );
264
+ // Scan on the raw TML content
265
+ do_action( 'wpmc_scan_post', $html, $post );
266
+ $html = do_shortcode( $html );
267
+ $html = wp_make_content_images_responsive( $html );
268
+ // Scan with shortcodes resolved and src-set
269
+ do_action( 'wpmc_scan_post', $html, $post );
270
+ }
271
+ $this->core->timeout_check_additem();
272
+ }
273
+ // Write the references cached by the scanners
274
+ $this->core->write_references();
275
+
276
+ $finished = count( $posts ) < $limitsize;
277
+ if ( $finished ) {
278
+ $found = array();
279
+ // Optimize DB (but that takes too long!)
280
+ //$table_name = $wpdb->prefix . "mclean_refs";
281
+ // $wpdb->query ("DELETE a FROM $table_name as a, $table_name as b
282
+ // WHERE (a.mediaId = b.mediaId OR a.mediaId IS NULL AND b.mediaId IS NULL)
283
+ // AND (a.mediaUrl = b.mediaUrl OR a.mediaUrl IS NULL AND b.mediaUrl IS NULL)
284
+ // AND (a.originType = b.originType OR a.originType IS NULL AND b.originType IS NULL)
285
+ // AND (a.origin = b.origin OR a.origin IS NULL AND b.origin IS NULL)
286
+ // AND a.ID < b.ID;" );
287
+ // $wpdb->query ("DELETE a FROM $table_name as a, $table_name as b WHERE a.mediaId = b.mediaId AND a.mediaId > 0 AND a.ID < b.ID;" );
288
+ // $wpdb->query ("DELETE a FROM $table_name as a, $table_name as b WHERE a.mediaUrl = b.mediaUrl AND LENGTH(a.mediaUrl) > 1 AND a.ID < b.ID;" );
289
+ }
290
+ if ( $finished && get_option( 'wpmc_debuglogs', false ) ) {
291
+ //$this->core->log( print_r( $found, true ) );
292
+ }
293
+ echo json_encode(
294
+ array(
295
+ 'success' => true,
296
+ 'finished' => $finished,
297
+ 'limit' => $limit + $limitsize,
298
+ 'message' => __( "Posts checked.", 'media-cleaner' ) )
299
+ );
300
+ die();
301
+ }
302
+
303
+ function wp_ajax_wpmc_scan() {
304
+ global $wpdb;
305
+
306
+ $method = get_option( 'wpmc_method', 'media' );
307
+ if ( !$this->admin->is_registered() )
308
+ $method = 'media';
309
+ $path = isset( $_POST['path'] ) ? $_POST['path'] : null;
310
+ $limit = isset( $_POST['limit'] ) ? $_POST['limit'] : 0;
311
+ $limitsize = get_option( 'wpmc_medias_buffer', 100 );
312
+
313
+ if ( $method == 'files' ) {
314
+ $output = apply_filters( 'wpmc_list_uploaded_files', array(
315
+ 'results' => array(), 'success' => false, 'message' => __( "Unavailable.", 'media-cleaner' )
316
+ ), $path );
317
+ echo json_encode( $output );
318
+ die();
319
+ }
320
+
321
+ if ( $method == 'media' ) {
322
+ // Prevent double scanning by removing filesystem entries that we have DB entries for
323
+ $results = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p
324
+ WHERE p.post_status = 'inherit'
325
+ AND p.post_type = 'attachment'
326
+ LIMIT %d, %d", $limit, $limitsize
327
+ )
328
+ );
329
+ $finished = count( $results ) < $limitsize;
330
+ echo json_encode(
331
+ array(
332
+ 'results' => $results,
333
+ 'success' => true,
334
+ 'finished' => $finished,
335
+ 'limit' => $limit + $limitsize,
336
+ 'message' => __( "Medias retrieved.", 'media-cleaner' ) )
337
+ );
338
+ die();
339
+ }
340
+
341
+ // No task.
342
+ echo json_encode( array( 'success' => false, 'message' => __( "No task.", 'media-cleaner' ) ) );
343
+ die();
344
+ }
345
+
346
+ function wp_ajax_wpmc_scan_do() {
347
+ // For debug, to pretend there is a timeout
348
+ //$this->core->deepsleep(10);
349
+ //header("HTTP/1.0 408 Request Timeout");
350
+ //exit;
351
+
352
+ ob_start();
353
+ $type = $_POST['type'];
354
+ $data = $_POST['data'];
355
+ $this->core->timeout_check_start( count( $data ) );
356
+ $success = 0;
357
+ foreach ( $data as $piece ) {
358
+ $this->core->timeout_check();
359
+ if ( $type == 'file' ) {
360
+ $this->core->log( "Check File: {$piece}" );
361
+ $result = ( apply_filters( 'wpmc_check_file', true, $piece ) ? 1 : 0 );
362
+ $this->core->log( "Success " . $result . "\n" );
363
+ $success += $result;
364
+ }
365
+ else if ( $type == 'media' ) {
366
+ $this->core->log( "Checking Media #{$piece}" );
367
+ $result = ( $this->core->wpmc_check_media( $piece ) ? 1 : 0 );
368
+ $this->core->log( "Success " . $result . "\n" );
369
+ $success += $result;
370
+ }
371
+ $this->core->timeout_check_additem();
372
+ }
373
+ ob_end_clean();
374
+ echo json_encode(
375
+ array(
376
+ 'success' => true,
377
+ 'result' => array( 'type' => $type, 'data' => $data, 'success' => $success ),
378
+ 'message' => __( "Items checked.", 'media-cleaner' )
379
+ )
380
+ );
381
+ die();
382
+ }
383
+
384
+ function wp_ajax_wpmc_get_all_issues() {
385
+ global $wpdb;
386
+ $isTrash = ( isset( $_POST['isTrash'] ) && $_POST['isTrash'] == 1 ) ? true : false;
387
+ $table_name = $wpdb->prefix . "mclean_scan";
388
+ $q = "SELECT id FROM $table_name WHERE ignored = 0 AND deleted = " . ( $isTrash ? 1 : 0 );
389
+ if ( $search = ( isset( $_POST['s'] ) && $_POST['s'] ) ? sanitize_text_field( $_POST['s'] ) : '' )
390
+ $q = $wpdb->prepare( $q . ' AND path LIKE %s', '%' . $wpdb->esc_like( $search ) . '%' );
391
+ $ids = $wpdb->get_col( $q );
392
+
393
+ echo json_encode(
394
+ array(
395
+ 'results' => array( 'ids' => $ids ),
396
+ 'success' => true,
397
+ 'message' => __( "List generated.", 'media-cleaner' )
398
+ )
399
+ );
400
+ die;
401
+ }
402
+
403
+ function wp_ajax_wpmc_get_all_deleted() {
404
+ global $wpdb;
405
+ $table_name = $wpdb->prefix . "mclean_scan";
406
+ $ids = $wpdb->get_col( "SELECT id FROM $table_name WHERE ignored = 0 AND deleted = 1" );
407
+ echo json_encode(
408
+ array(
409
+ 'results' => array( 'ids' => $ids ),
410
+ 'success' => true,
411
+ 'message' => __( "List generated.", 'media-cleaner' )
412
+ )
413
+ );
414
+ die;
415
+ }
416
+
417
+ function wp_ajax_wpmc_delete_do() {
418
+ ob_start();
419
+ $data = $_POST['data'];
420
+ $success = 0;
421
+ foreach ( $data as $piece ) {
422
+ $success += ( $this->core->wpmc_delete( $piece ) ? 1 : 0 );
423
+ }
424
+ ob_end_clean();
425
+ echo json_encode(
426
+ array(
427
+ 'success' => true,
428
+ 'result' => array( 'data' => $data, 'success' => $success ),
429
+ 'message' => __( "Status unknown.", 'media-cleaner' )
430
+ )
431
+ );
432
+ die();
433
+ }
434
+
435
+ function wp_ajax_wpmc_ignore_do() {
436
+ ob_start();
437
+ $data = $_POST['data'];
438
+ $success = 0;
439
+ foreach ( $data as $piece ) {
440
+ $success += ( $this->core->wpmc_ignore( $piece ) ? 1 : 0 );
441
+ }
442
+ ob_end_clean();
443
+ echo json_encode(
444
+ array(
445
+ 'success' => true,
446
+ 'result' => array( 'data' => $data, 'success' => $success ),
447
+ 'message' => __( "Status unknown.", 'media-cleaner' )
448
+ )
449
+ );
450
+ die();
451
+ }
452
+
453
+ function wp_ajax_wpmc_recover_do() {
454
+ ob_start();
455
+ $data = $_POST['data'];
456
+ $success = 0;
457
+ foreach ( $data as $piece ) {
458
+ $success += ( $this->core->wpmc_recover( $piece ) ? 1 : 0 );
459
+ }
460
+ ob_end_clean();
461
+ echo json_encode(
462
+ array(
463
+ 'success' => true,
464
+ 'result' => array( 'data' => $data, 'success' => $success ),
465
+ 'message' => __( "Status unknown.", 'media-cleaner' )
466
+ )
467
+ );
468
+ die();
469
+ }
470
+ }
views/menu-screen.php ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class='wrap'>
2
+
3
+ <?php
4
+ echo $admin->display_title( "Media Cleaner" );
5
+ $posts_per_page = get_option( 'wpmc_results_per_page', 20 );
6
+ $view = isset ( $_GET[ 'view' ] ) ? sanitize_text_field( $_GET[ 'view' ] ) : "issues";
7
+ $paged = isset ( $_GET[ 'paged' ] ) ? sanitize_text_field( $_GET[ 'paged' ] ) : 1;
8
+ $reset = isset ( $_GET[ 'reset' ] ) ? $_GET[ 'reset' ] : 0;
9
+ if ( $reset ) {
10
+ wpmc_reset();
11
+ $core->wpmc_reset_issues();
12
+ }
13
+ $s = isset ( $_GET[ 's' ] ) ? sanitize_text_field( $_GET[ 's' ] ) : null;
14
+ $table_name = $wpdb->prefix . "mclean_scan";
15
+ $issues_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE ignored = 0 AND deleted = 0" );
16
+ $total_size = $wpdb->get_var( "SELECT SUM(size) FROM $table_name WHERE ignored = 0 AND deleted = 0" );
17
+ $trash_total_size = $wpdb->get_var( "SELECT SUM(size) FROM $table_name WHERE ignored = 0 AND deleted = 1" );
18
+ $ignored_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE ignored = 1" );
19
+ $deleted_count = $wpdb->get_var( "SELECT COUNT(*) FROM $table_name WHERE deleted = 1" );
20
+
21
+ if ( $view == 'deleted' ) {
22
+ $items_count = $deleted_count;
23
+ $items = $wpdb->get_results( $wpdb->prepare( "SELECT id, type, postId, path, size, ignored, deleted, issue
24
+ FROM $table_name WHERE ignored = 0 AND deleted = 1 AND path LIKE %s
25
+ ORDER BY time
26
+ DESC LIMIT %d, %d", '%' . $s . '%', ( $paged - 1 ) * $posts_per_page, $posts_per_page ), OBJECT );
27
+ }
28
+ else if ( $view == 'ignored' ) {
29
+ $items_count = $ignored_count;
30
+ $items = $wpdb->get_results( $wpdb->prepare( "SELECT id, type, postId, path, size, ignored, deleted, issue
31
+ FROM $table_name
32
+ WHERE ignored = 1 AND deleted = 0 AND path LIKE %s
33
+ ORDER BY time
34
+ DESC LIMIT %d, %d", '%' . $s . '%', ( $paged - 1 ) * $posts_per_page, $posts_per_page ), OBJECT );
35
+ }
36
+ else {
37
+ $items_count = $issues_count;
38
+ $items = $wpdb->get_results( $wpdb->prepare( "SELECT id, type, postId, path, size, ignored, deleted, issue
39
+ FROM $table_name
40
+ WHERE ignored = 0 AND deleted = 0 AND path LIKE %s
41
+ ORDER BY time
42
+ DESC LIMIT %d, %d", '%' . $s . '%', ( $paged - 1 ) * $posts_per_page, $posts_per_page ), OBJECT );
43
+ }
44
+ ?>
45
+
46
+ <style>
47
+ #wpmc-pages {
48
+ float: right;
49
+ position: relative;
50
+ top: 12px;
51
+ }
52
+
53
+ #wpmc-pages a {
54
+ text-decoration: none;
55
+ border: 1px solid black;
56
+ padding: 2px 5px;
57
+ border-radius: 4px;
58
+ background: #E9E9E9;
59
+ color: lightslategrey;
60
+ border-color: #BEBEBE;
61
+ }
62
+
63
+ #wpmc-pages .current {
64
+ font-weight: bold;
65
+ }
66
+ </style>
67
+
68
+ <div id="wpmc_actions" style='margin-top: 0px; background: #FFF; padding: 5px; border-radius: 4px; height: 28px; box-shadow: 0px 0px 6px #C2C2C2;'>
69
+
70
+ <!-- SCAN -->
71
+ <?php if ( $view != 'deleted' ): ?>
72
+ <a id='wpmc_scan' class='button-primary' style='float: left;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-search"></span><?php _e("Start Scan", 'media-cleaner'); ?></a>
73
+ <?php endif; ?>
74
+
75
+ <!-- PAUSE -->
76
+ <?php if ( $view != 'deleted' ): ?>
77
+ <a id='wpmc_pause' onclick='wpmc_pause()' class='button' style='float: left; margin-left: 5px; display: none;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-pause"></span><?php _e("Pause", 'media-cleaner'); ?></a>
78
+ <?php endif; ?>
79
+
80
+ <!-- DELETE SELECTED -->
81
+ <a id='wpmc_delete' class='button exclusive' style='float: left; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-no"></span><?php _e("Delete", 'media-cleaner'); ?></a>
82
+ <?php if ( $view == 'deleted' ): ?>
83
+ <a id='wpmc_recover' onclick='wpmc_recover()' class='button-secondary' style='float: left; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-repeat"></span><?php _e( "Recover", 'media-cleaner' ); ?></a>
84
+ <?php endif; ?>
85
+
86
+ <!-- IGNORE SELECTED -->
87
+ <a id='wpmc_ignore' class='button exclusive' style='float: left; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-yes"></span><?php
88
+ if ( $view == 'ignored' )
89
+ _e( "Mark as Issue", 'media-cleaner' );
90
+ else
91
+ _e( "Ignore", 'media-cleaner' );
92
+ ?>
93
+ </a>
94
+
95
+ <!-- RESET -->
96
+ <?php if ( $view != 'deleted' ): ?>
97
+ <a id='wpmc_reset' href='?page=media-cleaner&reset=1' class='button-primary' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-sos"></span><?php _e("Reset", 'media-cleaner'); ?></a>
98
+ <?php endif; ?>
99
+
100
+ <!-- DELETE ALL -->
101
+ <?php if ( $view == 'deleted' ): // i ?>
102
+ <a id='wpmc_recover_all' class='button-primary exclusive' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-controls-repeat"></span><?php _e("Recover all", 'media-cleaner'); ?></a>
103
+ <a id='wpmc_empty_trash' class='button button-red exclusive' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-trash"></span><?php _e("Empty trash", 'media-cleaner'); ?></a>
104
+ <?php else: // i ?>
105
+ <?php if ( $s ): // ii ?>
106
+ <a id='wpmc_delete_all' class='button button-red exclusive' data-filter="<?php echo esc_attr( $s ); ?>" style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-trash"></span><?php _e("Delete all search results", 'media-cleaner'); ?></a>
107
+ <?php else: // ii ?>
108
+ <a id='wpmc_delete_all' class='button button-red exclusive' style='float: right; margin-left: 5px;'><span style="top: 3px; position: relative; left: -5px;" class="dashicons dashicons-trash"></span><?php _e("Delete all", 'media-cleaner'); ?></a>
109
+ <?php endif; // ii ?>
110
+ <?php endif; // i ?>
111
+
112
+ <form id="posts-filter" action="upload.php" method="get" style='float: right;'>
113
+ <p class="search-box" style='margin-left: 5px; float: left;'>
114
+ <input type="search" name="s" class="exclusive" style="width: 120px;" value="<?php echo $s ? esc_attr( $s ) : ""; ?>">
115
+ <input type="hidden" name="page" value="media-cleaner">
116
+ <input type="hidden" name="view" value="<?php echo $view; ?>">
117
+ <input type="hidden" name="paged" value="1">
118
+ <input type="submit" class="button exclusive" value="<?php _e( 'Search', 'media-cleaner' ) ?>"><span style='border-right: #A2A2A2 solid 1px; margin-left: 5px; margin-right: 3px;'>&nbsp;</span>
119
+ </p>
120
+ </form>
121
+
122
+ <!-- PROGRESS -->
123
+ <span style='margin-left: 12px; font-size: 15px; top: 5px; position: relative; color: #747474;' id='wpmc_progression'></span>
124
+
125
+ </div>
126
+
127
+ <p>
128
+ <?php
129
+
130
+ $table_scan = $wpdb->prefix . "mclean_scan";
131
+ $table_refs = $wpdb->prefix . "mclean_refs";
132
+ if ( $wpdb->get_var("SHOW TABLES LIKE '$table_scan'") != $table_scan ||
133
+ $wpdb->get_var("SHOW TABLES LIKE '$table_refs'") != $table_refs ) {
134
+ _e( "<div class='notice notice-error'><p><b>The database is not ready for Media Cleaner. The scan will not work.</b> Click on the <b>Reset</b> button, it re-creates the tables required by Media Cleaner. If this message still appear, contact the support.</p></div>", 'media-cleaner' );
135
+ }
136
+ else {
137
+ $method = get_option( 'wpmc_method', 'media' );
138
+ if ( !$admin->is_registered() )
139
+ $method = 'media';
140
+
141
+ $hide_warning = get_option( 'wpmc_hide_warning', false );
142
+
143
+ if ( !$hide_warning ) {
144
+ _e( "<div class='notice notice-warning'><p><b style='color: red;'>Important.</b> <b>Backup your DB and your /uploads directory before using Media Cleaner. </b> The deleted files will be temporarily moved to the <b>uploads/wpmc-trash</b> directory. After testing your website, you can check the <a href='?page=media-cleaner&s&view=deleted'>trash</a> to either empty it or recover the media and files. The Media Cleaner does its best to be safe to use. However, WordPress being a very dynamic and pluggable system, it is impossible to predict all the situations in which your files are used. <b style='color: red;'>Again, please backup!</b> If you don't know how, give a try to this: <a href='https://updraftplus.com/?afref=460' target='_blank'>UpdraftPlus</a>. <br /><br /><b style='color: red;'>Be thoughtful.</b> Don't blame Media Cleaner if it deleted too many or not enough of your files. It makes cleaning possible and this task is only possible this way; don't post a bad review because it broke your install. <b>If you have a proper backup, there is no risk</b>. Sorry for the lengthy message, but better be safe than sorry. You can disable this big warning in the options if you have a Pro license. Make sure you read this warning twice. Media Cleaner is awesome and always getting better so I hope you will enjoy it. Thank you :)</p></div>", 'media-cleaner' );
145
+ }
146
+
147
+ if ( !MEDIA_TRASH ) {
148
+ _e( "<div class='notice notice-warning'><p>The trash for the Media Library is disabled. Any media removed by the plugin will be <b>permanently deleted</b>. To enable it, modify your wp-config.php file and add this line (preferably at the top):<br /><b>define( 'MEDIA_TRASH', true );</b></p></div>", 'media-cleaner' );
149
+ }
150
+ }
151
+
152
+ if ( !$admin->is_registered() ) {
153
+ echo "<div class='notice notice-info'><p>";
154
+ _e( "<b>This version is not Pro.</b> This plugin is a lot of work so please consider <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a> in order to receive support and to contribute in the evolution of it. Also, <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a> version will also give you the option <b>to scan the physical files in your /uploads folder</b> and extra checks for the common Page Builders.", 'media-cleaner' );
155
+ echo "</p></div>";
156
+
157
+ if ( function_exists( '_et_core_find_latest' ) ) {
158
+ echo "<div class='notice notice-warning'><p>";
159
+ _e( "<b>Divi has been detected</b>. The free version might detect the files used by Divi correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
160
+ echo "</p></div>";
161
+ }
162
+
163
+ if ( class_exists( 'Vc_Manager' ) ) {
164
+ echo "<div class='notice notice-warning'><p>";
165
+ _e( "<b>Visual Composer has been detected</b>. The free version might detect the files used by Visual Composer correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
166
+ echo "</p></div>";
167
+ }
168
+
169
+ if ( function_exists( 'fusion_builder_map' ) ) {
170
+ echo "<div class='notice notice-warning'><p>";
171
+ _e( "<b>Fusion Builder has been detected</b>. The free version might detect the files used by Fusion Builder correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
172
+ echo "</p></div>";
173
+ }
174
+
175
+ if ( class_exists( 'FLBuilderModel' ) ) {
176
+ echo "<div class='notice notice-warning'><p>";
177
+ _e( "<b>Beaver Builder has been detected</b>. The free version might detect the files used by Beaver Builder correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
178
+ echo "</p></div>";
179
+ }
180
+
181
+ if ( function_exists( 'elementor_load_plugin_textdomain' ) ) {
182
+ echo "<div class='notice notice-warning'><p>";
183
+ _e( "<b>Elementor has been detected</b>. The free version might detect the files used by Elementor correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
184
+ echo "</p></div>";
185
+ }
186
+
187
+ if ( class_exists( 'SiteOrigin_Panels' ) ) {
188
+ echo "<div class='notice notice-warning'><p>";
189
+ _e( "<b>SiteOrigin Page Builder has been detected</b>. The free version might detect the files used by SiteOrigin Page Builder correctly, but its full support is only available in <a target='_blank' href='//meowapps.com/media-cleaner'>Media Cleaner Pro</a>.", 'media-cleaner' );
190
+ echo "</p></div>";
191
+ }
192
+
193
+ }
194
+
195
+ $anychecks = get_option( 'wpmc_posts', false ) || get_option( 'wpmc_postmeta', false ) || get_option( 'wpmc_widgets', false );
196
+ $check_library = get_option(' wpmc_media_library', true );
197
+
198
+ if ( $method == 'media' ) {
199
+ if ( !$anychecks )
200
+ _e( "<div class='error'><p>Media Cleaner will analyze your Media Library. However, There is <b>NOTHING MARKED TO BE CHECKED</b> in the Settings. Media Cleaner will therefore run a special scan: <b>only the broken medias will be detected as issues.</b></p></div>", 'media-cleaner' );
201
+ else
202
+ _e( "<div class='notice notice-success'><p>Media Cleaner will analyze your Media Library.</p></div>", 'media-cleaner' );
203
+ }
204
+ else if ( $method == 'files' ) {
205
+ if ( !$anychecks && !$check_library )
206
+ _e( "<div class='error'><p>Media Cleaner will analyze your Filesystem. However, There is <b>NOTHING MARKED TO BE CHECKED</b> in the Settings. If you scan now, all the files will be detected as <b>NOT USED</b>.</p></div>", 'media-cleaner' );
207
+ else
208
+ _e( "<div class='notice notice-success'><p>Media Cleaner will analyze your Filesystem.</p></div>", 'media-cleaner' );
209
+ }
210
+
211
+ echo sprintf( __( 'There are <b>%s issue(s)</b> with your files, accounting for <b>%s MB</b>. Your trash contains <b>%s MB.</b>', 'media-cleaner' ), number_format( $issues_count, 0 ), number_format( $total_size / 1000000, 2 ), number_format( $trash_total_size / 1000000, 2 ) );
212
+ ?>
213
+ </p>
214
+
215
+ <div id='wpmc-pages'>
216
+ <?php
217
+ echo paginate_links(array(
218
+ 'base' => '?page=media-cleaner&s=' . urlencode($s) . '&view=' . $view . '%_%',
219
+ 'current' => $paged,
220
+ 'format' => '&paged=%#%',
221
+ 'total' => ceil( $items_count / $posts_per_page ),
222
+ 'prev_next' => false
223
+ ));
224
+ ?>
225
+ </div>
226
+
227
+ <ul class="subsubsub">
228
+ <li class="all"><a <?php if ( $view == 'issues' ) echo "class='current'"; ?> href='?page=media-cleaner&s=<?php echo $s; ?>&view=issues'><?php _e( "Issues", 'media-cleaner' ); ?></a><span class="count">(<?php echo $issues_count; ?>)</span></li> |
229
+ <li class="all"><a <?php if ( $view == 'ignored' ) echo "class='current'"; ?> href='?page=media-cleaner&s=<?php echo $s; ?>&view=ignored'><?php _e( "Ignored", 'media-cleaner' ); ?></a><span class="count">(<?php echo $ignored_count; ?>)</span></li> |
230
+ <li class="all"><a <?php if ( $view == 'deleted' ) echo "class='current'"; ?> href='?page=media-cleaner&s=<?php echo $s; ?>&view=deleted'><?php _e( "Trash", 'media-cleaner' ); ?></a><span class="count">(<?php echo $deleted_count; ?>)</span></li>
231
+ </ul>
232
+
233
+ <table id='wpmc-table' class='wp-list-table widefat fixed media'>
234
+
235
+ <thead>
236
+ <tr>
237
+ <th scope="col" id="cb" class="manage-column column-cb check-column"><input id="wpmc-cb-select-all" type="checkbox"></th>
238
+ <?php if ( !get_option( 'wpmc_hide_thumbnails', false ) ): ?>
239
+ <th style='width: 64px;'><?php _e( 'Thumb', 'media-cleaner' ) ?></th>
240
+ <?php endif; ?>
241
+ <th style='width: 50px;'><?php _e( 'Type', 'media-cleaner' ) ?></th>
242
+ <th style='width: 80px;'><?php _e( 'Origin', 'media-cleaner' ) ?></th>
243
+
244
+ <?php if ( !empty( $wplr ) ): ?>
245
+ <th style='width: 70px;'><?php _e( 'LR ID', 'media-cleaner' ) ?></th>
246
+ <?php endif; ?>
247
+
248
+ <th><?php _e( 'Path', 'media-cleaner' ) ?></th>
249
+ <th style='width: 220px;'><?php _e( 'Issue', 'media-cleaner' ) ?></th>
250
+ <th style='width: 80px; text-align: right;'><?php _e( 'Size', 'media-cleaner' ) ?></th>
251
+ </tr>
252
+ </thead>
253
+
254
+ <tbody>
255
+ <?php
256
+ foreach ( $items as $issue ) {
257
+ $regex = "^(.*)(\\s\\(\\+.*)$";
258
+ $issue->path = preg_replace( '/' .$regex . '/i', '$1', $issue->path );
259
+ ?>
260
+ <tr>
261
+ <td><input type="checkbox" name="id" value="<?php echo $issue->id ?>"></td>
262
+ <?php if ( !get_option( 'wpmc_hide_thumbnails', false ) ): ?>
263
+ <td>
264
+ <?php
265
+ if ( $issue->deleted == 0 ) {
266
+ if ( $issue ->type == 0 ) {
267
+ // FILE
268
+ $upload_dir = wp_upload_dir();
269
+ $url = htmlspecialchars( $upload_dir['baseurl'] . '/' . $issue->path, ENT_QUOTES );
270
+ echo "<a target='_blank' href='" . $url .
271
+ "'><img style='max-width: 48px; max-height: 48px;' src='" . $url . "' /></a>";
272
+ }
273
+ else {
274
+ // MEDIA
275
+ $file = get_attached_file( $issue->postId );
276
+ if ( file_exists( $file ) ) {
277
+ $attachmentsrc = wp_get_attachment_image_src( $issue->postId, 'thumbnail' );
278
+ if ( empty( $attachmentsrc ) )
279
+ echo '<span class="dashicons dashicons-no-alt"></span>';
280
+ else {
281
+ $attachmentsrc_clean = htmlspecialchars( $attachmentsrc[0], ENT_QUOTES );
282
+ echo "<a target='_blank' href='" . $attachmentsrc_clean .
283
+ "'><img style='max-width: 48px; max-height: 48px;' src='" .
284
+ $attachmentsrc_clean . "' />";
285
+ }
286
+ }
287
+ else {
288
+ echo '<span class="dashicons dashicons-no-alt"></span>';
289
+ }
290
+ }
291
+ }
292
+ if ( $issue->deleted == 1 ) {
293
+ $upload_dir = wp_upload_dir();
294
+ $url = htmlspecialchars( $upload_dir['baseurl'] . '/wpmc-trash/' . $issue->path, ENT_QUOTES );
295
+ echo "<a target='_blank' href='" . $url .
296
+ "'><img style='max-width: 48px; max-height: 48px;' src='" . $url . "' /></a>";
297
+ }
298
+ ?>
299
+ </td>
300
+ <?php endif; ?>
301
+ <td><?php echo $issue->type == 0 ? 'FILE' : 'MEDIA'; ?></td>
302
+ <td><?php echo $issue->type == 0 ? 'Filesystem' : ("<a href='post.php?post=" .
303
+ $issue->postId . "&action=edit'>ID " . $issue->postId . "</a>"); ?></td>
304
+ <?php if ( !empty( $wplr ) ) { $info = $wplr->get_sync_info( $issue->postId ); ?>
305
+ <td style='width: 70px;'><?php echo ( !empty( $info ) && $info->lr_id ? $info->lr_id : "" ); ?></td>
306
+ <?php } ?>
307
+ <td><?php echo stripslashes( $issue->path ); ?></td>
308
+ <td><?php $core->echo_issue( $issue->issue ); ?></td>
309
+ <td style='text-align: right;'><?php echo number_format( $issue->size / 1000, 2 ); ?> KB</td>
310
+ </tr>
311
+ <?php } ?>
312
+ </tbody>
313
+
314
+ <tfoot>
315
+ <tr><th></th>
316
+ <?php if ( !get_option( 'hide_thumbnails', false ) ): ?>
317
+ <th></th>
318
+ <?php endif; ?>
319
+ <th><?php _e( 'Type', 'media-cleaner' ) ?></th><th><?php _e( 'Origin', 'media-cleaner' ) ?></th>
320
+ <?php if ( !empty( $wplr ) ): ?>
321
+ <th style='width: 70px;'><?php _e( 'LR ID', 'media-cleaner' ) ?></th>
322
+ <?php endif; ?>
323
+ <th><?php _e( 'Path', 'media-cleaner' ) ?></th><th><?php _e( 'Issue', 'media-cleaner' ) ?></th><th style='width: 80px; text-align: right;'><?php _e( 'Size', 'media-cleaner' ) ?></th></tr>
324
+ </tfoot>
325
+
326
+ </table>
327
+ </div>
328
+
329
+ <div id="wpmc-dialog" class="hidden" style="max-width:800px"></div>
330
+
331
+ <div id="wpmc-error-dialog" class="hidden" style="max-width:800px">
332
+ <h3><!-- The content will be inserted by JS --></h3>
333
+ <p>Please check your logs.<br>Do you want to <a href="#" class="retry">try again</a>, or <a href="#" class="skip">skip this entry</a>?</p>
334
+ </div>
335
+
wpmc_admin.php DELETED
@@ -1,365 +0,0 @@
1
- <?php
2
-
3
- include "common/admin.php";
4
-
5
- class Meow_WPMC_Admin extends MeowApps_Admin {
6
-
7
- public $core;
8
-
9
- public function __construct( $prefix, $mainfile, $domain ) {
10
- parent::__construct( $prefix, $mainfile, $domain );
11
- add_action( 'admin_menu', array( $this, 'app_menu' ) );
12
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
13
- }
14
-
15
- function admin_notices() {
16
-
17
- $mediasBuffer = get_option( 'wpmc_medias_buffer', null );
18
- $postsBuffer = get_option( 'wpmc_posts_buffer', null );
19
- $analysisBuffer = get_option( 'wpmc_analysis_buffer', null );
20
- $delay = get_option( 'wpmc_delay', null );
21
-
22
- if ( !is_numeric( $mediasBuffer ) || $mediasBuffer < 1 )
23
- update_option( 'wpmc_medias_buffer', 100 );
24
- if ( !is_numeric( $postsBuffer ) || $postsBuffer < 1 )
25
- update_option( 'wpmc_posts_buffer', 5 );
26
- if ( !is_numeric( $analysisBuffer ) || $analysisBuffer < 1 )
27
- update_option( 'wpmc_analysis_buffer', 50 );
28
- if ( !is_numeric( $delay ) )
29
- update_option( 'wpmc_delay', 100 );
30
-
31
- if ( !$this->is_registered() && get_option( 'wpmc_method', 'media' ) == 'files' ) {
32
- _e( "<div class='error'><p>The Pro version is required to scan files. You can <a target='_blank' href='http://meowapps.com/media-cleaner'>get a serial for the Pro version here</a>.</p></div>", 'media-cleaner' );
33
- }
34
- }
35
-
36
- function common_url( $file ) {
37
- return trailingslashit( plugin_dir_url( __FILE__ ) ) . 'common/' . $file;
38
- }
39
-
40
- function app_menu() {
41
-
42
- // SUBMENU > Settings
43
- add_submenu_page( 'meowapps-main-menu', 'Media Cleaner', 'Media Cleaner', 'manage_options',
44
- 'wpmc_settings-menu', array( $this, 'admin_settings' ) );
45
-
46
- // SUBMENU > Settings > Settings
47
- add_settings_section( 'wpmc_settings', null, null, 'wpmc_settings-menu' );
48
- add_settings_field( 'wpmc_method', "Method",
49
- array( $this, 'admin_method_callback' ),
50
- 'wpmc_settings-menu', 'wpmc_settings' );
51
- //if ( get_option( 'wpmc_method', 'media' ) == 'files' ) {
52
- add_settings_field( 'wpmc_media_library', "Media",
53
- array( $this, 'admin_media_library_callback' ),
54
- 'wpmc_settings-menu', 'wpmc_settings' );
55
- //}
56
- add_settings_field( 'wpmc_posts', "Posts",
57
- array( $this, 'admin_posts_callback' ),
58
- 'wpmc_settings-menu', 'wpmc_settings' );
59
- add_settings_field( 'wpmc_postmeta', "Post Meta",
60
- array( $this, 'admin_postmeta_callback' ),
61
- 'wpmc_settings-menu', 'wpmc_settings' );
62
- add_settings_field( 'wpmc_widgets', "Widgets",
63
- array( $this, 'admin_widgets_callback' ),
64
- 'wpmc_settings-menu', 'wpmc_settings' );
65
- // add_settings_field( 'wpmc_shortcode', "Shortcodes<br />(Pro)",
66
- // array( $this, 'admin_shortcode_callback' ),
67
- // 'wpmc_settings-menu', 'wpmc_settings' );
68
- // add_settings_field( 'wpmc_background', "Background CSS<br />(Pro)",
69
- // array( $this, 'admin_background_callback' ),
70
- // 'wpmc_settings-menu', 'wpmc_settings' );
71
- add_settings_field( 'wpmc_debuglogs', "Logs",
72
- array( $this, 'admin_debuglogs_callback' ),
73
- 'wpmc_settings-menu', 'wpmc_settings', array( "Enable" ) );
74
-
75
- // SUBMENU > Settings > UI
76
- add_settings_section( 'wpmc_ui_settings', null, null, 'wpmc_ui_settings-menu' );
77
- add_settings_field( 'wpmc_hide_thumbnails', "Thumbnails",
78
- array( $this, 'admin_hide_thumbnails_callback' ),
79
- 'wpmc_ui_settings-menu', 'wpmc_ui_settings' );
80
- add_settings_field( 'wpmc_hide_warning', "Warning Message",
81
- array( $this, 'admin_hide_warning_callback' ),
82
- 'wpmc_ui_settings-menu', 'wpmc_ui_settings' );
83
-
84
- // SUBMENU > Settings > Advanced
85
- add_settings_section( 'wpmc_advanced_settings', null, null, 'wpmc_advanced_settings-menu' );
86
- add_settings_field( 'wpmc_medias_buffer', "Medias Buffer",
87
- array( $this, 'admin_medias_buffer_callback' ),
88
- 'wpmc_advanced_settings-menu', 'wpmc_advanced_settings' );
89
- add_settings_field( 'wpmc_posts_buffer', "Posts Buffer",
90
- array( $this, 'admin_posts_buffer_callback' ),
91
- 'wpmc_advanced_settings-menu', 'wpmc_advanced_settings' );
92
- add_settings_field( 'wpmc_analysis_buffer', "Analysis Buffer",
93
- array( $this, 'admin_analysis_buffer_callback' ),
94
- 'wpmc_advanced_settings-menu', 'wpmc_advanced_settings' );
95
- add_settings_field( 'wpmc_delay', "Delay (in ms)",
96
- array( $this, 'admin_delay_callback' ),
97
- 'wpmc_advanced_settings-menu', 'wpmc_advanced_settings' );
98
-
99
- // SETTINGS
100
- register_setting( 'wpmc_settings', 'wpmc_method' );
101
- register_setting( 'wpmc_settings', 'wpmc_posts' );
102
- // register_setting( 'wpmc_settings', 'wpmc_shortcode' );
103
- // register_setting( 'wpmc_settings', 'wpmc_background' );
104
- register_setting( 'wpmc_settings', 'wpmc_widgets' );
105
- register_setting( 'wpmc_settings', 'wpmc_media_library' );
106
- register_setting( 'wpmc_settings', 'wpmc_postmeta' );
107
- register_setting( 'wpmc_settings', 'wpmc_debuglogs' );
108
-
109
- register_setting( 'wpmc_ui_settings', 'wpmc_hide_thumbnails' );
110
- register_setting( 'wpmc_ui_settings', 'wpmc_hide_warning' );
111
-
112
- register_setting( 'wpmc_advanced_settings', 'wpmc_medias_buffer' );
113
- register_setting( 'wpmc_advanced_settings', 'wpmc_posts_buffer' );
114
- register_setting( 'wpmc_advanced_settings', 'wpmc_analysis_buffer' );
115
- register_setting( 'wpmc_advanced_settings', 'wpmc_delay' );
116
- }
117
-
118
- function admin_medias_buffer_callback( $args ) {
119
- $value = get_option( 'wpmc_medias_buffer', 100 );
120
- $html = '<input type="number" style="width: 100%;" id="wpmc_medias_buffer" name="wpmc_medias_buffer" value="' . $value . '" />';
121
- $html .= '<br /><span class="description">The number of medias to read in one time during the preparation phase. This is fast, so the value should be between 50 and 1000.</label>';
122
- echo $html;
123
- }
124
-
125
- function admin_posts_buffer_callback( $args ) {
126
- $value = get_option( 'wpmc_posts_buffer', 5 );
127
- $html = '<input type="number" style="width: 100%;" id="wpmc_posts_buffer" name="wpmc_posts_buffer" value="' . $value . '" />';
128
- $html .= '<br /><span class="description">The number of posts to read in one time during the preparation phase. This takes a bit of time in case galleries are being used. Recommended value is between 1 and 20.</label>';
129
- echo $html;
130
- }
131
-
132
- function admin_analysis_buffer_callback( $args ) {
133
- $value = get_option( 'wpmc_analysis_buffer', 50 );
134
- $html = '<input type="number" style="width: 100%;" id="wpmc_analysis_buffer" name="wpmc_analysis_buffer" value="' . $value . '" />';
135
- $html .= '<br /><span class="description">The number of medias or files to analyse in one time. It is the main part of the process and it depends on the scanning options. Recommended value is between 10 and 500.</label>';
136
- echo $html;
137
- }
138
-
139
- function admin_delay_callback( $args ) {
140
- $value = get_option( 'wpmc_delay', 100 );
141
- $html = '<input type="number" style="width: 100%;" id="wpmc_delay" name="wpmc_delay" value="' . $value . '" />';
142
- $html .= '<br /><span class="description">This is a delay Media Cleaner will wait between each request. The process is intensive so this gives the server time to relax a little (hosting services sometimes require this). Recommended value is actually 0, 100 (ms) is for safety, some servers require 2000 or 500 (2 or 5 seconds).</label>';
143
- echo $html;
144
- }
145
-
146
- function admin_settings() {
147
- ?>
148
- <div class="wrap">
149
- <?php
150
- echo $this->display_title( "Media Cleaner" );
151
- ?>
152
- <div class="meow-section meow-group">
153
- <div class="meow-box meow-col meow-span_2_of_2">
154
- <h3>How to use</h3>
155
- <div class="inside">
156
- <?php echo _e( "You can choose two kind of methods, analyzing your Media Library for images which are not in used, or in your Filesystem for images which aren't registered in the Media Library or not in used. <b>Those checks can be very expensive in term of resources and might fail so you might want to play with those options depending on your install and what you need. I am working actively on making the plugin to work fine even on huge installs with all those options.</b>", 'media-cleaner' ); ?>
157
- <p class="submit">
158
- <a class="button button-primary" href="upload.php?page=media-cleaner"><?php echo _e( "Access Media Cleaner Dashboard", 'media-cleaner' ); ?></a>
159
- </p>
160
- </div>
161
- </div>
162
- </div>
163
-
164
- <div class="meow-section meow-group">
165
-
166
- <div class="meow-col meow-span_1_of_2">
167
- <div class="meow-box">
168
- <h3>Scanning</h3>
169
- <div class="inside">
170
- <form method="post" action="options.php">
171
- <?php settings_fields( 'wpmc_settings' ); ?>
172
- <?php do_settings_sections( 'wpmc_settings-menu' ); ?>
173
- <?php submit_button(); ?>
174
- </form>
175
- </div>
176
- </div>
177
- </div>
178
-
179
- <div class="meow-col meow-span_1_of_2">
180
- <?php $this->display_serialkey_box( "https://meowapps.com/media-cleaner/" ); ?>
181
-
182
- <div class="meow-box">
183
- <h3>UI</h3>
184
- <div class="inside">
185
- <form method="post" action="options.php">
186
- <?php settings_fields( 'wpmc_ui_settings' ); ?>
187
- <?php do_settings_sections( 'wpmc_ui_settings-menu' ); ?>
188
- <?php submit_button(); ?>
189
- </form>
190
- </div>
191
- </div>
192
-
193
- <div class="meow-box">
194
- <h3>Advanced</h3>
195
- <div class="inside">
196
- <form method="post" action="options.php">
197
- <?php settings_fields( 'wpmc_advanced_settings' ); ?>
198
- <?php do_settings_sections( 'wpmc_advanced_settings-menu' ); ?>
199
- <?php submit_button(); ?>
200
- </form>
201
- </div>
202
- </div>
203
-
204
- <!--
205
- <?php if ( get_option( 'wpmc_shortcode', false ) ): ?>
206
- <div class="meow-box">
207
- <h3>Shortcodes</h3>
208
- <div class="inside"><small>
209
- <p>Here are the shortcodes registered in your WordPress by your theme and other plugins.</p>
210
- <?php
211
- global $shortcode_tags;
212
- try {
213
- if ( is_array( $shortcode_tags ) ) {
214
- $my_shortcodes = array();
215
- foreach ( $shortcode_tags as $sc )
216
- if ( $sc != '__return_false' ) {
217
- if ( is_string( $sc ) )
218
- array_push( $my_shortcodes, str_replace( '_shortcode', '', (string)$sc ) );
219
- }
220
- $my_shortcodes = implode( ', ', $my_shortcodes );
221
- }
222
- }
223
- catch (Exception $e) {
224
- $my_shortcodes = "";
225
- }
226
- echo $my_shortcodes;
227
- ?>
228
- </small></div>
229
- </div>
230
- <?php endif; ?>
231
- -->
232
-
233
- </div>
234
-
235
- </div>
236
- </div>
237
- <?php
238
- }
239
-
240
-
241
-
242
- /*
243
- OPTIONS CALLBACKS
244
- */
245
-
246
- function admin_method_callback( $args ) {
247
- $value = get_option( 'wpmc_method', 'media' );
248
- $html = '<select id="wpmc_method" name="wpmc_method">
249
- <option ' . selected( 'media', $value, false ) . 'value="media">Media Library</option>
250
- <option ' . disabled( $this->is_registered(), false, false ) . ' ' . selected( 'files', $value, false ) . 'value="files">Filesystem (Pro)</option>
251
- </select><small><br />' . __( 'Check the <a target="_blank" href="//meowapps.com/media-cleaner/tutorial/">tutorial</a> for more information.', 'media-cleaner' ) . '</small>';
252
- echo $html;
253
- }
254
-
255
-
256
- // function admin_shortcode_callback( $args ) {
257
- // $value = get_option( 'wpmc_shortcode', null );
258
- // $html = '<input ' . disabled( $this->is_registered(), false, false ) . ' type="checkbox" id="wpmc_shortcode" name="wpmc_shortcode" value="1" ' .
259
- // checked( 1, get_option( 'wpmc_shortcode' ), false ) . '/>';
260
- // $html .= '<label>Resolve</label><br /><small>The shortcodes you are using in your <b>posts</b> and/or <b>widgets</b> (depending on your options) will be resolved and analyzed. You don\'t need to have this option enabled for the WP Gallery (as it is covered by the Galleries option).</small>';
261
- // echo $html;
262
- // }
263
-
264
- // function admin_background_callback( $args ) {
265
- // $value = get_option( 'wpmc_background', null );
266
- // $html = '<input ' . disabled( $this->is_registered(), false, false ) . ' type="checkbox" id="wpmc_background" name="wpmc_background" value="1" ' .
267
- // checked( 1, get_option( 'wpmc_background' ), false ) . '/>';
268
- // $html .= '<label>Analyze</label><br /><small>When parsing HTML, the CSS inline background will also be analyzed. A few page builders are using this.</small>';
269
- // echo $html;
270
- // }
271
-
272
- function admin_debuglogs_callback( $args ) {
273
- $debuglogs = get_option( 'wpmc_debuglogs' );
274
- $clearlogs = isset ( $_GET[ 'clearlogs' ] ) ? $_GET[ 'clearlogs' ] : 0;
275
- if ( $clearlogs && file_exists( plugin_dir_path( __FILE__ ) . '/media-cleaner.log' ) ) {
276
- unlink( plugin_dir_path( __FILE__ ) . '/media-cleaner.log' );
277
- }
278
- $html = '<input type="checkbox" id="wpmc_debuglogs" name="wpmc_debuglogs" value="1" ' .
279
- checked( 1, $debuglogs, false ) . '/>';
280
- $html .= '<label for="wpmc_debuglogs"> ' . $args[0] . '</label><br>';
281
- $html .= '<small>' . __( 'Creates an internal log file, for debugging purposes.', 'media-cleaner' );
282
- if ( $debuglogs && !file_exists( plugin_dir_path( __FILE__ ) . '/media-cleaner.log' ) ) {
283
- if ( !$this->core->log( "Testing the logging feature. It works!" ) ) {
284
- $html .= sprintf( __( '<br /><b>Cannot create the logging file. Logging will not work. The plugin as a whole might not be able to work neither.</b>', 'media-cleaner' ), plugin_dir_url( __FILE__ ) );
285
- }
286
- }
287
- if ( file_exists( plugin_dir_path( __FILE__ ) . '/media-cleaner.log' ) ) {
288
- $html .= sprintf( __( '<br />The <a target="_blank" href="%smedia-cleaner.log">log file</a> is available. You can also <a href="?page=wpmc_settings-menu&clearlogs=true">clear</a> it.', 'media-cleaner' ), plugin_dir_url( __FILE__ ) );
289
- }
290
- $html .= '</small>';
291
- echo $html;
292
- }
293
-
294
- function admin_media_library_callback( $args ) {
295
- $value = get_option( 'wpmc_media_library', true );
296
- $html = '<input type="checkbox" id="wpmc_media_library" name="wpmc_media_library" value="1" ' .
297
- disabled( get_option( 'wpmc_method', 'media' ) == 'files', false, false ) . ' ' .
298
- checked( 1, get_option( 'wpmc_media_library' ), false ) . '/>';
299
- $html .= '<label>Check (Filesystem only)</label><br /><small>Checks if the file is linked to a media.</small>';
300
- echo $html;
301
- }
302
-
303
- function admin_posts_callback( $args ) {
304
- $value = get_option( 'wpmc_posts', true );
305
- $html = '<input type="checkbox" id="wpmc_posts" name="wpmc_posts" value="1" ' .
306
- checked( 1, get_option( 'wpmc_posts' ), false ) . '/>';
307
- $html .= '<label>Analyze</label><br /><small>Check if the media/file is used by any post types.</small>';
308
- echo $html;
309
- }
310
-
311
- function admin_postmeta_callback( $args ) {
312
- $value = get_option( 'wpmc_postmeta', true );
313
- $html = '<input type="checkbox" id="wpmc_postmeta" name="wpmc_postmeta" value="1" ' .
314
- checked( 1, get_option( 'wpmc_postmeta' ), false ) . '/>';
315
- $html .= '<label>Analyze</label><br /><small>Checks if the media/file is used in the meta.</small>';
316
- echo $html;
317
- }
318
-
319
- function admin_widgets_callback( $args ) {
320
- $value = get_option( 'wpmc_widgets', false );
321
- $html = '<input type="checkbox" id="wpmc_widgets" name="wpmc_widgets" value="1" ' .
322
- checked( 1, get_option( 'wpmc_widgets' ), false ) . '/>';
323
- $html .= '<label>Analyze</label><br /><small>Checks if the media/file is used by any widget.</small>';
324
- echo $html;
325
- }
326
-
327
- function admin_hide_thumbnails_callback( $args ) {
328
- $value = get_option( 'wpmc_hide_thumbnails', null );
329
- $html = '<input type="checkbox" id="wpmc_hide_thumbnails" name="wpmc_hide_thumbnails" value="1" ' .
330
- checked( 1, get_option( 'wpmc_hide_thumbnails' ), false ) . '/>';
331
- $html .= '<label>Hide</label><br /><small>If you prefer not to see the thumbnails.</small>';
332
- echo $html;
333
- }
334
-
335
- function admin_hide_warning_callback( $args ) {
336
- $value = get_option( 'wpmc_hide_warning', null );
337
- $html = '<input type="checkbox" id="wpmc_hide_warning" name="wpmc_hide_warning" value="1" ' .
338
- checked( 1, get_option( 'wpmc_hide_warning' ), false ) . '/>';
339
- $html .= '<label>Hide</label><br /><small>Have you read it twice? If yes, hide it :)</small>';
340
- echo $html;
341
- }
342
-
343
- /**
344
- *
345
- * GET / SET OPTIONS (TO REMOVE)
346
- *
347
- */
348
-
349
- function old_getoption( $option, $section, $default = '' ) {
350
- $options = get_option( $section );
351
- if ( isset( $options[$option] ) ) {
352
- if ( $options[$option] == "off" ) {
353
- return false;
354
- }
355
- if ( $options[$option] == "on" ) {
356
- return true;
357
- }
358
- return $options[$option];
359
- }
360
- return $default;
361
- }
362
-
363
- }
364
-
365
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpmc_checkers.php DELETED
@@ -1,211 +0,0 @@
1
- <?php
2
-
3
- // This file will contains all the CORE checkers of the Media Cleaner system.
4
- // Each 'checker' checks the usage of the file by a certain feature of WordPress.
5
-
6
- class Meow_WPMC_Checkers {
7
-
8
- private $core;
9
-
10
- public function __construct( $core ) {
11
- $this->core = $core;
12
- }
13
-
14
- function has_background_or_header( $file, $mediaId = null ) {
15
-
16
- $theme_ids = get_transient( "wpmc_theme_ids" );
17
- if ( is_array( $theme_ids ) && in_array( $mediaId, $theme_ids ) ) {
18
- $this->core->log( "Media {$mediaId} found in theme" );
19
- $this->core->last_analysis = "THEME";
20
- return true;
21
- }
22
- $theme_urls = get_transient( "wpmc_theme_urls" );
23
- if ( is_array( $theme_urls ) && in_array( $file, $theme_urls ) ) {
24
- $this->core->log( "Media {$mediaId} found in theme" );
25
- $this->core->last_analysis = "THEME";
26
- return true;
27
- }
28
-
29
- return false;
30
- }
31
-
32
- function check_in_gallery( $file, $mediaId = 0 ) {
33
-
34
- $file = $this->core->wpmc_clean_uploaded_filename( $file );
35
- $pinfo = pathinfo( $file );
36
- $url = $pinfo['dirname'] . '/' . $pinfo['filename'] .
37
- ( isset( $pinfo['extension'] ) ? ( '.' . $pinfo['extension'] ) : '' );
38
-
39
- /***************************************************************************
40
- SEARCH BASED ON MEDIA ID
41
- ***************************************************************************/
42
-
43
- if ( $mediaId > 0 ) {
44
-
45
- // Galleries in Visual Composer (WPBakery)
46
- if ( class_exists( 'Vc_Manager' ) ) {
47
- $galleries_images_vc = get_transient( "wpmc_galleries_images_visualcomposer" );
48
- if ( is_array( $galleries_images_vc ) && in_array( $mediaId, $galleries_images_vc ) ) {
49
- $this->core->log( "Media {$mediaId} found in a Visual Composer gallery" );
50
- $this->core->last_analysis = "GALLERY";
51
- return true;
52
- }
53
- }
54
-
55
- // Galleries in Fusion Builder (Avada Theme)
56
- if ( function_exists( 'fusion_builder_map' ) ) {
57
- $galleries_images_fb = get_transient( "wpmc_galleries_images_fusionbuilder" );
58
- if ( is_array( $galleries_images_fb ) && in_array( $mediaId, $galleries_images_fb ) ) {
59
- $this->core->log( "Media {$mediaId} found in post_content (Fusion Builder)" );
60
- $this->core->last_analysis = "GALLERY";
61
- return true;
62
- }
63
- }
64
-
65
- // Check in WooCommerce Galleries
66
- if ( class_exists( 'WooCommerce' ) ) {
67
- $galleries_images_wc = get_transient( "wpmc_galleries_images_woocommerce" );
68
- if ( is_array( $galleries_images_wc ) && in_array( $mediaId, $galleries_images_wc ) ) {
69
- $this->core->log( "Media {$mediaId} found in a WooCommerce gallery" );
70
- $this->core->last_analysis = "GALLERY";
71
- return true;
72
- }
73
- }
74
-
75
- // Check in Divi
76
- if ( function_exists( '_et_core_find_latest' ) ) {
77
- $galleries_images_et = get_transient( "wpmc_galleries_images_divi" );
78
- if ( is_array( $galleries_images_et ) && in_array( $mediaId, $galleries_images_et ) ) {
79
- $this->core->log( "Media {$mediaId} found in a Divi gallery" );
80
- $this->core->last_analysis = "GALLERY";
81
- return true;
82
- }
83
- }
84
-
85
- }
86
-
87
- /***************************************************************************
88
- SEARCH BASED ON FILE
89
- ***************************************************************************/
90
-
91
- // Check in standard WP Galleries (URLS)
92
- $galleries_images_urls = get_transient( "wpmc_galleries_images_urls" );
93
- if ( is_array( $galleries_images_urls ) && in_array( $file, $galleries_images_urls ) ) {
94
- $this->core->log( "URL {$file} found in a standard WP Gallery" );
95
- $this->core->last_analysis = "GALLERY";
96
- return true;
97
- }
98
-
99
- return false;
100
- }
101
-
102
- function has_meta( $file, $mediaId = 0 ) {
103
-
104
- if ( !get_option( 'wpmc_postmeta', true ) )
105
- return false;
106
-
107
- $postmeta_images_ids = get_transient( "wpmc_postmeta_images_ids" );
108
- if ( is_array( $postmeta_images_ids ) && in_array( $mediaId, $postmeta_images_ids ) ) {
109
- $this->core->log( "Media {$mediaId} found in content (Post Meta IDs)" );
110
- $this->core->last_analysis = "META (ID)";
111
- return true;
112
- }
113
-
114
- if ( class_exists( 'acf' ) ) {
115
- $postmeta_images_acf_ids = get_transient( "wpmc_postmeta_images_acf_ids" );
116
- if ( is_array( $postmeta_images_acf_ids ) && in_array( $mediaId, $postmeta_images_acf_ids ) ) {
117
- $this->core->log( "Media {$mediaId} found in content (Post Meta ACF IDs)" );
118
- $this->core->last_analysis = "META ACF (ID)";
119
- return true;
120
- }
121
- }
122
-
123
- $file = $this->core->wpmc_clean_uploaded_filename( $file );
124
- $pinfo = pathinfo( $file );
125
- $url = $pinfo['dirname'] . '/' . $pinfo['filename'] .
126
- ( isset( $pinfo['extension'] ) ? ( '.' . $pinfo['extension'] ) : '' );
127
-
128
- $postmeta_images_urls = get_transient( "wpmc_postmeta_images_urls" );
129
- if ( is_array( $postmeta_images_urls ) && in_array( $url, $postmeta_images_urls ) ) {
130
- $this->core->log( "URL {$url} found in content (Post Meta URLs)" );
131
- $this->core->last_analysis = "META (URL)";
132
- return true;
133
- }
134
-
135
- if ( class_exists( 'acf' ) ) {
136
- $postmeta_images_acf_urls = get_transient( "wpmc_postmeta_images_acf_urls" );
137
- if ( is_array( $postmeta_images_acf_urls ) && in_array( $url, $postmeta_images_acf_urls ) ) {
138
- $this->core->log( "URL {$url} found in content (Post Meta ACF URLs)" );
139
- $this->core->last_analysis = "META ACF (URL)";
140
- return true;
141
- }
142
- }
143
-
144
- return false;
145
- }
146
-
147
-
148
- function has_content( $file, $mediaId = null ) {
149
-
150
- global $wpdb;
151
- $this->core->last_analysis_ids = null;
152
- $shortcode_support = get_option( 'wpmc_shortcode', false );
153
- $file = $this->core->wpmc_clean_uploaded_filename( $file );
154
- $url = $file;
155
-
156
- // Check in Posts Content
157
- if ( get_option( 'wpmc_posts', true ) ) {
158
-
159
- if ( !empty( $mediaId ) ) {
160
- // Search through the CSS class
161
- $posts_images_ids = get_transient( "wpmc_posts_images_ids" );
162
- if ( is_array( $posts_images_ids ) && in_array( $mediaId, $posts_images_ids ) ) {
163
- $this->core->log( "Media {$mediaId} found in content (Posts Images IDs)" );
164
- $this->core->last_analysis = "CONTENT (ID)";
165
- return true;
166
- }
167
-
168
- // Posts in Visual Composer (WPBakery)
169
- if ( class_exists( 'Vc_Manager' ) ) {
170
- $posts_images_vc = get_transient( "wpmc_posts_images_visualcomposer" );
171
- if ( is_array( $posts_images_vc ) && in_array( $mediaId, $posts_images_vc ) ) {
172
- $this->core->log( "Media {$mediaId} found in content (Visual Composer)" );
173
- $this->core->last_analysis = "PAGE BUILDER";
174
- return true;
175
- }
176
- }
177
- }
178
-
179
- // Search through the filename
180
- $posts_images_urls = get_transient( "wpmc_posts_images_urls" );
181
- if ( is_array( $posts_images_urls ) && in_array( $url, $posts_images_urls ) ) {
182
- $this->core->log( "URL {$url} found in content (Posts Images URLs)" );
183
- $this->core->last_analysis = "CONTENT (URL)";
184
- return true;
185
- }
186
- }
187
-
188
- // Search in widgets
189
- if ( get_option( 'wpmc_widgets', false ) ) {
190
- if ( !empty( $mediaId ) ) {
191
- $widgets_ids = get_transient( "wpmc_widgets_ids" );
192
- if ( is_array( $widgets_ids ) && in_array( $mediaId, $widgets_ids ) ) {
193
- $this->core->log( "Media {$mediaId} found in widgets (Widgets IDs)" );
194
- $this->core->last_analysis = "WIDGET";
195
- return true;
196
- }
197
- }
198
- $widgets_urls = get_transient( "wpmc_widgets_urls" );
199
- if ( is_array( $widgets_urls ) && in_array( $url, $widgets_urls ) ) {
200
- $this->core->log( "URL {$url} found in widgets (Widgets URLs)" );
201
- $this->core->last_analysis = "WIDGET";
202
- return true;
203
- }
204
- }
205
-
206
- return false;
207
- }
208
-
209
- }
210
-
211
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpmc_custom_checkers.php DELETED
@@ -1,20 +0,0 @@
1
- <?php
2
-
3
- // This file will contains all the CUSTOM checkers of the Media Cleaner system.
4
- // It will hook on the Media Cleaner filters to detect if certain media is in use by a plugin.
5
- // Each plugin or theme can have
6
-
7
- // WooCommerce
8
- // if ( is_plugin_active( 'woocommerce' ) ) ...
9
- //
10
-
11
- // WP/LR Sync
12
- // if ( is_plugin_active( 'wplr-sync' ) ) ...
13
- //
14
-
15
- // Justified Image Grid
16
- // Requested by: Alexander S. Kunz
17
- // Added by: Jordy Meow
18
- // Usage: Similar as WP internal gallery but use the justified_image_grid shortcode instead.
19
-
20
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpmc_scan.php DELETED
@@ -1,189 +0,0 @@
1
- <?php
2
-
3
- class MeowApps_WPMC_Scan {
4
-
5
- private $core = null;
6
- private $likes = "";
7
- private $metakeys = array( '%gallery%', '%ids%' );
8
-
9
- public function __construct( $core ) {
10
- $this->core = $core;
11
-
12
- // Prepare likes for SQL
13
- foreach ( $this->metakeys as $metakey )
14
- $this->likes .= "OR meta_key LIKE '$metakey' ";
15
-
16
- // Detect values in the general (known, based on %like%) Meta Keys
17
- add_action( 'wpmc_scan_postmeta', array( $this, 'scan_postmeta' ) );
18
-
19
- if ( class_exists( 'WooCommerce' ) )
20
- add_action( 'wpmc_scan_postmeta', array( $this, 'scan_postmeta_woocommerce' ) );
21
-
22
- // Check URLs, IDs, WP Gallery, WooCommerce
23
- add_action( 'wpmc_scan_post', array( $this, 'scan_post' ), 10, 2 );
24
-
25
- // Advanced Custom Fields
26
- if ( class_exists( 'acf' ) )
27
- add_action( 'wpmc_scan_postmeta', array( $this, 'scan_postmeta_acf' ) );
28
-
29
- }
30
-
31
- public function scan_post( $html, $id ) {
32
- $posts_images_urls = get_transient( "wpmc_posts_images_urls" );
33
- if ( empty( $posts_images_urls ) )
34
- $posts_images_urls = array();
35
- $posts_images_ids = get_transient( "wpmc_posts_images_ids" );
36
- if ( empty( $posts_images_ids ) )
37
- $posts_images_ids = array();
38
- $galleries_images = get_transient( "wpmc_galleries_images_urls" );
39
- if ( empty( $galleries_images ) )
40
- $galleries_images = array();
41
-
42
- // Check URLs in HTML
43
- $new_urls = $this->core->get_urls_from_html( $html );
44
- $posts_images_urls = array_merge( $posts_images_urls, $new_urls );
45
-
46
- // Check Excerpt for WooCommerce (= Product Short Description)
47
- if ( class_exists( 'WooCommerce' ) ) {
48
- $excerpt = get_post_field( 'post_excerpt', $id );
49
- if ( !empty( $excerpt ) ) {
50
- $new_urls = $this->core->get_urls_from_html( $excerpt );
51
- $posts_images_urls = array_merge( $posts_images_urls, $new_urls );
52
- }
53
- }
54
-
55
- // Check for images IDs through classes in in posts
56
- preg_match_all( "/wp-image-([0-9]+)/", $html, $res );
57
- if ( !empty( $res ) && isset( $res[1] ) && count( $res[1] ) > 0 )
58
- $posts_images_ids = array_merge( $posts_images_ids, $res[1] );
59
-
60
-
61
- // Standard WP Gallery
62
- $galleries = get_post_galleries_images( $id );
63
- foreach ( $galleries as $gallery ) {
64
- foreach ( $gallery as $image ) {
65
- array_push( $galleries_images, $this->core->wpmc_clean_url( $image ) );
66
- }
67
- }
68
-
69
- set_transient( "wpmc_posts_images_urls", $posts_images_urls, Meow_WPMC_Core::$transient_life );
70
- set_transient( "wpmc_posts_images_ids", $posts_images_ids, Meow_WPMC_Core::$transient_life );
71
- set_transient( "wpmc_galleries_images_urls", $galleries_images, Meow_WPMC_Core::$transient_life );
72
- }
73
-
74
- public function scan_postmeta( $id ) {
75
- global $wpdb;
76
- $query = $wpdb->prepare( "SELECT meta_value FROM $wpdb->postmeta
77
- WHERE post_id = %d
78
- AND meta_key = '_thumbnail_id' ", $id ) . $this->likes;
79
- $metas = $wpdb->get_col( $query );
80
- if ( count( $metas ) > 0 ) {
81
- $postmeta_images_ids = get_transient( "wpmc_postmeta_images_ids" );
82
- if ( empty( $postmeta_images_ids ) )
83
- $postmeta_images_ids = array();
84
- $postmeta_images_urls = get_transient( "wpmc_postmeta_images_urls" );
85
- if ( empty( $postmeta_images_urls ) )
86
- $postmeta_images_urls = array();
87
-
88
- foreach ( $metas as $meta ) {
89
- // Just a number, let's assume it's a Media ID
90
- if ( is_numeric( $meta ) ) {
91
- //error_log( "META NUMERIC: " . $meta );
92
- if ( $meta > 0 )
93
- array_push( $postmeta_images_ids, $meta );
94
- continue;
95
- }
96
- $decoded = @unserialize( $meta );
97
- if ( is_array( $decoded ) ) {
98
- // error_log( "META DECODED" );
99
- // error_log( print_r( $decoded, 1 ) );
100
- $this->core->array_to_ids_or_urls( $decoded, $postmeta_images_ids, $postmeta_images_urls );
101
- continue;
102
- }
103
- $exploded = explode( ',', $meta );
104
- if ( is_array( $exploded ) ) {
105
- // error_log( "META EXPLODED" );
106
- // error_log( print_r( $exploded, 1 ) );
107
- $this->core->array_to_ids_or_urls( $exploded, $postmeta_images_ids, $postmeta_images_urls );
108
- continue;
109
- }
110
- }
111
- set_transient( "wpmc_postmeta_images_ids", $postmeta_images_ids, Meow_WPMC_Core::$transient_life );
112
- set_transient( "wpmc_postmeta_images_urls", $postmeta_images_urls, Meow_WPMC_Core::$transient_life );
113
- }
114
- }
115
-
116
- function scan_postmeta_woocommerce( $id ) {
117
- global $wpdb;
118
- $galleries_images_wc = get_transient( "wpmc_galleries_images_woocommerce" );
119
- if ( empty( $galleries_images_wc ) )
120
- $galleries_images_wc = array();
121
- $res = $wpdb->get_col( "SELECT meta_value FROM $wpdb->postmeta WHERE post_id = $id
122
- AND meta_key = '_product_image_gallery'" );
123
- foreach ( $res as $values ) {
124
- $ids = explode( ',', $values );
125
- $galleries_images_wc = array_merge( $galleries_images_wc, $ids );
126
- }
127
- set_transient( "wpmc_galleries_images_woocommerce", $galleries_images_wc, Meow_WPMC_Core::$transient_life );
128
- }
129
-
130
- public function scan_postmeta_acf( $id ) {
131
- $postmeta_images_acf_ids = get_transient( "wpmc_postmeta_images_acf_ids" );
132
- if ( empty( $postmeta_images_acf_ids ) )
133
- $postmeta_images_acf_ids = array();
134
- $postmeta_images_acf_urls = get_transient( "wpmc_postmeta_images_acf_urls" );
135
- if ( empty( $postmeta_images_acf_urls ) )
136
- $postmeta_images_acf_urls = array();
137
- $fields = get_field_objects( $id );
138
- if ( is_array( $fields ) ) {
139
- foreach ( $fields as $field ) {
140
- $format = "";
141
- if ( isset( $field['return_format'] ) )
142
- $format = $field['return_format'];
143
- else if ( isset( $field['save_format'] ) )
144
- $format = $field['save_format'];
145
-
146
- // ACF Repeater
147
- if ( $field['type'] == 'repeater' ) {
148
- if ( !empty( $field['value'] ) ) {
149
- foreach ( $field['value'] as $subfields ) {
150
- foreach ( $subfields as $subfield ) {
151
- if ( $subfield['type'] == 'image' ) {
152
- if ( !empty( $subfield['id'] ) )
153
- array_push( $postmeta_images_acf_ids, $subfield['id'] );
154
- if ( !empty( $subfield['url'] ) )
155
- array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $subfield['url'] ) );
156
- }
157
- }
158
- }
159
- }
160
- }
161
- // ACF Image ID and URL
162
- else if ( $field['type'] == 'image' && ( $format == 'array' || $format == 'object' ) ) {
163
- if ( !empty( $field['value']['id'] ) )
164
- array_push( $postmeta_images_acf_ids, $field['value']['id'] );
165
- if ( !empty( $field['value']['url'] ) )
166
- array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $field['value']['url'] ) );
167
- }
168
- // ACF Image ID
169
- else if ( $field['type'] == 'image' && $format == 'id' && !empty( $field['value'] ) ) {
170
- array_push( $postmeta_images_acf_ids, $field['value'] );
171
- }
172
- // ACF Image URL
173
- else if ( $field['type'] == 'image' && $format == 'url' && !empty( $field['value'] ) ) {
174
- array_push( $postmeta_images_acf_urls, $this->core->wpmc_clean_url( $field['value'] ) );
175
- }
176
- // ACF Gallery
177
- else if ( $field['type'] == 'gallery' && !empty( $field['value'] ) ) {
178
- foreach ( $field['value'] as $media ) {
179
- if ( !empty( $media['id'] ) )
180
- array_push( $postmeta_images_acf_ids, $media['id'] );
181
- }
182
- }
183
- }
184
- set_transient( "wpmc_postmeta_images_acf_ids", $postmeta_images_acf_ids, Meow_WPMC_Core::$transient_life );
185
- set_transient( "wpmc_postmeta_images_acf_urls", $postmeta_images_acf_urls, Meow_WPMC_Core::$transient_life );
186
- }
187
- }
188
-
189
- }