Version Description
- Add: Always Skip/Retry feature.
- Add: "Images Only" for Media Library scan.
- Add: Support for Salient theme.
- Info: This plugin is a lot of work. Please help me by giving it a nice review, here.
Download this release
Release Info
Developer | TigrouMeow |
Plugin | Media Cleaner |
Version | 5.6.2 |
Comparing to | |
See all releases |
Code changes from version 5.6.1 to 5.6.2
- admin.php +13 -2
- api.php +40 -3
- engine.php +60 -26
- media-cleaner.php +2 -2
- readme.txt +8 -7
- scripts/dashboard.js +157 -30
- scripts/style.css +9 -0
- views/menu-screen.php +8 -0
admin.php
CHANGED
@@ -104,6 +104,9 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
|
|
104 |
|
105 |
// SUBMENU > Settings > Filters
|
106 |
add_settings_section( 'wpmc_filters_settings', null, null, 'wpmc_filters_settings-menu' );
|
|
|
|
|
|
|
107 |
add_settings_field( 'wpmc_thumbnails_only', __( 'Thumbnails Only', 'media-cleaner' ),
|
108 |
array( $this, 'admin_thumbnails_only_callback' ),
|
109 |
'wpmc_filters_settings-menu', 'wpmc_filters_settings' );
|
@@ -161,6 +164,7 @@ class Meow_WPMC_Admin extends MeowApps_Admin {
|
|
161 |
register_setting( 'wpmc_settings', 'wpmc_media_library' );
|
162 |
register_setting( 'wpmc_settings', 'wpmc_debuglogs' );
|
163 |
|
|
|
164 |
register_setting( 'wpmc_filters_settings', 'wpmc_thumbnails_only' );
|
165 |
register_setting( 'wpmc_filters_settings', 'wpmc_dirs_filter' );
|
166 |
register_setting( 'wpmc_filters_settings', 'wpmc_files_filter' );
|
@@ -413,12 +417,19 @@ HTML;
|
|
413 |
echo $html;
|
414 |
}
|
415 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
416 |
function admin_thumbnails_only_callback( $args ) {
|
417 |
-
$value = get_option( 'wpmc_thumbnails_only', false );
|
418 |
$html = '<input type="checkbox" id="wpmc_thumbnails_only" name="wpmc_thumbnails_only" value="1" ' .
|
419 |
disabled( get_option( 'wpmc_method', 'media' ) == 'files', false, false ) . ' ' .
|
420 |
checked( 1, get_option( 'wpmc_thumbnails_only' ), false ) . '/>';
|
421 |
-
$html .= '<label>' . __( 'Enable', 'media-cleaner' ) . '</label><br /><small>' . __( 'Restrict the
|
422 |
echo $html;
|
423 |
}
|
424 |
|
104 |
|
105 |
// SUBMENU > Settings > Filters
|
106 |
add_settings_section( 'wpmc_filters_settings', null, null, 'wpmc_filters_settings-menu' );
|
107 |
+
add_settings_field( 'wpmc_images_only', __( 'Images Only', 'media-cleaner' ),
|
108 |
+
array( $this, 'admin_images_only_callback' ),
|
109 |
+
'wpmc_filters_settings-menu', 'wpmc_filters_settings' );
|
110 |
add_settings_field( 'wpmc_thumbnails_only', __( 'Thumbnails Only', 'media-cleaner' ),
|
111 |
array( $this, 'admin_thumbnails_only_callback' ),
|
112 |
'wpmc_filters_settings-menu', 'wpmc_filters_settings' );
|
164 |
register_setting( 'wpmc_settings', 'wpmc_media_library' );
|
165 |
register_setting( 'wpmc_settings', 'wpmc_debuglogs' );
|
166 |
|
167 |
+
register_setting( 'wpmc_filters_settings', 'wpmc_images_only' );
|
168 |
register_setting( 'wpmc_filters_settings', 'wpmc_thumbnails_only' );
|
169 |
register_setting( 'wpmc_filters_settings', 'wpmc_dirs_filter' );
|
170 |
register_setting( 'wpmc_filters_settings', 'wpmc_files_filter' );
|
417 |
echo $html;
|
418 |
}
|
419 |
|
420 |
+
function admin_images_only_callback( $args ) {
|
421 |
+
$html = '<input type="checkbox" id="wpmc_images_only" name="wpmc_images_only" value="1" ' .
|
422 |
+
disabled( get_option( 'wpmc_method', 'media' ) == 'media', false, false ) . ' ' .
|
423 |
+
checked( 1, get_option( 'wpmc_images_only' ), false ) . '/>';
|
424 |
+
$html .= '<label>' . __( 'Enable', 'media-cleaner' ) . '</label><br /><small>' . __( 'Restrict the Media Library scan to images. Therefore, no documents or anything else will be scanned.', 'media-cleaner' ) . '</small>';
|
425 |
+
echo $html;
|
426 |
+
}
|
427 |
+
|
428 |
function admin_thumbnails_only_callback( $args ) {
|
|
|
429 |
$html = '<input type="checkbox" id="wpmc_thumbnails_only" name="wpmc_thumbnails_only" value="1" ' .
|
430 |
disabled( get_option( 'wpmc_method', 'media' ) == 'files', false, false ) . ' ' .
|
431 |
checked( 1, get_option( 'wpmc_thumbnails_only' ), false ) . '/>';
|
432 |
+
$html .= '<label>' . __( 'Enable', 'media-cleaner' ) . '</label><br /><small>' . __( 'Restrict the Filesystem scan to thumbnails (files containing the resolution). If none of the checks above are selected, you will get the list of all the images and be able to remove them.', 'media-cleaner' ) . '</small>';
|
433 |
echo $html;
|
434 |
}
|
435 |
|
api.php
CHANGED
@@ -2,10 +2,16 @@
|
|
2 |
|
3 |
class Meow_WPMC_API {
|
4 |
|
|
|
|
|
|
|
|
|
|
|
5 |
function __construct( $core, $admin, $engine ) {
|
6 |
$this->core = $core;
|
7 |
$this->engine = $engine;
|
8 |
$this->admin = $admin;
|
|
|
9 |
add_action( 'wp_ajax_wpmc_extract_references', array( $this, 'wp_ajax_wpmc_extract_references' ) );
|
10 |
add_action( 'wp_ajax_wpmc_retrieve_targets', array( $this, 'wp_ajax_wpmc_retrieve_targets' ) );
|
11 |
add_action( 'wp_ajax_wpmc_check_targets', array( $this, 'wp_ajax_wpmc_check_targets' ) );
|
@@ -21,17 +27,48 @@ class Meow_WPMC_API {
|
|
21 |
* ASYNCHRONOUS AJAX FUNCTIONS
|
22 |
******************************************************************************/
|
23 |
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
function wp_ajax_wpmc_extract_references() {
|
26 |
$limit = isset( $_POST['limit'] ) ? $_POST['limit'] : 0;
|
27 |
$source = isset( $_POST['source'] ) ? $_POST['source'] : null;
|
28 |
$limitsize = get_option( 'wpmc_posts_buffer', 5 );
|
29 |
|
30 |
$finished = false;
|
|
|
31 |
if ( $source === 'content' )
|
32 |
-
$finished = $this->engine->extractRefsFromContent( $limit, $limitsize, $message );
|
33 |
else if ( $source === 'media' )
|
34 |
-
$finished = $this->engine->extractRefsFromLibrary( $limit, $limitsize, $message );
|
35 |
else {
|
36 |
error_log('Media Cleaner: No source was mentioned while calling the extract_references action.');
|
37 |
}
|
2 |
|
3 |
class Meow_WPMC_API {
|
4 |
|
5 |
+
/**
|
6 |
+
* @param Meow_WPMC_Core $core
|
7 |
+
* @param Meow_WPMC_Admin $admin
|
8 |
+
* @param Meow_WPMC_Engine $engine
|
9 |
+
*/
|
10 |
function __construct( $core, $admin, $engine ) {
|
11 |
$this->core = $core;
|
12 |
$this->engine = $engine;
|
13 |
$this->admin = $admin;
|
14 |
+
add_action( 'wp_ajax_wpmc_get_num_posts', array( $this, 'wp_ajax_wpmc_get_num_posts' ) );
|
15 |
add_action( 'wp_ajax_wpmc_extract_references', array( $this, 'wp_ajax_wpmc_extract_references' ) );
|
16 |
add_action( 'wp_ajax_wpmc_retrieve_targets', array( $this, 'wp_ajax_wpmc_retrieve_targets' ) );
|
17 |
add_action( 'wp_ajax_wpmc_check_targets', array( $this, 'wp_ajax_wpmc_check_targets' ) );
|
27 |
* ASYNCHRONOUS AJAX FUNCTIONS
|
28 |
******************************************************************************/
|
29 |
|
30 |
+
/**
|
31 |
+
* Method: POST
|
32 |
+
* Params:
|
33 |
+
* - source: 'content' | 'media'
|
34 |
+
* Return:
|
35 |
+
* - data.action: 'get_num_posts'
|
36 |
+
* - data.num: A number of the posts
|
37 |
+
*/
|
38 |
+
function wp_ajax_wpmc_get_num_posts() {
|
39 |
+
$src = isset( $_POST['source'] ) ? $_POST['source'] : null;
|
40 |
+
$num = 0;
|
41 |
+
|
42 |
+
switch ($src) {
|
43 |
+
case 'content':
|
44 |
+
$num = count( $this->engine->get_posts_to_check() );
|
45 |
+
break;
|
46 |
+
case 'media':
|
47 |
+
$num = count( $this->engine->get_media_entries() );
|
48 |
+
break;
|
49 |
+
}
|
50 |
+
|
51 |
+
exit( json_encode( array (
|
52 |
+
'success' => true,
|
53 |
+
'data' => array (
|
54 |
+
'action' => 'get_num_posts',
|
55 |
+
'num' => $num
|
56 |
+
)
|
57 |
+
)));
|
58 |
+
}
|
59 |
+
|
60 |
+
// Analyze the posts to extract the references.
|
61 |
function wp_ajax_wpmc_extract_references() {
|
62 |
$limit = isset( $_POST['limit'] ) ? $_POST['limit'] : 0;
|
63 |
$source = isset( $_POST['source'] ) ? $_POST['source'] : null;
|
64 |
$limitsize = get_option( 'wpmc_posts_buffer', 5 );
|
65 |
|
66 |
$finished = false;
|
67 |
+
$message = ""; // will be filled by extractRefsFrom...
|
68 |
if ( $source === 'content' )
|
69 |
+
$finished = $this->engine->extractRefsFromContent( $limit, $limitsize, $message );
|
70 |
else if ( $source === 'media' )
|
71 |
+
$finished = $this->engine->extractRefsFromLibrary( $limit, $limitsize, $message );
|
72 |
else {
|
73 |
error_log('Media Cleaner: No source was mentioned while calling the extract_references action.');
|
74 |
}
|
engine.php
CHANGED
@@ -11,6 +11,37 @@ class Meow_WPMC_Engine {
|
|
11 |
STEP 1: Parse the content, and look for references
|
12 |
*/
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
// Parse the posts for references (based on $limit and $limitsize for paging the scan)
|
15 |
function extractRefsFromContent( $limit, $limitsize, &$message = '' ) {
|
16 |
if ( empty( $limit ) )
|
@@ -36,18 +67,7 @@ class Meow_WPMC_Engine {
|
|
36 |
do_action( 'wpmc_initialize_parsers' );
|
37 |
|
38 |
global $wpdb;
|
39 |
-
|
40 |
-
// SELECT post_type, COUNT(*) FROM `wp_posts` GROUP BY post_type
|
41 |
-
$posts = $wpdb->get_col( $wpdb->prepare( "SELECT p.ID FROM $wpdb->posts p
|
42 |
-
WHERE p.post_status NOT IN ('inherit', 'trash', 'auto-draft')
|
43 |
-
AND p.post_type NOT IN ('attachment', 'shop_order', 'shop_order_refund', 'nav_menu_item', 'revision', 'auto-draft', 'wphb_minify_group', 'customize_changeset', 'oembed_cache', 'nf_sub')
|
44 |
-
AND p.post_type NOT LIKE 'dlssus_%'
|
45 |
-
AND p.post_type NOT LIKE 'ml-slide%'
|
46 |
-
AND p.post_type NOT LIKE '%acf-%'
|
47 |
-
AND p.post_type NOT LIKE '%edd_%'
|
48 |
-
LIMIT %d, %d", $limit, $limitsize
|
49 |
-
)
|
50 |
-
);
|
51 |
|
52 |
// Only at the beginning
|
53 |
if ( empty( $limit ) ) {
|
@@ -116,12 +136,7 @@ class Meow_WPMC_Engine {
|
|
116 |
}
|
117 |
|
118 |
global $wpdb;
|
119 |
-
$medias = $
|
120 |
-
WHERE p.post_status = 'inherit'
|
121 |
-
AND p.post_type = 'attachment'
|
122 |
-
LIMIT %d, %d", $limit, $limitsize
|
123 |
-
)
|
124 |
-
);
|
125 |
|
126 |
// Only at the beginning
|
127 |
if ( empty( $limit ) ) {
|
@@ -158,15 +173,34 @@ class Meow_WPMC_Engine {
|
|
158 |
return $files;
|
159 |
}
|
160 |
|
161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
global $wpdb;
|
163 |
-
$
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
}
|
171 |
|
172 |
/*
|
11 |
STEP 1: Parse the content, and look for references
|
12 |
*/
|
13 |
|
14 |
+
/**
|
15 |
+
* Returns the posts to check the references
|
16 |
+
* @param int $offset Negative number means no limit
|
17 |
+
* @param int $size Negative number means no limit
|
18 |
+
* @return NULL|array
|
19 |
+
*/
|
20 |
+
function get_posts_to_check( $offset = -1, $size = -1 ) {
|
21 |
+
global $wpdb;
|
22 |
+
$r = null;
|
23 |
+
|
24 |
+
// Maybe we could avoid to check more post_types.
|
25 |
+
// SELECT post_type, COUNT(*) FROM `wp_posts` GROUP BY post_type
|
26 |
+
$q = <<<SQL
|
27 |
+
SELECT p.ID FROM $wpdb->posts p
|
28 |
+
WHERE p.post_status NOT IN ('inherit', 'trash', 'auto-draft')
|
29 |
+
AND p.post_type NOT IN ('attachment', 'shop_order', 'shop_order_refund', 'nav_menu_item', 'revision', 'auto-draft', 'wphb_minify_group', 'customize_changeset', 'oembed_cache', 'nf_sub')
|
30 |
+
AND p.post_type NOT LIKE 'dlssus_%'
|
31 |
+
AND p.post_type NOT LIKE 'ml-slide%'
|
32 |
+
AND p.post_type NOT LIKE '%acf-%'
|
33 |
+
AND p.post_type NOT LIKE '%edd_%'
|
34 |
+
SQL;
|
35 |
+
if ( $offset >= 0 && $size >= 0 ) {
|
36 |
+
$q .= " LIMIT %d, %d";
|
37 |
+
$r = $wpdb->get_col( $wpdb->prepare( $q, $offset, $size ) );
|
38 |
+
|
39 |
+
} else // No limit
|
40 |
+
$r = $wpdb->get_col( $q );
|
41 |
+
|
42 |
+
return $r;
|
43 |
+
}
|
44 |
+
|
45 |
// Parse the posts for references (based on $limit and $limitsize for paging the scan)
|
46 |
function extractRefsFromContent( $limit, $limitsize, &$message = '' ) {
|
47 |
if ( empty( $limit ) )
|
67 |
do_action( 'wpmc_initialize_parsers' );
|
68 |
|
69 |
global $wpdb;
|
70 |
+
$posts = $this->get_posts_to_check( $limit, $limitsize );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
|
72 |
// Only at the beginning
|
73 |
if ( empty( $limit ) ) {
|
136 |
}
|
137 |
|
138 |
global $wpdb;
|
139 |
+
$medias = $this->get_media_entries( $limit, $limitsize );
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
// Only at the beginning
|
142 |
if ( empty( $limit ) ) {
|
173 |
return $files;
|
174 |
}
|
175 |
|
176 |
+
/**
|
177 |
+
* Returns the media entries to check the references
|
178 |
+
* @param int $offset Negative number means no limit
|
179 |
+
* @param int $size Negative number means no limit
|
180 |
+
* @return NULL|array
|
181 |
+
*/
|
182 |
+
function get_media_entries( $offset = -1, $size = -1 ) {
|
183 |
global $wpdb;
|
184 |
+
$r = null;
|
185 |
+
|
186 |
+
$q = <<<SQL
|
187 |
+
SELECT p.ID FROM $wpdb->posts p
|
188 |
+
WHERE p.post_status = 'inherit'
|
189 |
+
AND p.post_type = 'attachment'
|
190 |
+
SQL;
|
191 |
+
if ( get_option( 'wpmc_images_only' ) ) {
|
192 |
+
// Get only media entries which are images
|
193 |
+
$q .= " AND p.post_mime_type IN ( 'image/jpeg' )";
|
194 |
+
}
|
195 |
+
|
196 |
+
if ( $offset >= 0 && $size >= 0 ) {
|
197 |
+
$q .= " LIMIT %d, %d";
|
198 |
+
$r = $wpdb->get_col( $wpdb->prepare( $q, $offset, $size ) );
|
199 |
+
|
200 |
+
} else // No limit
|
201 |
+
$r = $wpdb->get_col( $q );
|
202 |
+
|
203 |
+
return $r;
|
204 |
}
|
205 |
|
206 |
/*
|
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: 5.6.
|
7 |
Author: Jordy Meow
|
8 |
Author URI: https://meowapps.com
|
9 |
Text Domain: media-cleaner
|
@@ -25,7 +25,7 @@ if ( is_admin() ) {
|
|
25 |
|
26 |
global $wpmc_version;
|
27 |
global $wpmc;
|
28 |
-
$wpmc_version = '5.6.
|
29 |
|
30 |
require __DIR__ . '/admin.php';
|
31 |
require __DIR__ . '/core.php';
|
3 |
Plugin Name: Media Cleaner
|
4 |
Plugin URI: https://meowapps.com
|
5 |
Description: Clean your Media Library, many options, trash system.
|
6 |
+
Version: 5.6.2
|
7 |
Author: Jordy Meow
|
8 |
Author URI: https://meowapps.com
|
9 |
Text Domain: media-cleaner
|
25 |
|
26 |
global $wpmc_version;
|
27 |
global $wpmc;
|
28 |
+
$wpmc_version = '5.6.2';
|
29 |
|
30 |
require __DIR__ . '/admin.php';
|
31 |
require __DIR__ . '/core.php';
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Donate link: https://commerce.coinbase.com/checkout/d047546a-77a8-41c8-9ea9-4a95
|
|
5 |
Requires at least: 4.8
|
6 |
Tested up to: 5.3
|
7 |
Requires PHP: 7.0
|
8 |
-
Stable tag: 5.6.
|
9 |
|
10 |
Clean your WordPress from unused or broken media and files. It has its own trash system and recovery features. Please read the description.
|
11 |
|
@@ -74,9 +74,14 @@ Better to be safe than sorry. This plugin deletes files! Therefore, backup is no
|
|
74 |
|
75 |
== Changelog ==
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
= 5.6.1 =
|
78 |
* Add: You can now sort the results by size and path. Little present for the week-end ;)
|
79 |
-
* Info: This plugin is a lot of work. Please help me by giving it a nice review, [here](https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post).
|
80 |
|
81 |
= 5.5.8 =
|
82 |
* Add: Support for Image Map Pro.
|
@@ -86,7 +91,6 @@ Better to be safe than sorry. This plugin deletes files! Therefore, backup is no
|
|
86 |
* Fix: Check if the filename exists in the trash for every new upload (and if yes, give it a different filename).
|
87 |
* Fix: Avoid crash related to unserialization.
|
88 |
* Fix: Ignore some other plugins' files which are not supposed to be scanned.
|
89 |
-
* Info: This plugin is a lot of work. Please help me by giving it a nice review, [here](https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post).
|
90 |
|
91 |
= 5.5.7 =
|
92 |
* Update: UI improved in many ways, I hope you will love it more!
|
@@ -115,7 +119,6 @@ Better to be safe than sorry. This plugin deletes files! Therefore, backup is no
|
|
115 |
* Fix: Issue with the URLs pointing at the plugin's tutorial page.
|
116 |
* Fix: Avoid the scan to be halted by error logging.
|
117 |
* Add: Basic support for WCFM MarketPlace.
|
118 |
-
* Info: This plugin is a lot of work. Please help by giving it a nice review, here: https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post. Thank you :)
|
119 |
|
120 |
= 5.5.1 =
|
121 |
* Update: Admin refreshed to 2.4.
|
@@ -262,7 +265,7 @@ Better to be safe than sorry. This plugin deletes files! Therefore, backup is no
|
|
262 |
* Fix: Avoid checking the empty arrays.
|
263 |
|
264 |
= 4.2.0 =
|
265 |
-
* Info: This is a MAJOR UPDATE both in term of optimization and detection.
|
266 |
* Add: Support for Fusion Builder (Avada).
|
267 |
* Add: Cache the results found in posts to analyze them much faster later.
|
268 |
* Add: Debugging log file (option).
|
@@ -297,14 +300,12 @@ Better to be safe than sorry. This plugin deletes files! Therefore, backup is no
|
|
297 |
|
298 |
= 3.6.4 =
|
299 |
* Fix: Plugin was not working properly with broken Media metadata. It now handles it properly.
|
300 |
-
* Info: If you want to give me a bit of motivation, write a review on https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post.
|
301 |
|
302 |
= 3.6.2 =
|
303 |
* Fix: When over 1 GO, was displaying a lower size value.
|
304 |
* Fix: Counting wasn't exact with a Filesystem scan.
|
305 |
* Info: Please read the previous changelog as it didn't appear in WP for some reason.
|
306 |
* Add: Check Posts also look for the Media ID in the classes (more secure).
|
307 |
-
* Info: If you want to give me a bit of motivation, write a review on https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post.
|
308 |
|
309 |
= 3.6.0 =
|
310 |
* Add: Now the Media can be recovered! You can remove your Media through the plugin, make sure they are not in use (by testing your website thoroughly) and later delete them definitely from the trash. I think you will find it awesome.
|
5 |
Requires at least: 4.8
|
6 |
Tested up to: 5.3
|
7 |
Requires PHP: 7.0
|
8 |
+
Stable tag: 5.6.2
|
9 |
|
10 |
Clean your WordPress from unused or broken media and files. It has its own trash system and recovery features. Please read the description.
|
11 |
|
74 |
|
75 |
== Changelog ==
|
76 |
|
77 |
+
= 5.6.2 =
|
78 |
+
* Add: Always Skip/Retry feature.
|
79 |
+
* Add: "Images Only" for Media Library scan.
|
80 |
+
* Add: Support for Salient theme.
|
81 |
+
* Info: This plugin is a lot of work. Please help me by giving it a nice review, [here](https://wordpress.org/support/plugin/media-cleaner/reviews/?rate=5#new-post).
|
82 |
+
|
83 |
= 5.6.1 =
|
84 |
* Add: You can now sort the results by size and path. Little present for the week-end ;)
|
|
|
85 |
|
86 |
= 5.5.8 =
|
87 |
* Add: Support for Image Map Pro.
|
91 |
* Fix: Check if the filename exists in the trash for every new upload (and if yes, give it a different filename).
|
92 |
* Fix: Avoid crash related to unserialization.
|
93 |
* Fix: Ignore some other plugins' files which are not supposed to be scanned.
|
|
|
94 |
|
95 |
= 5.5.7 =
|
96 |
* Update: UI improved in many ways, I hope you will love it more!
|
119 |
* Fix: Issue with the URLs pointing at the plugin's tutorial page.
|
120 |
* Fix: Avoid the scan to be halted by error logging.
|
121 |
* Add: Basic support for WCFM MarketPlace.
|
|
|
122 |
|
123 |
= 5.5.1 =
|
124 |
* Update: Admin refreshed to 2.4.
|
265 |
* Fix: Avoid checking the empty arrays.
|
266 |
|
267 |
= 4.2.0 =
|
268 |
+
* Info: This is a MAJOR UPDATE both in term of optimization and detection.
|
269 |
* Add: Support for Fusion Builder (Avada).
|
270 |
* Add: Cache the results found in posts to analyze them much faster later.
|
271 |
* Add: Debugging log file (option).
|
300 |
|
301 |
= 3.6.4 =
|
302 |
* Fix: Plugin was not working properly with broken Media metadata. It now handles it properly.
|
|
|
303 |
|
304 |
= 3.6.2 =
|
305 |
* Fix: When over 1 GO, was displaying a lower size value.
|
306 |
* Fix: Counting wasn't exact with a Filesystem scan.
|
307 |
* Info: Please read the previous changelog as it didn't appear in WP for some reason.
|
308 |
* Add: Check Posts also look for the Media ID in the classes (more secure).
|
|
|
309 |
|
310 |
= 3.6.0 =
|
311 |
* Add: Now the Media can be recovered! You can remove your Media through the plugin, make sure they are not in use (by testing your website thoroughly) and later delete them definitely from the trash. I think you will find it awesome.
|
scripts/dashboard.js
CHANGED
@@ -9,6 +9,8 @@ const WPMC_TARGET_MEDIAS = 'media';
|
|
9 |
const WPMC_SOURCE_CONTENT = 'content';
|
10 |
const WPMC_SOURCE_MEDIAS = 'media';
|
11 |
|
|
|
|
|
12 |
function wpmc_pop_array(items, count) {
|
13 |
var newItems = [];
|
14 |
while ( newItems.length < count && items.length > 0 ) {
|
@@ -164,11 +166,12 @@ function wpmc_ignore_do(items, totalcount) {
|
|
164 |
*
|
165 |
*/
|
166 |
|
167 |
-
var wpmc = wpmc_new_context();
|
168 |
-
|
169 |
/**
|
170 |
* Creates a context object that preserves various states and variables for scanning
|
171 |
* @return {object}
|
|
|
|
|
|
|
172 |
*/
|
173 |
function wpmc_new_context() {
|
174 |
return {
|
@@ -181,16 +184,49 @@ function wpmc_new_context() {
|
|
181 |
isPause: false,
|
182 |
isPendingPause: false,
|
183 |
currentPhase: null,
|
|
|
184 |
|
185 |
phases: {
|
186 |
extractReferencesFromPosts: {
|
187 |
init: function () {
|
188 |
this.progress = 0; // Scanned posts count
|
189 |
this.progressPrev = 0;
|
|
|
190 |
return this;
|
191 |
},
|
192 |
run: function () {
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
},
|
195 |
pause: function () {
|
196 |
jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at preparing posts (' +
|
@@ -207,10 +243,42 @@ function wpmc_new_context() {
|
|
207 |
init: function () {
|
208 |
this.progress = 0; // Scanned posts count
|
209 |
this.progressPrev = 0;
|
|
|
210 |
return this;
|
211 |
},
|
212 |
run: function () {
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
},
|
215 |
pause: function () {
|
216 |
jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at preparing medias (' +
|
@@ -302,7 +370,7 @@ function wpmc_extract_references_from(source) {
|
|
302 |
if (!wpmc.currentPhase) return; // Aborted
|
303 |
var reply = wpmc_parse_response(response);
|
304 |
if (!reply.success)
|
305 |
-
return
|
306 |
if (!reply.finished) {
|
307 |
wpmc.currentPhase.progressPrev = wpmc.currentPhase.progress;
|
308 |
wpmc.currentPhase.progress = reply.limit;
|
@@ -310,7 +378,7 @@ function wpmc_extract_references_from(source) {
|
|
310 |
else wpmc.currentPhase = wpmc.currentPhase.nextPhase().init();
|
311 |
return wpmc.currentPhase.run();
|
312 |
}).fail(function (e) { // Server Error
|
313 |
-
|
314 |
});
|
315 |
}, wpmc_cfg.delay
|
316 |
);
|
@@ -354,7 +422,7 @@ function wpmc_retrieve_targets_for(target, path = null, limit = 0) {
|
|
354 |
wpmc.currentPhase.method = method;
|
355 |
|
356 |
if (!reply.success)
|
357 |
-
return
|
358 |
|
359 |
// Store results
|
360 |
for (var i = 0, len = reply.results.length; i < len; i++) {
|
@@ -394,7 +462,7 @@ function wpmc_retrieve_targets_for(target, path = null, limit = 0) {
|
|
394 |
wpmc.currentPhase.run();
|
395 |
|
396 |
}).fail(function (e) { // Server Error
|
397 |
-
|
398 |
});
|
399 |
|
400 |
}, wpmc_cfg.delay
|
@@ -449,26 +517,6 @@ function wpmc_parse_response(response) {
|
|
449 |
return r;
|
450 |
}
|
451 |
|
452 |
-
/**
|
453 |
-
* Pauses the scan and Displays an error dialog
|
454 |
-
* @param {string} msg=null The error message
|
455 |
-
* @param {int} status=null The actual status code that the server responded
|
456 |
-
*/
|
457 |
-
function wpmc_handle_error(msg = null, status = null) {
|
458 |
-
wpmc.isPendingPause = true;
|
459 |
-
wpmc_update_to_pause();
|
460 |
-
|
461 |
-
var errDialog = jQuery('#wpmc-error-dialog');
|
462 |
-
if (!msg) msg = 'An error happened'; // Default error message
|
463 |
-
if (status) {
|
464 |
-
console.error('Media Cleaner got an error from server:', status + ' ' + msg);
|
465 |
-
msg = '<span class="error-status">' + status + '</span> ' + msg;
|
466 |
-
} else
|
467 |
-
console.error(msg);
|
468 |
-
errDialog.find('h3').html(msg);
|
469 |
-
errDialog.dialog('open');
|
470 |
-
}
|
471 |
-
|
472 |
function wpmc_update_to_error() {
|
473 |
var current = wpmc.total - (wpmc.files.length + wpmc.medias.length);
|
474 |
var totalcount = wpmc.total;
|
@@ -524,11 +572,11 @@ function wpmc_check_targets() {
|
|
524 |
}).done(function (response) {
|
525 |
var reply = wpmc_parse_response(response);
|
526 |
if (!reply.success)
|
527 |
-
return
|
528 |
wpmc.issues += expectedSuccess - reply.results;
|
529 |
wpmc_check_targets();
|
530 |
}).fail(function (e) { // Server Error
|
531 |
-
|
532 |
});
|
533 |
}, wpmc_cfg.delay
|
534 |
);
|
@@ -561,12 +609,70 @@ function wpmc_open_dialog(content) {
|
|
561 |
return dialog;
|
562 |
}
|
563 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
564 |
/**
|
565 |
*
|
566 |
* INIT
|
567 |
*
|
568 |
*/
|
569 |
(function ($) {
|
|
|
|
|
570 |
|
571 |
// Bulk Selection
|
572 |
$('#wpmc-cb-select-all').on('change', function (cb) {
|
@@ -792,6 +898,27 @@ function wpmc_open_dialog(content) {
|
|
792 |
wpmc_pause(); // Resume
|
793 |
errDialog.dialog('close');
|
794 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
795 |
})();
|
796 |
|
797 |
})(jQuery);
|
9 |
const WPMC_SOURCE_CONTENT = 'content';
|
10 |
const WPMC_SOURCE_MEDIAS = 'media';
|
11 |
|
12 |
+
var wpmc = null; // Global Context
|
13 |
+
|
14 |
function wpmc_pop_array(items, count) {
|
15 |
var newItems = [];
|
16 |
while ( newItems.length < count && items.length > 0 ) {
|
166 |
*
|
167 |
*/
|
168 |
|
|
|
|
|
169 |
/**
|
170 |
* Creates a context object that preserves various states and variables for scanning
|
171 |
* @return {object}
|
172 |
+
*
|
173 |
+
* TODO: Make this an actual class
|
174 |
+
* TODO: Create 'Phase' class as the base class of each kind of phase
|
175 |
*/
|
176 |
function wpmc_new_context() {
|
177 |
return {
|
184 |
isPause: false,
|
185 |
isPendingPause: false,
|
186 |
currentPhase: null,
|
187 |
+
errorHandler: new ErrorHandler(),
|
188 |
|
189 |
phases: {
|
190 |
extractReferencesFromPosts: {
|
191 |
init: function () {
|
192 |
this.progress = 0; // Scanned posts count
|
193 |
this.progressPrev = 0;
|
194 |
+
this.progressMax = 0;
|
195 |
return this;
|
196 |
},
|
197 |
run: function () {
|
198 |
+
var me = this;
|
199 |
+
var src = WPMC_SOURCE_CONTENT;
|
200 |
+
|
201 |
+
if (!this.progressMax) {
|
202 |
+
jQuery.ajax(ajaxurl, {
|
203 |
+
type: 'POST',
|
204 |
+
dataType: 'text',
|
205 |
+
data: {
|
206 |
+
action: 'wpmc_get_num_posts',
|
207 |
+
source: src
|
208 |
+
},
|
209 |
+
timeout: wpmc_cfg.timeout + 5000
|
210 |
+
|
211 |
+
}).done(function (result) {
|
212 |
+
result = wpmc_parse_response(result);
|
213 |
+
me.progressMax = result.data.num;
|
214 |
+
wpmc_extract_references_from(src);
|
215 |
+
|
216 |
+
}).fail(function (e) {
|
217 |
+
wpmc.errorHandler.handle(e.statusText, e.status);
|
218 |
+
});
|
219 |
+
|
220 |
+
return;
|
221 |
+
}
|
222 |
+
|
223 |
+
if (this.progress >= this.progressMax) {
|
224 |
+
wpmc.currentPhase = this.nextPhase().init();
|
225 |
+
wpmc.currentPhase.run();
|
226 |
+
return;
|
227 |
+
}
|
228 |
+
|
229 |
+
wpmc_extract_references_from(src);
|
230 |
},
|
231 |
pause: function () {
|
232 |
jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at preparing posts (' +
|
243 |
init: function () {
|
244 |
this.progress = 0; // Scanned posts count
|
245 |
this.progressPrev = 0;
|
246 |
+
this.progressMax = 0;
|
247 |
return this;
|
248 |
},
|
249 |
run: function () {
|
250 |
+
var me = this;
|
251 |
+
var src = WPMC_SOURCE_MEDIAS;
|
252 |
+
|
253 |
+
if (!this.progressMax) {
|
254 |
+
jQuery.ajax(ajaxurl, {
|
255 |
+
type: 'POST',
|
256 |
+
dataType: 'text',
|
257 |
+
data: {
|
258 |
+
action: 'wpmc_get_num_posts',
|
259 |
+
source: src
|
260 |
+
},
|
261 |
+
timeout: wpmc_cfg.timeout + 5000
|
262 |
+
|
263 |
+
}).done(function (result) {
|
264 |
+
result = wpmc_parse_response(result);
|
265 |
+
me.progressMax = result.data.num;
|
266 |
+
wpmc_extract_references_from(src);
|
267 |
+
|
268 |
+
}).fail(function (e) {
|
269 |
+
wpmc.errorHandler.handle(e.statusText, e.status);
|
270 |
+
});
|
271 |
+
|
272 |
+
return
|
273 |
+
}
|
274 |
+
|
275 |
+
if (this.progress >= this.progressMax) {
|
276 |
+
wpmc.currentPhase = this.nextPhase().init();
|
277 |
+
wpmc.currentPhase.run();
|
278 |
+
return;
|
279 |
+
}
|
280 |
+
|
281 |
+
wpmc_extract_references_from(src);
|
282 |
},
|
283 |
pause: function () {
|
284 |
jQuery('#wpmc_progression').html('<span class="dashicons dashicons-controls-pause"></span> Paused at preparing medias (' +
|
370 |
if (!wpmc.currentPhase) return; // Aborted
|
371 |
var reply = wpmc_parse_response(response);
|
372 |
if (!reply.success)
|
373 |
+
return wpmc.errorHandler.handle(reply.message);
|
374 |
if (!reply.finished) {
|
375 |
wpmc.currentPhase.progressPrev = wpmc.currentPhase.progress;
|
376 |
wpmc.currentPhase.progress = reply.limit;
|
378 |
else wpmc.currentPhase = wpmc.currentPhase.nextPhase().init();
|
379 |
return wpmc.currentPhase.run();
|
380 |
}).fail(function (e) { // Server Error
|
381 |
+
wpmc.errorHandler.handle(e.statusText, e.status);
|
382 |
});
|
383 |
}, wpmc_cfg.delay
|
384 |
);
|
422 |
wpmc.currentPhase.method = method;
|
423 |
|
424 |
if (!reply.success)
|
425 |
+
return wpmc.errorHandler.handle(reply.message);
|
426 |
|
427 |
// Store results
|
428 |
for (var i = 0, len = reply.results.length; i < len; i++) {
|
462 |
wpmc.currentPhase.run();
|
463 |
|
464 |
}).fail(function (e) { // Server Error
|
465 |
+
wpmc.errorHandler.handle(e.statusText, e.status);
|
466 |
});
|
467 |
|
468 |
}, wpmc_cfg.delay
|
517 |
return r;
|
518 |
}
|
519 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
520 |
function wpmc_update_to_error() {
|
521 |
var current = wpmc.total - (wpmc.files.length + wpmc.medias.length);
|
522 |
var totalcount = wpmc.total;
|
572 |
}).done(function (response) {
|
573 |
var reply = wpmc_parse_response(response);
|
574 |
if (!reply.success)
|
575 |
+
return wpmc.errorHandler.handle(reply.message);
|
576 |
wpmc.issues += expectedSuccess - reply.results;
|
577 |
wpmc_check_targets();
|
578 |
}).fail(function (e) { // Server Error
|
579 |
+
wpmc.errorHandler.handle(e.statusText, e.status);
|
580 |
});
|
581 |
}, wpmc_cfg.delay
|
582 |
);
|
609 |
return dialog;
|
610 |
}
|
611 |
|
612 |
+
/**
|
613 |
+
* @constructor
|
614 |
+
*/
|
615 |
+
function ErrorHandler() {
|
616 |
+
this.mode = 'ASK'; // 'RETRY', 'SKIP'
|
617 |
+
this.MAX_RETRY = 30; // 30;
|
618 |
+
this.RETRY_DELAY = 5; // in sec
|
619 |
+
this.nRetried = 0;
|
620 |
+
this.nSkipped = 0;
|
621 |
+
}
|
622 |
+
ErrorHandler.prototype.setMode = function (mode) {
|
623 |
+
this.mode = mode;
|
624 |
+
return this;
|
625 |
+
};
|
626 |
+
ErrorHandler.prototype.handle = function (msg = null, status = null) {
|
627 |
+
var me = this;
|
628 |
+
switch (this.mode) {
|
629 |
+
case 'RETRY':
|
630 |
+
if (this.nRetried >= this.MAX_RETRY - 1) {
|
631 |
+
// Too many retries, switch back to ASK mode
|
632 |
+
console.warn('Auto-Retry is turned off due to too many fruitless attempts');
|
633 |
+
this.setMode('ASK');
|
634 |
+
this.nRetried = 0;
|
635 |
+
}
|
636 |
+
// Retry after few seconds
|
637 |
+
console.log('Retry starts in ' + this.RETRY_DELAY + ' seconds...');
|
638 |
+
setTimeout(function () {
|
639 |
+
me.nRetried++;
|
640 |
+
wpmc.currentPhase.run();
|
641 |
+
|
642 |
+
}, this.RETRY_DELAY * 1000);
|
643 |
+
break;
|
644 |
+
case 'SKIP':
|
645 |
+
wpmc.currentPhase.skip();
|
646 |
+
this.nSkipped++;
|
647 |
+
console.warn(this.nSkipped + ' ' + (this.nSkipped > 1 ? 'errors are' : 'error is') + ' ignored automatically');
|
648 |
+
wpmc.currentPhase.run();
|
649 |
+
break;
|
650 |
+
default: // ASK
|
651 |
+
wpmc.isPendingPause = true;
|
652 |
+
wpmc_update_to_pause();
|
653 |
+
|
654 |
+
// Show Error Dialog
|
655 |
+
var errDialog = jQuery('#wpmc-error-dialog');
|
656 |
+
if (!msg) msg = 'An error happened'; // Default error message
|
657 |
+
if (status) {
|
658 |
+
console.error('Media Cleaner got an error from server:', status + ' ' + msg);
|
659 |
+
msg = '<span class="error-status">' + status + '</span> ' + msg;
|
660 |
+
} else
|
661 |
+
console.error(msg);
|
662 |
+
|
663 |
+
errDialog.find('h3').html(msg);
|
664 |
+
errDialog.dialog('open');
|
665 |
+
}
|
666 |
+
};
|
667 |
+
|
668 |
/**
|
669 |
*
|
670 |
* INIT
|
671 |
*
|
672 |
*/
|
673 |
(function ($) {
|
674 |
+
// Initialize Global Context
|
675 |
+
wpmc = wpmc_new_context();
|
676 |
|
677 |
// Bulk Selection
|
678 |
$('#wpmc-cb-select-all').on('change', function (cb) {
|
898 |
wpmc_pause(); // Resume
|
899 |
errDialog.dialog('close');
|
900 |
});
|
901 |
+
|
902 |
+
// Always Retry
|
903 |
+
errDialog.find('a.always-retry').on('click', function (ev) {
|
904 |
+
ev.preventDefault();
|
905 |
+
|
906 |
+
wpmc.errorHandler.setMode('RETRY');
|
907 |
+
|
908 |
+
wpmc_pause(); // Resume
|
909 |
+
errDialog.dialog('close');
|
910 |
+
});
|
911 |
+
|
912 |
+
// Skip All
|
913 |
+
errDialog.find('a.skip-all').on('click', function (ev) {
|
914 |
+
ev.preventDefault();
|
915 |
+
|
916 |
+
wpmc.errorHandler.setMode('SKIP');
|
917 |
+
|
918 |
+
wpmc_pause(); // Resume
|
919 |
+
errDialog.dialog('close');
|
920 |
+
});
|
921 |
+
|
922 |
})();
|
923 |
|
924 |
})(jQuery);
|
scripts/style.css
CHANGED
@@ -55,6 +55,15 @@
|
|
55 |
margin-left: 5px;
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
/* Settings */
|
59 |
.wrap-media-cleaner .meow-box form input:invalid {
|
60 |
color: red;
|
55 |
margin-left: 5px;
|
56 |
}
|
57 |
|
58 |
+
/* Error Dialog */
|
59 |
+
#wpmc-error-dialog .options {
|
60 |
+
margin-top: 20px;
|
61 |
+
text-align: right;
|
62 |
+
}
|
63 |
+
#wpmc-error-dialog .options a + a {
|
64 |
+
margin-left: 16px;
|
65 |
+
}
|
66 |
+
|
67 |
/* Settings */
|
68 |
.wrap-media-cleaner .meow-box form input:invalid {
|
69 |
color: red;
|
views/menu-screen.php
CHANGED
@@ -249,6 +249,10 @@
|
|
249 |
if ( class_exists( 'ImageMapPro' ) )
|
250 |
array_push( $unsupported, 'Image Map Pro' );
|
251 |
|
|
|
|
|
|
|
|
|
252 |
if ( !empty( $unsupported ) ) {
|
253 |
echo "<div class='notice notice-error'><p>";
|
254 |
_e( "<b>Important note about the following plugin(s): </b>", 'media-cleaner' );
|
@@ -470,4 +474,8 @@
|
|
470 |
<div id="wpmc-error-dialog" class="hidden" style="max-width:800px">
|
471 |
<h3><!-- The content will be inserted by JS --></h3>
|
472 |
<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>
|
|
|
|
|
|
|
|
|
473 |
</div>
|
249 |
if ( class_exists( 'ImageMapPro' ) )
|
250 |
array_push( $unsupported, 'Image Map Pro' );
|
251 |
|
252 |
+
if ( class_exists( 'YOOtheme\Builder\Wordpress\BuilderListener' ) ) {
|
253 |
+
array_push( $unsupported, 'YooTheme Builder' );
|
254 |
+
}
|
255 |
+
|
256 |
if ( !empty( $unsupported ) ) {
|
257 |
echo "<div class='notice notice-error'><p>";
|
258 |
_e( "<b>Important note about the following plugin(s): </b>", 'media-cleaner' );
|
474 |
<div id="wpmc-error-dialog" class="hidden" style="max-width:800px">
|
475 |
<h3><!-- The content will be inserted by JS --></h3>
|
476 |
<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>
|
477 |
+
<div class="options">
|
478 |
+
<a href="#" class="always-retry"><?php _e( 'Always Retry', 'media-cleaner' ) ?></a>
|
479 |
+
<a href="#" class="skip-all"><?php _e( 'Skip All', 'media-cleaner' ) ?></a>
|
480 |
+
</div>
|
481 |
</div>
|