Media Cleaner - Version 4.2.0

Version Description

  • Info: This is a MAJOR UPDATE both in term of optimization and detection. Keep my motivation up and give a good review to the plugin here: https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post. That helps me a lot.
  • Add: Support for Fusion Builder (Avada).
  • Add: Cache the results found in posts to analyze them much faster later.
  • Add: Debugging log file (option).
Download this release

Release Info

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

Code changes from version 4.1.0 to 4.2.0

Files changed (5) hide show
  1. core.php +229 -63
  2. media-cleaner.php +10 -2
  3. readme.txt +7 -1
  4. wpmc_admin.php +31 -9
  5. wpmc_checkers.php +79 -146
core.php CHANGED
@@ -4,7 +4,6 @@ class Meow_WPMC_Core {
4
 
5
  public $checkers = null;
6
  public $admin = null;
7
- public $debug = false;
8
 
9
  public $last_analysis = null;
10
  public $last_analysis_ids = null;
@@ -42,21 +41,29 @@ class Meow_WPMC_Core {
42
  }
43
 
44
  function display_metabox( $post ) {
45
- if ( $this->wpmc_check_media( $post->ID ) ) {
 
 
 
 
 
 
 
 
46
  if ( $this->last_analysis == "CONTENT" ) {
47
- $result = array();
48
- foreach ( $this->last_analysis_ids as $id )
49
- array_push( $result, "<a href='post.php?post=$id&action=edit'>$id</a>" );
50
- echo "Seems to be used in your content (" . implode( ', ', $result ) . ").";
51
  }
52
- else if ( $this->last_analysis == "BACKGROUND_OR_HEADER" ) {
53
- echo "Seems to be used as a background or header.";
54
  }
55
  else if ( $this->last_analysis == "GALLERY" ) {
56
- echo "Seems to be used in a gallery.";
57
  }
58
  else if ( $this->last_analysis == "META" ) {
59
- echo "Seems to be used as a meta.";
 
 
 
60
  }
61
  else {
62
  echo "Used: " . $this->last_analysis;
@@ -135,17 +142,13 @@ class Meow_WPMC_Core {
135
  $success = 0;
136
  foreach ( $data as $piece ) {
137
  if ( $type == 'file' ) {
138
- if ( $this->debug )
139
- error_log( "Check File: {$piece}" );
140
  $success += ( apply_filters( 'wpmc_check_file', true, $piece ) ? 1 : 0 );
141
- if ( $this->debug )
142
- error_log( "Success " . $success . "\n" );
143
  } elseif ( $type == 'media' ) {
144
- if ( $this->debug )
145
- error_log( "Check Media: {$piece}" );
146
  $success += ( $this->wpmc_check_media( $piece ) ? 1 : 0 );
147
- if ( $this->debug )
148
- error_log( "Success " . $success . "\n" );
149
  }
150
  }
151
  ob_end_clean();
@@ -196,7 +199,6 @@ class Meow_WPMC_Core {
196
  $limitsize = get_option( 'wpmc_posts_buffer', 10 );
197
  if ( empty( $limit ) )
198
  $this->wpmc_reset_issues();
199
-
200
  $check_posts = get_option( 'wpmc_posts', false );
201
  $check_galleries = get_option( 'wpmc_galleries', false );
202
  if ( !$check_galleries && !$check_posts ) {
@@ -212,30 +214,97 @@ class Meow_WPMC_Core {
212
  global $wpdb;
213
  $posts = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p
214
  WHERE p.post_status != 'inherit'
 
215
  AND p.post_type != 'attachment'
216
  AND p.post_type != 'revision'
217
  LIMIT %d, %d", $limit, $limitsize
218
  )
219
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  foreach ( $posts as $post ) {
221
 
 
 
222
  if ( $check_posts ) {
223
- // TODO: Not yet creating this.
224
- $posts_images = get_transient( "wpmc_posts_images" );
225
- set_transient( "wpmc_posts_images", $posts_images, 60 * 60 * 2 );
226
 
227
  // Single Image in Visual Composer (WPBakery)
228
  if ( class_exists( 'Vc_Manager' ) ) {
229
  $posts_images_vc = get_transient( "wpmc_posts_images_visualcomposer" );
230
  if ( empty( $posts_images_vc ) )
231
  $posts_images_vc = array();
232
- $html = get_post_field( 'post_content', $post );
233
  preg_match_all( "/image=\"([0-9]+)\"/", $html, $res );
234
- if ( !empty( $res ) && isset( $res[1] ) ) {
235
  $posts_images_vc = array_merge( $posts_images_vc, $res[1] );
236
  }
237
  set_transient( "wpmc_posts_images_visualcomposer", $posts_images_vc, 60 * 60 * 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  }
 
 
 
 
 
 
 
 
 
 
 
 
239
  }
240
 
241
  if ( $check_galleries ) {
@@ -245,7 +314,6 @@ class Meow_WPMC_Core {
245
  $galleries_images_vc = get_transient( "wpmc_galleries_images_visualcomposer" );
246
  if ( empty( $galleries_images_vc ) )
247
  $galleries_images_vc = array();
248
- $html = get_post_field( 'post_content', $post );
249
  preg_match_all( "/images=\"([0-9,]+)/", $html, $res );
250
  if ( !empty( $res ) && isset( $res[1] ) ) {
251
  foreach ( $res[1] as $r ) {
@@ -254,6 +322,23 @@ class Meow_WPMC_Core {
254
  }
255
  }
256
  set_transient( "wpmc_galleries_images_visualcomposer", $galleries_images_vc, 60 * 60 * 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
258
 
259
  // WooCommerce
@@ -261,13 +346,14 @@ class Meow_WPMC_Core {
261
  $galleries_images_wc = get_transient( "wpmc_galleries_images_woocommerce" );
262
  if ( empty( $galleries_images_wc ) )
263
  $galleries_images_wc = array();
264
- $res = $wpdb->get_col( "SELECT meta_value FROM $wpdb->postmeta WHERE post_id = $post
265
  AND meta_key = '_product_image_gallery'" );
266
  foreach ( $res as $values ) {
267
  $ids = explode( ',', $values );
268
  $galleries_images_wc = array_merge( $galleries_images_wc, $ids );
269
  }
270
  set_transient( "wpmc_galleries_images_woocommerce", $galleries_images_wc, 60 * 60 * 2 );
 
271
  }
272
 
273
  // Standard WP Gallery
@@ -277,23 +363,64 @@ class Meow_WPMC_Core {
277
  $galleries = get_post_galleries_images( $post );
278
  foreach ( $galleries as $gallery ) {
279
  foreach ( $gallery as $image ) {
280
- array_push( $galleries_images, $image );
281
  }
282
  }
283
  set_transient( "wpmc_galleries_images", $galleries_images, 60 * 60 * 2 );
 
284
  }
285
  }
286
  $finished = count( $posts ) < $limitsize;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  echo json_encode(
288
  array(
289
  'success' => true,
290
  'finished' => $finished,
291
  'limit' => $limit + $limitsize,
292
- 'message' => __( "Galleries prepared.", 'media-cleaner' ) )
 
293
  );
294
  die();
295
  }
296
 
 
 
 
 
 
 
 
 
 
297
  function wp_ajax_wpmc_scan() {
298
  global $wpdb;
299
 
@@ -371,8 +498,7 @@ class Meow_WPMC_Core {
371
  die( 'Failed to create folder.' );
372
  }
373
  if ( !file_exists( $trashPath ) ) {
374
- if ( $this->debug )
375
- error_log( "The file $originalPath actually does not exist in the trash." );
376
  return true;
377
  }
378
  if ( !rename( $trashPath, $originalPath ) ) {
@@ -402,8 +528,10 @@ class Meow_WPMC_Core {
402
  $baseUp = pathinfo( $mainfile );
403
  $baseUp = $baseUp['dirname'];
404
  $file = $this->wpmc_clean_uploaded_filename( $fullpath );
405
- if ( !$this->wpmc_recover_file( $file ) )
406
- error_log( "Could not recover $file." );
 
 
407
 
408
  // If images, copy the other files as well
409
  $meta = wp_get_attachment_metadata( $issue->postId );
@@ -416,13 +544,16 @@ class Meow_WPMC_Core {
416
  $filepath = $filepath['basedir'];
417
  $filepath = trailingslashit( $filepath ) . trailingslashit( $baseUp ) . $attr['file'];
418
  $file = $this->wpmc_clean_uploaded_filename( $filepath );
419
- if ( !$this->wpmc_recover_file( $file ) )
420
- error_log( "Could not recover $file." );
 
 
421
  }
422
  }
423
  }
424
- if ( !wp_untrash_post( $issue->postId ) )
425
  die( "Failed to untrash Media {$issue->postId}." );
 
426
  $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET deleted = 0 WHERE id = %d", $id ) );
427
  return true;
428
  }
@@ -441,12 +572,12 @@ class Meow_WPMC_Core {
441
  }
442
  // Rename the file (move). 'is_dir' is just there for security (no way we should move a whole directory)
443
  if ( is_dir( $originalPath ) ) {
444
- error_log( "Attempted to delete a directory instead of a file ($originalPath). Can't do that." );
 
445
  return false;
446
  }
447
  if ( !file_exists( $originalPath ) ) {
448
- if ( $this->debug )
449
- error_log( "The file $originalPath actually does not exist." );
450
  return true;
451
  }
452
  if ( !rename( $originalPath, $trashPath ) ) {
@@ -499,7 +630,8 @@ class Meow_WPMC_Core {
499
  if ( $issue->type == 0 ) {
500
  $attachmentid = $this->wpmc_find_attachment_id_by_file( $issue->path );
501
  if ( $attachmentid ) {
502
- error_log( "File Cleaner: Issue listed as filesystem but Media {$attachmentid} exists." );
 
503
  }
504
  }
505
 
@@ -514,8 +646,10 @@ class Meow_WPMC_Core {
514
  else {
515
  // Delete file from the trash
516
  $trashPath = trailingslashit( $this->wpmc_trashdir() ) . $issue->path;
517
- if ( !unlink( $trashPath ) )
518
- error_log( 'Failed to delete the file.' );
 
 
519
  $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE id = %d", $id ) );
520
  $this->wpmc_clean_dir( dirname( $trashPath ) );
521
  return true;
@@ -531,8 +665,10 @@ class Meow_WPMC_Core {
531
  $baseUp = pathinfo( $mainfile );
532
  $baseUp = $baseUp['dirname'];
533
  $file = $this->wpmc_clean_uploaded_filename( $fullpath );
534
- if ( !$this->wpmc_trash_file( $file ) )
535
- error_log( "Could not trash $file." );
 
 
536
 
537
  // If images, check the other files as well
538
  $meta = wp_get_attachment_metadata( $issue->postId );
@@ -545,8 +681,10 @@ class Meow_WPMC_Core {
545
  $filepath = $filepath['basedir'];
546
  $filepath = trailingslashit( $filepath ) . trailingslashit( $baseUp ) . $attr['file'];
547
  $file = $this->wpmc_clean_uploaded_filename( $filepath );
548
- if ( !$this->wpmc_trash_file( $file ) )
549
- error_log( "Could not trash $file." );
 
 
550
  }
551
  }
552
  }
@@ -580,8 +718,9 @@ class Meow_WPMC_Core {
580
  FROM $table_name
581
  WHERE ignored = 1
582
  AND path LIKE '%". esc_sql( $wpdb->esc_like( $file ) ) . "%'" );
583
- if ( $this->debug && $count > 0 )
584
- error_log("{$file} found in IGNORE");
 
585
  return ($count > 0);
586
  }
587
 
@@ -595,10 +734,10 @@ class Meow_WPMC_Core {
595
  AND meta_value = %s", $file
596
  );
597
  $ret = $wpdb->get_var( $sql );
598
- if ( $this->debug && empty( $ret ) )
599
- error_log( "File $file not found as _wp_attached_file (Library)." );
600
- else if ( $this->debug ) {
601
- error_log( "File $file found as Media $ret." );
602
  }
603
  return $ret;
604
  }
@@ -622,6 +761,22 @@ class Meow_WPMC_Core {
622
  return $sizes;
623
  }
624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
 
626
  // From a fullpath to the shortened and cleaned path (for example '2013/02/file.png')
627
  function wpmc_clean_uploaded_filename( $fullpath ) {
@@ -654,16 +809,18 @@ class Meow_WPMC_Core {
654
 
655
  // ANALYSIS
656
  $this->last_analysis = "NONE";
 
657
  if ( $this->wpmc_check_is_ignore( $mainfile, $attachmentId ) ) {
658
  $this->last_analysis = "IGNORED";
659
  return true;
660
  }
661
  if ( $this->checkers->has_background_or_header( $mainfile, $attachmentId ) ) {
662
- $this->last_analysis = "BACKGROUND_OR_HEADER";
663
  return true;
664
  }
665
  if ( $this->checkers->has_content( $mainfile, $attachmentId ) ) {
666
- $this->last_analysis = "CONTENT";
 
667
  return true;
668
  }
669
  if ( $this->checkers->check_in_gallery( $mainfile, $attachmentId ) ) {
@@ -687,21 +844,24 @@ class Meow_WPMC_Core {
687
  if ( file_exists( $filepath ) ) {
688
  $size += filesize( $filepath );
689
  }
690
- $file = $this->wpmc_clean_uploaded_filename( $attr['file'] );
691
  $countfiles++;
692
- if ( $this->debug )
693
- error_log("checking MEDIA-IMAGE {$filepath}");
694
 
695
  // ANALYSIS
696
- if ( $this->checkers->check_in_gallery( $filepath, $attachmentId ) ) {
 
 
 
 
697
  $this->last_analysis = "GALLERY";
698
  return true;
699
  }
700
- if ( $this->checkers->has_background_or_header( $filepath, $attachmentId ) ) {
701
- $this->last_analysis = "BACKGROUND_OR_HEADER";
702
  return true;
703
  }
704
- if ( $this->checkers->has_meta( $filepath, $attachmentId ) ) {
705
  $this->last_analysis = "META";
706
  return true;
707
  }
@@ -737,12 +897,17 @@ class Meow_WPMC_Core {
737
  else {
738
  $wpdb->query( "DELETE FROM $table_name WHERE ignored = 0 AND deleted = 0" );
739
  }
 
 
 
 
 
740
  delete_transient( "wpmc_posts_images_visualcomposer" );
741
  delete_transient( "wpmc_galleries_images_visualcomposer" );
 
742
  delete_transient( "wpmc_galleries_images_woocommerce" );
743
  delete_transient( "wpmc_galleries_images" );
744
- delete_transient( "wpmc_posts_images" );
745
- delete_transient( 'wpmc_posts_with_shortcode' );
746
  }
747
 
748
  /**
@@ -814,6 +979,7 @@ class Meow_WPMC_Core {
814
  $reset = isset ( $_GET[ 'reset' ] ) ? $_GET[ 'reset' ] : 0;
815
  if ( $reset ) {
816
  wpmc_reset();
 
817
  }
818
  $s = isset ( $_GET[ 's' ] ) ? sanitize_text_field( $_GET[ 's' ] ) : null;
819
  $table_name = $wpdb->prefix . "wpmcleaner";
@@ -1089,7 +1255,7 @@ register_activation_hook( __FILE__, 'wpmc_activate' );
1089
  register_deactivation_hook( __FILE__, 'wpmc_uninstall' );
1090
  register_uninstall_hook( __FILE__, 'wpmc_uninstall' );
1091
 
1092
- function wpmc_reset () {
1093
  wpmc_uninstall();
1094
  wpmc_activate();
1095
  }
4
 
5
  public $checkers = null;
6
  public $admin = null;
 
7
 
8
  public $last_analysis = null;
9
  public $last_analysis_ids = null;
41
  }
42
 
43
  function display_metabox( $post ) {
44
+ $posts_images_urls = get_transient( "wpmc_posts_images_urls" );
45
+ if ( !is_array( $posts_images_urls ) ) {
46
+ echo "You need to run a scan first.";
47
+ return;
48
+ }
49
+ $this->log( "Media Edit > Checking Media #{$post->ID}" );
50
+ $success = $this->wpmc_check_media( $post->ID );
51
+ $this->log( "Success " . $success . "\n" );
52
+ if ( $success ) {
53
  if ( $this->last_analysis == "CONTENT" ) {
54
+ echo "Found in the content.";
 
 
 
55
  }
56
+ else if ( $this->last_analysis == "THEME" ) {
57
+ echo "Found in the theme.";
58
  }
59
  else if ( $this->last_analysis == "GALLERY" ) {
60
+ echo "Found in a gallery.";
61
  }
62
  else if ( $this->last_analysis == "META" ) {
63
+ echo "Found in meta.";
64
+ }
65
+ else if ( $this->last_analysis == "WIDGET" ) {
66
+ echo "Found in widget.";
67
  }
68
  else {
69
  echo "Used: " . $this->last_analysis;
142
  $success = 0;
143
  foreach ( $data as $piece ) {
144
  if ( $type == 'file' ) {
145
+ $this->log( "Check File: {$piece}" );
 
146
  $success += ( apply_filters( 'wpmc_check_file', true, $piece ) ? 1 : 0 );
147
+ $this->log( "Success " . $success . "\n" );
 
148
  } elseif ( $type == 'media' ) {
149
+ $this->log( "Checking Media #{$piece}" );
 
150
  $success += ( $this->wpmc_check_media( $piece ) ? 1 : 0 );
151
+ $this->log( "Success " . $success . "\n" );
 
152
  }
153
  }
154
  ob_end_clean();
199
  $limitsize = get_option( 'wpmc_posts_buffer', 10 );
200
  if ( empty( $limit ) )
201
  $this->wpmc_reset_issues();
 
202
  $check_posts = get_option( 'wpmc_posts', false );
203
  $check_galleries = get_option( 'wpmc_galleries', false );
204
  if ( !$check_galleries && !$check_posts ) {
214
  global $wpdb;
215
  $posts = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p
216
  WHERE p.post_status != 'inherit'
217
+ AND p.post_status != 'trash'
218
  AND p.post_type != 'attachment'
219
  AND p.post_type != 'revision'
220
  LIMIT %d, %d", $limit, $limitsize
221
  )
222
  );
223
+
224
+ $found = array();
225
+ $shortcode_support = get_option( 'wpmc_shortcode', false );
226
+
227
+ // Analyze Widgets
228
+ if ( get_option( 'wpmc_widgets', false ) && empty( $limit ) ) {
229
+ $widgets_content = "";
230
+ global $wp_registered_widgets;
231
+ $syswidgets = $wp_registered_widgets;
232
+ $active_widgets = get_option( 'sidebars_widgets' );
233
+ // Contatenation of the widgets
234
+ foreach ( $active_widgets as $sidebar_name => $widgets ) {
235
+ if ( $sidebar_name != 'wp_inactive_widgets' && !empty( $widgets ) && is_array( $widgets ) ) {
236
+ $i = 0;
237
+ foreach ( $widgets as $widget ) {
238
+ $widget_class = $syswidgets[$widget]['callback'][0]->option_name;
239
+ $instance_id = $syswidgets[$widget]['params'][0]['number'];
240
+ $widget_data = get_option($widget_class);
241
+ if ( !empty( $widget_data[$instance_id]['text'] ) ) {
242
+ if ( $shortcode_support )
243
+ $widgets_content .= do_shortcode( $widget_data[$instance_id]['text'] );
244
+ else
245
+ $widgets_content .= $widget_data[$instance_id]['text'];
246
+ }
247
+ $i++;
248
+ }
249
+ }
250
+ }
251
+ $widgets_images = array();
252
+ preg_match_all( "/https?:\/\/[^\/\s]+\/\S+\.(jpg|png|gif)/", $widgets_content, $res );
253
+ if ( !empty( $res ) && isset( $res[0] ) && count( $res[0] ) > 0 ) {
254
+ array_walk( $res[0], array( $this, "wpmc_clean_url_direct" ) );
255
+ $widgets_images = array_merge( $widgets_images, $res[0] );
256
+ }
257
+ set_transient( "wpmc_widgets_images", $widgets_images, 60 * 60 * 2 );
258
+ $found['wpmc_widgets_images'] = $widgets_images;
259
+
260
+
261
+ }
262
+
263
+ // Analyze Posts
264
  foreach ( $posts as $post ) {
265
 
266
+ $html = get_post_field( 'post_content', $post );
267
+
268
  if ( $check_posts ) {
 
 
 
269
 
270
  // Single Image in Visual Composer (WPBakery)
271
  if ( class_exists( 'Vc_Manager' ) ) {
272
  $posts_images_vc = get_transient( "wpmc_posts_images_visualcomposer" );
273
  if ( empty( $posts_images_vc ) )
274
  $posts_images_vc = array();
 
275
  preg_match_all( "/image=\"([0-9]+)\"/", $html, $res );
276
+ if ( !empty( $res ) && isset( $res[1] ) && count( $res[1] ) > 0 ) {
277
  $posts_images_vc = array_merge( $posts_images_vc, $res[1] );
278
  }
279
  set_transient( "wpmc_posts_images_visualcomposer", $posts_images_vc, 60 * 60 * 2 );
280
+ $found['wpmc_posts_images_visualcomposer'] = $posts_images_vc;
281
+ }
282
+
283
+ // Let's resolve the shortcodes if the option is on
284
+ if ( $shortcode_support )
285
+ $html = do_shortcode( $html );
286
+
287
+ // Check for images urls in posts
288
+ $posts_images_urls = get_transient( "wpmc_posts_images_urls" );
289
+ if ( empty( $posts_images_urls ) )
290
+ $posts_images_urls = array();
291
+ preg_match_all( "/https?:\/\/[^\/\s]+\/\S+\.(jpg|png|gif)/", $html, $res );
292
+ if ( !empty( $res ) && isset( $res[0] ) && count( $res[0] ) > 0 ) {
293
+ array_walk( $res[0], array( $this, "wpmc_clean_url_direct" ) );
294
+ $posts_images_urls = array_merge( $posts_images_urls, $res[0] );
295
  }
296
+ set_transient( "wpmc_posts_images_urls", $posts_images_urls, 60 * 60 * 2 );
297
+ $found['wpmc_posts_images_urls'] = $posts_images_urls;
298
+
299
+ // Check for images IDs through classes in in posts
300
+ $posts_images_ids = get_transient( "wpmc_posts_images_ids" );
301
+ if ( empty( $posts_images_ids ) )
302
+ $posts_images_ids = array();
303
+ preg_match_all( "/wp-image-([0-9]+)/", $html, $res );
304
+ if ( !empty( $res ) && isset( $res[1] ) && count( $res[1] ) > 0 )
305
+ $posts_images_ids = array_merge( $posts_images_ids, $res[1] );
306
+ set_transient( "wpmc_posts_images_ids", $posts_images_ids, 60 * 60 * 2 );
307
+ $found['wpmc_posts_images_ids'] = $posts_images_ids;
308
  }
309
 
310
  if ( $check_galleries ) {
314
  $galleries_images_vc = get_transient( "wpmc_galleries_images_visualcomposer" );
315
  if ( empty( $galleries_images_vc ) )
316
  $galleries_images_vc = array();
 
317
  preg_match_all( "/images=\"([0-9,]+)/", $html, $res );
318
  if ( !empty( $res ) && isset( $res[1] ) ) {
319
  foreach ( $res[1] as $r ) {
322
  }
323
  }
324
  set_transient( "wpmc_galleries_images_visualcomposer", $galleries_images_vc, 60 * 60 * 2 );
325
+ $found['wpmc_galleries_images_visualcomposer'] = $galleries_images_vc;
326
+ }
327
+
328
+ // Galleries in Fusion Builder (Avada Theme)
329
+ if ( function_exists( 'fusion_builder_map' ) ) {
330
+ $galleries_images_fb = get_transient( "wpmc_galleries_images_fusionbuilder" );
331
+ if ( empty( $galleries_images_fb ) )
332
+ $galleries_images_fb = array();
333
+ preg_match_all( "/image_ids=\"([0-9,]+)/", $html, $res );
334
+ if ( !empty( $res ) && isset( $res[1] ) ) {
335
+ foreach ( $res[1] as $r ) {
336
+ $ids = explode( ',', $r );
337
+ $galleries_images_fb = array_merge( $galleries_images_fb, $ids );
338
+ }
339
+ }
340
+ set_transient( "wpmc_galleries_images_fusionbuilder", $galleries_images_fb, 60 * 60 * 2 );
341
+ $found['wpmc_galleries_images_fusionbuilder'] = $galleries_images_fb;
342
  }
343
 
344
  // WooCommerce
346
  $galleries_images_wc = get_transient( "wpmc_galleries_images_woocommerce" );
347
  if ( empty( $galleries_images_wc ) )
348
  $galleries_images_wc = array();
349
+ $res = $wpdb->get_col( "SELECT maeta_value FROM $wpdb->postmeta WHERE post_id = $post
350
  AND meta_key = '_product_image_gallery'" );
351
  foreach ( $res as $values ) {
352
  $ids = explode( ',', $values );
353
  $galleries_images_wc = array_merge( $galleries_images_wc, $ids );
354
  }
355
  set_transient( "wpmc_galleries_images_woocommerce", $galleries_images_wc, 60 * 60 * 2 );
356
+ $found['wpmc_galleries_images_woocommerce'] = $galleries_images_wc;
357
  }
358
 
359
  // Standard WP Gallery
363
  $galleries = get_post_galleries_images( $post );
364
  foreach ( $galleries as $gallery ) {
365
  foreach ( $gallery as $image ) {
366
+ array_push( $galleries_images, $this->wpmc_clean_url( $image ) );
367
  }
368
  }
369
  set_transient( "wpmc_galleries_images", $galleries_images, 60 * 60 * 2 );
370
+ $found['wpmc_galleries_images'] = $galleries_images;
371
  }
372
  }
373
  $finished = count( $posts ) < $limitsize;
374
+ if ( $finished ) {
375
+ $found = array();
376
+ $posts_images_urls = get_transient( "wpmc_posts_images_urls" );
377
+ $posts_images_ids = get_transient( "wpmc_posts_images_ids" );
378
+ $posts_images_vc = get_transient( "wpmc_posts_images_visualcomposer" );
379
+ $galleries_images = get_transient( "wpmc_galleries_images" );
380
+ $galleries_images_vc = get_transient( "wpmc_galleries_images_visualcomposer" );
381
+ $galleries_images_fb = get_transient( "wpmc_galleries_images_fusionbuilder" );
382
+ $galleries_images_wc = get_transient( "wpmc_galleries_images_woocommerce" );
383
+ $widgets_images = get_transient( "wpmc_widgets_images" );
384
+ $found['posts_images_urls'] = is_array( $posts_images_urls ) ? array_unique( $posts_images_urls ) : array();
385
+ $found['posts_images_ids'] = is_array( $posts_images_ids ) ? array_unique( $posts_images_ids ) : array();
386
+ $found['posts_images_vc'] = is_array( $posts_images_vc ) ? array_unique( $posts_images_vc ) : array();
387
+ $found['galleries_images'] = is_array( $galleries_images ) ? array_unique( $galleries_images ) : array();
388
+ $found['galleries_images_vc'] = is_array( $galleries_images_vc ) ? array_unique( $galleries_images_vc ) : array();
389
+ $found['galleries_images_fb'] = is_array( $galleries_images_fb ) ? array_unique( $galleries_images_fb ) : array();
390
+ $found['galleries_images_wc'] = is_array( $galleries_images_wc ) ? array_unique( $galleries_images_wc ) : array();
391
+ $found['widgets_images'] = is_array( $widgets_images ) ? array_unique( $widgets_images ) : array();
392
+ set_transient( "wpmc_posts_images_urls", $found['posts_images_urls'], 60 * 60 * 2 );
393
+ set_transient( "wpmc_posts_images_ids", $found['posts_images_ids'], 60 * 60 * 2 );
394
+ set_transient( "wpmc_posts_images_visualcomposer", $found['posts_images_vc'], 60 * 60 * 2 );
395
+ set_transient( "wpmc_galleries_images_visualcomposer", $found['galleries_images_vc'], 60 * 60 * 2 );
396
+ set_transient( "wpmc_galleries_images_fusionbuilder", $found['galleries_images_fb'], 60 * 60 * 2 );
397
+ set_transient( "wpmc_galleries_images_woocommerce", $found['galleries_images_wc'], 60 * 60 * 2 );
398
+ set_transient( "wpmc_galleries_images", $found['galleries_images'], 60 * 60 * 2 );
399
+ set_transient( "wpmc_widgets_images", $found['widgets_images'], 60 * 60 * 2 );
400
+ }
401
+ if ( $finished && get_option( 'wpmc_debuglogs', false ) ) {
402
+ $this->log( print_r( $found, true ) );
403
+ }
404
  echo json_encode(
405
  array(
406
  'success' => true,
407
  'finished' => $finished,
408
  'limit' => $limit + $limitsize,
409
+ 'found' => $found,
410
+ 'message' => __( "Posts checked.", 'media-cleaner' ) )
411
  );
412
  die();
413
  }
414
 
415
+ function log( $data, $force = false ) {
416
+ if ( !get_option( 'wpmc_debuglogs', false ) && !$force )
417
+ return;
418
+ $fh = fopen( trailingslashit( dirname(__FILE__) ) . '/media-cleaner.log', 'a' );
419
+ $date = date( "Y-m-d H:i:s" );
420
+ fwrite( $fh, "$date: {$data}\n" );
421
+ fclose( $fh );
422
+ }
423
+
424
  function wp_ajax_wpmc_scan() {
425
  global $wpdb;
426
 
498
  die( 'Failed to create folder.' );
499
  }
500
  if ( !file_exists( $trashPath ) ) {
501
+ $this->log( "The file $originalPath actually does not exist in the trash." );
 
502
  return true;
503
  }
504
  if ( !rename( $trashPath, $originalPath ) ) {
528
  $baseUp = pathinfo( $mainfile );
529
  $baseUp = $baseUp['dirname'];
530
  $file = $this->wpmc_clean_uploaded_filename( $fullpath );
531
+ if ( !$this->wpmc_recover_file( $file ) ) {
532
+ $this->log( "Could not recover $file." );
533
+ error_log( "Media Cleaner: Could not recover $file." );
534
+ }
535
 
536
  // If images, copy the other files as well
537
  $meta = wp_get_attachment_metadata( $issue->postId );
544
  $filepath = $filepath['basedir'];
545
  $filepath = trailingslashit( $filepath ) . trailingslashit( $baseUp ) . $attr['file'];
546
  $file = $this->wpmc_clean_uploaded_filename( $filepath );
547
+ if ( !$this->wpmc_recover_file( $file ) ) {
548
+ $this->log( "Could not recover $file." );
549
+ error_log( "Media Cleaner: Could not recover $file." );
550
+ }
551
  }
552
  }
553
  }
554
+ if ( !wp_untrash_post( $issue->postId ) ) {
555
  die( "Failed to untrash Media {$issue->postId}." );
556
+ }
557
  $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET deleted = 0 WHERE id = %d", $id ) );
558
  return true;
559
  }
572
  }
573
  // Rename the file (move). 'is_dir' is just there for security (no way we should move a whole directory)
574
  if ( is_dir( $originalPath ) ) {
575
+ $this->log( "Attempted to delete a directory instead of a file ($originalPath). Can't do that." );
576
+ error_log( "Media Cleaner: Attempted to delete a directory instead of a file ($originalPath). Can't do that." );
577
  return false;
578
  }
579
  if ( !file_exists( $originalPath ) ) {
580
+ $this->log( "The file $originalPath actually does not exist." );
 
581
  return true;
582
  }
583
  if ( !rename( $originalPath, $trashPath ) ) {
630
  if ( $issue->type == 0 ) {
631
  $attachmentid = $this->wpmc_find_attachment_id_by_file( $issue->path );
632
  if ( $attachmentid ) {
633
+ $this->log( "Issue listed as filesystem but Media {$attachmentid} exists." );
634
+ error_log( "Media Cleaner: Issue listed as filesystem but Media {$attachmentid} exists." );
635
  }
636
  }
637
 
646
  else {
647
  // Delete file from the trash
648
  $trashPath = trailingslashit( $this->wpmc_trashdir() ) . $issue->path;
649
+ if ( !unlink( $trashPath ) ) {
650
+ $this->log( "Failed to delete the file." );
651
+ error_log( "Media Cleaner: Failed to delete the file." );
652
+ }
653
  $wpdb->query( $wpdb->prepare( "DELETE FROM $table_name WHERE id = %d", $id ) );
654
  $this->wpmc_clean_dir( dirname( $trashPath ) );
655
  return true;
665
  $baseUp = pathinfo( $mainfile );
666
  $baseUp = $baseUp['dirname'];
667
  $file = $this->wpmc_clean_uploaded_filename( $fullpath );
668
+ if ( !$this->wpmc_trash_file( $file ) ) {
669
+ $this->log( "Could not trash $file." );
670
+ error_log( "Media Cleaner: Could not trash $file." );
671
+ }
672
 
673
  // If images, check the other files as well
674
  $meta = wp_get_attachment_metadata( $issue->postId );
681
  $filepath = $filepath['basedir'];
682
  $filepath = trailingslashit( $filepath ) . trailingslashit( $baseUp ) . $attr['file'];
683
  $file = $this->wpmc_clean_uploaded_filename( $filepath );
684
+ if ( !$this->wpmc_trash_file( $file ) ) {
685
+ $this->log( "Could not trash $file." );
686
+ error_log( "Media Cleaner: Could not trash $file." );
687
+ }
688
  }
689
  }
690
  }
718
  FROM $table_name
719
  WHERE ignored = 1
720
  AND path LIKE '%". esc_sql( $wpdb->esc_like( $file ) ) . "%'" );
721
+ if ( $count > 0 ) {
722
+ $this->log( "Could not trash $file." );
723
+ }
724
  return ($count > 0);
725
  }
726
 
734
  AND meta_value = %s", $file
735
  );
736
  $ret = $wpdb->get_var( $sql );
737
+ if ( empty( $ret ) )
738
+ $this->log( "File $file not found as _wp_attached_file (Library)." );
739
+ else {
740
+ $this->log( "File $file found as Media $ret." );
741
  }
742
  return $ret;
743
  }
761
  return $sizes;
762
  }
763
 
764
+ function wpmc_clean_url_direct( &$url ) {
765
+ $url = $this->wpmc_clean_url( $url );
766
+ }
767
+
768
+ // From a url to the shortened and cleaned url (for example '2013/02/file.png')
769
+ function wpmc_clean_url( $url ) {
770
+ $upload_folder = wp_upload_dir();
771
+ $baseurl = $upload_folder['baseurl'];
772
+ $baseurl = str_replace( 'https://', 'http://', $baseurl );
773
+ $baseurl = str_replace( 'http://www.', 'http://', $baseurl );
774
+ $url = str_replace( 'https://', 'http://', $url );
775
+ $url = str_replace( 'http://www.', 'http://', $url );
776
+ $url = str_replace( $baseurl, '', $url );
777
+ $url = trim( $url, "/" );
778
+ return $url;
779
+ }
780
 
781
  // From a fullpath to the shortened and cleaned path (for example '2013/02/file.png')
782
  function wpmc_clean_uploaded_filename( $fullpath ) {
809
 
810
  // ANALYSIS
811
  $this->last_analysis = "NONE";
812
+ $this->log( "Checking Media #{$attachmentId}: {$mainfile}" );
813
  if ( $this->wpmc_check_is_ignore( $mainfile, $attachmentId ) ) {
814
  $this->last_analysis = "IGNORED";
815
  return true;
816
  }
817
  if ( $this->checkers->has_background_or_header( $mainfile, $attachmentId ) ) {
818
+ $this->last_analysis = "THEME";
819
  return true;
820
  }
821
  if ( $this->checkers->has_content( $mainfile, $attachmentId ) ) {
822
+ if ( empty( $this->last_analysis ) )
823
+ $this->last_analysis = "CONTENT";
824
  return true;
825
  }
826
  if ( $this->checkers->check_in_gallery( $mainfile, $attachmentId ) ) {
844
  if ( file_exists( $filepath ) ) {
845
  $size += filesize( $filepath );
846
  }
847
+ $file = $this->wpmc_clean_uploaded_filename( $filepath );
848
  $countfiles++;
849
+ $this->log( "Checking Media #{$attachmentId}: {$file}" );
 
850
 
851
  // ANALYSIS
852
+ if ( $this->checkers->has_content( $file, $attachmentId ) ) {
853
+ $this->last_analysis = "CONTENT";
854
+ return true;
855
+ }
856
+ if ( $this->checkers->check_in_gallery( $file, $attachmentId ) ) {
857
  $this->last_analysis = "GALLERY";
858
  return true;
859
  }
860
+ if ( $this->checkers->has_background_or_header( $file, $attachmentId ) ) {
861
+ $this->last_analysis = "THEME";
862
  return true;
863
  }
864
+ if ( $this->checkers->has_meta( $file, $attachmentId ) ) {
865
  $this->last_analysis = "META";
866
  return true;
867
  }
897
  else {
898
  $wpdb->query( "DELETE FROM $table_name WHERE ignored = 0 AND deleted = 0" );
899
  }
900
+ if ( file_exists( plugin_dir_path( __FILE__ ) . '/media-cleaner.log' ) ) {
901
+ file_put_contents( plugin_dir_path( __FILE__ ) . '/media-cleaner.log', '' );
902
+ }
903
+ delete_transient( "wpmc_posts_images_urls" );
904
+ delete_transient( "wpmc_posts_images_ids" );
905
  delete_transient( "wpmc_posts_images_visualcomposer" );
906
  delete_transient( "wpmc_galleries_images_visualcomposer" );
907
+ delete_transient( "wpmc_galleries_images_fusionbuilder" );
908
  delete_transient( "wpmc_galleries_images_woocommerce" );
909
  delete_transient( "wpmc_galleries_images" );
910
+ delete_transient( "wpmc_widgets_images" );
 
911
  }
912
 
913
  /**
979
  $reset = isset ( $_GET[ 'reset' ] ) ? $_GET[ 'reset' ] : 0;
980
  if ( $reset ) {
981
  wpmc_reset();
982
+ $this->wpmc_reset_issues();
983
  }
984
  $s = isset ( $_GET[ 's' ] ) ? sanitize_text_field( $_GET[ 's' ] ) : null;
985
  $table_name = $wpdb->prefix . "wpmcleaner";
1255
  register_deactivation_hook( __FILE__, 'wpmc_uninstall' );
1256
  register_uninstall_hook( __FILE__, 'wpmc_uninstall' );
1257
 
1258
+ function wpmc_reset() {
1259
  wpmc_uninstall();
1260
  wpmc_activate();
1261
  }
media-cleaner.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Media Cleaner
4
  Plugin URI: http://meowapps.com
5
  Description: Clean your Media Library, many options, trash system.
6
- Version: 4.1.0
7
  Author: Jordy Meow
8
  Author URI: http://meowapps.com
9
  Text Domain: media-cleaner
@@ -16,10 +16,18 @@ Originally developed for two of my websites:
16
  - Haikyo (http://haikyo.org)
17
  */
18
 
 
 
 
 
 
 
 
 
19
  if ( is_admin() ) {
20
 
21
  global $wpmc_version;
22
- $wpmc_version = '4.1.0';
23
 
24
  // Admin
25
  require( 'wpmc_admin.php' );
3
  Plugin Name: Media Cleaner
4
  Plugin URI: http://meowapps.com
5
  Description: Clean your Media Library, many options, trash system.
6
+ Version: 4.2.0
7
  Author: Jordy Meow
8
  Author URI: http://meowapps.com
9
  Text Domain: media-cleaner
16
  - Haikyo (http://haikyo.org)
17
  */
18
 
19
+ if ( class_exists( 'Meow_WPMC_Core' ) ) {
20
+ function mfrh_admin_notices() {
21
+ echo '<div class="error"><p>Thanks for installing the Pro version of Media Cleaner :) However, the free version is still enabled. Please disable or uninstall it.</p></div>';
22
+ }
23
+ add_action( 'admin_notices', 'mfrh_admin_notices' );
24
+ return;
25
+ }
26
+
27
  if ( is_admin() ) {
28
 
29
  global $wpmc_version;
30
+ $wpmc_version = '4.2.0';
31
 
32
  // Admin
33
  require( 'wpmc_admin.php' );
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: TigrouMeow
3
  Tags: management, admin, file, files, images, image, media, library, upload, clean, cleaning
4
  Requires at least: 4.2
5
  Tested up to: 4.8
6
- Stable tag: 4.1.0
7
 
8
  Clean your Media Library and Uploads directory. It has an internal trash and recovery features. Please read the description.
9
 
@@ -50,6 +50,12 @@ It re-creates the Media Cleaner table in the database. You will need to re-run t
50
 
51
  == Changelog ==
52
 
 
 
 
 
 
 
53
  = 4.1.0 =
54
  * Add: Support for WooCommerce Gallery.
55
  * Add: Support for Visual Composer (Single Image and Gallery).
3
  Tags: management, admin, file, files, images, image, media, library, upload, clean, cleaning
4
  Requires at least: 4.2
5
  Tested up to: 4.8
6
+ Stable tag: 4.2.0
7
 
8
  Clean your Media Library and Uploads directory. It has an internal trash and recovery features. Please read the description.
9
 
50
 
51
  == Changelog ==
52
 
53
+ = 4.2.0 =
54
+ * Info: This is a MAJOR UPDATE both in term of optimization and detection. Keep my motivation up and give a good review to the plugin here: https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post. That helps me a lot.
55
+ * Add: Support for Fusion Builder (Avada).
56
+ * Add: Cache the results found in posts to analyze them much faster later.
57
+ * Add: Debugging log file (option).
58
+
59
  = 4.1.0 =
60
  * Add: Support for WooCommerce Gallery.
61
  * Add: Support for Visual Composer (Single Image and Gallery).
wpmc_admin.php CHANGED
@@ -73,6 +73,10 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
73
  array( $this, 'admin_utf8_callback' ),
74
  'wpmc_settings-menu', 'wpmc_settings' );
75
 
 
 
 
 
76
  // SUBMENU > Settings > UI
77
  add_settings_section( 'wpmc_ui_settings', null, null, 'wpmc_ui_settings-menu' );
78
  add_settings_field( 'wpmc_hide_thumbnails', "Thumbnails",
@@ -106,6 +110,7 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
106
  register_setting( 'wpmc_settings', 'wpmc_media_library' );
107
  register_setting( 'wpmc_settings', 'wpmc_postmeta' );
108
  register_setting( 'wpmc_settings', 'wpmc_utf8' );
 
109
 
110
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_thumbnails' );
111
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_warning' );
@@ -211,14 +216,15 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
211
  <?php
212
  global $shortcode_tags;
213
  try {
214
- $allshortcodes = array_diff( $shortcode_tags, array( ) );
215
- $my_shortcodes = array();
216
- foreach ( $allshortcodes as $sc )
217
- if ( $sc != '__return_false' ) {
218
- if ( is_string( $sc ) )
219
- array_push( $my_shortcodes, str_replace( '_shortcode', '', (string)$sc ) );
220
- }
221
- $my_shortcodes = implode( '<br />', $my_shortcodes );
 
222
  }
223
  catch (Exception $e) {
224
  $my_shortcodes = "";
@@ -256,7 +262,7 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
256
  $value = get_option( 'wpmc_shortcode', null );
257
  $html = '<input ' . disabled( $this->is_registered(), false, false ) . ' type="checkbox" id="wpmc_shortcode" name="wpmc_shortcode" value="1" ' .
258
  checked( 1, get_option( 'wpmc_shortcode' ), false ) . '/>';
259
- $html .= '<label>Analyze</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. This process takes resources and if the scanning suddenly stops, this might be the cause. You don\'t need to have this option enabled for the WP Gallery (this is covered by the Galleries option).</small>';
260
  echo $html;
261
  }
262
 
@@ -268,6 +274,22 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
268
  echo $html;
269
  }
270
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  function admin_media_library_callback( $args ) {
272
  $value = get_option( 'wpmc_media_library', null );
273
  $html = '<input type="checkbox" id="wpmc_media_library" name="wpmc_media_library" value="1" ' .
73
  array( $this, 'admin_utf8_callback' ),
74
  'wpmc_settings-menu', 'wpmc_settings' );
75
 
76
+ add_settings_field( 'wpmc_debuglogs', "Logs",
77
+ array( $this, 'admin_debuglogs_callback' ),
78
+ 'wpmc_settings-menu', 'wpmc_settings', array( "Enable" ) );
79
+
80
  // SUBMENU > Settings > UI
81
  add_settings_section( 'wpmc_ui_settings', null, null, 'wpmc_ui_settings-menu' );
82
  add_settings_field( 'wpmc_hide_thumbnails', "Thumbnails",
110
  register_setting( 'wpmc_settings', 'wpmc_media_library' );
111
  register_setting( 'wpmc_settings', 'wpmc_postmeta' );
112
  register_setting( 'wpmc_settings', 'wpmc_utf8' );
113
+ register_setting( 'wpmc_settings', 'wpmc_debuglogs' );
114
 
115
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_thumbnails' );
116
  register_setting( 'wpmc_ui_settings', 'wpmc_hide_warning' );
216
  <?php
217
  global $shortcode_tags;
218
  try {
219
+ if ( is_array( $shortcode_tags ) ) {
220
+ $my_shortcodes = array();
221
+ foreach ( $shortcode_tags as $sc )
222
+ if ( $sc != '__return_false' ) {
223
+ if ( is_string( $sc ) )
224
+ array_push( $my_shortcodes, str_replace( '_shortcode', '', (string)$sc ) );
225
+ }
226
+ $my_shortcodes = implode( '<br />', $my_shortcodes );
227
+ }
228
  }
229
  catch (Exception $e) {
230
  $my_shortcodes = "";
262
  $value = get_option( 'wpmc_shortcode', null );
263
  $html = '<input ' . disabled( $this->is_registered(), false, false ) . ' type="checkbox" id="wpmc_shortcode" name="wpmc_shortcode" value="1" ' .
264
  checked( 1, get_option( 'wpmc_shortcode' ), false ) . '/>';
265
+ $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>';
266
  echo $html;
267
  }
268
 
274
  echo $html;
275
  }
276
 
277
+ function admin_debuglogs_callback( $args ) {
278
+ $clearlogs = isset ( $_GET[ 'clearlogs' ] ) ? $_GET[ 'clearlogs' ] : 0;
279
+ if ( $clearlogs && file_exists( plugin_dir_path( __FILE__ ) . '/media-cleaner.log' ) ) {
280
+ file_put_contents( plugin_dir_path( __FILE__ ) . '/media-cleaner.log', '' );
281
+ }
282
+ $html = '<input type="checkbox" id="wpmc_debuglogs" name="wpmc_debuglogs" value="1" ' .
283
+ checked( 1, get_option( 'wpmc_debuglogs' ), false ) . '/>';
284
+ $html .= '<label for="wpmc_debuglogs"> ' . $args[0] . '</label><br>';
285
+ $html .= '<span class="description">' . __( 'Create an internal log file. For advanced users only.', 'media-cleaner' );
286
+ if ( file_exists( plugin_dir_path( __FILE__ ) . '/media-cleaner.log' ) ) {
287
+ $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__ ) );
288
+ }
289
+ $html .= '</span>';
290
+ echo $html;
291
+ }
292
+
293
  function admin_media_library_callback( $args ) {
294
  $value = get_option( 'wpmc_media_library', null );
295
  $html = '<input type="checkbox" id="wpmc_media_library" name="wpmc_media_library" value="1" ' .
wpmc_checkers.php CHANGED
@@ -11,43 +11,70 @@ class Meow_WPMC_Checkers {
11
  $this->core = $core;
12
  }
13
 
14
- function has_background_or_header( $file ) {
15
  if ( current_theme_supports( 'custom-header' ) ) {
16
  $custom_header = get_custom_header();
17
  if ( $custom_header && $custom_header->url ) {
18
  if ( strpos( $custom_header->url, $file ) !== false ) {
19
- if ($this->core->debug)
20
- error_log("{$file} found in header");
21
  return true;
22
  }
23
  }
24
  }
25
 
26
  if ( current_theme_supports( 'custom-background' ) ) {
27
- $custom_background = get_theme_mod('background_image');
28
  if ( $custom_background ) {
29
  if ( strpos( $custom_background, $file ) !== false ) {
30
- if ($this->core->debug)
31
- error_log("{$file} found in background");
32
  return true;
33
  }
34
  }
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  return false;
38
  }
39
 
40
- function check_in_gallery( $file, $attachment_id = 0 ) {
41
 
42
  if ( !get_option( 'wpmc_galleries', false ) )
43
  return false;
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 ( in_array( $attachment_id, $galleries_images_vc ) ) {
49
- if ( $this->core->debug )
50
- error_log( "Media {$attachment_id} found in a Visual Composer gallery" );
 
 
 
 
 
 
 
 
51
  return true;
52
  }
53
  }
@@ -55,35 +82,23 @@ class Meow_WPMC_Checkers {
55
  // Check in WooCommerce Galleries
56
  if ( class_exists( 'WooCommerce' ) ) {
57
  $galleries_images_wc = get_transient( "wpmc_galleries_images_woocommerce" );
58
- if ( in_array( $attachment_id, $galleries_images_wc ) ) {
59
- if ( $this->core->debug )
60
- error_log( "Media {$attachment_id} found in a WooCommerce gallery" );
61
  return true;
62
  }
63
  }
64
 
65
- // Check in standard WP Galleries
66
- $file = $this->core->wpmc_clean_uploaded_filename( $file );
67
- $uploads = wp_upload_dir();
68
- $parsedURL = parse_url( $uploads['baseurl'] );
69
- $regex_match_file = '(' . preg_quote( $file ) . ')';
70
- $regex = addcslashes( '(?:(?:http(?:s)?\\:)?//' .
71
- preg_quote( $parsedURL['host'] ).')?' .
72
- preg_quote( $parsedURL['path'] ) . '/' . $regex_match_file, '/');
73
- $images = get_transient( "wpmc_galleries_images" );
74
- if ( !empty( $images ) ) {
75
- foreach ( $images as $image ) {
76
- $found = preg_match('/' . $regex . '/i', $image);
77
- if ( $this->core->debug && $found )
78
- error_log("{$file} found in a gallery");
79
- if ( $found )
80
- return true;
81
- }
82
  }
 
83
  return false;
84
  }
85
 
86
- function has_meta( $file, $attachment_id = 0 ) {
87
 
88
  if ( !get_option( 'wpmc_postmeta', true ) )
89
  return false;
@@ -97,14 +112,14 @@ class Meow_WPMC_Checkers {
97
  preg_quote( $parsedURL['host']) . ')?(?:' .
98
  preg_quote( $parsedURL['path']) . '/)|^)' . $regex_match_file, '/');
99
  $regex_mysql = str_replace( '(?:', '(', $regex );
100
- if ( $attachment_id > 0 ) {
101
  $mediaCount = $wpdb->get_var(
102
  $wpdb->prepare( "SELECT COUNT(*)
103
  FROM $wpdb->postmeta
104
  WHERE post_id != %d
105
  AND meta_key != '_wp_attached_file'
106
  AND (meta_value REGEXP %s OR meta_value = %d)",
107
- $attachment_id, $regex_mysql, $attachment_id
108
  )
109
  );
110
  } else {
@@ -117,8 +132,8 @@ class Meow_WPMC_Checkers {
117
  )
118
  );
119
  }
120
- if ( $this->core->debug && $mediaCount > 0 )
121
- error_log("{$file} found in POSTMETA");
122
  return $mediaCount > 0;
123
  }
124
 
@@ -128,132 +143,50 @@ class Meow_WPMC_Checkers {
128
  global $wpdb;
129
  $this->core->last_analysis_ids = null;
130
  $shortcode_support = get_option( 'wpmc_shortcode', false );
 
 
 
 
131
 
132
  // Check in Posts Content
133
  if ( get_option( 'wpmc_posts', true ) ) {
134
 
135
- // Galleries in Visual Composer (WPBakery)
136
- if ( class_exists( 'Vc_Manager' ) ) {
137
- $posts_images_vc = get_transient( "wpmc_posts_images_visualcomposer" );
138
- if ( in_array( $mediaId, $posts_images_vc ) ) {
139
- if ( $this->core->debug )
140
- error_log( "Media {$mediaId} found in post_content (Visual Composer)" );
141
- return true;
142
- }
143
- }
144
-
145
- // Search through the CSS class
146
  if ( !empty( $mediaId ) ) {
147
- $sql = $wpdb->prepare( "SELECT ID
148
- FROM $wpdb->posts
149
- WHERE post_type <> 'revision'
150
- AND post_type <> 'attachment'
151
- AND post_content LIKE %s", "%wp-image-$mediaId%" );
152
- $foundIds = $wpdb->get_col( $sql );
153
- $this->core->last_analysis_ids = $foundIds;
154
- $mediaCount = count( $foundIds );
155
- if ( $this->core->debug && $mediaCount > 0 )
156
- error_log( "Media {$mediaId} found in post_content, $mediaCount time(s)" );
157
- if ( $mediaCount > 0 )
158
  return true;
159
- }
160
-
161
- // Search through the filename
162
- $file = $this->core->wpmc_clean_uploaded_filename( $file );
163
- $uploads = wp_upload_dir();
164
- $parsedURL = parse_url( $uploads['baseurl'] );
165
- $pinfo = pathinfo( $file );
166
- $regex_match_file = '(' . $pinfo['dirname'] . '/' . $pinfo['filename'] . "(\\-[0-9]{1,8}x[0-9]{1,8})?\\." .
167
- ( isset( $pinfo['extension'] ) ? $pinfo['extension'] : '' ) . ')';
168
-
169
- // SUPER STRICT MODE
170
- // $regex = addcslashes('=[\'"](?:(?:http(?:s)?\\:)?//'
171
- // . preg_quote( $parsedURL['host'] ) . ')?'
172
- // . preg_quote( $parsedURL['path'] ) . '/'
173
- // . $regex_match_file . '(?:\\?[^\'"]*)*[\'"]', '/' );
174
-
175
- // NORMAL REGEX
176
- $regex = addcslashes( preg_quote( $parsedURL['path']) . '/' . $regex_match_file . '(?:\\?[^\'"]*)*[\'"]', '/' );
177
- $regex_mysql = str_replace('(?:', '(', $regex);
178
- $sql = $wpdb->prepare( "SELECT ID
179
- FROM $wpdb->posts
180
- WHERE post_type <> 'revision'
181
- AND post_type <> 'attachment'
182
- AND post_content REGEXP %s", $regex_mysql );
183
- $foundIds = $wpdb->get_col( $sql );
184
- $this->core->last_analysis_ids = $foundIds;
185
- $mediaCount = count( $foundIds );
186
- if ( $this->core->debug && $mediaCount > 0 )
187
- error_log( "File {$file} found in post_content, $mediaCount time(s)" );
188
- if ( $mediaCount > 0 )
189
- return true;
190
- }
191
-
192
- // Shortcode analysis
193
- global $shortcode_tags;
194
- $active_tags = array_keys( $shortcode_tags );
195
- if ( !empty( $active_tags ) ) {
196
- $post_contents = get_transient( 'wpmc_posts_with_shortcode' );
197
- if ( $post_contents === false ) {
198
-
199
- $post_contents = array();
200
-
201
- // Resolve shortcodes from posts
202
- if ( $shortcode_support ) {
203
- $query = array();
204
- $query[] = "SELECT ID, post_content FROM {$wpdb->posts}";
205
- $query[] = "WHERE post_type <> 'revision' AND post_type <> 'attachment'";
206
- $sub_query = array();
207
- foreach ( $active_tags as $tag ) {
208
- $sub_query[] = "post_content LIKE '%[" . esc_sql( $wpdb->esc_like( $tag ) ) . "%'";
209
- }
210
- $query[] = "AND (" . implode ( " OR ", $sub_query ) . ")";
211
- $sql = join( ' ', $query );
212
- $results = $wpdb->get_results( $sql );
213
- foreach ( $results as $key => $data ) {
214
- $post_contents['post_' . $data->ID] = do_shortcode( $data->post_content );
215
- }
216
  }
217
 
218
- // Read Widgets
219
- if ( get_option( 'wpmc_widgets', false ) ) {
220
- global $wp_registered_widgets;
221
- $active_widgets = get_option( 'sidebars_widgets' );
222
- foreach ( $active_widgets as $sidebar_name => $sidebar_widgets ) {
223
- if ( $sidebar_name != 'wp_inactive_widgets' && !empty( $sidebar_widgets ) && is_array( $sidebar_widgets ) ) {
224
- $i = 0;
225
- foreach ( $sidebar_widgets as $widget_instance ) {
226
- $widget_class = $wp_registered_widgets[$widget_instance]['callback'][0]->option_name;
227
- $instance_id = $wp_registered_widgets[$widget_instance]['params'][0]['number'];
228
- $widget_data = get_option($widget_class);
229
- if ( !empty( $widget_data[$instance_id]['text'] ) ) {
230
-
231
- // Resolve Widgets or just get them
232
- if ( $shortcode_support )
233
- $post_contents['widget_' . $i] = do_shortcode( $widget_data[$instance_id]['text'] );
234
- else
235
- $post_contents['widget_' . $i] = $widget_data[$instance_id]['text'];
236
- }
237
- $i++;
238
- }
239
- }
240
  }
241
  }
 
242
 
243
- if ( !empty( $post_contents ) )
244
- set_transient( 'wpmc_posts_with_shortcode', $post_contents, 2 * 60 * 60 );
 
 
 
245
  }
 
246
 
247
- if ( !empty( $post_contents ) ) {
248
- foreach ( $post_contents as $key => $content ) {
249
- $found = preg_match( '/' . $regex . '/i', $content );
250
- if ( $this->core->debug && $found )
251
- error_log( "File Cleaner: {$file} found in {$key} shortcode or widget" );
252
- if ( $found )
253
- return true;
254
- }
255
  }
256
  }
 
257
  return false;
258
  }
259
 
11
  $this->core = $core;
12
  }
13
 
14
+ function has_background_or_header( $file, $mediaId ) {
15
  if ( current_theme_supports( 'custom-header' ) ) {
16
  $custom_header = get_custom_header();
17
  if ( $custom_header && $custom_header->url ) {
18
  if ( strpos( $custom_header->url, $file ) !== false ) {
19
+ $this->core->log( "{$file} found in theme (Custom Header)" );
 
20
  return true;
21
  }
22
  }
23
  }
24
 
25
  if ( current_theme_supports( 'custom-background' ) ) {
26
+ $custom_background = get_theme_mod( 'background_image' );
27
  if ( $custom_background ) {
28
  if ( strpos( $custom_background, $file ) !== false ) {
29
+ $this->core->log( "{$file} found in theme (Custom Background)" );
 
30
  return true;
31
  }
32
  }
33
  }
34
 
35
+ // Support for Kantan Theme
36
+ $photography_hero_image = get_theme_mod( 'photography_hero_image' );
37
+ if ( !empty( $photography_hero_image ) ) {
38
+ if ( $photography_hero_image == $mediaId ) {
39
+ $this->core->log( "{$file} found in theme (Photography Hero Image)" );
40
+ return true;
41
+ }
42
+ }
43
+ $author_profile_picture = get_theme_mod( 'author_profile_picture' );
44
+ if ( !empty( $author_profile_picture ) ) {
45
+ if ( $author_profile_picture == $mediaId ) {
46
+ $this->core->log( "{$file} found in theme (Author Profile Photo)" );
47
+ return true;
48
+ }
49
+ }
50
+
51
  return false;
52
  }
53
 
54
+ function check_in_gallery( $file, $mediaId = 0 ) {
55
 
56
  if ( !get_option( 'wpmc_galleries', false ) )
57
  return false;
58
 
59
+ $file = $this->core->wpmc_clean_uploaded_filename( $file );
60
+ $pinfo = pathinfo( $file );
61
+ $url = $pinfo['dirname'] . '/' . $pinfo['filename'] .
62
+ ( isset( $pinfo['extension'] ) ? ( '.' . $pinfo['extension'] ) : '' );
63
+
64
  // Galleries in Visual Composer (WPBakery)
65
  if ( class_exists( 'Vc_Manager' ) ) {
66
  $galleries_images_vc = get_transient( "wpmc_galleries_images_visualcomposer" );
67
+ if ( in_array( $mediaId, $galleries_images_vc ) ) {
68
+ $this->core->log( "Media {$mediaId} found in a Visual Composer gallery" );
69
+ return true;
70
+ }
71
+ }
72
+
73
+ // Galleries in Fusion Builder (Avada Theme)
74
+ if ( function_exists( 'fusion_builder_map' ) ) {
75
+ $galleries_images_fb = get_transient( "wpmc_galleries_images_fusionbuilder" );
76
+ if ( in_array( $mediaId, $galleries_images_fb ) ) {
77
+ $this->core->log( "Media {$mediaId} found in post_content (Fusion Builder)" );
78
  return true;
79
  }
80
  }
82
  // Check in WooCommerce Galleries
83
  if ( class_exists( 'WooCommerce' ) ) {
84
  $galleries_images_wc = get_transient( "wpmc_galleries_images_woocommerce" );
85
+ if ( in_array( $mediaId, $galleries_images_wc ) ) {
86
+ $this->core->log( "Media {$mediaId} found in a WooCommerce gallery" );
 
87
  return true;
88
  }
89
  }
90
 
91
+ // Check in standard WP Galleries (URLS)
92
+ $galleries_images = get_transient( "wpmc_galleries_images" );
93
+ if ( in_array( $file, $galleries_images ) ) {
94
+ $this->core->log( "URL {$file} found in a standard WP Gallery" );
95
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
+
98
  return false;
99
  }
100
 
101
+ function has_meta( $file, $mediaId = 0 ) {
102
 
103
  if ( !get_option( 'wpmc_postmeta', true ) )
104
  return false;
112
  preg_quote( $parsedURL['host']) . ')?(?:' .
113
  preg_quote( $parsedURL['path']) . '/)|^)' . $regex_match_file, '/');
114
  $regex_mysql = str_replace( '(?:', '(', $regex );
115
+ if ( $mediaId > 0 ) {
116
  $mediaCount = $wpdb->get_var(
117
  $wpdb->prepare( "SELECT COUNT(*)
118
  FROM $wpdb->postmeta
119
  WHERE post_id != %d
120
  AND meta_key != '_wp_attached_file'
121
  AND (meta_value REGEXP %s OR meta_value = %d)",
122
+ $mediaId, $regex_mysql, $mediaId
123
  )
124
  );
125
  } else {
132
  )
133
  );
134
  }
135
+ if ( $mediaCount > 0 )
136
+ $this->core->log( "{$file} found in Post Meta" );
137
  return $mediaCount > 0;
138
  }
139
 
143
  global $wpdb;
144
  $this->core->last_analysis_ids = null;
145
  $shortcode_support = get_option( 'wpmc_shortcode', false );
146
+ $file = $this->core->wpmc_clean_uploaded_filename( $file );
147
+ $pinfo = pathinfo( $file );
148
+ $url = $pinfo['dirname'] . '/' . $pinfo['filename'] .
149
+ ( isset( $pinfo['extension'] ) ? ( '.' . $pinfo['extension'] ) : '' );
150
 
151
  // Check in Posts Content
152
  if ( get_option( 'wpmc_posts', true ) ) {
153
 
 
 
 
 
 
 
 
 
 
 
 
154
  if ( !empty( $mediaId ) ) {
155
+ // Search through the CSS class
156
+ $posts_images_ids = get_transient( "wpmc_posts_images_ids" );
157
+ if ( in_array( $mediaId, $posts_images_ids ) ) {
158
+ $this->core->log( "Media {$mediaId} found in content (Posts Images IDs)" );
 
 
 
 
 
 
 
159
  return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  }
161
 
162
+ // Posts in Visual Composer (WPBakery)
163
+ if ( class_exists( 'Vc_Manager' ) ) {
164
+ $posts_images_vc = get_transient( "wpmc_posts_images_visualcomposer" );
165
+ if ( in_array( $mediaId, $posts_images_vc ) ) {
166
+ $this->core->log( "Media {$mediaId} found in content (Visual Composer)" );
167
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  }
169
  }
170
+ }
171
 
172
+ // Search through the filename
173
+ $posts_images_urls = get_transient( "wpmc_posts_images_urls" );
174
+ if ( in_array( $url, $posts_images_urls ) ) {
175
+ $this->core->log( "URL {$url} found in content (Posts Images URLs)" );
176
+ return true;
177
  }
178
+ }
179
 
180
+ // Search in widgets
181
+ if ( get_option( 'wpmc_widgets', false ) ) {
182
+ $widgets_images = get_transient( "wpmc_widgets_images" );
183
+ if ( in_array( $url, $widgets_images ) ) {
184
+ $this->core->log( "URL {$url} found in widgets (Widgets Images)" );
185
+ $this->core->last_analysis = "WIDGET";
186
+ return true;
 
187
  }
188
  }
189
+
190
  return false;
191
  }
192