Version Description
Release date: September 5th, 2022
* New: added the functionality to remove the background for any image;
* Fix: images added to the new block-style widgets were not replaced;
* Fix: the original file was not removed after replacement if a multilingual plugin was installed;
* Fix: additional checks were added to the new upload path for replacements, to avoid possible vulnerabilities, kudos to @soulseekah;
* Fix: an object cache flush was added after an image was replaced to prevent the content from still being cached in the post editor;
* Fix: if there was no _wp_attached_file
in the postmeta table a fatal error was thrown;
* Fix: the time zone was not displayed correctly on the Replace Media screen;
* Fix: added some additional checks for file path to avoid open_basedir
restrictions;
* Fix: added titles for the Replace Media and Remove Background screens;
* Fix: various small CSS/JS fixes, wording updates and code cleanups;
Release Info
Developer | petredobrescu |
Plugin | Enable Media Replace |
Version | 4.0.0 |
Comparing to | |
See all releases |
Code changes from version 3.6.3 to 4.0.0
- build/shortpixel/autoload.php +1 -1
- build/shortpixel/composer.json +1 -1
- build/shortpixel/filesystem/composer.json +18 -0
- build/shortpixel/filesystem/src/Controller/FileSystemController.php +311 -0
- build/shortpixel/filesystem/src/Model/File/DirectoryModel.php +541 -0
- build/shortpixel/filesystem/src/Model/File/FileModel.php +656 -0
- build/shortpixel/log/src/ShortPixelLogger.php +46 -8
- build/shortpixel/log/src/view-debug-box.php +2 -2
- build/shortpixel/notices/src/NoticeController.php +19 -9
- build/shortpixel/notices/src/NoticeModel.php +54 -14
- build/shortpixel/notices/src/css/notices.css +41 -14
- build/shortpixel/notices/src/css/notices.css.map +1 -0
- build/shortpixel/notices/src/css/notices.scss +26 -2
- classes/ajax.php +37 -0
- classes/api.php +236 -0
- classes/cache.php +3 -3
- classes/emr-plugin.php +472 -354
- classes/file.php +0 -104
- classes/installHelper.php +20 -0
- classes/replacer.php +77 -36
- classes/uihelper.php +130 -26
- css/admin.css +3 -1
- css/admin.css.map +1 -1
- css/remove_background.css +151 -0
- css/remove_background.css.map +1 -0
- enable-media-replace.php +35 -30
- js/emr_admin.js +1 -0
- js/remove_bg.js +131 -0
- readme.txt +43 -15
- scss/admin.scss +7 -2
- scss/remove_background.scss +165 -0
- views/do-replace-background.php +87 -0
- views/popup.php +40 -18
- views/prepare-remove-background.php +153 -0
- views/upload.php +132 -135
- views/upsell.php +4 -4
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
require_once (
|
3 |
$loader = new EnableMediaReplace\Build\PackageLoader();
|
4 |
$loader->load(__DIR__);
|
5 |
|
1 |
<?php
|
2 |
+
require_once (__DIR__ . "/PackageLoader.php");
|
3 |
$loader = new EnableMediaReplace\Build\PackageLoader();
|
4 |
$loader->load(__DIR__);
|
5 |
|
@@ -1 +1 @@
|
|
1 |
-
{"name":"EnableMediaReplace\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"EnableMediaReplace\\ShortPixelLogger":"log\/src","EnableMediaReplace\\Notices":"notices\/src"}}}
|
1 |
+
{"name":"EnableMediaReplace\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"EnableMediaReplace\\ShortPixelLogger":"log\/src","EnableMediaReplace\\Notices":"notices\/src","EnableMediaReplace\\FileSystem":"filesystem\/src"}}}
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "shortpixel/filesystem",
|
3 |
+
"description": "ShortPixel FileSystem",
|
4 |
+
"version": 1.0,
|
5 |
+
"type": "library",
|
6 |
+
"license": "MIT",
|
7 |
+
"authors": [
|
8 |
+
{
|
9 |
+
"name": "Bas",
|
10 |
+
"email": "bas@weblogmechanic.com"
|
11 |
+
}
|
12 |
+
],
|
13 |
+
"minimum-stability": "dev",
|
14 |
+
"require": {},
|
15 |
+
"autoload": {
|
16 |
+
"psr-4": { "ShortPixel\\FileSystem\\" : "src" }
|
17 |
+
}
|
18 |
+
}
|
@@ -0,0 +1,311 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace\FileSystem\Controller;
|
3 |
+
use EnableMediaReplace\ShortpixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
use EnableMediaReplace\FileSystem\Model\File\DirectoryModel as DirectoryModel;
|
6 |
+
use EnableMediaReplace\FileSystem\Model\File\FileModel as FileModel;
|
7 |
+
|
8 |
+
|
9 |
+
/** Controller for FileSystem operations
|
10 |
+
*
|
11 |
+
* This controller is used for -compound- ( complex ) FS operations, using the provided models File en Directory.
|
12 |
+
* USE via \wpSPIO()->filesystem();
|
13 |
+
*/
|
14 |
+
Class FileSystemController
|
15 |
+
{
|
16 |
+
|
17 |
+
public function __construct()
|
18 |
+
{
|
19 |
+
|
20 |
+
}
|
21 |
+
|
22 |
+
/** Get FileModel for a certain path. This can exist or not
|
23 |
+
*
|
24 |
+
* @param String Path Full Path to the file
|
25 |
+
* @return FileModel FileModel Object. If file does not exist, not all values are set.
|
26 |
+
*/
|
27 |
+
public function getFile($path)
|
28 |
+
{
|
29 |
+
return new FileModel($path);
|
30 |
+
}
|
31 |
+
|
32 |
+
|
33 |
+
|
34 |
+
/** Get DirectoryModel for a certain path. This can exist or not
|
35 |
+
*
|
36 |
+
* @param String $path Full Path to the Directory.
|
37 |
+
* @return DirectoryModel Object with status set on current directory.
|
38 |
+
*/
|
39 |
+
public function getDirectory($path)
|
40 |
+
{
|
41 |
+
return new DirectoryModel($path);
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
/** This function returns the WordPress Basedir for uploads ( without date and such )
|
48 |
+
* Normally this would point to /wp-content/uploads.
|
49 |
+
* @returns DirectoryModel
|
50 |
+
*/
|
51 |
+
public function getWPUploadBase()
|
52 |
+
{
|
53 |
+
$upload_dir = wp_upload_dir(null, false);
|
54 |
+
|
55 |
+
return $this->getDirectory($upload_dir['basedir']);
|
56 |
+
}
|
57 |
+
|
58 |
+
/** This function returns the Absolute Path of the WordPress installation where the **CONTENT** directory is located.
|
59 |
+
* Normally this would be the same as ABSPATH, but there are installations out there with -cough- alternative approaches
|
60 |
+
* @returns DirectoryModel Either the ABSPATH or where the WP_CONTENT_DIR is located
|
61 |
+
*/
|
62 |
+
public function getWPAbsPath()
|
63 |
+
{
|
64 |
+
$wpContentAbs = str_replace( 'wp-content', '', WP_CONTENT_DIR);
|
65 |
+
if (ABSPATH == $wpContentAbs)
|
66 |
+
$abspath = ABSPATH;
|
67 |
+
else
|
68 |
+
$abspath = $wpContentAbs;
|
69 |
+
|
70 |
+
if (defined('UPLOADS')) // if this is set, lead.
|
71 |
+
$abspath = trailingslashit(ABSPATH) . UPLOADS;
|
72 |
+
|
73 |
+
$abspath = apply_filters('shortpixel/filesystem/abspath', $abspath );
|
74 |
+
|
75 |
+
return $this->getDirectory($abspath);
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
/** Utility function that tries to convert a file-path to a webURL.
|
80 |
+
*
|
81 |
+
* If possible, rely on other better methods to find URL ( e.g. via WP functions ).
|
82 |
+
*/
|
83 |
+
public function pathToUrl(FileModel $file)
|
84 |
+
{
|
85 |
+
$filepath = $file->getFullPath();
|
86 |
+
$directory = $file->getFileDir();
|
87 |
+
|
88 |
+
$is_multi_site = $this->env->is_multisite;
|
89 |
+
$is_main_site = $this->env->is_mainsite;
|
90 |
+
|
91 |
+
// stolen from wp_get_attachment_url
|
92 |
+
if ( ( $uploads = wp_get_upload_dir() ) && (false === $uploads['error'] || strlen(trim($uploads['error'])) == 0 ) ) {
|
93 |
+
// Check that the upload base exists in the file location.
|
94 |
+
if ( 0 === strpos( $filepath, $uploads['basedir'] ) ) { // Simple as it should, filepath and basedir share.
|
95 |
+
// Replace file location with url location.
|
96 |
+
$url = str_replace( $uploads['basedir'], $uploads['baseurl'], $filepath );
|
97 |
+
}
|
98 |
+
// Multisite backups are stored under uploads/ShortpixelBackups/etc , but basedir would include uploads/sites/2 etc, not matching above
|
99 |
+
// If this is case, test if removing the last two directories will result in a 'clean' uploads reference.
|
100 |
+
// This is used by getting preview path ( backup pathToUrl) in bulk and for comparer..
|
101 |
+
elseif ($is_multi_site && ! $is_main_site && 0 === strpos($filepath, dirname(dirname($uploads['basedir']))) )
|
102 |
+
{
|
103 |
+
|
104 |
+
$url = str_replace( dirname(dirname($uploads['basedir'])), dirname(dirname($uploads['baseurl'])), $filepath );
|
105 |
+
$homeUrl = home_url();
|
106 |
+
|
107 |
+
// The result didn't end in a full URL because URL might have less subdirs ( dirname dirname) .
|
108 |
+
// This happens when site has blogs.dir (sigh) on a subdomain . Try to substitue the ABSPATH root with the home_url
|
109 |
+
if (strpos($url, $homeUrl) === false)
|
110 |
+
{
|
111 |
+
$url = str_replace( trailingslashit(ABSPATH), trailingslashit($homeUrl), $filepath);
|
112 |
+
}
|
113 |
+
|
114 |
+
} elseif ( false !== strpos( $filepath, 'wp-content/uploads' ) ) {
|
115 |
+
// Get the directory name relative to the basedir (back compat for pre-2.7 uploads)
|
116 |
+
$url = trailingslashit( $uploads['baseurl'] . '/' . _wp_get_attachment_relative_path( $filepath ) ) . wp_basename( $filepath );
|
117 |
+
} else {
|
118 |
+
// It's a newly-uploaded file, therefore $file is relative to the basedir.
|
119 |
+
$url = $uploads['baseurl'] . "/$filepath";
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
$wp_home_path = (string) $this->getWPAbsPath();
|
124 |
+
// If the whole WP homepath is still in URL, assume the replace when wrong ( not replaced w/ URL)
|
125 |
+
// This happens when file is outside of wp_uploads_dir
|
126 |
+
if (strpos($url, $wp_home_path) !== false)
|
127 |
+
{
|
128 |
+
// This is SITE URL, for the same reason it should be home_url in FILEMODEL. The difference is when the site is running on a subdirectory
|
129 |
+
// (1) ** This is a fix for a real-life issue, do not change if this causes issues, another fix is needed then.
|
130 |
+
// (2) ** Also a real life fix when a path is /wwwroot/assets/sites/2/ etc, in get site url, the home URL is the site URL, without appending the sites stuff. Fails on original image.
|
131 |
+
if ($is_multi_site && ! $is_main_site)
|
132 |
+
{
|
133 |
+
$wp_home_path = wp_normalize_path(trailingslashit($uploads['basedir']));
|
134 |
+
$home_url = trailingslashit($uploads['baseurl']);
|
135 |
+
}
|
136 |
+
else
|
137 |
+
$home_url = trailingslashit(get_site_url()); // (1)
|
138 |
+
$url = str_replace($wp_home_path, $home_url, $filepath);
|
139 |
+
}
|
140 |
+
|
141 |
+
// can happen if there are WP path errors.
|
142 |
+
if (is_null($url))
|
143 |
+
return false;
|
144 |
+
|
145 |
+
$parsed = parse_url($url); // returns array, null, or false.
|
146 |
+
|
147 |
+
// Some hosts set the content dir to a relative path instead of a full URL. Api can't handle that, so add domain and such if this is the case.
|
148 |
+
if ( !isset($parsed['scheme']) ) {//no absolute URLs used -> we implement a hack
|
149 |
+
|
150 |
+
if (isset($parsed['host'])) // This is for URL's for // without http or https. hackhack.
|
151 |
+
{
|
152 |
+
$scheme = is_ssl() ? 'https:' : 'http:';
|
153 |
+
return $scheme. $url;
|
154 |
+
}
|
155 |
+
else
|
156 |
+
{
|
157 |
+
// From Metafacade. Multiple solutions /hacks.
|
158 |
+
$home_url = trailingslashit((function_exists("is_multisite") && is_multisite()) ? trim(network_site_url("/")) : trim(home_url()));
|
159 |
+
return $home_url . ltrim($url,'/');//get the file URL
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
if (! is_null($parsed) && $parsed !== false)
|
164 |
+
return $url;
|
165 |
+
|
166 |
+
return false;
|
167 |
+
}
|
168 |
+
|
169 |
+
/** Utility function to check if a path is an URL
|
170 |
+
* Checks if this path looks like an URL.
|
171 |
+
* @param $path String Path to check
|
172 |
+
* @return Boolean If path seems domain.
|
173 |
+
*/
|
174 |
+
public function pathIsUrl($path)
|
175 |
+
{
|
176 |
+
$is_http = (substr($path, 0, 4) == 'http') ? true : false;
|
177 |
+
$is_https = (substr($path, 0, 5) == 'https') ? true : false;
|
178 |
+
$is_neutralscheme = (substr($path, 0, 2) == '//') ? true : false; // when URL is relative like //wp-content/etc
|
179 |
+
$has_urldots = (strpos($path, '://') !== false) ? true : false; // Like S3 offloads
|
180 |
+
|
181 |
+
if ($is_http || $is_https || $is_neutralscheme || $has_urldots)
|
182 |
+
return true;
|
183 |
+
else
|
184 |
+
return false;
|
185 |
+
}
|
186 |
+
|
187 |
+
/** Sort files / directories in a certain way.
|
188 |
+
* Future dev to include options via arg.
|
189 |
+
*/
|
190 |
+
public function sortFiles($array, $args = array() )
|
191 |
+
{
|
192 |
+
if (count($array) == 0)
|
193 |
+
return $array;
|
194 |
+
|
195 |
+
// what are we sorting.
|
196 |
+
$class = get_class($array[0]);
|
197 |
+
$is_files = ($class == 'EnableMediaReplace\FileModel') ? true : false; // if not files, then dirs.
|
198 |
+
|
199 |
+
usort($array, function ($a, $b) use ($is_files)
|
200 |
+
{
|
201 |
+
if ($is_files)
|
202 |
+
return strcmp($a->getFileName(), $b->getFileName());
|
203 |
+
else {
|
204 |
+
return strcmp($a->getName(), $b->getName());
|
205 |
+
}
|
206 |
+
}
|
207 |
+
);
|
208 |
+
|
209 |
+
return $array;
|
210 |
+
|
211 |
+
}
|
212 |
+
|
213 |
+
public function downloadFile($url, $destinationPath)
|
214 |
+
{
|
215 |
+
|
216 |
+
//$downloadTimeout = defined(SHORTPIXEL_MAX_EXECUTION_TIME) ? max(SHORTPIXEL_MAX_EXECUTION_TIME - 10, 15) :;
|
217 |
+
$max_exec = intval(ini_get('max_execution_time'));
|
218 |
+
if ($max_exec === 0) // max execution time of zero means infinite. Quantify.
|
219 |
+
$max_exec = 60;
|
220 |
+
elseif($max_exec < 0) // some hosts like to set negative figures on this. Ignore that.
|
221 |
+
$max_exec = 30;
|
222 |
+
|
223 |
+
$downloadTimeout = $max_exec;
|
224 |
+
|
225 |
+
|
226 |
+
$destinationFile = $this->getFile($destinationPath);
|
227 |
+
|
228 |
+
$args_for_get = array(
|
229 |
+
'stream' => true,
|
230 |
+
'filename' => $destinationPath,
|
231 |
+
);
|
232 |
+
|
233 |
+
$response = wp_remote_get( $url, $args_for_get );
|
234 |
+
|
235 |
+
if(is_wp_error( $response )) {
|
236 |
+
Log::addError('Download file failed', array($url, $response->get_error_messages(), $response->get_error_codes() ));
|
237 |
+
|
238 |
+
// Try to get it then via this way.
|
239 |
+
$response = download_url($url, $downloadTimeout);
|
240 |
+
if (!is_wp_error($response)) // response when alright is a tmp filepath. But given path can't be trusted since that can be reason for fail.
|
241 |
+
{
|
242 |
+
$tmpFile = $this->getFile($response);
|
243 |
+
$result = $tmpFile->move($destinationFile);
|
244 |
+
|
245 |
+
} // download_url ..
|
246 |
+
else {
|
247 |
+
Log::addError('Secondary download failed', array($url, $response->get_error_messages(), $response->get_error_codes() ));
|
248 |
+
}
|
249 |
+
}
|
250 |
+
else { // success, at least the download.
|
251 |
+
$destinationFile = $this->getFile($response['filename']);
|
252 |
+
}
|
253 |
+
|
254 |
+
Log::addDebug('Remote Download attempt result', array($url, $destinationPath));
|
255 |
+
if ($destinationFile->exists())
|
256 |
+
return true;
|
257 |
+
else
|
258 |
+
return false;
|
259 |
+
}
|
260 |
+
|
261 |
+
|
262 |
+
|
263 |
+
/** Get all files from a directory tree, starting at given dir.
|
264 |
+
* @param DirectoryModel $dir to recursive into
|
265 |
+
* @param Array $filters Collection of optional filters as accepted by FileFilter in directoryModel
|
266 |
+
* @return Array Array of FileModel Objects
|
267 |
+
**/
|
268 |
+
public function getFilesRecursive(DirectoryModel $dir, $filters = array() )
|
269 |
+
{
|
270 |
+
$fileArray = array();
|
271 |
+
|
272 |
+
if (! $dir->exists())
|
273 |
+
return $fileArray;
|
274 |
+
|
275 |
+
$files = $dir->getFiles($filters);
|
276 |
+
$fileArray = array_merge($fileArray, $files);
|
277 |
+
|
278 |
+
$subdirs = $dir->getSubDirectories();
|
279 |
+
|
280 |
+
foreach($subdirs as $subdir)
|
281 |
+
{
|
282 |
+
$fileArray = array_merge($fileArray, $this->getFilesRecursive($subdir, $filters));
|
283 |
+
}
|
284 |
+
|
285 |
+
return $fileArray;
|
286 |
+
}
|
287 |
+
|
288 |
+
// Url very sparingly.
|
289 |
+
public function url_exists($url)
|
290 |
+
{
|
291 |
+
if (! function_exists('curl_init'))
|
292 |
+
{
|
293 |
+
return null;
|
294 |
+
}
|
295 |
+
|
296 |
+
$ch = curl_init($url);
|
297 |
+
curl_setopt($ch, CURLOPT_NOBODY, true);
|
298 |
+
curl_exec($ch);
|
299 |
+
$responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
300 |
+
curl_close($ch);
|
301 |
+
|
302 |
+
if ($responseCode == 200)
|
303 |
+
{
|
304 |
+
return true;
|
305 |
+
}
|
306 |
+
else {
|
307 |
+
return false;
|
308 |
+
}
|
309 |
+
|
310 |
+
}
|
311 |
+
}
|
@@ -0,0 +1,541 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace\FileSystem\Model\File;
|
3 |
+
use EnableMediaReplace\ShortpixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
/* Model for Directories
|
6 |
+
*
|
7 |
+
* For all low-level operations on directories
|
8 |
+
* Private model of FileSystemController. Please get your directories via there.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
class DirectoryModel
|
13 |
+
{
|
14 |
+
// Directory info
|
15 |
+
protected $path;
|
16 |
+
protected $name;
|
17 |
+
|
18 |
+
// Directory status
|
19 |
+
protected $exists = null;
|
20 |
+
protected $is_writable = null;
|
21 |
+
protected $is_readable = null;
|
22 |
+
protected $is_virtual = null;
|
23 |
+
|
24 |
+
protected $fields = array();
|
25 |
+
|
26 |
+
protected $new_directory_permission = 0755;
|
27 |
+
|
28 |
+
/** Creates a directory model object. DirectoryModel directories don't need to exist on FileSystem
|
29 |
+
*
|
30 |
+
* When a filepath is given, it will remove the file part.
|
31 |
+
* @param $path String The Path
|
32 |
+
*/
|
33 |
+
public function __construct($path)
|
34 |
+
{
|
35 |
+
$path = wp_normalize_path($path);
|
36 |
+
$fs = $this->getFS();
|
37 |
+
|
38 |
+
if ($fs->pathIsUrl($path))
|
39 |
+
{
|
40 |
+
$pathinfo = pathinfo($path);
|
41 |
+
if (isset($pathinfo['extension'])) // check if this is a file, remove the file information.
|
42 |
+
{
|
43 |
+
$path = $pathinfo['dirname'];
|
44 |
+
}
|
45 |
+
|
46 |
+
$this->is_virtual = true;
|
47 |
+
$this->is_readable = true; // assume
|
48 |
+
$this->exists = true;
|
49 |
+
}
|
50 |
+
|
51 |
+
if (! $this->is_virtual() && ! is_dir($path) ) // path is wrong, *or* simply doesn't exist.
|
52 |
+
{
|
53 |
+
/* Test for file input.
|
54 |
+
* If pathinfo is fed a fullpath, it rips of last entry without setting extension, don't further trust.
|
55 |
+
* If it's a file extension is set, then trust.
|
56 |
+
*/
|
57 |
+
$pathinfo = pathinfo($path);
|
58 |
+
|
59 |
+
if (isset($pathinfo['extension']))
|
60 |
+
{
|
61 |
+
$path = $pathinfo['dirname'];
|
62 |
+
}
|
63 |
+
elseif (is_file($path))
|
64 |
+
$path = dirname($path);
|
65 |
+
}
|
66 |
+
|
67 |
+
if (! $this->is_virtual() && ! is_dir($path))
|
68 |
+
{
|
69 |
+
/* Check if realpath improves things. We support non-existing paths, which realpath fails on, so only apply on result.
|
70 |
+
Moved realpath to check after main pathinfo is set. Reason is that symlinked directories which don't include the WordPress upload dir will start to fail in file_model on processpath ( doesn't see it as a wp path, starts to try relative path). Not sure if realpath should be used anyhow in this model /BS
|
71 |
+
*/
|
72 |
+
$testpath = realpath($path);
|
73 |
+
if ($testpath)
|
74 |
+
$path = $testpath;
|
75 |
+
}
|
76 |
+
|
77 |
+
$this->path = trailingslashit($path);
|
78 |
+
|
79 |
+
// Basename doesn't work properly on non-latin ( cyrillic, greek etc ) directory names, returning the parent path instead.
|
80 |
+
$dir = new \SplFileInfo($path);
|
81 |
+
//basename($this->path);
|
82 |
+
$this->name = $dir->getFileName();
|
83 |
+
|
84 |
+
// Off the keep resources / not sure if needed.
|
85 |
+
// if (file_exists($this->path))
|
86 |
+
// {
|
87 |
+
// $this->exists();
|
88 |
+
// $this->is_writable();
|
89 |
+
// $this->is_readable();
|
90 |
+
// }
|
91 |
+
}
|
92 |
+
|
93 |
+
private function getFS()
|
94 |
+
{
|
95 |
+
return new \EnableMediaReplace\FileSystem\Controller\FileSystemController();
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
public function __toString()
|
100 |
+
{
|
101 |
+
return (string) $this->path;
|
102 |
+
}
|
103 |
+
|
104 |
+
/** Returns path *with* trailing slash
|
105 |
+
*
|
106 |
+
* @return String Path with trailing slash
|
107 |
+
*/
|
108 |
+
public function getPath()
|
109 |
+
{
|
110 |
+
return $this->path;
|
111 |
+
}
|
112 |
+
|
113 |
+
public function getModified()
|
114 |
+
{
|
115 |
+
return filemtime($this->path);
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Get basename of the directory. Without path
|
120 |
+
*/
|
121 |
+
public function getName()
|
122 |
+
{
|
123 |
+
return $this->name;
|
124 |
+
}
|
125 |
+
|
126 |
+
public function exists()
|
127 |
+
{
|
128 |
+
if (is_null($this->exists))
|
129 |
+
{
|
130 |
+
$this->exists = file_exists($this->path) && is_dir($this->path);
|
131 |
+
}
|
132 |
+
return $this->exists;
|
133 |
+
}
|
134 |
+
|
135 |
+
public function is_writable()
|
136 |
+
{
|
137 |
+
if (is_null($this->is_writable))
|
138 |
+
{
|
139 |
+
$this->is_writable = is_writable($this->path);
|
140 |
+
}
|
141 |
+
return $this->is_writable;
|
142 |
+
}
|
143 |
+
|
144 |
+
|
145 |
+
public function is_readable()
|
146 |
+
{
|
147 |
+
if (is_null($this->is_readable))
|
148 |
+
{
|
149 |
+
$this->is_readable = is_readable($this->path);
|
150 |
+
}
|
151 |
+
|
152 |
+
return $this->is_readable;
|
153 |
+
}
|
154 |
+
|
155 |
+
public function is_virtual()
|
156 |
+
{
|
157 |
+
return $this->is_virtual;
|
158 |
+
}
|
159 |
+
/** Try to obtain the path, minus the installation directory.
|
160 |
+
* @return Mixed False if this didn't work, Path as string without basedir if it did. With trailing slash, without starting slash.
|
161 |
+
*/
|
162 |
+
public function getRelativePath()
|
163 |
+
{
|
164 |
+
// not used anywhere in directory.
|
165 |
+
// $upload_dir = wp_upload_dir(null, false);
|
166 |
+
|
167 |
+
$install_dir = get_home_path();
|
168 |
+
if($install_dir == '/') {
|
169 |
+
$install_dir = $this->getFS()->getWPAbsPath();
|
170 |
+
}
|
171 |
+
|
172 |
+
$install_dir = trailingslashit($install_dir);
|
173 |
+
|
174 |
+
$path = $this->getPath();
|
175 |
+
// try to build relativePath without first slash.
|
176 |
+
$relativePath = str_replace($install_dir, '', $path);
|
177 |
+
|
178 |
+
if (is_dir( $install_dir . $relativePath) === false)
|
179 |
+
{
|
180 |
+
$test_path = $this->reverseConstructPath($path, $install_dir);
|
181 |
+
if ($test_path !== false)
|
182 |
+
{
|
183 |
+
$relativePath = $test_path;
|
184 |
+
}
|
185 |
+
else {
|
186 |
+
if($test_path = $this->constructUsualDirectories($path))
|
187 |
+
{
|
188 |
+
$relativePath = $test_path;
|
189 |
+
}
|
190 |
+
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
// If relativePath has less amount of characters, changes are this worked.
|
195 |
+
if (strlen($path) > strlen($relativePath))
|
196 |
+
{
|
197 |
+
return ltrim(trailingslashit($relativePath), '/');
|
198 |
+
}
|
199 |
+
return false;
|
200 |
+
}
|
201 |
+
|
202 |
+
|
203 |
+
private function reverseConstructPath($path, $install_path)
|
204 |
+
{
|
205 |
+
// Array value to reset index
|
206 |
+
$pathar = array_values(array_filter(explode('/', $path)));
|
207 |
+
$parts = array();
|
208 |
+
|
209 |
+
if (is_array($pathar))
|
210 |
+
{
|
211 |
+
// Reverse loop the structure until solid ground is found.
|
212 |
+
for ($i = (count($pathar)); $i > 0; $i--)
|
213 |
+
{
|
214 |
+
$parts[] = $pathar[$i - 1];
|
215 |
+
$testpath = implode('/', array_reverse($parts));
|
216 |
+
// if the whole thing exists
|
217 |
+
if (is_dir($install_path . $testpath) === true)
|
218 |
+
{
|
219 |
+
return $testpath;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
}
|
223 |
+
return false;
|
224 |
+
|
225 |
+
}
|
226 |
+
|
227 |
+
|
228 |
+
/* Last Resort function to just reduce path to various known WorPress paths. */
|
229 |
+
private function constructUsualDirectories($path)
|
230 |
+
{
|
231 |
+
$pathar = array_values(array_filter(explode('/', $path))); // array value to reset index
|
232 |
+
$testpath = false;
|
233 |
+
if ( ($key = array_search('wp-content', $pathar)) !== false)
|
234 |
+
{
|
235 |
+
$testpath = implode('/', array_slice($pathar, $key));
|
236 |
+
}
|
237 |
+
elseif ( ($key = array_search('uploads', $pathar)) !== false)
|
238 |
+
{
|
239 |
+
$testpath = implode('/', array_slice($pathar, $key));
|
240 |
+
}
|
241 |
+
|
242 |
+
return $testpath;
|
243 |
+
}
|
244 |
+
|
245 |
+
/** Checks the directory into working order
|
246 |
+
* Tries to create directory if it doesn't exist
|
247 |
+
* Tries to fix file permission if writable is needed
|
248 |
+
* @param $check_writable Boolean Directory should be writable
|
249 |
+
*/
|
250 |
+
public function check($check_writable = false)
|
251 |
+
{
|
252 |
+
$permission = $this->getPermissionRecursive();
|
253 |
+
|
254 |
+
if ($permission === false) // if something wrong, return to default.
|
255 |
+
{
|
256 |
+
$permission = $this->new_directory_permission;
|
257 |
+
}
|
258 |
+
|
259 |
+
if (! $this->exists())
|
260 |
+
{
|
261 |
+
|
262 |
+
Log::addInfo('Directory does not exists. Try to create recursive ' . $this->path . ' with ' . $permission);
|
263 |
+
|
264 |
+
|
265 |
+
$result = @mkdir($this->path, $permission , true);
|
266 |
+
chmod ($this->path, $permission );
|
267 |
+
|
268 |
+
if (! $result)
|
269 |
+
{
|
270 |
+
$error = error_get_last();
|
271 |
+
Log::addWarn('MkDir failed: ' . $error['message'], array($error));
|
272 |
+
}
|
273 |
+
// reset.
|
274 |
+
$this->exists = null;
|
275 |
+
$this->is_readable = null;
|
276 |
+
$this->is_writable = null;
|
277 |
+
|
278 |
+
}
|
279 |
+
if ($this->exists() && $check_writable && ! $this->is_writable())
|
280 |
+
{
|
281 |
+
chmod($this->path, $this->permission);
|
282 |
+
if (! $this->is_writable()) // perhaps parent permission is no good.
|
283 |
+
{
|
284 |
+
chmod($this->path, $this->new_directory_permission);
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
if (! $this->exists())
|
289 |
+
{
|
290 |
+
Log::addInfo('Directory does not exist :' . $this->path);
|
291 |
+
return false;
|
292 |
+
}
|
293 |
+
if ($check_writable && !$this->is_writable())
|
294 |
+
{
|
295 |
+
Log::addInfo('Directory not writable :' . $this->path);
|
296 |
+
return false;
|
297 |
+
}
|
298 |
+
return true;
|
299 |
+
}
|
300 |
+
|
301 |
+
public function getPermissionRecursive()
|
302 |
+
{
|
303 |
+
$parent = $this->getParent();
|
304 |
+
if (! $parent->exists())
|
305 |
+
{
|
306 |
+
return $parent->getPermissionRecursive();
|
307 |
+
}
|
308 |
+
else
|
309 |
+
{
|
310 |
+
return $parent->getPermissions();
|
311 |
+
}
|
312 |
+
|
313 |
+
}
|
314 |
+
|
315 |
+
/* Get files from directory
|
316 |
+
* @returns Array|boolean Returns false if something wrong w/ directory, otherwise a files array of FileModel Object.
|
317 |
+
*/
|
318 |
+
public function getFiles($args = array())
|
319 |
+
{
|
320 |
+
|
321 |
+
$defaults = array(
|
322 |
+
'date_newer' => null,
|
323 |
+
'exclude_files' => null,
|
324 |
+
'include_files' => null,
|
325 |
+
);
|
326 |
+
$args = wp_parse_args($args, $defaults);
|
327 |
+
|
328 |
+
// if all filters are set to null, so point in checking those.
|
329 |
+
$has_filters = (count(array_filter($args)) > 0) ? true : false;
|
330 |
+
|
331 |
+
if ( ! $this->exists() || ! $this->is_readable() )
|
332 |
+
return false;
|
333 |
+
|
334 |
+
$fileArray = array();
|
335 |
+
|
336 |
+
if ($handle = opendir($this->path)) {
|
337 |
+
while (false !== ($entry = readdir($handle))) {
|
338 |
+
if ( ($entry != "." && $entry != "..") && ! is_dir($this->path . $entry) ) {
|
339 |
+
|
340 |
+
|
341 |
+
$fileObj = new FileModel($this->path . $entry);
|
342 |
+
if ($has_filters)
|
343 |
+
{
|
344 |
+
if ($this->fileFilter($fileObj,$args) === false)
|
345 |
+
{
|
346 |
+
$fileObj = null;
|
347 |
+
}
|
348 |
+
}
|
349 |
+
|
350 |
+
if (! is_null($fileObj))
|
351 |
+
$fileArray[] = $fileObj;
|
352 |
+
}
|
353 |
+
}
|
354 |
+
closedir($handle);
|
355 |
+
}
|
356 |
+
|
357 |
+
/*
|
358 |
+
if ($has_filters)
|
359 |
+
{
|
360 |
+
$fileArray = array_filter($fileArray, function ($file) use ($args) {
|
361 |
+
return $this->fileFilter($file, $args);
|
362 |
+
} );
|
363 |
+
} */
|
364 |
+
return $fileArray;
|
365 |
+
}
|
366 |
+
|
367 |
+
// @return boolean true if it should be kept in array, false if not.
|
368 |
+
private function fileFilter(FileModel $file, $args)
|
369 |
+
{
|
370 |
+
$filter = true;
|
371 |
+
|
372 |
+
if (! is_null($args['include_files']))
|
373 |
+
{
|
374 |
+
foreach($args['include_files'] as $inc)
|
375 |
+
{
|
376 |
+
// If any in included is true, filter is good for us.
|
377 |
+
$filter = false;
|
378 |
+
if (strpos( strtolower($file->getRawFullPath()), strtolower($inc) ) !== false)
|
379 |
+
{
|
380 |
+
$filter = true;
|
381 |
+
break;
|
382 |
+
}
|
383 |
+
}
|
384 |
+
}
|
385 |
+
if (! is_null($args['date_newer']))
|
386 |
+
{
|
387 |
+
$modified = $file->getModified();
|
388 |
+
if ($modified < $args['date_newer'] )
|
389 |
+
$filter = false;
|
390 |
+
}
|
391 |
+
if (! is_null($args['exclude_files']))
|
392 |
+
{
|
393 |
+
foreach($args['exclude_files'] as $ex)
|
394 |
+
{
|
395 |
+
if (strpos( strtolower($file->getRawFullPath()), strtolower($ex) ) !== false)
|
396 |
+
$filter = false;
|
397 |
+
}
|
398 |
+
}
|
399 |
+
|
400 |
+
return $filter;
|
401 |
+
}
|
402 |
+
|
403 |
+
/** Get subdirectories from directory
|
404 |
+
* * @returns Array|boolean Returns false if something wrong w/ directory, otherwise a files array of DirectoryModel Object.
|
405 |
+
*/
|
406 |
+
public function getSubDirectories()
|
407 |
+
{
|
408 |
+
|
409 |
+
if (! $this->exists() || ! $this->is_readable())
|
410 |
+
{
|
411 |
+
return false;
|
412 |
+
}
|
413 |
+
|
414 |
+
$dirIt = new \DirectoryIterator($this->path);
|
415 |
+
$dirArray = array();
|
416 |
+
foreach ($dirIt as $fileInfo)
|
417 |
+
{ // IsDot must go first here, or there is possiblity to run into openbasedir restrictions.
|
418 |
+
if (! $fileInfo->isDot() && $fileInfo->isDir() && $fileInfo->isReadable())
|
419 |
+
{
|
420 |
+
if ('EnableMediaReplace\Model\File\DirectoryOtherMediaModel' == get_called_class())
|
421 |
+
{
|
422 |
+
$dir = new DirectoryOtherMediaModel($fileInfo->getRealPath());
|
423 |
+
}
|
424 |
+
else
|
425 |
+
{
|
426 |
+
$dir = new DirectoryModel($fileInfo->getRealPath());
|
427 |
+
}
|
428 |
+
|
429 |
+
if ($dir->exists())
|
430 |
+
$dirArray[] = $dir;
|
431 |
+
}
|
432 |
+
|
433 |
+
}
|
434 |
+
return $dirArray;
|
435 |
+
}
|
436 |
+
|
437 |
+
/** Check if this dir is a subfolder
|
438 |
+
* @param DirectoryModel The directoryObject that is tested as the parent */
|
439 |
+
public function isSubFolderOf(DirectoryModel $dir)
|
440 |
+
{
|
441 |
+
// the same path, is not a subdir of.
|
442 |
+
if ($this->getPath() === $dir->getPath())
|
443 |
+
return false;
|
444 |
+
|
445 |
+
// the main path must be followed from the beginning to be a subfolder.
|
446 |
+
if (strpos($this->getPath(), $dir->getPath() ) === 0)
|
447 |
+
{
|
448 |
+
return true;
|
449 |
+
}
|
450 |
+
return false;
|
451 |
+
}
|
452 |
+
|
453 |
+
//** Note, use sparingly, recursive function
|
454 |
+
public function getFolderSize()
|
455 |
+
{
|
456 |
+
$size = 0;
|
457 |
+
$files = $this->getFiles();
|
458 |
+
|
459 |
+
// GetFiles can return Boolean false on missing directory.
|
460 |
+
if (! is_array($files))
|
461 |
+
{
|
462 |
+
return $size;
|
463 |
+
}
|
464 |
+
|
465 |
+
foreach($files as $fileObj)
|
466 |
+
{
|
467 |
+
$size += $fileObj->getFileSize();
|
468 |
+
}
|
469 |
+
unset($files); //attempt at performance.
|
470 |
+
|
471 |
+
$subdirs = $this->getSubDirectories();
|
472 |
+
|
473 |
+
foreach($subdirs as $subdir)
|
474 |
+
{
|
475 |
+
$size += $subdir->getFolderSize();
|
476 |
+
}
|
477 |
+
|
478 |
+
return $size;
|
479 |
+
}
|
480 |
+
|
481 |
+
/** Get this paths parent */
|
482 |
+
public function getParent()
|
483 |
+
{
|
484 |
+
$path = $this->getPath();
|
485 |
+
$parentPath = dirname($path);
|
486 |
+
|
487 |
+
$parentDir = new DirectoryModel($parentPath);
|
488 |
+
|
489 |
+
return $parentDir;
|
490 |
+
}
|
491 |
+
|
492 |
+
public function getPermissions()
|
493 |
+
{
|
494 |
+
if (! $this->exists())
|
495 |
+
{
|
496 |
+
Log::addWarning('Directory not existing (fileperms): '. $this->getPath() );
|
497 |
+
return false;
|
498 |
+
}
|
499 |
+
$perms = fileperms($this->getPath());
|
500 |
+
|
501 |
+
if ($perms !== false)
|
502 |
+
{
|
503 |
+
return $perms;
|
504 |
+
}
|
505 |
+
else
|
506 |
+
return false;
|
507 |
+
|
508 |
+
}
|
509 |
+
|
510 |
+
public function delete()
|
511 |
+
{
|
512 |
+
return rmdir($this->getPath());
|
513 |
+
}
|
514 |
+
|
515 |
+
/** This will try to remove the whole structure. Use with care.
|
516 |
+
* This is mostly used to clear the backups.
|
517 |
+
*/
|
518 |
+
public function recursiveDelete()
|
519 |
+
{
|
520 |
+
if (! $this->exists() || ! $this->is_writable())
|
521 |
+
return false;
|
522 |
+
|
523 |
+
// This is a security measure to prevent unintended wipes.
|
524 |
+
$wpdir = $this->getFS()->getWPUploadBase();
|
525 |
+
if (! $this->isSubFolderOf($wpdir))
|
526 |
+
return false;
|
527 |
+
|
528 |
+
$files = $this->getFiles();
|
529 |
+
$subdirs = $this->getSubDirectories();
|
530 |
+
|
531 |
+
foreach($files as $file)
|
532 |
+
$file->delete();
|
533 |
+
|
534 |
+
foreach($subdirs as $subdir)
|
535 |
+
$subdir->recursiveDelete();
|
536 |
+
|
537 |
+
$this->delete();
|
538 |
+
|
539 |
+
}
|
540 |
+
|
541 |
+
}
|
@@ -0,0 +1,656 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace\FileSystem\Model\File;
|
3 |
+
use EnableMediaReplace\ShortpixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
/* FileModel class.
|
6 |
+
*
|
7 |
+
*
|
8 |
+
* - Represents a -single- file.
|
9 |
+
* - Can handle any type
|
10 |
+
* - Usually controllers would use a collection of files
|
11 |
+
* - Meant for all low-level file operations and checks.
|
12 |
+
* - Every file can have a backup counterpart.
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
class FileModel
|
16 |
+
{
|
17 |
+
|
18 |
+
// File info
|
19 |
+
protected $fullpath = null;
|
20 |
+
protected $filename = null; // filename + extension
|
21 |
+
protected $filebase = null; // filename without extension
|
22 |
+
protected $directory = null;
|
23 |
+
protected $extension = null;
|
24 |
+
protected $mime = null;
|
25 |
+
protected $permissions = null;
|
26 |
+
|
27 |
+
// File Status
|
28 |
+
protected $exists = null;
|
29 |
+
protected $is_writable = null;
|
30 |
+
protected $is_readable = null;
|
31 |
+
protected $is_file = null;
|
32 |
+
protected $is_virtual = false;
|
33 |
+
|
34 |
+
protected $status;
|
35 |
+
|
36 |
+
protected $backupDirectory;
|
37 |
+
|
38 |
+
const FILE_OK = 1;
|
39 |
+
const FILE_UNKNOWN_ERROR = 2;
|
40 |
+
|
41 |
+
|
42 |
+
/** Creates a file model object. FileModel files don't need to exist on FileSystem */
|
43 |
+
public function __construct($path)
|
44 |
+
{
|
45 |
+
$this->fullpath = trim($path);
|
46 |
+
$fs = $this->getFS();
|
47 |
+
if ($fs->pathIsUrl($path)) // Asap check for URL's to prevent remote wrappers from running.
|
48 |
+
{
|
49 |
+
|
50 |
+
$this->UrlToPath($path);
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
private function getFS()
|
55 |
+
{
|
56 |
+
return new \EnableMediaReplace\FileSystem\Controller\FileSystemController();
|
57 |
+
}
|
58 |
+
|
59 |
+
/* Get a string representation of file, the fullpath
|
60 |
+
* Note - this might be risky, without processedpath, in cases.
|
61 |
+
* @return String Full path processed or unprocessed.
|
62 |
+
*/
|
63 |
+
public function __toString()
|
64 |
+
{
|
65 |
+
return (string) $this->fullpath;
|
66 |
+
}
|
67 |
+
|
68 |
+
protected function setFileInfo()
|
69 |
+
{
|
70 |
+
$processed_path = $this->processPath($this->fullpath);
|
71 |
+
if ($processed_path !== false)
|
72 |
+
$this->fullpath = $processed_path; // set processed path if that went alright
|
73 |
+
|
74 |
+
|
75 |
+
$info = $this->mb_pathinfo($this->fullpath);
|
76 |
+
// Todo, maybe replace this with splFileINfo.
|
77 |
+
if ($this->is_file()) // only set fileinfo when it's an actual file.
|
78 |
+
{
|
79 |
+
$this->filename = isset($info['basename']) ? $info['basename'] : null; // filename + extension
|
80 |
+
$this->filebase = isset($info['filename']) ? $info['filename'] : null; // only filename
|
81 |
+
$this->extension = isset($info['extension']) ? strtolower($info['extension']) : null; // only (last) extension
|
82 |
+
}
|
83 |
+
|
84 |
+
}
|
85 |
+
|
86 |
+
/** Call when file status changed, so writable / readable / exists are not reliable anymore */
|
87 |
+
public function resetStatus()
|
88 |
+
{
|
89 |
+
$this->is_writable = null;
|
90 |
+
$this->is_readable = null;
|
91 |
+
$this->is_file = null;
|
92 |
+
$this->exists = null;
|
93 |
+
$this->is_virtual = null;
|
94 |
+
}
|
95 |
+
|
96 |
+
public function exists()
|
97 |
+
{
|
98 |
+
if (is_null($this->exists))
|
99 |
+
{
|
100 |
+
$this->exists = (@file_exists($this->fullpath) && is_file($this->fullpath));
|
101 |
+
}
|
102 |
+
|
103 |
+
$this->exists = apply_filters('shortpixel_image_exists', $this->exists, $this->fullpath, $this); //legacy
|
104 |
+
$this->exists = apply_filters('shortpixel/file/exists', $this->exists, $this->fullpath, $this);
|
105 |
+
return $this->exists;
|
106 |
+
}
|
107 |
+
|
108 |
+
public function is_writable()
|
109 |
+
{
|
110 |
+
if ($this->is_virtual())
|
111 |
+
{
|
112 |
+
$this->is_writable = false; // can't write to remote files
|
113 |
+
}
|
114 |
+
elseif (is_null($this->is_writable))
|
115 |
+
{
|
116 |
+
if ($this->exists())
|
117 |
+
{
|
118 |
+
$this->is_writable = @is_writable($this->fullpath);
|
119 |
+
}
|
120 |
+
else // quite expensive check to see if file is writable.
|
121 |
+
{
|
122 |
+
$res = $this->create();
|
123 |
+
$this->delete();
|
124 |
+
$this->is_writable = $res;
|
125 |
+
}
|
126 |
+
|
127 |
+
}
|
128 |
+
|
129 |
+
return $this->is_writable;
|
130 |
+
}
|
131 |
+
|
132 |
+
public function is_readable()
|
133 |
+
{
|
134 |
+
if (is_null($this->is_readable))
|
135 |
+
$this->is_readable = @is_readable($this->fullpath);
|
136 |
+
|
137 |
+
return $this->is_readable;
|
138 |
+
}
|
139 |
+
|
140 |
+
// A file is virtual when the file is remote with URL and no local alternative is present.
|
141 |
+
public function is_virtual()
|
142 |
+
{
|
143 |
+
if ( is_null($this->is_virtual))
|
144 |
+
$this->is_virtual = false; // return bool
|
145 |
+
return $this->is_virtual;
|
146 |
+
}
|
147 |
+
|
148 |
+
/* Function checks if path is actually a file. This can be used to check possible confusion if a directory path is given to filemodel */
|
149 |
+
public function is_file()
|
150 |
+
{
|
151 |
+
if ($this->is_virtual()) // don't look further when virtual
|
152 |
+
{
|
153 |
+
$this->is_file = true;
|
154 |
+
return $this->is_file;
|
155 |
+
}
|
156 |
+
elseif (is_null($this->is_file))
|
157 |
+
{
|
158 |
+
if ($this->exists())
|
159 |
+
{
|
160 |
+
if (basename($this->fullpath) == '..' || basename($this->fullpath) == '.')
|
161 |
+
$this->is_file = false;
|
162 |
+
else
|
163 |
+
$this->is_file = is_file($this->fullpath);
|
164 |
+
}
|
165 |
+
else // file can not exist, but still have a valid filepath format. In that case, if file should return true.
|
166 |
+
{
|
167 |
+
|
168 |
+
/* if file does not exist on disk, anything can become a file ( with/ without extension, etc). Meaning everything non-existing is a potential file ( or directory ) until created. */
|
169 |
+
|
170 |
+
if (basename($this->fullpath) == '..' || basename($this->fullpath) == '.') // don't see this as file.
|
171 |
+
{
|
172 |
+
$this->is_file = false;
|
173 |
+
}
|
174 |
+
else if (! file_exists($this->fullpath) && ! is_dir($this->fullpath))
|
175 |
+
{
|
176 |
+
$this->is_file = true;
|
177 |
+
}
|
178 |
+
else //if (! is_file($this->fullpath)) // can be a non-existing directory. /
|
179 |
+
{
|
180 |
+
$this->is_file = false;
|
181 |
+
}
|
182 |
+
|
183 |
+
}
|
184 |
+
}
|
185 |
+
return $this->is_file;
|
186 |
+
}
|
187 |
+
|
188 |
+
public function getModified()
|
189 |
+
{
|
190 |
+
return filemtime($this->fullpath);
|
191 |
+
}
|
192 |
+
|
193 |
+
public function hasBackup()
|
194 |
+
{
|
195 |
+
$directory = $this->getBackupDirectory();
|
196 |
+
if (! $directory)
|
197 |
+
return false;
|
198 |
+
|
199 |
+
$backupFile = $directory . $this->getFileName();
|
200 |
+
|
201 |
+
if (file_exists($backupFile) && ! is_dir($backupFile) )
|
202 |
+
return true;
|
203 |
+
else {
|
204 |
+
return false;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
|
209 |
+
/** Returns the Directory Model this file resides in
|
210 |
+
*
|
211 |
+
* @return DirectoryModel Directorymodel Object
|
212 |
+
*/
|
213 |
+
public function getFileDir()
|
214 |
+
{
|
215 |
+
$fullpath = $this->getFullPath(); // triggers a file lookup if needed.
|
216 |
+
// create this only when needed.
|
217 |
+
if (is_null($this->directory) && strlen($fullpath) > 0)
|
218 |
+
{
|
219 |
+
// Feed to full path to DirectoryModel since it checks if input is file, or dir. Using dirname here would cause errors when fullpath is already just a dirpath ( faulty input )
|
220 |
+
$this->directory = new DirectoryModel($fullpath);
|
221 |
+
}
|
222 |
+
|
223 |
+
return $this->directory;
|
224 |
+
}
|
225 |
+
|
226 |
+
public function getFileSize()
|
227 |
+
{
|
228 |
+
if ($this->exists())
|
229 |
+
return filesize($this->fullpath);
|
230 |
+
else
|
231 |
+
return 0;
|
232 |
+
}
|
233 |
+
|
234 |
+
// Creates an empty file
|
235 |
+
public function create()
|
236 |
+
{
|
237 |
+
if (! $this->exists() )
|
238 |
+
{
|
239 |
+
$fileDir = $this->getFileDir();
|
240 |
+
|
241 |
+
if (! is_null($fileDir) && $fileDir->exists())
|
242 |
+
{
|
243 |
+
$res = @touch($this->fullpath);
|
244 |
+
$this->exists = $res;
|
245 |
+
return $res;
|
246 |
+
}
|
247 |
+
}
|
248 |
+
else
|
249 |
+
Log::addWarn('Could not create/write file: ' . $this->fullpath);
|
250 |
+
|
251 |
+
return false;
|
252 |
+
}
|
253 |
+
|
254 |
+
public function append($message)
|
255 |
+
{
|
256 |
+
if (! $this->exists() )
|
257 |
+
$this->create();
|
258 |
+
|
259 |
+
if (! $this->is_writable() )
|
260 |
+
{
|
261 |
+
Log::addWarn('File append failed on ' . $this->getFullPath() . ' - not writable');
|
262 |
+
return false;
|
263 |
+
}
|
264 |
+
$handle = fopen($this->getFullPath(), 'a');
|
265 |
+
fwrite($handle, $message);
|
266 |
+
fclose($handle);
|
267 |
+
|
268 |
+
return true;
|
269 |
+
}
|
270 |
+
|
271 |
+
|
272 |
+
/** Copy a file to somewhere
|
273 |
+
*
|
274 |
+
* @param $destination String Full Path to new file.
|
275 |
+
*/
|
276 |
+
public function copy(FileModel $destination)
|
277 |
+
{
|
278 |
+
$sourcePath = $this->getFullPath();
|
279 |
+
$destinationPath = $destination->getFullPath();
|
280 |
+
Log::addDebug("Copy from $sourcePath to $destinationPath ");
|
281 |
+
|
282 |
+
if (! strlen($sourcePath) > 0 || ! strlen($destinationPath) > 0)
|
283 |
+
{
|
284 |
+
Log::addWarn('Attempted Copy on Empty Path', array($sourcePath, $destinationPath));
|
285 |
+
return false;
|
286 |
+
}
|
287 |
+
|
288 |
+
if (! $this->exists())
|
289 |
+
{
|
290 |
+
Log::addWarn('Tried to copy non-existing file - ' . $sourcePath);
|
291 |
+
return false;
|
292 |
+
}
|
293 |
+
|
294 |
+
$is_new = ($destination->exists()) ? false : true;
|
295 |
+
$status = @copy($sourcePath, $destinationPath);
|
296 |
+
|
297 |
+
if (! $status)
|
298 |
+
{
|
299 |
+
Log::addWarn('Could not copy file ' . $sourcePath . ' to' . $destinationPath);
|
300 |
+
}
|
301 |
+
else
|
302 |
+
{
|
303 |
+
$destination->resetStatus();
|
304 |
+
$destination->setFileInfo(); // refresh info.
|
305 |
+
}
|
306 |
+
//
|
307 |
+
do_action('shortpixel/filesystem/addfile', array($destinationPath, $destination, $this, $is_new));
|
308 |
+
return $status;
|
309 |
+
}
|
310 |
+
|
311 |
+
/** Move a file to somewhere
|
312 |
+
* This uses copy and delete functions and will fail if any of those fail.
|
313 |
+
* @param $destination String Full Path to new file.
|
314 |
+
*/
|
315 |
+
public function move(FileModel $destination)
|
316 |
+
{
|
317 |
+
$result = false;
|
318 |
+
if ($this->copy($destination))
|
319 |
+
{
|
320 |
+
$result = $this->delete();
|
321 |
+
if ($result == false)
|
322 |
+
{
|
323 |
+
Log::addError('Move can\'t remove file ' . $this->getFullPath());
|
324 |
+
}
|
325 |
+
|
326 |
+
$this->resetStatus();
|
327 |
+
$destination->resetStatus();
|
328 |
+
}
|
329 |
+
return $result;
|
330 |
+
}
|
331 |
+
|
332 |
+
/** Deletes current file
|
333 |
+
* This uses the WP function since it has a filter that might be useful
|
334 |
+
*/
|
335 |
+
public function delete()
|
336 |
+
{
|
337 |
+
if ($this->exists())
|
338 |
+
{
|
339 |
+
\wp_delete_file($this->fullpath); // delete file hook via wp_delete_file
|
340 |
+
}
|
341 |
+
else
|
342 |
+
{
|
343 |
+
Log::addWarn('Trying to remove non-existing file: ' . $this->getFullPath());
|
344 |
+
}
|
345 |
+
|
346 |
+
if (! file_exists($this->fullpath))
|
347 |
+
{
|
348 |
+
$this->resetStatus();
|
349 |
+
return true;
|
350 |
+
}
|
351 |
+
else {
|
352 |
+
$writable = ($this->is_writable()) ? 'true' : 'false';
|
353 |
+
Log::addWarn('File seems not removed - ' . $this->getFullPath() . ' (writable:' . $writable . ')');
|
354 |
+
return false;
|
355 |
+
}
|
356 |
+
|
357 |
+
}
|
358 |
+
|
359 |
+
public function getContents()
|
360 |
+
{
|
361 |
+
return file_get_contents($this->getFullPath());
|
362 |
+
}
|
363 |
+
|
364 |
+
public function getFullPath()
|
365 |
+
{
|
366 |
+
// filename here since fullpath is set unchecked in constructor, but might be a different take
|
367 |
+
if (is_null($this->filename))
|
368 |
+
{
|
369 |
+
$this->setFileInfo();
|
370 |
+
}
|
371 |
+
|
372 |
+
return $this->fullpath;
|
373 |
+
}
|
374 |
+
|
375 |
+
// Testing this. Principle is that when the plugin is absolutely sure this is a file, not something remote, not something non-existing, get the fullpath without any check.
|
376 |
+
// This function should *only* be used when processing mega amounts of files while not doing optimization or any processing.
|
377 |
+
// So far, testing use for file Filter */
|
378 |
+
public function getRawFullPath()
|
379 |
+
{
|
380 |
+
return $this->fullpath;
|
381 |
+
}
|
382 |
+
|
383 |
+
public function getFileName()
|
384 |
+
{
|
385 |
+
if (is_null($this->filename))
|
386 |
+
$this->setFileInfo();
|
387 |
+
|
388 |
+
return $this->filename;
|
389 |
+
}
|
390 |
+
|
391 |
+
public function getFileBase()
|
392 |
+
{
|
393 |
+
if (is_null($this->filebase))
|
394 |
+
$this->setFileInfo();
|
395 |
+
|
396 |
+
return $this->filebase;
|
397 |
+
}
|
398 |
+
|
399 |
+
|
400 |
+
public function getExtension()
|
401 |
+
{
|
402 |
+
if (is_null($this->extension))
|
403 |
+
$this->setFileInfo();
|
404 |
+
|
405 |
+
return $this->extension;
|
406 |
+
}
|
407 |
+
|
408 |
+
public function getMime()
|
409 |
+
{
|
410 |
+
if (is_null($this->mime))
|
411 |
+
$this->setFileInfo();
|
412 |
+
|
413 |
+
if ($this->exists() && ! $this->is_virtual() )
|
414 |
+
{
|
415 |
+
$this->mime = wp_get_image_mime($this->fullpath);
|
416 |
+
}
|
417 |
+
else
|
418 |
+
$this->mime = false;
|
419 |
+
|
420 |
+
return $this->mime;
|
421 |
+
}
|
422 |
+
|
423 |
+
|
424 |
+
/* Internal function to check if path is a real path
|
425 |
+
* - Test for URL's based on http / https
|
426 |
+
* - Test if given path is absolute, from the filesystem root.
|
427 |
+
* @param $path String The file path
|
428 |
+
* @param String The Fixed filepath.
|
429 |
+
*/
|
430 |
+
protected function processPath($path)
|
431 |
+
{
|
432 |
+
$original_path = $path;
|
433 |
+
$fs = $this->getFS();
|
434 |
+
|
435 |
+
if ($fs->pathIsUrl($path))
|
436 |
+
{
|
437 |
+
$path = $this->UrlToPath($path);
|
438 |
+
}
|
439 |
+
|
440 |
+
if ($path === false) // don't process further
|
441 |
+
return false;
|
442 |
+
|
443 |
+
$path = wp_normalize_path($path);
|
444 |
+
$abspath = $fs->getWPAbsPath();
|
445 |
+
|
446 |
+
if ( is_file($path) && ! is_dir($path) ) // if path and file exist, all should be okish.
|
447 |
+
{
|
448 |
+
return $path;
|
449 |
+
}
|
450 |
+
// If attempted file does not exist, but the file is in a dir that exists, that is good enough.
|
451 |
+
elseif ( ! is_dir($path) && is_dir(dirname($path)) )
|
452 |
+
{
|
453 |
+
return $path;
|
454 |
+
}
|
455 |
+
// If path is not in the abspath, it might be relative.
|
456 |
+
elseif (strpos($path, $abspath->getPath()) === false)
|
457 |
+
{
|
458 |
+
// if path does not contain basepath.
|
459 |
+
//$uploadDir = $fs->getWPUploadBase();
|
460 |
+
//$abspath = $fs->getWPAbsPath();
|
461 |
+
|
462 |
+
$path = $this->relativeToFullPath($path);
|
463 |
+
}
|
464 |
+
$path = apply_filters('shortpixel/filesystem/processFilePath', $path, $original_path);
|
465 |
+
/* This needs some check here on malformed path's, but can't be test for existing since that's not a requirement.
|
466 |
+
if (file_exists($path) === false) // failed to process path to something workable.
|
467 |
+
{
|
468 |
+
// Log::addInfo('Failed to process path', array($path));
|
469 |
+
$path = false;
|
470 |
+
} */
|
471 |
+
|
472 |
+
return $path;
|
473 |
+
}
|
474 |
+
|
475 |
+
|
476 |
+
|
477 |
+
/** Resolve an URL to a local path
|
478 |
+
* This partially comes from WordPress functions attempting the same
|
479 |
+
* @param String $url The URL to resolve
|
480 |
+
* @return String/Boolean - False is this seems an external domain, otherwise resolved path.
|
481 |
+
*/
|
482 |
+
private function UrlToPath($url)
|
483 |
+
{
|
484 |
+
//$uploadDir = wp_upload_dir();
|
485 |
+
|
486 |
+
$site_url = str_replace('http:', '', home_url('', 'http'));
|
487 |
+
$url = str_replace(array('http:', 'https:'), '', $url);
|
488 |
+
$fs = $this->getFS();
|
489 |
+
|
490 |
+
if (strpos($url, $site_url) !== false)
|
491 |
+
{
|
492 |
+
// try to replace URL for Path
|
493 |
+
$abspath = $this->getFS()->getWPAbsPath();
|
494 |
+
$path = str_replace($site_url, rtrim($abspath->getPath(),'/'), $url);
|
495 |
+
|
496 |
+
|
497 |
+
if (! $fs->pathIsUrl($path)) // test again.
|
498 |
+
{
|
499 |
+
return $path;
|
500 |
+
}
|
501 |
+
}
|
502 |
+
|
503 |
+
$this->is_virtual = true;
|
504 |
+
|
505 |
+
// This filter checks if some supplier will be able to handle the file when needed.
|
506 |
+
$path = apply_filters('shortpixel/image/urltopath', false, $url);
|
507 |
+
|
508 |
+
if ($path !== false)
|
509 |
+
{
|
510 |
+
$this->exists = true;
|
511 |
+
$this->is_readable = true;
|
512 |
+
$this->is_file = true;
|
513 |
+
}
|
514 |
+
else
|
515 |
+
{
|
516 |
+
$this->exists = false;
|
517 |
+
$this->is_readable = false;
|
518 |
+
$this->is_file = false;
|
519 |
+
}
|
520 |
+
|
521 |
+
|
522 |
+
return false; // seems URL from other server, use virtual mode.
|
523 |
+
}
|
524 |
+
|
525 |
+
/** Tries to find the full path for a perceived relative path.
|
526 |
+
*
|
527 |
+
* Relative path is detected on basis of WordPress ABSPATH. If this doesn't appear in the file path, it might be a relative path.
|
528 |
+
* Function checks for expections on this rule ( tmp path ) and returns modified - or not - path.
|
529 |
+
* @param $path The path for the file_exists
|
530 |
+
* @returns String The updated path, if that was possible.
|
531 |
+
*/
|
532 |
+
private function relativeToFullPath($path)
|
533 |
+
{
|
534 |
+
$originalPath = $path; // for safe-keeping
|
535 |
+
|
536 |
+
// A file with no path, can never be created to a fullpath.
|
537 |
+
if (strlen($path) == 0)
|
538 |
+
return $path;
|
539 |
+
|
540 |
+
// if the file plainly exists, it's usable /**
|
541 |
+
if (file_exists($path))
|
542 |
+
{
|
543 |
+
return $path;
|
544 |
+
}
|
545 |
+
|
546 |
+
// Test if our 'relative' path is not a path to /tmp directory.
|
547 |
+
|
548 |
+
// This ini value might not exist.
|
549 |
+
$tempdirini = ini_get('upload_tmp_dir');
|
550 |
+
if ( (strlen($tempdirini) > 0) && strpos($path, $tempdirini) !== false)
|
551 |
+
return $path;
|
552 |
+
|
553 |
+
$tempdir = sys_get_temp_dir();
|
554 |
+
if ( (strlen($tempdir) > 0) && strpos($path, $tempdir) !== false)
|
555 |
+
return $path;
|
556 |
+
|
557 |
+
// Path contains upload basedir. This happens when upload dir is outside of usual WP.
|
558 |
+
$fs = $this->getFS();
|
559 |
+
$uploadDir = $fs->getWPUploadBase();
|
560 |
+
$abspath = $fs->getWPAbsPath();
|
561 |
+
|
562 |
+
if (strpos($path, $uploadDir->getPath()) !== false) // If upload Dir is feature in path, consider it ok.
|
563 |
+
{
|
564 |
+
return $path;
|
565 |
+
}
|
566 |
+
elseif (file_exists($abspath->getPath() . $path)) // If upload dir is abspath plus return path. Exceptions.
|
567 |
+
{
|
568 |
+
return $abspath->getPath() . $path;
|
569 |
+
}
|
570 |
+
elseif(file_exists($uploadDir->getPath() . $path)) // This happens when upload_dir is not properly prepended in get_attachment_file due to WP errors
|
571 |
+
{
|
572 |
+
return $uploadDir->getPath() . $path;
|
573 |
+
}
|
574 |
+
|
575 |
+
// this is probably a bit of a sharp corner to take.
|
576 |
+
// if path starts with / remove it due to trailingslashing ABSPATH
|
577 |
+
$path = ltrim($path, '/');
|
578 |
+
$fullpath = $abspath->getPath() . $path;
|
579 |
+
|
580 |
+
// We can't test for file_exists here, since file_model allows non-existing files.
|
581 |
+
// Test if directory exists, perhaps. Otherwise we are in for a failure anyhow.
|
582 |
+
//if (is_dir(dirname($fullpath)))
|
583 |
+
return $fullpath;
|
584 |
+
//else
|
585 |
+
// return $originalPath;
|
586 |
+
}
|
587 |
+
|
588 |
+
public function getPermissions()
|
589 |
+
{
|
590 |
+
if (is_null($this->permissions))
|
591 |
+
$this->permissions = fileperms($this->fullpath) & 0777;
|
592 |
+
|
593 |
+
return $this->permissions;
|
594 |
+
}
|
595 |
+
|
596 |
+
// @tozo Lazy IMplementation / copy, should be brought in line w/ other attributes.
|
597 |
+
public function setPermissions($permissions)
|
598 |
+
{
|
599 |
+
@chmod($this->fullpath, $permissions);
|
600 |
+
}
|
601 |
+
|
602 |
+
|
603 |
+
/** Fix for multibyte pathnames and pathinfo which doesn't take into regard the locale.
|
604 |
+
* This snippet taken from PHPMailer.
|
605 |
+
*/
|
606 |
+
private function mb_pathinfo($path, $options = null)
|
607 |
+
{
|
608 |
+
$ret = ['dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''];
|
609 |
+
$pathinfo = [];
|
610 |
+
if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^.\\\\/]+?)|))[\\\\/.]*$#m', $path, $pathinfo)) {
|
611 |
+
if (array_key_exists(1, $pathinfo)) {
|
612 |
+
$ret['dirname'] = $pathinfo[1];
|
613 |
+
}
|
614 |
+
if (array_key_exists(2, $pathinfo)) {
|
615 |
+
$ret['basename'] = $pathinfo[2];
|
616 |
+
}
|
617 |
+
if (array_key_exists(5, $pathinfo)) {
|
618 |
+
$ret['extension'] = $pathinfo[5];
|
619 |
+
}
|
620 |
+
if (array_key_exists(3, $pathinfo)) {
|
621 |
+
$ret['filename'] = $pathinfo[3];
|
622 |
+
}
|
623 |
+
}
|
624 |
+
switch ($options) {
|
625 |
+
case PATHINFO_DIRNAME:
|
626 |
+
case 'dirname':
|
627 |
+
return $ret['dirname'];
|
628 |
+
case PATHINFO_BASENAME:
|
629 |
+
case 'basename':
|
630 |
+
return $ret['basename'];
|
631 |
+
case PATHINFO_EXTENSION:
|
632 |
+
case 'extension':
|
633 |
+
return $ret['extension'];
|
634 |
+
case PATHINFO_FILENAME:
|
635 |
+
case 'filename':
|
636 |
+
return $ret['filename'];
|
637 |
+
default:
|
638 |
+
return $ret;
|
639 |
+
}
|
640 |
+
}
|
641 |
+
|
642 |
+
public function __debuginfo()
|
643 |
+
{
|
644 |
+
return [
|
645 |
+
'fullpath' => $this->fullpath,
|
646 |
+
'filename' => $this->filename,
|
647 |
+
'filebase' => $this->filebase,
|
648 |
+
'exists' => $this->exists,
|
649 |
+
'is_writable' => $this->is_writable,
|
650 |
+
'is_readable' => $this->is_readable,
|
651 |
+
'is_virtual' => $this->is_virtual,
|
652 |
+
];
|
653 |
+
}
|
654 |
+
|
655 |
+
|
656 |
+
} // FileModel Class
|
@@ -24,6 +24,8 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
24 |
protected $format_data = "\t %%data%% ";
|
25 |
|
26 |
protected $hooks = array();
|
|
|
|
|
27 |
/* protected $hooks = array(
|
28 |
'shortpixel_image_exists' => array('numargs' => 3),
|
29 |
'shortpixel_webp_image_base' => array('numargs' => 2),
|
@@ -49,16 +51,19 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
49 |
$ns = __NAMESPACE__;
|
50 |
$this->namespace = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
|
51 |
|
|
|
52 |
if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants
|
53 |
{
|
54 |
$this->is_manual_request = true;
|
55 |
$this->is_active = true;
|
56 |
|
|
|
57 |
if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true')
|
58 |
{
|
59 |
$this->logLevel = DebugItem::LEVEL_INFO;
|
60 |
}
|
61 |
else {
|
|
|
62 |
$this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']);
|
63 |
}
|
64 |
|
@@ -75,8 +80,6 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
75 |
|
76 |
if (defined('SHORTPIXEL_DEBUG_TARGET') && SHORTPIXEL_DEBUG_TARGET || $this->is_manual_request)
|
77 |
{
|
78 |
-
//$this->logPath = SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log";
|
79 |
-
//$this->logMode = defined('SHORTPIXEL_LOG_OVERWRITE') ? 0 : FILE_APPEND;
|
80 |
if (defined('SHORTPIXEL_LOG_OVERWRITE')) // if overwrite, do this on init once.
|
81 |
file_put_contents($this->logPath,'-- Log Reset -- ' .PHP_EOL);
|
82 |
|
@@ -127,6 +130,7 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
127 |
public function setLogPath($logPath)
|
128 |
{
|
129 |
$this->logPath = $logPath;
|
|
|
130 |
}
|
131 |
protected function addLog($message, $level, $data = array())
|
132 |
{
|
@@ -174,7 +178,7 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
174 |
{
|
175 |
$items = $debugItem->getForFormat();
|
176 |
$items['time_passed'] = round ( ($items['time'] - $this->start_time), 5);
|
177 |
-
$items['time'] = date('Y-m-d H:i:s', $items['time'] );
|
178 |
|
179 |
if ( ($items['caller']) && is_array($items['caller']) && count($items['caller']) > 0)
|
180 |
{
|
@@ -184,16 +188,50 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
184 |
|
185 |
$line = $this->formatLine($items);
|
186 |
|
|
|
|
|
187 |
// try to write to file. Don't write if directory doesn't exists (leads to notices)
|
188 |
-
if ($
|
189 |
{
|
190 |
-
|
|
|
191 |
}
|
192 |
else {
|
193 |
-
|
194 |
}
|
195 |
}
|
196 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
protected function formatLine($args = array() )
|
198 |
{
|
199 |
$line= $this->format;
|
@@ -344,8 +382,8 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
344 |
include($template_path);
|
345 |
}
|
346 |
else {
|
347 |
-
self::addError("View $template could not be found in " . $template_path,
|
348 |
-
array('class' => get_class($this)
|
349 |
}
|
350 |
}
|
351 |
|
24 |
protected $format_data = "\t %%data%% ";
|
25 |
|
26 |
protected $hooks = array();
|
27 |
+
|
28 |
+
private $logFile; // pointer resource to the logFile.
|
29 |
/* protected $hooks = array(
|
30 |
'shortpixel_image_exists' => array('numargs' => 3),
|
31 |
'shortpixel_webp_image_base' => array('numargs' => 2),
|
51 |
$ns = __NAMESPACE__;
|
52 |
$this->namespace = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
|
53 |
|
54 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
|
55 |
if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants
|
56 |
{
|
57 |
$this->is_manual_request = true;
|
58 |
$this->is_active = true;
|
59 |
|
60 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
|
61 |
if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true')
|
62 |
{
|
63 |
$this->logLevel = DebugItem::LEVEL_INFO;
|
64 |
}
|
65 |
else {
|
66 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
|
67 |
$this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']);
|
68 |
}
|
69 |
|
80 |
|
81 |
if (defined('SHORTPIXEL_DEBUG_TARGET') && SHORTPIXEL_DEBUG_TARGET || $this->is_manual_request)
|
82 |
{
|
|
|
|
|
83 |
if (defined('SHORTPIXEL_LOG_OVERWRITE')) // if overwrite, do this on init once.
|
84 |
file_put_contents($this->logPath,'-- Log Reset -- ' .PHP_EOL);
|
85 |
|
130 |
public function setLogPath($logPath)
|
131 |
{
|
132 |
$this->logPath = $logPath;
|
133 |
+
$this->getWriteFile(true); // reset the writeFile here.
|
134 |
}
|
135 |
protected function addLog($message, $level, $data = array())
|
136 |
{
|
178 |
{
|
179 |
$items = $debugItem->getForFormat();
|
180 |
$items['time_passed'] = round ( ($items['time'] - $this->start_time), 5);
|
181 |
+
$items['time'] = date('Y-m-d H:i:s', (int) $items['time'] );
|
182 |
|
183 |
if ( ($items['caller']) && is_array($items['caller']) && count($items['caller']) > 0)
|
184 |
{
|
188 |
|
189 |
$line = $this->formatLine($items);
|
190 |
|
191 |
+
$file = $this->getWriteFile();
|
192 |
+
|
193 |
// try to write to file. Don't write if directory doesn't exists (leads to notices)
|
194 |
+
if ($file )
|
195 |
{
|
196 |
+
fwrite($file, $line);
|
197 |
+
// file_put_contents($this->logPath,$line, FILE_APPEND);
|
198 |
}
|
199 |
else {
|
200 |
+
// error_log($line);
|
201 |
}
|
202 |
}
|
203 |
|
204 |
+
protected function getWriteFile($reset = false)
|
205 |
+
{
|
206 |
+
if (! is_null($this->logFile) && $reset === false)
|
207 |
+
{
|
208 |
+
return $this->logFile;
|
209 |
+
}
|
210 |
+
elseif(is_object($this->logFile))
|
211 |
+
{
|
212 |
+
fclose($this->logFile);
|
213 |
+
}
|
214 |
+
|
215 |
+
$logDir = dirname($this->logPath);
|
216 |
+
if (! is_dir($logDir) || ! is_writable($logDir))
|
217 |
+
{
|
218 |
+
error_log('ShortpixelLogger: Log Directory is not writable');
|
219 |
+
$this->logFile = false;
|
220 |
+
return false;
|
221 |
+
}
|
222 |
+
|
223 |
+
$file = fopen($this->logPath, 'a');
|
224 |
+
if ($file === false)
|
225 |
+
{
|
226 |
+
error_log('ShortpixelLogger: File could not be opened / created: ' . $this->logPath);
|
227 |
+
$this->logFile = false;
|
228 |
+
return $file;
|
229 |
+
}
|
230 |
+
|
231 |
+
$this->logFile = $file;
|
232 |
+
return $file;
|
233 |
+
}
|
234 |
+
|
235 |
protected function formatLine($args = array() )
|
236 |
{
|
237 |
$line= $this->format;
|
382 |
include($template_path);
|
383 |
}
|
384 |
else {
|
385 |
+
self::addError("View $template for ShortPixelLogger could not be found in " . $template_path,
|
386 |
+
array('class' => get_class($this)));
|
387 |
}
|
388 |
}
|
389 |
|
@@ -49,8 +49,8 @@ wp_enqueue_script( 'jquery-ui-draggable' );
|
|
49 |
|
50 |
|
51 |
<div class='sp_debug_box'>
|
52 |
-
<div class='header'><?php echo $view->namespace ?> Debug Box </div>
|
53 |
-
<a target="_blank" href='<?php echo $view->logLink ?>'>Logfile</a>
|
54 |
<div class='content_box'>
|
55 |
|
56 |
</div>
|
49 |
|
50 |
|
51 |
<div class='sp_debug_box'>
|
52 |
+
<div class='header'><?php echo esc_html($view->namespace) ?> Debug Box </div>
|
53 |
+
<a target="_blank" href='<?php echo esc_url($view->logLink) ?>'>Logfile</a>
|
54 |
<div class='content_box'>
|
55 |
|
56 |
</div>
|
@@ -108,7 +108,7 @@ class NoticeController //extends ShortPixelController
|
|
108 |
}
|
109 |
self::$notices[] = $notice;
|
110 |
$this->countNotices();
|
111 |
-
|
112 |
$this->update();
|
113 |
return $notice;
|
114 |
}
|
@@ -212,14 +212,23 @@ class NoticeController //extends ShortPixelController
|
|
212 |
{
|
213 |
$response = array('result' => false, 'reason' => '');
|
214 |
|
215 |
-
if ( wp_verify_nonce( $_POST['nonce'], 'dismiss') )
|
216 |
{
|
217 |
-
if ($_POST['plugin_action']
|
218 |
{
|
219 |
-
$id = sanitize_text_field($_POST['id']);
|
220 |
-
|
221 |
-
|
222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
{
|
224 |
$notice->dismiss();
|
225 |
$this->update();
|
@@ -228,7 +237,8 @@ class NoticeController //extends ShortPixelController
|
|
228 |
else
|
229 |
{
|
230 |
Log::addError('Notice not found when dismissing -> ' . $id, self::$notices);
|
231 |
-
|
|
|
232 |
}
|
233 |
|
234 |
}
|
@@ -349,7 +359,7 @@ class NoticeController //extends ShortPixelController
|
|
349 |
{
|
350 |
if (file_exists(__DIR__ . '/css/notices.css'))
|
351 |
{
|
352 |
-
echo '<style>' . file_get_contents(__DIR__ . '/css/notices.css') . '</style>';
|
353 |
}
|
354 |
else {
|
355 |
Log::addDebug('Notices : css/notices.css could not be loaded');
|
108 |
}
|
109 |
self::$notices[] = $notice;
|
110 |
$this->countNotices();
|
111 |
+
|
112 |
$this->update();
|
113 |
return $notice;
|
114 |
}
|
212 |
{
|
213 |
$response = array('result' => false, 'reason' => '');
|
214 |
|
215 |
+
if (isset($_POST['nonce']) && wp_verify_nonce( sanitize_key($_POST['nonce']), 'dismiss') )
|
216 |
{
|
217 |
+
if (isset($_POST['plugin_action']) && 'dismiss' == $_POST['plugin_action'] )
|
218 |
{
|
219 |
+
$id = (isset($_POST['id'])) ? sanitize_text_field( wp_unslash($_POST['id'])) : null;
|
220 |
+
|
221 |
+
if (! is_null($id))
|
222 |
+
{
|
223 |
+
|
224 |
+
$notice = $this->getNoticeByID($id);
|
225 |
+
}
|
226 |
+
else
|
227 |
+
{
|
228 |
+
$notice = false;
|
229 |
+
}
|
230 |
+
|
231 |
+
if(false !== $notice)
|
232 |
{
|
233 |
$notice->dismiss();
|
234 |
$this->update();
|
237 |
else
|
238 |
{
|
239 |
Log::addError('Notice not found when dismissing -> ' . $id, self::$notices);
|
240 |
+
$response['result'] = false;
|
241 |
+
$response['reason'] = ' Notice ' . $id . ' not found. ';
|
242 |
}
|
243 |
|
244 |
}
|
359 |
{
|
360 |
if (file_exists(__DIR__ . '/css/notices.css'))
|
361 |
{
|
362 |
+
echo '<style>' . esc_html(file_get_contents(__DIR__ . '/css/notices.css')) . '</style>';
|
363 |
}
|
364 |
else {
|
365 |
Log::addDebug('Notices : css/notices.css could not be loaded');
|
@@ -21,6 +21,8 @@ class NoticeModel //extends ShortPixelModel
|
|
21 |
|
22 |
public static $icons = array();
|
23 |
|
|
|
|
|
24 |
const NOTICE_NORMAL = 1;
|
25 |
const NOTICE_ERROR = 2;
|
26 |
const NOTICE_SUCCESS = 3;
|
@@ -142,7 +144,7 @@ class NoticeModel //extends ShortPixelModel
|
|
142 |
public function getForDisplay()
|
143 |
{
|
144 |
$this->viewed = true;
|
145 |
-
$class = 'shortpixel notice ';
|
146 |
|
147 |
$icon = '';
|
148 |
|
@@ -217,10 +219,31 @@ class NoticeModel //extends ShortPixelModel
|
|
217 |
$output .= "<div class='detail-content-wrapper'><p class='detail-content'>" . $this->parseDetails() . "</p></div>";
|
218 |
$output .= '<label for="check-' . $id . '" class="hide-details"><span>' . __('Hide Details', 'shortpixel-image-optimiser') . '</span></label>';
|
219 |
|
220 |
-
$output .= '</div>'; // detail
|
|
|
|
|
|
|
221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
}
|
223 |
-
|
|
|
224 |
|
225 |
if ($this->is_persistent && $this->is_removable)
|
226 |
{
|
@@ -245,20 +268,37 @@ class NoticeModel //extends ShortPixelModel
|
|
245 |
|
246 |
private function getDismissJS()
|
247 |
{
|
248 |
-
$url = wp_json_encode(admin_url('admin-ajax.php'));
|
249 |
-
// $action = 'dismiss';
|
250 |
-
$nonce = wp_create_nonce('dismiss');
|
251 |
|
252 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
|
254 |
-
|
255 |
|
256 |
-
$js = "jQuery(document).on('click','#$this->id button.notice-dismiss',
|
257 |
-
function() {
|
258 |
-
var data = $data;
|
259 |
-
var url = $url;
|
260 |
-
jQuery.post(url, data); }
|
261 |
-
);";
|
262 |
return "\n jQuery(document).ready(function(){ \n" . $js . "\n});";
|
263 |
}
|
264 |
|
21 |
|
22 |
public static $icons = array();
|
23 |
|
24 |
+
private static $jsDismissLoaded;
|
25 |
+
|
26 |
const NOTICE_NORMAL = 1;
|
27 |
const NOTICE_ERROR = 2;
|
28 |
const NOTICE_SUCCESS = 3;
|
144 |
public function getForDisplay()
|
145 |
{
|
146 |
$this->viewed = true;
|
147 |
+
$class = 'shortpixel shortpixel-notice ';
|
148 |
|
149 |
$icon = '';
|
150 |
|
219 |
$output .= "<div class='detail-content-wrapper'><p class='detail-content'>" . $this->parseDetails() . "</p></div>";
|
220 |
$output .= '<label for="check-' . $id . '" class="hide-details"><span>' . __('Hide Details', 'shortpixel-image-optimiser') . '</span></label>';
|
221 |
|
222 |
+
$output .= '</div>'; // detail wrapper
|
223 |
+
|
224 |
+
}
|
225 |
+
$output .= "</span>";
|
226 |
|
227 |
+
if ($this->is_removable)
|
228 |
+
{
|
229 |
+
$output .= '<button type="button" id="button-' . $id . '" class="notice-dismiss" data-dismiss="' . $this->suppress_period . '" ><span class="screen-reader-text">' . __('Dismiss this notice', 'shortpixel-image-optimiser') . '</span></button>';
|
230 |
+
|
231 |
+
if (! $this->is_persistent)
|
232 |
+
{
|
233 |
+
$output .= "<script type='text/javascript'>\n
|
234 |
+
document.getElementById('button-$id').onclick = function()
|
235 |
+
{
|
236 |
+
var el = document.getElementById('$id');
|
237 |
+
$(el).fadeTo(100,0,function() {
|
238 |
+
$(el).slideUp(100, 0, function () {
|
239 |
+
$(el).remove();
|
240 |
+
})
|
241 |
+
});
|
242 |
+
} </script>";
|
243 |
+
}
|
244 |
}
|
245 |
+
|
246 |
+
$output .= "</div>";
|
247 |
|
248 |
if ($this->is_persistent && $this->is_removable)
|
249 |
{
|
268 |
|
269 |
private function getDismissJS()
|
270 |
{
|
|
|
|
|
|
|
271 |
|
272 |
+
$js = '';
|
273 |
+
if (is_null(self::$jsDismissLoaded))
|
274 |
+
{
|
275 |
+
$nonce = wp_create_nonce('dismiss');
|
276 |
+
$url = wp_json_encode(admin_url('admin-ajax.php'));
|
277 |
+
$js = "function shortpixel_notice_dismiss(event) {
|
278 |
+
event.preventDefault();
|
279 |
+
var ev = event.detail;
|
280 |
+
var target = event.target;
|
281 |
+
var parent = target.parentElement;
|
282 |
+
|
283 |
+
var data = {
|
284 |
+
'plugin_action': 'dismiss',
|
285 |
+
'action' : '$this->notice_action',
|
286 |
+
'nonce' : '$nonce',
|
287 |
+
}
|
288 |
+
data.time = target.getAttribute('data-dismiss');
|
289 |
+
data.id = parent.getAttribute('id');
|
290 |
+
jQuery.post($url,data);
|
291 |
+
|
292 |
+
jQuery(parent).fadeTo(100,0,function() {
|
293 |
+
jQuery(parent).slideUp(100, 0, function () {
|
294 |
+
jQuery(parent).remove();
|
295 |
+
})
|
296 |
+
});
|
297 |
+
}";
|
298 |
+
}
|
299 |
|
300 |
+
$js .= ' jQuery("#' . $this->id . '").find(".notice-dismiss").on("click", shortpixel_notice_dismiss); ';
|
301 |
|
|
|
|
|
|
|
|
|
|
|
|
|
302 |
return "\n jQuery(document).ready(function(){ \n" . $js . "\n});";
|
303 |
}
|
304 |
|
@@ -1,21 +1,48 @@
|
|
1 |
-
.shortpixel.notice {
|
2 |
-
padding: 8px;
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
/* In-view notice ( not on top, between the options ) - styled after WP notice */
|
11 |
.view-notice {
|
12 |
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
|
13 |
border: 4px solid #fff;
|
14 |
-
padding: 1px 12px;
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
19 |
|
20 |
.view-notice-row {
|
21 |
-
display: none;
|
|
|
|
|
|
1 |
+
.shortpixel.shortpixel-notice {
|
2 |
+
padding: 8px;
|
3 |
+
background: #fff;
|
4 |
+
border: 1px solid #c3c4c7;
|
5 |
+
border-left-width: 4px;
|
6 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
7 |
+
margin: 5px 15px 2px;
|
8 |
+
position: relative;
|
9 |
+
}
|
10 |
+
.shortpixel.shortpixel-notice img {
|
11 |
+
display: inline-block;
|
12 |
+
margin: 0 25px 0 0;
|
13 |
+
max-height: 50px;
|
14 |
+
}
|
15 |
+
.shortpixel.shortpixel-notice .notice-dismiss {
|
16 |
+
margin-top: 6px;
|
17 |
+
}
|
18 |
+
.shortpixel.shortpixel-notice.notice-success {
|
19 |
+
border-left-color: #00a32a;
|
20 |
+
}
|
21 |
+
.shortpixel.shortpixel-notice.notice-warning {
|
22 |
+
border-left-color: #dba617;
|
23 |
+
}
|
24 |
+
.shortpixel.shortpixel-notice.notice-error {
|
25 |
+
border-left-color: #ff0000;
|
26 |
+
}
|
27 |
+
.shortpixel.shortpixel-notice.notice-info {
|
28 |
+
border-left-color: #72aee6;
|
29 |
+
}
|
30 |
|
31 |
/* In-view notice ( not on top, between the options ) - styled after WP notice */
|
32 |
.view-notice {
|
33 |
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
|
34 |
border: 4px solid #fff;
|
35 |
+
padding: 1px 12px;
|
36 |
+
}
|
37 |
+
.view-notice p {
|
38 |
+
margin: 1em 0 !important;
|
39 |
+
}
|
40 |
+
.view-notice.warning {
|
41 |
+
border-left-color: #ffb900;
|
42 |
+
}
|
43 |
|
44 |
.view-notice-row {
|
45 |
+
display: none;
|
46 |
+
}
|
47 |
+
|
48 |
+
/*# sourceMappingURL=notices.css.map */
|
@@ -0,0 +1 @@
|
|
|
1 |
+
{"version":3,"sourceRoot":"","sources":["notices.scss"],"names":[],"mappings":"AACA;EAIG;EACF;EACA;EACA;EACA;EACA;EACA;;AAEE;EAEE;EACA;EACA;;AAEF;EAEE;;AAGH;EAEC;;AAED;EAEC;;AAED;EAEC;;AAED;EAEE;;;AAIJ;AACA;EAGE;EACA;EAEA;;AACA;EACE;;AAEF;EAEE;;;AAIJ;EAEE","file":"notices.css"}
|
@@ -1,9 +1,16 @@
|
|
1 |
|
2 |
-
.shortpixel.notice
|
3 |
{
|
4 |
//padding: 18px;
|
5 |
//min-height: 50px;
|
6 |
padding: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
img
|
8 |
{
|
9 |
display:inline-block;
|
@@ -12,8 +19,25 @@
|
|
12 |
}
|
13 |
.notice-dismiss
|
14 |
{
|
15 |
-
margin-top:
|
16 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
}
|
18 |
|
19 |
/* In-view notice ( not on top, between the options ) - styled after WP notice */
|
1 |
|
2 |
+
.shortpixel.shortpixel-notice
|
3 |
{
|
4 |
//padding: 18px;
|
5 |
//min-height: 50px;
|
6 |
padding: 8px;
|
7 |
+
background: #fff;
|
8 |
+
border: 1px solid #c3c4c7;
|
9 |
+
border-left-width: 4px;
|
10 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
11 |
+
margin: 5px 15px 2px;
|
12 |
+
position: relative;
|
13 |
+
|
14 |
img
|
15 |
{
|
16 |
display:inline-block;
|
19 |
}
|
20 |
.notice-dismiss
|
21 |
{
|
22 |
+
margin-top: 6px;
|
23 |
}
|
24 |
+
|
25 |
+
&.notice-success
|
26 |
+
{
|
27 |
+
border-left-color: #00a32a;
|
28 |
+
}
|
29 |
+
&.notice-warning
|
30 |
+
{
|
31 |
+
border-left-color: #dba617;
|
32 |
+
}
|
33 |
+
&.notice-error
|
34 |
+
{
|
35 |
+
border-left-color: #ff0000;
|
36 |
+
}
|
37 |
+
&.notice-info
|
38 |
+
{
|
39 |
+
border-left-color: #72aee6;
|
40 |
+
}
|
41 |
}
|
42 |
|
43 |
/* In-view notice ( not on top, between the options ) - styled after WP notice */
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace;
|
3 |
+
|
4 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
5 |
+
use EnableMediaReplace\Api as Api;
|
6 |
+
|
7 |
+
class Ajax {
|
8 |
+
public function __construct() {
|
9 |
+
$endpoints = array(
|
10 |
+
'remove_background',
|
11 |
+
|
12 |
+
);
|
13 |
+
foreach ( $endpoints as $action ) {
|
14 |
+
add_action( "wp_ajax_emr_{$action}", array( $this, $action ) );
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
public function remove_background() {
|
19 |
+
if ( $this->check_nonce() ) {
|
20 |
+
$api = new Api;
|
21 |
+
$response = $api->request( $_POST );
|
22 |
+
wp_send_json($response);
|
23 |
+
}
|
24 |
+
else {
|
25 |
+
die('Wrong nonce');
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
private function check_nonce() {
|
30 |
+
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : '';
|
31 |
+
$action = isset( $_POST['action'] ) ? sanitize_text_field( $_POST['action'] ) : '';
|
32 |
+
return wp_verify_nonce( $nonce, $action );
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
|
37 |
+
new Ajax();
|
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This page contains api class.
|
4 |
+
*/
|
5 |
+
namespace EnableMediaReplace;
|
6 |
+
|
7 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
8 |
+
|
9 |
+
use Exception;
|
10 |
+
use stdClass;
|
11 |
+
/**
|
12 |
+
* This class contains api methods
|
13 |
+
*/
|
14 |
+
class Api {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Request Counter
|
18 |
+
*
|
19 |
+
* @var int $counter
|
20 |
+
*/
|
21 |
+
private $counter = 0;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* ShortPixel api url
|
25 |
+
*
|
26 |
+
* @var string $url
|
27 |
+
*/
|
28 |
+
private $url = 'http://api.shortpixel.com/v2/free-reducer.php';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* ShortPixel api request headers
|
32 |
+
*
|
33 |
+
* @var array $headers
|
34 |
+
*/
|
35 |
+
private $headers = array(
|
36 |
+
'Content-Type: application/json',
|
37 |
+
'Accept: application/json',
|
38 |
+
);
|
39 |
+
|
40 |
+
private $refresh = true; // only first request should be fresh
|
41 |
+
|
42 |
+
|
43 |
+
|
44 |
+
public function __construct()
|
45 |
+
{
|
46 |
+
|
47 |
+
}
|
48 |
+
/**
|
49 |
+
* Create ShortPixel api request
|
50 |
+
*
|
51 |
+
* @param array $data
|
52 |
+
* @return stdClass $result
|
53 |
+
*/
|
54 |
+
public function request( array $posted_data ) {
|
55 |
+
$bg_remove = '1';
|
56 |
+
$compression_level = 0; // intval($posted_data['compression_level']); // off for now.
|
57 |
+
|
58 |
+
$attachment_id = isset($_POST['attachment_id']) ? intval($_POST['attachment_id']) : null;
|
59 |
+
|
60 |
+
if (is_null($attachment_id))
|
61 |
+
{
|
62 |
+
$result = $this->getResponseObject();
|
63 |
+
$result->success = false;
|
64 |
+
$result->message = __('No attachment ID given', 'enable-media-replace');
|
65 |
+
return $result;
|
66 |
+
}
|
67 |
+
|
68 |
+
$replacer = new Replacer($attachment_id);
|
69 |
+
$url = $replacer->getSourceUrl();
|
70 |
+
|
71 |
+
$settings = get_option('enable_media_replace', array()); // save settings and show last loaded.
|
72 |
+
$settings['bg_type'] = isset($_POST['background']['type']) ? sanitize_text_field($_POST['background']['type']) : false;
|
73 |
+
$settings['bg_color'] = isset($_POST['background']['color']) ? sanitize_text_field($_POST['background']['color']) : '#ffffff'; // default to white.
|
74 |
+
$settings['bg_transparency'] = isset($_POST['background']['transparency']) ? sanitize_text_field($_POST['background']['transparency']) : false;
|
75 |
+
|
76 |
+
update_option('enable_media_replace', $settings, false);
|
77 |
+
|
78 |
+
|
79 |
+
if ( 'solid' === $posted_data['background']['type'] ) {
|
80 |
+
$bg_remove = $posted_data['background']['color'];
|
81 |
+
|
82 |
+
$transparency = isset($posted_data['background']['transparency']) ? intval($posted_data['background']['transparency']) : -1;
|
83 |
+
// if transparancy without acceptable boundaries, add it to color ( as rgba I presume )
|
84 |
+
if ($transparency >= 0 && $transparency < 100)
|
85 |
+
{
|
86 |
+
if ($transparency == 100)
|
87 |
+
$transparency = 'FF';
|
88 |
+
|
89 |
+
// Strpad for lower than 10 should add 09, 08 etc.
|
90 |
+
$bg_remove .= str_pad($transparency, 2, '0', STR_PAD_LEFT);
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
|
95 |
+
|
96 |
+
$data = array(
|
97 |
+
'plugin_version' => EMR_VERSION,
|
98 |
+
'bg_remove' => $bg_remove,
|
99 |
+
'urllist' => array( urlencode( esc_url($url) ) ),
|
100 |
+
'lossy' => $compression_level,
|
101 |
+
'refresh' => $this->refresh,
|
102 |
+
);
|
103 |
+
|
104 |
+
$request = array(
|
105 |
+
'method' => 'POST',
|
106 |
+
'timeout' => 60,
|
107 |
+
'headers' => $this->headers,
|
108 |
+
'body' => json_encode( $data ),
|
109 |
+
|
110 |
+
);
|
111 |
+
|
112 |
+
$settingsData = '';
|
113 |
+
//unset($settingsData['url']);
|
114 |
+
|
115 |
+
foreach($data as $key => $val)
|
116 |
+
{
|
117 |
+
if ($key == 'urllist' || $key == 'refresh')
|
118 |
+
{
|
119 |
+
continue;
|
120 |
+
}
|
121 |
+
$settingsData .= " $key:$val ";
|
122 |
+
}
|
123 |
+
|
124 |
+
|
125 |
+
//we need to wait a bit until we try to check if the image is ready
|
126 |
+
if ($this->counter > 0)
|
127 |
+
sleep( $this->counter + 3 );
|
128 |
+
|
129 |
+
$this->counter++;
|
130 |
+
|
131 |
+
$result = $this->getResponseObject();
|
132 |
+
|
133 |
+
if ( $this->counter < 10 ) {
|
134 |
+
try {
|
135 |
+
|
136 |
+
Log::addDebug('Sending request', $request);
|
137 |
+
$response = wp_remote_post( $this->url, $request );
|
138 |
+
|
139 |
+
$this->refresh = false;
|
140 |
+
|
141 |
+
if ( is_wp_error( $response ) ) {
|
142 |
+
$result->message = $response->get_error_message();
|
143 |
+
} else {
|
144 |
+
|
145 |
+
$json = json_decode( $response['body'] );
|
146 |
+
|
147 |
+
Log::addDebug('Response Json', $json);
|
148 |
+
if ( is_array( $json ) && '2' === $json[0]->Status->Code ) {
|
149 |
+
$result->success = true;
|
150 |
+
|
151 |
+
if ( '1' === $compression_level || '2' === $compression_level ) {
|
152 |
+
$result->image = $json[0]->LossyURL;
|
153 |
+
} else {
|
154 |
+
$result->image = $json[0]->LosslessURL;
|
155 |
+
}
|
156 |
+
|
157 |
+
$key = $this->handleSuccess($result);
|
158 |
+
$result->key = $key;
|
159 |
+
$result->url = $url;
|
160 |
+
$result->image = add_query_arg('ts', time(), $result->image);
|
161 |
+
|
162 |
+
$result->settings = $settingsData;
|
163 |
+
|
164 |
+
// $this->handleSuccess($result);
|
165 |
+
} elseif ( is_array( $json ) && '1' === $json[0]->Status->Code ) {
|
166 |
+
return $this->request( $posted_data );
|
167 |
+
} else {
|
168 |
+
if (is_array($json))
|
169 |
+
{
|
170 |
+
$result->message = $json[0]->Status->Message;
|
171 |
+
}
|
172 |
+
elseif (is_object($json) && property_exists($json, 'Status'))
|
173 |
+
{
|
174 |
+
$result->message = $json->Status->Message;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
}
|
178 |
+
} catch ( Exception $e ) {
|
179 |
+
$result->message = $e->getMessage();
|
180 |
+
}
|
181 |
+
} else {
|
182 |
+
$result->message = __( 'The background could not be removed in a reasonable amount of time. The file might be too big, or the API could be busy. Please try again later!', 'enable-media-replace' );
|
183 |
+
}
|
184 |
+
|
185 |
+
return $result;
|
186 |
+
}
|
187 |
+
|
188 |
+
public function handleSuccess($result)
|
189 |
+
{
|
190 |
+
// $fs = emr()->filesystem();
|
191 |
+
// $result = $fs->downloadFile($result->image, wp_tempnam($result->image));
|
192 |
+
$nonce = isset($_POST['nonce']) ? sanitize_text_field($_POST['nonce']) : wp_create_nonce();
|
193 |
+
$key = wp_hash($nonce . $result->image, 'logged_in');
|
194 |
+
|
195 |
+
set_transient('emr_' . $key, $result->image, 30 * MINUTE_IN_SECONDS);
|
196 |
+
return $key;
|
197 |
+
}
|
198 |
+
|
199 |
+
public function handleDownload($key)
|
200 |
+
{
|
201 |
+
$url = get_transient('emr_' . $key);
|
202 |
+
$result = $this->getResponseObject();
|
203 |
+
|
204 |
+
if ($url === false)
|
205 |
+
{
|
206 |
+
$result->message = __('This file seems not available anymore. Please try again', 'enable-media-replace');
|
207 |
+
return $result;
|
208 |
+
}
|
209 |
+
|
210 |
+
$fs = emr()->filesystem();
|
211 |
+
$target = wp_tempnam($url);
|
212 |
+
|
213 |
+
$bool = $fs->downloadFile($url, $target);
|
214 |
+
|
215 |
+
if ($bool === false)
|
216 |
+
{
|
217 |
+
$result->message = __('Download failed', 'enable-media-replace');
|
218 |
+
}
|
219 |
+
else {
|
220 |
+
$result->success = true;
|
221 |
+
$result->image = $target;
|
222 |
+
}
|
223 |
+
return $result;
|
224 |
+
}
|
225 |
+
|
226 |
+
protected function getResponseObject()
|
227 |
+
{
|
228 |
+
$result = new stdClass;
|
229 |
+
$result->success = false;
|
230 |
+
$result->image = null;
|
231 |
+
$result->message = null;
|
232 |
+
|
233 |
+
return $result;
|
234 |
+
}
|
235 |
+
|
236 |
+
}
|
@@ -65,9 +65,9 @@ class emrCache
|
|
65 |
$this->checkCaches();
|
66 |
|
67 |
// general WP
|
68 |
-
if ($post_id > 0)
|
69 |
-
|
70 |
-
else
|
71 |
wp_cache_flush();
|
72 |
|
73 |
/* Verified working without.
|
65 |
$this->checkCaches();
|
66 |
|
67 |
// general WP
|
68 |
+
//if ($post_id > 0)
|
69 |
+
// clean_post_cache($post_id);
|
70 |
+
//else
|
71 |
wp_cache_flush();
|
72 |
|
73 |
/* Verified working without.
|
@@ -1,378 +1,481 @@
|
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
|
|
3 |
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
use EnableMediaReplace\Notices\NoticeController as Notices;
|
|
|
|
|
5 |
|
6 |
// Does what a plugin does.
|
7 |
class EnableMediaReplacePlugin
|
8 |
{
|
9 |
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
private $user_cap = false;
|
14 |
-
private $general_cap = false;
|
15 |
-
|
16 |
-
public function __construct()
|
17 |
-
{
|
18 |
-
add_action('plugins_loaded', array($this, 'runtime'));
|
19 |
-
}
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
$this->nopriv_plugin_actions();
|
24 |
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
$this->general_cap = EMR_CAPABILITY[0];
|
30 |
-
$this->user_cap = EMR_CAPABILITY[1];
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
{
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
return;
|
40 |
}
|
41 |
-
}
|
42 |
-
elseif (! current_user_can('upload_files'))
|
43 |
-
return;
|
44 |
|
45 |
-
|
46 |
-
}
|
47 |
-
|
48 |
-
public static function get()
|
49 |
-
{
|
50 |
-
if (is_null(self::$instance))
|
51 |
-
self::$instance = new EnableMediaReplacePlugin();
|
52 |
-
|
53 |
-
$log = Log::getInstance();
|
54 |
-
if (Log::debugIsActive())
|
55 |
-
{
|
56 |
-
$uploaddir = wp_upload_dir(null, false, false);
|
57 |
-
if (isset($uploaddir['basedir']))
|
58 |
-
$log->setLogPath($uploaddir['basedir'] . "/emr_log");
|
59 |
}
|
60 |
-
return self::$instance;
|
61 |
-
}
|
62 |
-
|
63 |
-
// Actions for EMR that always need to hook
|
64 |
-
protected function nopriv_plugin_actions()
|
65 |
-
{
|
66 |
-
// shortcode
|
67 |
-
add_shortcode('file_modified', array($this, 'get_modified_date'));
|
68 |
-
}
|
69 |
-
|
70 |
-
public function plugin_actions()
|
71 |
-
{
|
72 |
-
$this->plugin_path = plugin_dir_path(EMR_ROOT_FILE);
|
73 |
-
$this->plugin_url = plugin_dir_url(EMR_ROOT_FILE);
|
74 |
-
|
75 |
-
// init plugin
|
76 |
-
add_action('admin_menu', array($this,'menu'));
|
77 |
-
add_action('admin_init', array($this,'init'));
|
78 |
-
add_action('admin_enqueue_scripts', array($this,'admin_scripts'));
|
79 |
-
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
|
91 |
-
|
92 |
-
add_action( 'add_meta_boxes', array($this, 'add_meta_boxes'),10,2 );
|
93 |
-
add_filter('attachment_fields_to_edit', array($this, 'attachment_editor'), 10, 2);
|
94 |
-
|
95 |
-
/** Just after an image is replaced, try to browser decache the images */
|
96 |
-
if (isset($_GET['emr_replaced']) && intval($_GET['emr_replaced'] == 1))
|
97 |
{
|
98 |
-
|
|
|
|
|
99 |
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
103 |
}
|
104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
|
108 |
/**
|
109 |
* Register this file in WordPress so we can call it with a ?page= GET var.
|
110 |
* To suppress it in the menu we give it an empty menu title.
|
111 |
*/
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
|
118 |
/**
|
119 |
* Initialize this plugin. Called by 'admin_init' hook.
|
120 |
*
|
121 |
*/
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
|
126 |
-
|
127 |
|
128 |
-
$notices = Notices::getInstance();
|
129 |
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
|
134 |
-
|
135 |
-
|
|
|
136 |
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
global $plugin_page;
|
141 |
-
switch($plugin_page)
|
142 |
-
{
|
143 |
-
case 'enable-media-replace/enable-media-replace.php':
|
144 |
-
$action = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : '';
|
145 |
-
wp_enqueue_style('emr_style');
|
146 |
-
wp_enqueue_script('jquery-ui-datepicker');
|
147 |
-
wp_enqueue_style('jquery-ui-datepicker');
|
148 |
-
wp_enqueue_script('emr_admin');
|
149 |
-
|
150 |
-
if (! check_admin_referer( $action, '_wpnonce') )
|
151 |
-
{
|
152 |
-
die('Invalid Nonce');
|
153 |
-
}
|
154 |
|
155 |
-
|
156 |
-
|
157 |
-
if ( array_key_exists("attachment_id", $_GET) && intval($_GET["attachment_id"]) > 0) {
|
158 |
-
wp_enqueue_script('emr_upsell');
|
159 |
-
require_once($this->plugin_path . "views/popup.php"); // warning variables like $action be overwritten here.
|
160 |
-
}
|
161 |
-
}
|
162 |
-
elseif ( $action == 'media_replace_upload' ) {
|
163 |
-
require_once($this->plugin_path . 'views/upload.php');
|
164 |
-
}
|
165 |
-
else {
|
166 |
-
exit('Something went wrong loading page, please try again');
|
167 |
-
}
|
168 |
|
169 |
-
|
170 |
-
|
|
|
171 |
|
172 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
|
179 |
/** register styles and scripts
|
180 |
*
|
181 |
* Nothing should ever by -enqueued- here, just registered.
|
182 |
*/
|
183 |
-
|
184 |
-
{
|
185 |
-
if (is_rtl())
|
186 |
{
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
|
193 |
-
|
194 |
|
195 |
-
|
196 |
|
197 |
-
|
198 |
-
|
199 |
-
'
|
|
|
|
|
200 |
'maxfilesize' => wp_max_upload_size(),
|
201 |
'allowed_mime' => $mimes,
|
202 |
-
|
203 |
|
204 |
-
|
205 |
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
|
210 |
-
|
211 |
|
212 |
-
|
213 |
-
|
214 |
|
215 |
-
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
|
218 |
/** Utility function for the Jquery UI Datepicker */
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
|
|
224 |
break;
|
225 |
-
|
226 |
-
|
227 |
break;
|
228 |
-
|
229 |
-
|
230 |
break;
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
|
253 |
/** Get the URL to the media replace page
|
254 |
* @param $attach_id The attachment ID to replace
|
255 |
* @return Admin URL to the page.
|
256 |
*/
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
'page' => 'enable-media-replace/enable-media-replace.php',
|
262 |
'action' => 'media_replace',
|
263 |
'attachment_id' => $attach_id,
|
264 |
-
|
265 |
|
266 |
-
|
|
|
267 |
|
268 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
|
270 |
-
|
271 |
-
|
272 |
-
// Because some plugins don't like to play by the rules.
|
273 |
-
if (is_null($post_type) || is_null($post))
|
274 |
-
return false;
|
275 |
|
276 |
-
|
277 |
-
|
|
|
|
|
|
|
|
|
278 |
|
279 |
-
|
|
|
|
|
280 |
|
281 |
-
|
282 |
-
{
|
283 |
-
add_meta_box('emr-showthumbs-box', __('Replaced Thumbnails Preview', 'enable-media-replace'), array($this, 'show_thumbs_box'), 'attachment', 'side', 'low');
|
284 |
-
}
|
285 |
|
286 |
-
|
|
|
|
|
|
|
287 |
|
288 |
-
|
289 |
-
|
290 |
|
291 |
-
|
|
|
292 |
|
293 |
-
|
294 |
-
|
295 |
|
296 |
-
|
297 |
-
if (FORCE_SSL_ADMIN) {
|
298 |
-
$editurl = str_replace("http:", "https:", $editurl);
|
299 |
-
} */
|
300 |
-
$link = "href=\"$editurl\"";
|
301 |
|
|
|
|
|
|
|
302 |
|
303 |
-
|
304 |
-
|
305 |
|
306 |
-
|
307 |
-
{
|
308 |
-
if (! $this->checkImagePermission($post->post_author, $post->ID))
|
309 |
-
{ return; }
|
310 |
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
if (! isset($meta['sizes']) )
|
316 |
-
{ echo __('Thumbnails were not generated', 'enable-media-replace');
|
317 |
-
return false;
|
318 |
}
|
319 |
|
320 |
-
|
321 |
{
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
|
326 |
-
|
327 |
-
{
|
328 |
-
echo "<div class='original previewwrapper'><img src='" . $source_url_oldway . "'><span class='label'>" . __('Original') . "</span></div>";
|
329 |
-
}
|
330 |
|
331 |
-
|
332 |
|
|
|
|
|
|
|
|
|
333 |
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
}
|
340 |
-
}
|
341 |
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
|
346 |
-
|
347 |
-
|
|
|
348 |
|
349 |
-
|
350 |
-
|
351 |
-
$screen = get_current_screen();
|
352 |
|
353 |
-
|
354 |
-
|
355 |
-
|
|
|
356 |
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
|
361 |
-
|
362 |
-
|
363 |
"label" => esc_html__("Replace media", "enable-media-replace"),
|
364 |
"input" => "html",
|
365 |
-
"html" => "<a class='button-secondary' $link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a>", "helps" => esc_html__("To replace the current file, click the link and upload a replacement.", "enable-media-replace")
|
366 |
);
|
367 |
|
368 |
-
|
369 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
370 |
|
371 |
/**
|
372 |
* @param array $mime_types
|
373 |
* @return array
|
374 |
*/
|
375 |
-
|
376 |
public function add_mime_types($mime_types)
|
377 |
{
|
378 |
$mime_types['dat'] = 'text/plain'; // Adding .dat extension
|
@@ -383,102 +486,117 @@ class EnableMediaReplacePlugin
|
|
383 |
* Function called by filter 'media_row_actions'
|
384 |
* Enables linking to EMR straight from the media library
|
385 |
*/
|
386 |
-
|
|
|
387 |
|
|
|
|
|
|
|
388 |
|
389 |
-
|
390 |
-
|
|
|
|
|
|
|
|
|
391 |
|
392 |
-
|
393 |
-
|
394 |
-
|
|
|
|
|
|
|
395 |
|
396 |
-
|
397 |
-
if (FORCE_SSL_ADMIN) {
|
398 |
-
$editurl = str_replace("http:", "https:", $editurl);
|
399 |
-
} */
|
400 |
-
$link = "href=\"$editurl\"";
|
401 |
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
|
|
|
|
|
|
|
406 |
|
407 |
-
public function display_notices() {
|
408 |
-
$current_screen = get_current_screen();
|
409 |
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
|
|
|
|
|
|
|
|
414 |
//for network installed plugins, don't display the message on subsites.
|
415 |
&& !(function_exists('is_multisite') && is_multisite() && is_plugin_active_for_network('enable-media-replace/enable-media-replace.php') && !is_main_site()))
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
|
|
426 |
|
427 |
/* Ajax function to dismiss notice */
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
|
|
432 |
|
433 |
/** Outputs the replaced date of the media on the edit_attachment screen
|
434 |
*
|
435 |
* @param $post Obj Post Object
|
436 |
*/
|
437 |
-
|
438 |
-
|
439 |
-
// Fallback for before version 4.9, doens't pass post.
|
440 |
-
if (! is_object($post))
|
441 |
-
global $post;
|
442 |
|
443 |
-
|
444 |
-
|
|
|
|
|
445 |
|
446 |
-
|
447 |
-
|
|
|
448 |
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
|
|
|
|
454 |
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
?>
|
463 |
<div class="misc-pub-section replace_author">
|
464 |
-
<span><?php echo esc_html__(
|
465 |
</div>
|
466 |
-
|
|
|
467 |
}
|
468 |
|
469 |
-
}
|
470 |
-
|
471 |
/** When an image is just replaced, it can stuck in the browser cache making a look like it was not replaced. Try
|
472 |
* undo that effect by adding a timestamp to the query string */
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
|
|
477 |
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
|
483 |
/**
|
484 |
* Shorttag function to show the media file modification date/time.
|
@@ -486,35 +604,35 @@ class EnableMediaReplacePlugin
|
|
486 |
* @return string content / replacement shorttag
|
487 |
* @todo Note this returns the wrong date, ie. server date not corrected for timezone. Function could be removed altogether, not sure about purpose.
|
488 |
*/
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
extract(shortcode_atts(array(
|
494 |
-
'id' => '',
|
495 |
-
'format' => get_option('date_format') . " " . get_option('time_format'),
|
496 |
-
), $atts));
|
497 |
-
|
498 |
-
if ($id == '') return false;
|
499 |
-
|
500 |
-
// Get path to file
|
501 |
-
$current_file = get_attached_file($id);
|
502 |
|
503 |
-
|
504 |
-
|
505 |
-
|
|
|
506 |
|
507 |
-
|
508 |
-
|
|
|
509 |
|
510 |
-
|
511 |
-
|
512 |
-
return date( $format, $filetime );
|
513 |
-
}
|
514 |
|
515 |
-
|
516 |
-
|
|
|
517 |
|
|
|
|
|
518 |
|
|
|
|
|
|
|
|
|
519 |
|
|
|
|
|
520 |
} // class
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
+
|
4 |
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
5 |
use EnableMediaReplace\Notices\NoticeController as Notices;
|
6 |
+
use EnableMediaReplace\FileSystem\Controller\FileSystemController as FileSystem;
|
7 |
+
use EnableMediaReplace\Ajax;
|
8 |
|
9 |
// Does what a plugin does.
|
10 |
class EnableMediaReplacePlugin
|
11 |
{
|
12 |
|
13 |
+
protected $plugin_path;
|
14 |
+
private static $instance;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
+
private $user_cap = false;
|
17 |
+
private $general_cap = false;
|
|
|
18 |
|
19 |
+
public function __construct()
|
20 |
+
{
|
21 |
+
add_action('plugins_loaded', array($this, 'runtime'));
|
22 |
+
}
|
|
|
|
|
23 |
|
24 |
+
public function runtime()
|
25 |
+
{
|
26 |
+
$this->nopriv_plugin_actions();
|
27 |
+
|
28 |
+
if (EMR_CAPABILITY !== false) {
|
29 |
+
if (is_array(EMR_CAPABILITY)) {
|
30 |
+
$this->general_cap = EMR_CAPABILITY[0];
|
31 |
+
$this->user_cap = EMR_CAPABILITY[1];
|
32 |
+
|
33 |
+
if (! current_user_can($this->general_cap) && ! current_user_can($this->user_cap)) {
|
34 |
+
return;
|
35 |
+
}
|
36 |
+
} else {
|
37 |
+
$this->general_cap = EMR_CAPABILITY;
|
38 |
+
if (! current_user_can($this->general_cap)) {
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
}
|
42 |
+
} elseif (! current_user_can('upload_files')) {
|
43 |
return;
|
44 |
}
|
|
|
|
|
|
|
45 |
|
46 |
+
$this->plugin_actions(); // init
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
+
public function filesystem()
|
50 |
+
{
|
51 |
+
return new FileSystem();
|
52 |
+
}
|
53 |
|
54 |
+
public function uiHelper()
|
55 |
+
{
|
56 |
+
return Uihelper::getInstance();
|
57 |
+
}
|
58 |
|
59 |
+
public static function get()
|
|
|
|
|
|
|
|
|
|
|
60 |
{
|
61 |
+
if (is_null(self::$instance)) {
|
62 |
+
self::$instance = new EnableMediaReplacePlugin();
|
63 |
+
}
|
64 |
|
65 |
+
$log = Log::getInstance();
|
66 |
+
if (Log::debugIsActive()) {
|
67 |
+
$uploaddir = wp_upload_dir(null, false, false);
|
68 |
+
if (isset($uploaddir['basedir'])) {
|
69 |
+
$log->setLogPath($uploaddir['basedir'] . "/emr_log");
|
70 |
+
}
|
71 |
+
}
|
72 |
+
return self::$instance;
|
73 |
}
|
74 |
|
75 |
+
// Actions for EMR that always need to hook
|
76 |
+
protected function nopriv_plugin_actions()
|
77 |
+
{
|
78 |
+
// shortcode
|
79 |
+
add_shortcode('file_modified', array($this, 'get_modified_date'));
|
80 |
+
}
|
81 |
|
82 |
+
public function plugin_actions()
|
83 |
+
{
|
84 |
+
$this->plugin_path = plugin_dir_path(EMR_ROOT_FILE);
|
85 |
+
$this->plugin_url = plugin_dir_url(EMR_ROOT_FILE);
|
86 |
+
|
87 |
+
// loads the dismiss hook.
|
88 |
+
$notices = Notices::getInstance();
|
89 |
+
|
90 |
+
// init plugin
|
91 |
+
add_action('admin_menu', array($this,'menu'));
|
92 |
+
add_action('submenu_file', array($this, 'hide_sub_menu'));
|
93 |
+
add_action('admin_init', array($this,'init'));
|
94 |
+
add_action( 'current_screen', array($this, 'setScreen') ); // annoying workaround for notices in edit-attachment screen
|
95 |
+
add_action('admin_enqueue_scripts', array($this,'admin_scripts'));
|
96 |
+
|
97 |
+
|
98 |
+
// content filters
|
99 |
+
add_filter('media_row_actions', array($this,'add_media_action'), 10, 2);
|
100 |
+
add_action('attachment_submitbox_misc_actions', array($this,'admin_date_replaced_media_on_edit_media_screen'), 91);
|
101 |
+
//add_filter('upload_mimes', array($this,'add_mime_types'), 1, 1);
|
102 |
+
|
103 |
+
// notices
|
104 |
+
add_action('admin_notices', array($this,'display_notices'));
|
105 |
+
add_action('network_admin_notices', array($this,'display_network_notices'));
|
106 |
+
add_action('wp_ajax_emr_dismiss_notices', array($this,'dismiss_notices'));
|
107 |
+
|
108 |
+
// editors
|
109 |
+
add_action('add_meta_boxes', array($this, 'add_meta_boxes'), 10, 2);
|
110 |
+
add_filter('attachment_fields_to_edit', array($this, 'attachment_editor'), 10, 2);
|
111 |
+
|
112 |
+
/** Just after an image is replaced, try to browser decache the images */
|
113 |
+
if (isset($_GET['emr_replaced']) && intval($_GET['emr_replaced'] == 1)) {
|
114 |
+
add_filter('wp_get_attachment_image_src', array($this, 'attempt_uncache_image'), 10, 4);
|
115 |
+
|
116 |
+
// adds a metabox to list thumbnails. This is a cache reset hidden as feature.
|
117 |
+
//add_action( 'add_meta_boxes', function () { );
|
118 |
+
add_filter('postbox_classes_attachment_emr-showthumbs-box', function ($classes) {
|
119 |
+
$classes[] = 'closed';
|
120 |
+
return $classes;
|
121 |
+
});
|
122 |
+
}
|
123 |
+
}
|
124 |
|
125 |
/**
|
126 |
* Register this file in WordPress so we can call it with a ?page= GET var.
|
127 |
* To suppress it in the menu we give it an empty menu title.
|
128 |
*/
|
129 |
+
public function menu()
|
130 |
+
{
|
131 |
+
$title = esc_html__("Replace media", "enable-media-replace");
|
132 |
+
$title = (isset($_REQUEST['action']) && ($_REQUEST['action'] === 'emr_prepare_remove')) ? esc_html__("Remove background", "enable-media-replace") : $title;
|
133 |
+
add_submenu_page('upload.php',$title, $title, 'upload_files', 'enable-media-replace/enable-media-replace.php', array($this, 'route'));
|
134 |
+
/* add_submenu_page(null, esc_html__("Remove background", "enable-media-replace"), esc_html__("Remove the media Background", "enable-media-replace"), 'upload_files', 'emr-remove-background', array($this, 'route')); */
|
135 |
+
|
136 |
+
|
137 |
+
}
|
138 |
+
|
139 |
+
public function hide_sub_menu($submenu_file)
|
140 |
+
{
|
141 |
+
global $plugin_page;
|
142 |
+
// Select another submenu item to highlight (optional).
|
143 |
+
if ( $plugin_page && $plugin_page == 'enable-media-replace/enable-media-replace.php' ) {
|
144 |
+
$submenu_file = 'upload.php';
|
145 |
+
}
|
146 |
+
|
147 |
+
// Hide the submenu.
|
148 |
+
|
149 |
+
remove_submenu_page( 'upload.php', 'enable-media-replace/enable-media-replace.php' );
|
150 |
+
|
151 |
+
return $submenu_file;
|
152 |
+
}
|
153 |
|
154 |
/**
|
155 |
* Initialize this plugin. Called by 'admin_init' hook.
|
156 |
*
|
157 |
*/
|
158 |
+
public function init()
|
159 |
+
{
|
160 |
+
load_plugin_textdomain('enable-media-replace', false, basename(dirname(EMR_ROOT_FILE)) . '/languages');
|
161 |
|
162 |
+
// Load Submodules
|
163 |
|
|
|
164 |
|
165 |
+
new Externals();
|
166 |
+
new Ajax();
|
167 |
+
}
|
168 |
|
169 |
+
public function setScreen()
|
170 |
+
{
|
171 |
+
$screen = get_current_screen();
|
172 |
|
173 |
+
$notice_pages = array('attachment', 'media_page_enable-media-replace/enable-media-replace', 'upload' );
|
174 |
+
if ( in_array($screen->id, $notice_pages) )
|
175 |
+
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
|
177 |
+
$notices = Notices::getInstance();
|
178 |
+
add_action('admin_notices', array($notices, 'admin_notices')); // previous page / init time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
|
180 |
+
}
|
181 |
+
// var_dump($screen);
|
182 |
+
}
|
183 |
|
184 |
+
/** Load EMR views based on request */
|
185 |
+
public function route()
|
186 |
+
{
|
187 |
+
global $plugin_page;
|
188 |
+
switch ($plugin_page) {
|
189 |
+
case 'enable-media-replace/enable-media-replace.php':
|
190 |
+
$action = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : '';
|
191 |
+
wp_enqueue_style('emr_style');
|
192 |
+
wp_enqueue_script('jquery-ui-datepicker');
|
193 |
+
wp_enqueue_style('jquery-ui-datepicker');
|
194 |
+
wp_enqueue_script('emr_admin');
|
195 |
+
|
196 |
+
$this->uiHelper()->featureNotice();
|
197 |
+
|
198 |
+
|
199 |
+
|
200 |
+
|
201 |
+
if (! check_admin_referer($action, '_wpnonce')) {
|
202 |
+
die('Invalid Nonce');
|
203 |
+
}
|
204 |
+
|
205 |
+
// @todo Later this should be move to it's own controller, and built view from there.
|
206 |
+
if ($action == 'media_replace') {
|
207 |
+
if (array_key_exists("attachment_id", $_GET) && intval($_GET["attachment_id"]) > 0) {
|
208 |
+
wp_enqueue_script('emr_upsell');
|
209 |
+
require_once($this->plugin_path . "views/popup.php"); // warning variables like $action be overwritten here.
|
210 |
+
}
|
211 |
+
}
|
212 |
+
elseif ($action == 'media_replace_upload') {
|
213 |
+
require_once($this->plugin_path . 'views/upload.php');
|
214 |
+
}
|
215 |
+
elseif ('emr_prepare_remove' === $action) {
|
216 |
+
$attachment_id = intval($_GET['attachment_id']);
|
217 |
+
$attachment = get_post($attachment_id);
|
218 |
+
//We're adding a timestamp to the image URL for cache busting
|
219 |
+
|
220 |
+
wp_enqueue_script('emr_remove_bg');
|
221 |
+
|
222 |
+
wp_enqueue_style('emr_style');
|
223 |
+
wp_enqueue_style('emr-remove-background');
|
224 |
+
wp_enqueue_script('emr_upsell');
|
225 |
+
require_once($this->plugin_path . "views/prepare-remove-background.php");
|
226 |
+
|
227 |
+
} elseif ('do_background_replace' === $action && check_admin_referer($action, '_wpnonce')) {
|
228 |
+
require_once($this->plugin_path . 'views/do-replace-background.php');
|
229 |
+
}
|
230 |
+
else {
|
231 |
+
exit('Something went wrong loading page, please try again');
|
232 |
+
}
|
233 |
+
break;
|
234 |
+
}
|
235 |
+
}
|
236 |
|
237 |
+
public function getPluginURL($path = '')
|
238 |
+
{
|
239 |
+
return plugins_url($path, EMR_ROOT_FILE);
|
240 |
+
}
|
241 |
|
242 |
/** register styles and scripts
|
243 |
*
|
244 |
* Nothing should ever by -enqueued- here, just registered.
|
245 |
*/
|
246 |
+
public function admin_scripts()
|
|
|
|
|
247 |
{
|
248 |
+
if (is_rtl()) {
|
249 |
+
wp_register_style('emr_style', plugins_url('css/admin.rtl.css', EMR_ROOT_FILE));
|
250 |
+
} else {
|
251 |
+
wp_register_style('emr_style', plugins_url('css/admin.css', EMR_ROOT_FILE));
|
252 |
+
}
|
253 |
|
254 |
+
wp_register_style('emr_edit-attachment', plugins_url('css/edit_attachment.css', EMR_ROOT_FILE));
|
255 |
|
256 |
+
wp_register_style('emr-remove-background', plugins_url('css/remove_background.css', EMR_ROOT_FILE));
|
257 |
|
258 |
+
$mimes = array_values(get_allowed_mime_types());
|
259 |
+
|
260 |
+
wp_register_script('emr_admin', plugins_url('js/emr_admin.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true);
|
261 |
+
$emr_options = array(
|
262 |
+
'dateFormat' => $this->convertdate(get_option('date_format')),
|
263 |
'maxfilesize' => wp_max_upload_size(),
|
264 |
'allowed_mime' => $mimes,
|
265 |
+
);
|
266 |
|
267 |
+
wp_register_script('emr_upsell', plugins_url('js/upsell.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true);
|
268 |
|
269 |
+
wp_localize_script('emr_upsell', 'emr_upsell', array(
|
270 |
+
'ajax' => admin_url('admin-ajax.php'),
|
271 |
+
'installing' => __('Installing ...', 'enable-media-replace'),
|
272 |
|
273 |
+
));
|
274 |
|
275 |
+
$ts = time();
|
276 |
+
$ajax_url = admin_url('admin-ajax.php');
|
277 |
|
278 |
+
|
279 |
+
wp_register_script('emr_remove_bg', plugins_url('js/remove_bg.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true);
|
280 |
+
wp_localize_script('emr_remove_bg', 'emrObject', array(
|
281 |
+
'ajax_url' => $ajax_url,
|
282 |
+
'nonce' => wp_create_nonce('emr_remove_background')
|
283 |
+
));
|
284 |
+
|
285 |
+
|
286 |
+
if (Log::debugIsActive()) {
|
287 |
+
$emr_options['is_debug'] = true;
|
288 |
+
}
|
289 |
+
|
290 |
+
wp_localize_script('emr_admin', 'emr_options', $emr_options);
|
291 |
+
}
|
292 |
|
293 |
/** Utility function for the Jquery UI Datepicker */
|
294 |
+
public function convertdate($sFormat)
|
295 |
+
{
|
296 |
+
switch ($sFormat) {
|
297 |
+
//Predefined WP date formats
|
298 |
+
case 'F j, Y':
|
299 |
+
return( 'MM dd, yy' );
|
300 |
break;
|
301 |
+
case 'Y/m/d':
|
302 |
+
return( 'yy/mm/dd' );
|
303 |
break;
|
304 |
+
case 'm/d/Y':
|
305 |
+
return( 'mm/dd/yy' );
|
306 |
break;
|
307 |
+
case 'd/m/Y':
|
308 |
+
default:
|
309 |
+
return( 'dd/mm/yy' );
|
310 |
+
break;
|
311 |
+
}
|
312 |
+
}
|
313 |
|
314 |
+
public function checkImagePermission($author_id, $post_id)
|
315 |
+
{
|
316 |
+
if ($this->general_cap === false && $this->user_cap === false) {
|
317 |
+
if (current_user_can('edit_post', $post_id) === true) {
|
318 |
+
return true;
|
319 |
+
}
|
320 |
+
} elseif (current_user_can($this->general_cap)) {
|
321 |
+
return true;
|
322 |
+
} elseif (current_user_can($this->user_cap) && $author_id == get_current_user_id()) {
|
323 |
+
return true;
|
324 |
+
}
|
325 |
+
|
326 |
+
return false;
|
327 |
+
}
|
328 |
|
329 |
/** Get the URL to the media replace page
|
330 |
* @param $attach_id The attachment ID to replace
|
331 |
* @return Admin URL to the page.
|
332 |
*/
|
333 |
+
protected function getMediaReplaceURL($attach_id)
|
334 |
+
{
|
335 |
+
$url = admin_url("upload.php");
|
336 |
+
$url = add_query_arg(array(
|
337 |
'page' => 'enable-media-replace/enable-media-replace.php',
|
338 |
'action' => 'media_replace',
|
339 |
'attachment_id' => $attach_id,
|
340 |
+
), $url);
|
341 |
|
342 |
+
return $url;
|
343 |
+
}
|
344 |
|
345 |
+
protected function getRemoveBgURL($attach_id)
|
346 |
+
{
|
347 |
+
$url = admin_url("upload.php");
|
348 |
+
$url = add_query_arg(array(
|
349 |
+
'page' => 'enable-media-replace/enable-media-replace.php',
|
350 |
+
'action' => 'emr_prepare_remove',
|
351 |
+
'attachment_id' => $attach_id,
|
352 |
+
), $url);
|
353 |
|
354 |
+
return $url;
|
355 |
+
}
|
|
|
|
|
|
|
356 |
|
357 |
+
public function add_meta_boxes($post_type, $post)
|
358 |
+
{
|
359 |
+
// Because some plugins don't like to play by the rules.
|
360 |
+
if (is_null($post_type) || is_null($post)) {
|
361 |
+
return false;
|
362 |
+
}
|
363 |
|
364 |
+
if (! $this->checkImagePermission($post->post_author, $post->ID)) {
|
365 |
+
return;
|
366 |
+
}
|
367 |
|
368 |
+
add_meta_box('emr-replace-box', __('Replace Media', 'enable-media-replace'), array($this, 'replace_meta_box'), 'attachment', 'side', 'low');
|
|
|
|
|
|
|
369 |
|
370 |
+
if (isset($_GET['emr_replaced']) && intval($_GET['emr_replaced'] == 1)) {
|
371 |
+
add_meta_box('emr-showthumbs-box', __('Replaced Thumbnails Preview', 'enable-media-replace'), array($this, 'show_thumbs_box'), 'attachment', 'side', 'low');
|
372 |
+
}
|
373 |
+
}
|
374 |
|
375 |
+
public function replace_meta_box($post)
|
376 |
+
{
|
377 |
|
378 |
+
//Replace media button
|
379 |
+
$replace_url = $this->getMediaReplaceURL($post->ID);
|
380 |
|
381 |
+
$replace_action = "media_replace";
|
382 |
+
$replace_editurl = wp_nonce_url($replace_url, $replace_action);
|
383 |
|
384 |
+
$replace_link = "href=\"$replace_editurl\"";
|
|
|
|
|
|
|
|
|
385 |
|
386 |
+
echo "<p><a class='button-secondary' $replace_link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a></p><p>" . esc_html__("To replace the current file, click the link and upload a replacement file.", "enable-media-replace") . "</p>";
|
387 |
+
//Remove background button
|
388 |
+
$removeBg_url = $this->getRemoveBgURL($post->ID);
|
389 |
|
390 |
+
$removeBg_action = "emr_prepare_remove";
|
391 |
+
$removeBg_editurl = wp_nonce_url($removeBg_url, $removeBg_action);
|
392 |
|
393 |
+
$removeBg_link = "href=\"$removeBg_editurl\"";
|
|
|
|
|
|
|
394 |
|
395 |
+
if ($this->uiHelper()->isBackgroundRemovable($post))
|
396 |
+
{
|
397 |
+
echo "<p><a class='button-secondary' $removeBg_link>" . esc_html__("Remove background", "enable-media-replace") . "</a></p><p>" . esc_html__("To remove the background, click the link and select the options.", "enable-media-replace") . "</p>";
|
398 |
+
}
|
|
|
|
|
|
|
399 |
}
|
400 |
|
401 |
+
public function show_thumbs_box($post)
|
402 |
{
|
403 |
+
if (! $this->checkImagePermission($post->post_author, $post->ID)) {
|
404 |
+
return;
|
405 |
+
}
|
406 |
|
407 |
+
wp_enqueue_style('emr_edit-attachment');
|
|
|
|
|
|
|
408 |
|
409 |
+
$meta = wp_get_attachment_metadata($post->ID);
|
410 |
|
411 |
+
if (! isset($meta['sizes'])) {
|
412 |
+
echo __('Thumbnails were not generated', 'enable-media-replace');
|
413 |
+
return false;
|
414 |
+
}
|
415 |
|
416 |
+
if (function_exists('wp_get_original_image_url')) { // indicating WP 5.3+
|
417 |
+
$source_url = wp_get_original_image_url($post->ID);
|
418 |
+
// oldway will give -scaled in case of scaling.
|
419 |
+
$source_url_oldway = wp_get_attachment_url($post->ID);
|
420 |
+
|
421 |
+
if ($source_url !== $source_url_oldway) {
|
422 |
+
echo "<div class='original previewwrapper'><img src='" . $source_url_oldway . "'><span class='label'>" . __('Original') . "</span></div>";
|
423 |
+
}
|
424 |
+
}
|
425 |
+
|
426 |
+
|
427 |
+
foreach ($meta['sizes'] as $size => $data) {
|
428 |
+
$display_size = ucfirst(str_replace("_", " ", $size));
|
429 |
+
$img = wp_get_attachment_image_src($post->ID, $size);
|
430 |
+
echo "<div class='$size previewwrapper'><img src='" . $img[0] . "'><span class='label'>$display_size</span></div>";
|
431 |
+
}
|
432 |
}
|
|
|
433 |
|
434 |
+
public function attachment_editor($form_fields, $post)
|
435 |
+
{
|
436 |
+
$screen = null;
|
437 |
|
438 |
+
if (! $this->checkImagePermission($post->post_author, $post->ID)) {
|
439 |
+
return $form_fields;
|
440 |
+
}
|
441 |
|
442 |
+
if (function_exists('get_current_screen')) {
|
443 |
+
$screen = get_current_screen();
|
|
|
444 |
|
445 |
+
if (! is_null($screen) && $screen->id == 'attachment') { // hide on edit attachment screen.
|
446 |
+
return $form_fields;
|
447 |
+
}
|
448 |
+
}
|
449 |
|
450 |
+
$url = $this->getMediaReplaceURL($post->ID);
|
451 |
+
$action = "media_replace";
|
452 |
+
$editurl = wp_nonce_url($url, $action);
|
453 |
|
454 |
+
$link = "href=\"$editurl\"";
|
455 |
+
$form_fields["enable-media-replace"] = array(
|
456 |
"label" => esc_html__("Replace media", "enable-media-replace"),
|
457 |
"input" => "html",
|
458 |
+
"html" => "<a class='button-secondary' $link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a>", "helps" => esc_html__("To replace the current file, click the link and upload a replacement file.", "enable-media-replace")
|
459 |
);
|
460 |
|
461 |
+
if ($this->uiHelper()->isBackgroundRemovable($post))
|
462 |
+
{
|
463 |
+
$link = $this->getRemoveBgURL($post->ID);
|
464 |
+
$link = "href='" . wp_nonce_url($link, 'emr_prepare_remove') . "'";
|
465 |
+
$form_fields["emr-remove-background"] = array(
|
466 |
+
"label" => esc_html__("Remove background", "enable-media-replace"),
|
467 |
+
"input" => "html",
|
468 |
+
"html" => "<a class='button-secondary' $link>" . esc_html__("Remove background", "enable-media-replace") . "</a>", "helps" => esc_html__("To remove the background, click the link.", "enable-media-replace")
|
469 |
+
);
|
470 |
+
}
|
471 |
+
return $form_fields;
|
472 |
+
}
|
473 |
|
474 |
/**
|
475 |
* @param array $mime_types
|
476 |
* @return array
|
477 |
*/
|
478 |
+
/* Off, no clue why this is here.
|
479 |
public function add_mime_types($mime_types)
|
480 |
{
|
481 |
$mime_types['dat'] = 'text/plain'; // Adding .dat extension
|
486 |
* Function called by filter 'media_row_actions'
|
487 |
* Enables linking to EMR straight from the media library
|
488 |
*/
|
489 |
+
public function add_media_action($actions, $post)
|
490 |
+
{
|
491 |
|
492 |
+
if (! $this->checkImagePermission($post->post_author, $post->ID)) {
|
493 |
+
return $actions;
|
494 |
+
}
|
495 |
|
496 |
+
$url = $this->getMediaReplaceURL($post->ID);
|
497 |
+
$media_replace_action = "media_replace";
|
498 |
+
$media_replace_editurl = wp_nonce_url($url, $media_replace_action);
|
499 |
+
$url = $this->getRemoveBgURL($post->ID);
|
500 |
+
$background_remove_action = "emr_prepare_remove";
|
501 |
+
$background_remove_editurl = wp_nonce_url($url, $background_remove_action);
|
502 |
|
503 |
+
/* See above, not needed.
|
504 |
+
if (FORCE_SSL_ADMIN) {
|
505 |
+
$editurl = str_replace("http:", "https:", $editurl);
|
506 |
+
} */
|
507 |
+
$media_replace_link = "href=\"$media_replace_editurl\"";
|
508 |
+
$background_remove_link = "href=\"$background_remove_editurl\"";
|
509 |
|
510 |
+
$newaction['media_replace'] = '<a ' . $media_replace_link . ' aria-label="' . esc_attr__("Replace media", "enable-media-replace") . '" rel="permalink">' . esc_html__("Replace media", "enable-media-replace") . '</a>';
|
|
|
|
|
|
|
|
|
511 |
|
512 |
+
if ($this->uiHelper()->isBackgroundRemovable($post))
|
513 |
+
{
|
514 |
+
$newaction['remove_background'] = '<a ' . $background_remove_link . ' aria-label="' . esc_attr__("Remove background", "enable-media-replace") . '" rel="permalink">' . esc_html__("Remove background", "enable-media-replace") . '</a>';
|
515 |
|
516 |
+
}
|
517 |
+
return array_merge($actions, $newaction);
|
518 |
+
}
|
519 |
|
|
|
|
|
520 |
|
521 |
+
public function display_notices()
|
522 |
+
{
|
523 |
+
$current_screen = get_current_screen();
|
524 |
+
|
525 |
+
$crtScreen = function_exists("get_current_screen") ? get_current_screen() : (object)array("base" => false);
|
526 |
+
/*
|
527 |
+
if(current_user_can( 'activate_plugins' ) && !get_option( 'emr_news') && !is_plugin_active('shortpixel-image-optimiser/wp-shortpixel.php')
|
528 |
+
&& ($crtScreen->base == "upload" || $crtScreen->base == "plugins")
|
529 |
//for network installed plugins, don't display the message on subsites.
|
530 |
&& !(function_exists('is_multisite') && is_multisite() && is_plugin_active_for_network('enable-media-replace/enable-media-replace.php') && !is_main_site()))
|
531 |
+
{
|
532 |
+
require_once($this->plugin_path . '/views/notice.php');
|
533 |
+
} */
|
534 |
+
}
|
535 |
|
536 |
+
public function display_network_notices()
|
537 |
+
{
|
538 |
+
if (current_user_can('activate_plugins') && !get_option('emr_news') && !is_plugin_active_for_network('shortpixel-image-optimiser/wp-shortpixel.php')) {
|
539 |
+
require_once(str_replace("enable-media-replace.php", "notice.php", __FILE__));
|
540 |
+
}
|
541 |
+
}
|
542 |
|
543 |
/* Ajax function to dismiss notice */
|
544 |
+
public function dismiss_notices()
|
545 |
+
{
|
546 |
+
update_option('emr_news', true);
|
547 |
+
exit(json_encode(array("Status" => 0)));
|
548 |
+
}
|
549 |
|
550 |
/** Outputs the replaced date of the media on the edit_attachment screen
|
551 |
*
|
552 |
* @param $post Obj Post Object
|
553 |
*/
|
554 |
+
function admin_date_replaced_media_on_edit_media_screen($post)
|
555 |
+
{
|
|
|
|
|
|
|
556 |
|
557 |
+
// Fallback for before version 4.9, doens't pass post.
|
558 |
+
if (! is_object($post)) {
|
559 |
+
global $post;
|
560 |
+
}
|
561 |
|
562 |
+
if (! is_object($post)) { // try to global, if it doesn't work - return.
|
563 |
+
return false;
|
564 |
+
}
|
565 |
|
566 |
+
$post_id = $post->ID;
|
567 |
+
if ($post->post_modified !== $post->post_date) {
|
568 |
+
$modified = date_i18n(__('M j, Y @ H:i'), strtotime($post->post_modified));
|
569 |
+
?>
|
570 |
+
<div class="misc-pub-section curtime">
|
571 |
+
<span id="timestamp"><?php echo esc_html__('Revised', 'enable-media-replace'); ?>: <b><?php echo $modified; ?></b></span>
|
572 |
+
</div>
|
573 |
|
574 |
+
<?php
|
575 |
+
}
|
576 |
+
$author_id = get_post_meta($post_id, '_emr_replace_author', true);
|
577 |
|
578 |
+
if ($author_id) {
|
579 |
+
$display_name = get_the_author_meta('display_name', $author_id);
|
580 |
+
?>
|
|
|
581 |
<div class="misc-pub-section replace_author">
|
582 |
+
<span><?php echo esc_html__('Replaced By', 'enable-media-replace'); ?>: <b><?php echo $display_name; ?></b></span>
|
583 |
</div>
|
584 |
+
<?php
|
585 |
+
}
|
586 |
}
|
587 |
|
|
|
|
|
588 |
/** When an image is just replaced, it can stuck in the browser cache making a look like it was not replaced. Try
|
589 |
* undo that effect by adding a timestamp to the query string */
|
590 |
+
public function attempt_uncache_image($image, $attachment_id, $size, $icon)
|
591 |
+
{
|
592 |
+
if ($image === false) {
|
593 |
+
return $image;
|
594 |
+
}
|
595 |
|
596 |
+
// array with image src on 0
|
597 |
+
$image[0] = add_query_arg('time', time(), $image[0]);
|
598 |
+
return $image;
|
599 |
+
}
|
600 |
|
601 |
/**
|
602 |
* Shorttag function to show the media file modification date/time.
|
604 |
* @return string content / replacement shorttag
|
605 |
* @todo Note this returns the wrong date, ie. server date not corrected for timezone. Function could be removed altogether, not sure about purpose.
|
606 |
*/
|
607 |
+
public function get_modified_date($atts)
|
608 |
+
{
|
609 |
+
$id=0;
|
610 |
+
$format= '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
611 |
|
612 |
+
extract(shortcode_atts(array(
|
613 |
+
'id' => '',
|
614 |
+
'format' => get_option('date_format') . " " . get_option('time_format'),
|
615 |
+
), $atts));
|
616 |
|
617 |
+
if ($id == '') {
|
618 |
+
return false;
|
619 |
+
}
|
620 |
|
621 |
+
// Get path to file
|
622 |
+
$current_file = get_attached_file($id);
|
|
|
|
|
623 |
|
624 |
+
if (! file_exists($current_file)) {
|
625 |
+
return false;
|
626 |
+
}
|
627 |
|
628 |
+
// Get file modification time
|
629 |
+
$filetime = filemtime($current_file);
|
630 |
|
631 |
+
if (false !== $filetime) {
|
632 |
+
// do date conversion
|
633 |
+
return date($format, $filetime);
|
634 |
+
}
|
635 |
|
636 |
+
return false;
|
637 |
+
}
|
638 |
} // class
|
@@ -1,104 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace EnableMediaReplace;
|
3 |
-
|
4 |
-
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
5 |
-
use EnableMediaReplace\Notices\NoticeController as Notices;
|
6 |
-
|
7 |
-
class emrFile
|
8 |
-
{
|
9 |
-
|
10 |
-
protected $file; // the full file w/ path.
|
11 |
-
protected $extension;
|
12 |
-
protected $fileName;
|
13 |
-
protected $filePath; // with trailing slash! not the image name.
|
14 |
-
protected $fileURL;
|
15 |
-
protected $fileMime;
|
16 |
-
protected $permissions = 0;
|
17 |
-
|
18 |
-
protected $exists = false;
|
19 |
-
|
20 |
-
public function __construct($file)
|
21 |
-
{
|
22 |
-
clearstatcache($file);
|
23 |
-
// file can not exist i.e. crashed files replacement and the lot.
|
24 |
-
if ( file_exists($file))
|
25 |
-
{
|
26 |
-
$this->exists = true;
|
27 |
-
}
|
28 |
-
|
29 |
-
$this->file = $file;
|
30 |
-
$fileparts = pathinfo($file);
|
31 |
-
|
32 |
-
$this->fileName = isset($fileparts['basename']) ? $fileparts['basename'] : '';
|
33 |
-
$this->filePath = isset($fileparts['dirname']) ? trailingslashit($fileparts['dirname']) : '';
|
34 |
-
$this->extension = isset($fileparts['extension']) ? $fileparts['extension'] : '';
|
35 |
-
if ($this->exists) // doesn't have to be.
|
36 |
-
$this->permissions = fileperms($file) & 0777;
|
37 |
-
|
38 |
-
$filedata = wp_check_filetype_and_ext($this->file, $this->fileName);
|
39 |
-
// This will *not* be checked, is not meant for permission of validation!
|
40 |
-
// Note: this function will work on non-existing file, but not on existing files containing wrong mime in file.
|
41 |
-
$this->fileMime = (isset($filedata['type']) && strlen($filedata['type']) > 0) ? $filedata['type'] : false;
|
42 |
-
|
43 |
-
if ($this->fileMime == false && strlen($this->file) > 0 && function_exists('mime_content_type') && $this->exists)
|
44 |
-
{
|
45 |
-
// If it's not a registered mimetype
|
46 |
-
$this->fileMime = mime_content_type($this->file);
|
47 |
-
}
|
48 |
-
|
49 |
-
}
|
50 |
-
|
51 |
-
public function checkAndCreateFolder()
|
52 |
-
{
|
53 |
-
$path = $this->getFilePath();
|
54 |
-
if (! is_dir($path) && ! file_exists($path))
|
55 |
-
{
|
56 |
-
return wp_mkdir_p($path);
|
57 |
-
}
|
58 |
-
}
|
59 |
-
|
60 |
-
public function getFullFilePath()
|
61 |
-
{
|
62 |
-
return $this->file;
|
63 |
-
}
|
64 |
-
|
65 |
-
public function getPermissions()
|
66 |
-
{
|
67 |
-
return $this->permissions;
|
68 |
-
}
|
69 |
-
|
70 |
-
public function setPermissions($permissions)
|
71 |
-
{
|
72 |
-
@chmod($this->file, $permissions);
|
73 |
-
}
|
74 |
-
|
75 |
-
public function getFileSize()
|
76 |
-
{
|
77 |
-
return filesize($this->file);
|
78 |
-
}
|
79 |
-
|
80 |
-
public function getFilePath()
|
81 |
-
{
|
82 |
-
return $this->filePath;
|
83 |
-
}
|
84 |
-
|
85 |
-
public function getFileName()
|
86 |
-
{
|
87 |
-
return $this->fileName;
|
88 |
-
}
|
89 |
-
|
90 |
-
public function getFileExtension()
|
91 |
-
{
|
92 |
-
return $this->extension;
|
93 |
-
}
|
94 |
-
|
95 |
-
public function getFileMime()
|
96 |
-
{
|
97 |
-
return $this->fileMime;
|
98 |
-
}
|
99 |
-
|
100 |
-
public function exists()
|
101 |
-
{
|
102 |
-
return $this->exists;
|
103 |
-
}
|
104 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace;
|
3 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
use EnableMediaReplace\Notices\NoticeController as Notices;
|
5 |
+
|
6 |
+
class InstallHelper
|
7 |
+
{
|
8 |
+
|
9 |
+
public static function unInstallPlugin()
|
10 |
+
{
|
11 |
+
delete_option( 'enable_media_replace' );
|
12 |
+
delete_option( 'emr_news' );
|
13 |
+
delete_option( 'emr_url_cache');
|
14 |
+
}
|
15 |
+
|
16 |
+
public static function deactivatePlugin()
|
17 |
+
{
|
18 |
+
Notices::resetNotices();
|
19 |
+
}
|
20 |
+
}
|
@@ -62,7 +62,7 @@ class Replacer
|
|
62 |
}
|
63 |
|
64 |
Log::addDebug('SourceFile ' . $source_file);
|
65 |
-
$this->sourceFile =
|
66 |
|
67 |
$this->source_post = get_post($post_id);
|
68 |
$this->source_is_image = wp_attachment_is('image', $this->source_post);
|
@@ -82,6 +82,11 @@ class Replacer
|
|
82 |
//$this->ThumbnailUpdater->setOldMetadata($this->source_metadata);
|
83 |
}
|
84 |
|
|
|
|
|
|
|
|
|
|
|
85 |
public function setMode($mode)
|
86 |
{
|
87 |
$this->replaceMode = $mode;
|
@@ -107,6 +112,7 @@ class Replacer
|
|
107 |
$this->targetName = $fileName;
|
108 |
|
109 |
$targetFile = $this->getTargetFile();
|
|
|
110 |
|
111 |
if (is_null($targetFile))
|
112 |
{
|
@@ -115,34 +121,41 @@ class Replacer
|
|
115 |
// throw new \RuntimeException($ex);
|
116 |
}
|
117 |
|
118 |
-
$targetFileObj =
|
119 |
-
$
|
|
|
|
|
120 |
if ($result === false)
|
121 |
Log::addError('Directory creation for targetFile failed');
|
122 |
|
|
|
123 |
|
124 |
$this->removeCurrent(); // tries to remove the current files.
|
125 |
-
|
126 |
/* @todo See if wp_handle_sideload / wp_handle_upload can be more securely used for this */
|
127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
-
if (false === $result_moved)
|
130 |
-
{
|
131 |
-
$ex = sprintf( esc_html__('The uploaded file could not be moved to %1$s. This is most likely an issue with permissions, or upload failed.', "enable-media-replace"), $targetFile );
|
132 |
-
throw new \RuntimeException($ex);
|
133 |
-
}
|
134 |
|
135 |
// init targetFile.
|
136 |
-
$this->targetFile =
|
137 |
|
138 |
-
if ($
|
139 |
-
chmod( $targetFile, $
|
140 |
else {
|
141 |
Log::addWarn('Setting permissions failed');
|
142 |
}
|
143 |
|
144 |
// update the file attached. This is required for wp_get_attachment_url to work.
|
145 |
-
$updated = update_attached_file($this->post_id, $this->targetFile->
|
146 |
if (! $updated)
|
147 |
Log::addError('Update Attached File reports as not updated or same value');
|
148 |
|
@@ -150,31 +163,31 @@ class Replacer
|
|
150 |
|
151 |
// Run the filter, so other plugins can hook if needed.
|
152 |
$filtered = apply_filters( 'wp_handle_upload', array(
|
153 |
-
'file' => $this->targetFile->
|
154 |
'url' => $this->target_url,
|
155 |
-
'type' => $this->targetFile->
|
156 |
), 'sideload');
|
157 |
|
158 |
// check if file changed during filter. Set changed to attached file meta properly.
|
159 |
-
if (isset($filtered['file']) && $filtered['file'] != $this->targetFile->
|
160 |
{
|
161 |
update_attached_file($this->post_id, $filtered['file'] );
|
162 |
-
$this->targetFile =
|
163 |
Log::addInfo('WP_Handle_upload filter returned different file', $filtered);
|
164 |
}
|
165 |
|
166 |
// Check and update post mimetype, otherwise badly coded plugins cry.
|
167 |
$post_mime = get_post_mime_type($this->post_id);
|
168 |
-
$target_mime = $this->targetFile->
|
169 |
|
170 |
// update DB post mime type, if somebody decided to mess it up, and the target one is not empty.
|
171 |
if ($target_mime !== $post_mime && strlen($target_mime) > 0)
|
172 |
{
|
173 |
|
174 |
-
\wp_update_post(array('post_mime_type' => $this->targetFile->
|
175 |
}
|
176 |
|
177 |
-
$metadata = wp_generate_attachment_metadata( $this->post_id, $this->targetFile->
|
178 |
wp_update_attachment_metadata( $this->post_id, $metadata );
|
179 |
$this->target_metadata = $metadata;
|
180 |
|
@@ -259,7 +272,7 @@ class Replacer
|
|
259 |
protected function getNewTitle()
|
260 |
{
|
261 |
// get basename without extension
|
262 |
-
$title = basename($this->targetFile->getFileName(), '.' . $this->targetFile->
|
263 |
$meta = $this->target_metadata;
|
264 |
|
265 |
if (isset($meta['image_meta']))
|
@@ -304,11 +317,24 @@ class Replacer
|
|
304 |
return $this->sourceFile;
|
305 |
}
|
306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
public function setNewTargetLocation($new_rel_location)
|
308 |
{
|
309 |
$uploadDir = wp_upload_dir();
|
310 |
$newPath = trailingslashit($uploadDir['basedir']) . $new_rel_location;
|
311 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
312 |
if (! is_dir($newPath))
|
313 |
{
|
314 |
Notices::addError(__('Specificed new directory does not exist. Path must be a relative path from the upload directory and exist', 'enable-media-replace'));
|
@@ -324,14 +350,14 @@ class Replacer
|
|
324 |
$targetPath = null;
|
325 |
if ($this->replaceMode == self::MODE_REPLACE)
|
326 |
{
|
327 |
-
$targetFile = $this->sourceFile->
|
328 |
}
|
329 |
elseif ($this->replaceMode == self::MODE_SEARCHREPLACE)
|
330 |
{
|
331 |
-
$path = $this->sourceFile->
|
332 |
if ($this->target_location) // Replace to another path.
|
333 |
{
|
334 |
-
$otherTarget =
|
335 |
if ($otherTarget->exists())
|
336 |
{
|
337 |
Notices::addError(__('In specificied directory there is already a file with the same name. Can\'t replace.', 'enable-media-replace'));
|
@@ -343,7 +369,7 @@ class Replacer
|
|
343 |
$targetpath = $path . $this->targetName;
|
344 |
|
345 |
// If the source and target path AND filename are identical, user has wrong mode, just overwrite the sourceFile.
|
346 |
-
if ($targetpath == $this->sourceFile->
|
347 |
{
|
348 |
$unique = $this->sourceFile->getFileName();
|
349 |
$this->replaceMode == self::MODE_REPLACE;
|
@@ -390,7 +416,7 @@ class Replacer
|
|
390 |
if (strpos($url, '://') === false)
|
391 |
{
|
392 |
$uploads = wp_get_upload_dir();
|
393 |
-
$url = str_replace($uploads['basedir'], $uploads['baseurl'], $this->targetFile->
|
394 |
}
|
395 |
// This can happen when WordPress is not taking from attached file, but wrong /old GUID. Try to replace it to the new one.
|
396 |
elseif ($this->targetFile->getFileName() != $url_basename)
|
@@ -412,12 +438,14 @@ class Replacer
|
|
412 |
$backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true );
|
413 |
|
414 |
// this must be -scaled if that exists, since wp_delete_attachment_files checks for original_files but doesn't recheck if scaled is included since that the one 'that exists' in WP . $this->source_file replaces original image, not the -scaled one.
|
415 |
-
$file = $this->sourceFile->
|
416 |
$result = \wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $file );
|
417 |
|
418 |
// If Attached file is not the same path as file, this indicates a -scaled images is in play.
|
|
|
|
|
419 |
$attached_file = get_attached_file($this->post_id);
|
420 |
-
if (
|
421 |
{
|
422 |
@unlink($attached_file);
|
423 |
}
|
@@ -466,8 +494,9 @@ class Replacer
|
|
466 |
$base_url = str_replace('.' . pathinfo($base_url, PATHINFO_EXTENSION), '', $base_url);
|
467 |
|
468 |
|
|
|
469 |
/** Fail-safe if base_url is a whole directory, don't go search/replace */
|
470 |
-
if (is_dir($base_url))
|
471 |
{
|
472 |
Log::addError('Search Replace tried to replace to directory - ' . $base_url);
|
473 |
Notices::addError(__('Fail Safe :: Source Location seems to be a directory.', 'enable-media-replace'));
|
@@ -603,13 +632,9 @@ class Replacer
|
|
603 |
|
604 |
if ($replaced_content !== $post_content)
|
605 |
{
|
606 |
-
//Log::addDebug('POST CONTENT TO SAVE', $replaced_content);
|
607 |
-
|
608 |
-
// $result = wp_update_post($post_ar);
|
609 |
$sql = 'UPDATE ' . $wpdb->posts . ' SET post_content = %s WHERE ID = %d';
|
610 |
$sql = $wpdb->prepare($sql, $replaced_content, $post_id);
|
611 |
|
612 |
-
//Log::addTemp("POSt update query " . $sql);
|
613 |
$result = $wpdb->query($sql);
|
614 |
|
615 |
if ($result === false)
|
@@ -630,7 +655,7 @@ class Replacer
|
|
630 |
{
|
631 |
global $wpdb;
|
632 |
|
633 |
-
$meta_options = apply_filters('emr/metadata_tables', array('post', 'comment', 'term', 'user'));
|
634 |
$number_of_updates = 0;
|
635 |
|
636 |
foreach($meta_options as $type)
|
@@ -644,6 +669,13 @@ class Replacer
|
|
644 |
|
645 |
$update_sql = ' UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d';
|
646 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
647 |
default:
|
648 |
$table = $wpdb->{$type . 'meta'}; // termmeta, commentmeta etc
|
649 |
|
@@ -651,6 +683,7 @@ class Replacer
|
|
651 |
if ($type == 'user')
|
652 |
$meta_id = 'umeta_id';
|
653 |
|
|
|
654 |
$sql = 'SELECT ' . $meta_id . ' as id, meta_value FROM ' . $table . '
|
655 |
WHERE meta_value like %s';
|
656 |
|
@@ -659,6 +692,10 @@ class Replacer
|
|
659 |
}
|
660 |
|
661 |
$sql = $wpdb->prepare($sql, '%' . $url . '%');
|
|
|
|
|
|
|
|
|
662 |
|
663 |
// This is a desparate solution. Can't find anyway for wpdb->prepare not the add extra slashes to the query, which messes up the query.
|
664 |
// $postmeta_sql = str_replace('[JSON_URL]', $json_url, $postmeta_sql);
|
@@ -681,6 +718,9 @@ class Replacer
|
|
681 |
Log::addDebug('Update Meta SQl' . $prepared_sql);
|
682 |
$result = $wpdb->query($prepared_sql);
|
683 |
|
|
|
|
|
|
|
684 |
}
|
685 |
}
|
686 |
} // foreach
|
@@ -734,10 +774,11 @@ class Replacer
|
|
734 |
}
|
735 |
}
|
736 |
}
|
737 |
-
elseif(is_object($content)) // metadata objects, they exist.
|
738 |
{
|
739 |
foreach($content as $key => $value)
|
740 |
{
|
|
|
741 |
$content->{$key} = $this->replaceContent($value, $search, $replace, true); //str_replace($value, $search, $replace);
|
742 |
}
|
743 |
}
|
62 |
}
|
63 |
|
64 |
Log::addDebug('SourceFile ' . $source_file);
|
65 |
+
$this->sourceFile = $this->fs()->getFile($source_file);
|
66 |
|
67 |
$this->source_post = get_post($post_id);
|
68 |
$this->source_is_image = wp_attachment_is('image', $this->source_post);
|
82 |
//$this->ThumbnailUpdater->setOldMetadata($this->source_metadata);
|
83 |
}
|
84 |
|
85 |
+
private function fs()
|
86 |
+
{
|
87 |
+
return emr()->filesystem();
|
88 |
+
}
|
89 |
+
|
90 |
public function setMode($mode)
|
91 |
{
|
92 |
$this->replaceMode = $mode;
|
112 |
$this->targetName = $fileName;
|
113 |
|
114 |
$targetFile = $this->getTargetFile();
|
115 |
+
$fs = $this->fs();
|
116 |
|
117 |
if (is_null($targetFile))
|
118 |
{
|
121 |
// throw new \RuntimeException($ex);
|
122 |
}
|
123 |
|
124 |
+
$targetFileObj = $fs->getFile($targetFile);
|
125 |
+
$directoryObj = $targetFileObj->getFileDir();
|
126 |
+
$result = $directoryObj->check();
|
127 |
+
|
128 |
if ($result === false)
|
129 |
Log::addError('Directory creation for targetFile failed');
|
130 |
|
131 |
+
$permissions = $this->sourceFile->getPermissions();
|
132 |
|
133 |
$this->removeCurrent(); // tries to remove the current files.
|
|
|
134 |
/* @todo See if wp_handle_sideload / wp_handle_upload can be more securely used for this */
|
135 |
+
// @todo Use FS / File copy for this.
|
136 |
+
|
137 |
+
$fileObj = $fs->getFile($file);
|
138 |
+
$result_moved = $fileObj->move($targetFileObj);
|
139 |
+
|
140 |
+
if (false === $result_moved)
|
141 |
+
{
|
142 |
+
$ex = sprintf( esc_html__('The uploaded file could not be moved to %1$s. This is most likely an issue with permissions, or upload failed.', "enable-media-replace"), $targetFile );
|
143 |
+
throw new \RuntimeException($ex);
|
144 |
+
}
|
145 |
+
|
146 |
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
// init targetFile.
|
149 |
+
$this->targetFile = $fs->getFile($targetFile);
|
150 |
|
151 |
+
if ($permissions > 0)
|
152 |
+
chmod( $targetFile, $permissions ); // restore permissions
|
153 |
else {
|
154 |
Log::addWarn('Setting permissions failed');
|
155 |
}
|
156 |
|
157 |
// update the file attached. This is required for wp_get_attachment_url to work.
|
158 |
+
$updated = update_attached_file($this->post_id, $this->targetFile->getFullPath() );
|
159 |
if (! $updated)
|
160 |
Log::addError('Update Attached File reports as not updated or same value');
|
161 |
|
163 |
|
164 |
// Run the filter, so other plugins can hook if needed.
|
165 |
$filtered = apply_filters( 'wp_handle_upload', array(
|
166 |
+
'file' => $this->targetFile->getFullPath(),
|
167 |
'url' => $this->target_url,
|
168 |
+
'type' => $this->targetFile->getMime(),
|
169 |
), 'sideload');
|
170 |
|
171 |
// check if file changed during filter. Set changed to attached file meta properly.
|
172 |
+
if (isset($filtered['file']) && $filtered['file'] != $this->targetFile->getFullPath() )
|
173 |
{
|
174 |
update_attached_file($this->post_id, $filtered['file'] );
|
175 |
+
$this->targetFile = $this->fs()->getFile($filtered['file']); // handle as a new file
|
176 |
Log::addInfo('WP_Handle_upload filter returned different file', $filtered);
|
177 |
}
|
178 |
|
179 |
// Check and update post mimetype, otherwise badly coded plugins cry.
|
180 |
$post_mime = get_post_mime_type($this->post_id);
|
181 |
+
$target_mime = $this->targetFile->getMime();
|
182 |
|
183 |
// update DB post mime type, if somebody decided to mess it up, and the target one is not empty.
|
184 |
if ($target_mime !== $post_mime && strlen($target_mime) > 0)
|
185 |
{
|
186 |
|
187 |
+
\wp_update_post(array('post_mime_type' => $this->targetFile->getMime(), 'ID' => $this->post_id));
|
188 |
}
|
189 |
|
190 |
+
$metadata = wp_generate_attachment_metadata( $this->post_id, $this->targetFile->getFullPath() );
|
191 |
wp_update_attachment_metadata( $this->post_id, $metadata );
|
192 |
$this->target_metadata = $metadata;
|
193 |
|
272 |
protected function getNewTitle()
|
273 |
{
|
274 |
// get basename without extension
|
275 |
+
$title = basename($this->targetFile->getFileName(), '.' . $this->targetFile->getExtension());
|
276 |
$meta = $this->target_metadata;
|
277 |
|
278 |
if (isset($meta['image_meta']))
|
317 |
return $this->sourceFile;
|
318 |
}
|
319 |
|
320 |
+
|
321 |
+
public function getSourceUrl()
|
322 |
+
{
|
323 |
+
return $this->source_url;
|
324 |
+
}
|
325 |
+
|
326 |
public function setNewTargetLocation($new_rel_location)
|
327 |
{
|
328 |
$uploadDir = wp_upload_dir();
|
329 |
$newPath = trailingslashit($uploadDir['basedir']) . $new_rel_location;
|
330 |
|
331 |
+
// Detect traversal by making sure the canonical path starts with uploads' basedir.
|
332 |
+
if (($newPath = realpath($newPath)) && strpos($newPath, $uploadDir['basedir']) !== 0)
|
333 |
+
{
|
334 |
+
Notices::addError(__('Specificed directory is outside the upload directory. This is not allowed for security reasons', 'enable-media-replace'));
|
335 |
+
return false;
|
336 |
+
}
|
337 |
+
|
338 |
if (! is_dir($newPath))
|
339 |
{
|
340 |
Notices::addError(__('Specificed new directory does not exist. Path must be a relative path from the upload directory and exist', 'enable-media-replace'));
|
350 |
$targetPath = null;
|
351 |
if ($this->replaceMode == self::MODE_REPLACE)
|
352 |
{
|
353 |
+
$targetFile = $this->sourceFile->getFullPath(); // overwrite source
|
354 |
}
|
355 |
elseif ($this->replaceMode == self::MODE_SEARCHREPLACE)
|
356 |
{
|
357 |
+
$path = (string) $this->sourceFile->getFileDir();
|
358 |
if ($this->target_location) // Replace to another path.
|
359 |
{
|
360 |
+
$otherTarget = $this->fs()->getFile($this->target_location . $this->targetName);
|
361 |
if ($otherTarget->exists())
|
362 |
{
|
363 |
Notices::addError(__('In specificied directory there is already a file with the same name. Can\'t replace.', 'enable-media-replace'));
|
369 |
$targetpath = $path . $this->targetName;
|
370 |
|
371 |
// If the source and target path AND filename are identical, user has wrong mode, just overwrite the sourceFile.
|
372 |
+
if ($targetpath == $this->sourceFile->getFullPath())
|
373 |
{
|
374 |
$unique = $this->sourceFile->getFileName();
|
375 |
$this->replaceMode == self::MODE_REPLACE;
|
416 |
if (strpos($url, '://') === false)
|
417 |
{
|
418 |
$uploads = wp_get_upload_dir();
|
419 |
+
$url = str_replace($uploads['basedir'], $uploads['baseurl'], $this->targetFile->getFullPath());
|
420 |
}
|
421 |
// This can happen when WordPress is not taking from attached file, but wrong /old GUID. Try to replace it to the new one.
|
422 |
elseif ($this->targetFile->getFileName() != $url_basename)
|
438 |
$backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true );
|
439 |
|
440 |
// this must be -scaled if that exists, since wp_delete_attachment_files checks for original_files but doesn't recheck if scaled is included since that the one 'that exists' in WP . $this->source_file replaces original image, not the -scaled one.
|
441 |
+
$file = $this->sourceFile->getFullPath();
|
442 |
$result = \wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $file );
|
443 |
|
444 |
// If Attached file is not the same path as file, this indicates a -scaled images is in play.
|
445 |
+
// Also plugins like Polylang tend to block delete image while there is translation / duplicate item somewhere
|
446 |
+
// 10/06/22 : Added a hard delete if file still exists. Be gone, hard way.
|
447 |
$attached_file = get_attached_file($this->post_id);
|
448 |
+
if (file_exists($attached_file))
|
449 |
{
|
450 |
@unlink($attached_file);
|
451 |
}
|
494 |
$base_url = str_replace('.' . pathinfo($base_url, PATHINFO_EXTENSION), '', $base_url);
|
495 |
|
496 |
|
497 |
+
$abspath = $this->fs()->getWPAbsPath();
|
498 |
/** Fail-safe if base_url is a whole directory, don't go search/replace */
|
499 |
+
if (strpos($abspath, $base_url) === 0 && is_dir($base_url))
|
500 |
{
|
501 |
Log::addError('Search Replace tried to replace to directory - ' . $base_url);
|
502 |
Notices::addError(__('Fail Safe :: Source Location seems to be a directory.', 'enable-media-replace'));
|
632 |
|
633 |
if ($replaced_content !== $post_content)
|
634 |
{
|
|
|
|
|
|
|
635 |
$sql = 'UPDATE ' . $wpdb->posts . ' SET post_content = %s WHERE ID = %d';
|
636 |
$sql = $wpdb->prepare($sql, $replaced_content, $post_id);
|
637 |
|
|
|
638 |
$result = $wpdb->query($sql);
|
639 |
|
640 |
if ($result === false)
|
655 |
{
|
656 |
global $wpdb;
|
657 |
|
658 |
+
$meta_options = apply_filters('emr/metadata_tables', array('post', 'comment', 'term', 'user', 'options'));
|
659 |
$number_of_updates = 0;
|
660 |
|
661 |
foreach($meta_options as $type)
|
669 |
|
670 |
$update_sql = ' UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d';
|
671 |
break;
|
672 |
+
case "options": // basked case (for guten widgets).
|
673 |
+
$sql = 'SELECT option_id as id, option_name, option_value as meta_value FROM ' . $wpdb->options . '
|
674 |
+
WHERE option_value like %s and option_name = "widget_block" ';
|
675 |
+
$type = 'option';
|
676 |
+
|
677 |
+
$update_sql = ' UPDATE ' . $wpdb->options . ' SET option_value = %s WHERE option_id = %d';
|
678 |
+
break;
|
679 |
default:
|
680 |
$table = $wpdb->{$type . 'meta'}; // termmeta, commentmeta etc
|
681 |
|
683 |
if ($type == 'user')
|
684 |
$meta_id = 'umeta_id';
|
685 |
|
686 |
+
|
687 |
$sql = 'SELECT ' . $meta_id . ' as id, meta_value FROM ' . $table . '
|
688 |
WHERE meta_value like %s';
|
689 |
|
692 |
}
|
693 |
|
694 |
$sql = $wpdb->prepare($sql, '%' . $url . '%');
|
695 |
+
Log::addTemp('Handle MEta SQL ' . $sql);
|
696 |
+
|
697 |
+
if ($wpdb->last_error)
|
698 |
+
Log::addWarn('Error' . $wpdb->last_error, $wpdb->last_query);
|
699 |
|
700 |
// This is a desparate solution. Can't find anyway for wpdb->prepare not the add extra slashes to the query, which messes up the query.
|
701 |
// $postmeta_sql = str_replace('[JSON_URL]', $json_url, $postmeta_sql);
|
718 |
Log::addDebug('Update Meta SQl' . $prepared_sql);
|
719 |
$result = $wpdb->query($prepared_sql);
|
720 |
|
721 |
+
if ($wpdb->last_error)
|
722 |
+
Log::addWarn('Error' . $wpdb->last_error, $wpdb->last_query);
|
723 |
+
|
724 |
}
|
725 |
}
|
726 |
} // foreach
|
774 |
}
|
775 |
}
|
776 |
}
|
777 |
+
elseif(is_object($content) && '__PHP_Incomplete_Class' !== get_class($content)) // metadata objects, they exist. prevent incomplete classes from deactivated plugins or whatever. They crash.
|
778 |
{
|
779 |
foreach($content as $key => $value)
|
780 |
{
|
781 |
+
|
782 |
$content->{$key} = $this->replaceContent($value, $search, $replace, true); //str_replace($value, $search, $replace);
|
783 |
}
|
784 |
}
|
@@ -10,24 +10,41 @@ class UIHelper
|
|
10 |
protected $preview_width = 0;
|
11 |
protected $preview_height = 0;
|
12 |
|
13 |
-
|
14 |
-
protected $
|
15 |
|
16 |
protected $full_width = 0;
|
17 |
protected $full_height = 0;
|
18 |
|
|
|
|
|
|
|
|
|
19 |
public function __construct()
|
20 |
{
|
21 |
|
22 |
}
|
23 |
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
{
|
|
|
|
|
26 |
$url = admin_url('upload.php');
|
27 |
$url = add_query_arg(array(
|
28 |
'page' => 'enable-media-replace/enable-media-replace.php',
|
29 |
'noheader' => true,
|
30 |
-
'action' =>
|
31 |
'attachment_id' => $attach_id,
|
32 |
));
|
33 |
|
@@ -91,6 +108,7 @@ class UIHelper
|
|
91 |
|
92 |
public function setPreviewSizes()
|
93 |
{
|
|
|
94 |
list($this->preview_size, $this->preview_width, $this->preview_height) = $this->findImageSizeByMax($this->preview_max_width);
|
95 |
}
|
96 |
|
@@ -109,14 +127,15 @@ class UIHelper
|
|
109 |
}
|
110 |
|
111 |
// Returns Preview Image HTML Output.
|
112 |
-
public function getPreviewImage($attach_id,$file)
|
113 |
{
|
114 |
$data = false;
|
115 |
|
116 |
if ($attach_id > 0)
|
117 |
{
|
118 |
$data = $this->getImageSizes($attach_id, $this->preview_size); //wp_get_attachment_image_src($attach_id, $this->preview_size);
|
119 |
-
|
|
|
120 |
|
121 |
// If the file is relative, prepend upload dir.
|
122 |
if (! file_exists($file) && $file && 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) )
|
@@ -126,7 +145,6 @@ class UIHelper
|
|
126 |
$file = $uploads['basedir'] . "/$file";
|
127 |
}
|
128 |
*/
|
129 |
-
Log::addDebug('Attached File ' . $file->getFullFilePath(), $data);
|
130 |
}
|
131 |
|
132 |
$mime_type = get_post_mime_type($attach_id);
|
@@ -137,7 +155,7 @@ class UIHelper
|
|
137 |
$icon = ($attach_id < 0) ? '' : 'dashicons-no';
|
138 |
$is_document = false;
|
139 |
|
140 |
-
$
|
141 |
'width' => $this->preview_width,
|
142 |
'height' => $this->preview_height,
|
143 |
'is_image' => false,
|
@@ -146,7 +164,7 @@ class UIHelper
|
|
146 |
'mime_type' => null,
|
147 |
);
|
148 |
|
149 |
-
|
150 |
|
151 |
// failed, it might be this server doens't support PDF thumbnails. Fallback to File preview.
|
152 |
if ($mime_type == 'application/pdf')
|
@@ -157,26 +175,40 @@ class UIHelper
|
|
157 |
return $this->getPlaceHolder($args);
|
158 |
}
|
159 |
|
160 |
-
|
161 |
$url = $data[0];
|
162 |
$width = $data[1];
|
163 |
$height = $data[2];
|
164 |
|
165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
|
|
|
|
|
|
170 |
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
$height = $this->preview_max_height;
|
176 |
|
177 |
$image = "<img src='$url' width='$width' height='$height' class='image' style='max-width:100%; max-height: 100%;' />";
|
178 |
|
179 |
-
$
|
180 |
'width' => $width,
|
181 |
'height' => $height,
|
182 |
'image' => $image,
|
@@ -184,16 +216,44 @@ class UIHelper
|
|
184 |
'file_size' => $file->getFileSize(),
|
185 |
);
|
186 |
|
|
|
|
|
187 |
$output = $this->getPlaceHolder($args);
|
188 |
return $output;
|
189 |
}
|
190 |
|
191 |
protected function getImageSizes($attach_id, $size = 'thumbnail')
|
192 |
{
|
193 |
-
|
194 |
-
$
|
195 |
-
|
196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
$mime_type = wp_get_image_mime($file);
|
198 |
|
199 |
if (strpos($mime_type, 'svg') !== false && $width <= 5)
|
@@ -202,6 +262,7 @@ class UIHelper
|
|
202 |
$data = $this->fixSVGSize($data, $file);
|
203 |
}
|
204 |
|
|
|
205 |
return $data;
|
206 |
}
|
207 |
|
@@ -246,7 +307,7 @@ class UIHelper
|
|
246 |
$filename = false;
|
247 |
}
|
248 |
|
249 |
-
$mime_type = $file->
|
250 |
|
251 |
$args = array(
|
252 |
'width' => 300,
|
@@ -263,7 +324,7 @@ class UIHelper
|
|
263 |
|
264 |
public function findImageSizeByMax($maxwidth)
|
265 |
{
|
266 |
-
$image_sizes = $this->
|
267 |
|
268 |
$match_width = 0;
|
269 |
$match_height = 0;
|
@@ -295,6 +356,8 @@ class UIHelper
|
|
295 |
'is_document' => false,
|
296 |
'mime_type' => false,
|
297 |
'file_size' => false,
|
|
|
|
|
298 |
);
|
299 |
|
300 |
$args = wp_parse_args($args, $defaults);
|
@@ -330,11 +393,13 @@ class UIHelper
|
|
330 |
|
331 |
$filesize = ($args['file_size']) ? $args['file_size'] : '';
|
332 |
|
|
|
333 |
|
334 |
$output = "<div class='image_placeholder $placeholder_class' $filetype style='width:" . $w . "px; height:". $h ."px'> ";
|
335 |
$output .= $args['image'];
|
336 |
$output .= "<div class='dashicons $icon'> </div>";
|
337 |
$output .= "<span class='textlayer'>" . $args['layer'] . "</span>";
|
|
|
338 |
$output .= "<div class='image_size'>" . $this->convertFileSize($filesize). "</div>";
|
339 |
$output .= "</div>";
|
340 |
|
@@ -343,6 +408,35 @@ class UIHelper
|
|
343 |
return $output;
|
344 |
}
|
345 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
346 |
private function convertFileSize($filesize)
|
347 |
{
|
348 |
return size_format($filesize);
|
@@ -355,7 +449,7 @@ class UIHelper
|
|
355 |
* @uses get_intermediate_image_sizes()
|
356 |
* @return array $sizes Data for all currently-registered image sizes.
|
357 |
*/
|
358 |
-
private function
|
359 |
global $_wp_additional_image_sizes;
|
360 |
|
361 |
$sizes = array();
|
@@ -385,4 +479,14 @@ class UIHelper
|
|
385 |
return false;
|
386 |
}
|
387 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
388 |
} // class
|
10 |
protected $preview_width = 0;
|
11 |
protected $preview_height = 0;
|
12 |
|
13 |
+
protected $preview_max_width = 600;
|
14 |
+
protected $preview_max_height = 600;
|
15 |
|
16 |
protected $full_width = 0;
|
17 |
protected $full_height = 0;
|
18 |
|
19 |
+
private static $instance;
|
20 |
+
|
21 |
+
const NOTICE_NEW_FEATURE = 'EMR001';
|
22 |
+
|
23 |
public function __construct()
|
24 |
{
|
25 |
|
26 |
}
|
27 |
|
28 |
+
public static function getInstance()
|
29 |
+
{
|
30 |
+
if (is_null(self::$instance))
|
31 |
+
{
|
32 |
+
self::$instance = new UiHelper();
|
33 |
+
}
|
34 |
+
|
35 |
+
return self::$instance;
|
36 |
+
}
|
37 |
+
|
38 |
+
// @todo Add nonce URL to this url as well, in popup / prepare-remove-background
|
39 |
+
public function getFormUrl($attach_id, $action = null)
|
40 |
{
|
41 |
+
$action = (! is_null($action)) ? $action : 'media_replace_upload';
|
42 |
+
|
43 |
$url = admin_url('upload.php');
|
44 |
$url = add_query_arg(array(
|
45 |
'page' => 'enable-media-replace/enable-media-replace.php',
|
46 |
'noheader' => true,
|
47 |
+
'action' => $action,
|
48 |
'attachment_id' => $attach_id,
|
49 |
));
|
50 |
|
108 |
|
109 |
public function setPreviewSizes()
|
110 |
{
|
111 |
+
|
112 |
list($this->preview_size, $this->preview_width, $this->preview_height) = $this->findImageSizeByMax($this->preview_max_width);
|
113 |
}
|
114 |
|
127 |
}
|
128 |
|
129 |
// Returns Preview Image HTML Output.
|
130 |
+
public function getPreviewImage($attach_id,$file, $args = array())
|
131 |
{
|
132 |
$data = false;
|
133 |
|
134 |
if ($attach_id > 0)
|
135 |
{
|
136 |
$data = $this->getImageSizes($attach_id, $this->preview_size); //wp_get_attachment_image_src($attach_id, $this->preview_size);
|
137 |
+
/*$file = get_attached_file($attach_id);
|
138 |
+
|
139 |
|
140 |
// If the file is relative, prepend upload dir.
|
141 |
if (! file_exists($file) && $file && 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) )
|
145 |
$file = $uploads['basedir'] . "/$file";
|
146 |
}
|
147 |
*/
|
|
|
148 |
}
|
149 |
|
150 |
$mime_type = get_post_mime_type($attach_id);
|
155 |
$icon = ($attach_id < 0) ? '' : 'dashicons-no';
|
156 |
$is_document = false;
|
157 |
|
158 |
+
$defaults = array(
|
159 |
'width' => $this->preview_width,
|
160 |
'height' => $this->preview_height,
|
161 |
'is_image' => false,
|
164 |
'mime_type' => null,
|
165 |
);
|
166 |
|
167 |
+
$args = wp_parse_args($args, $defaults);
|
168 |
|
169 |
// failed, it might be this server doens't support PDF thumbnails. Fallback to File preview.
|
170 |
if ($mime_type == 'application/pdf')
|
175 |
return $this->getPlaceHolder($args);
|
176 |
}
|
177 |
|
|
|
178 |
$url = $data[0];
|
179 |
$width = $data[1];
|
180 |
$height = $data[2];
|
181 |
|
182 |
+
// width
|
183 |
+
$width_ratio = $height_ratio = 0;
|
184 |
+
if ($width > $this->preview_max_width)
|
185 |
+
{
|
186 |
+
$width_ratio = $width / $this->preview_max_width;
|
187 |
+
}
|
188 |
+
if ($height > $this->preview_max_height) // height
|
189 |
+
{
|
190 |
+
$height_ratio = $height / $this->preview_max_height;
|
191 |
+
}
|
192 |
+
|
193 |
+
$ratio = ($width_ratio > $height_ratio) ? $width_ratio : $height_ratio;
|
194 |
|
195 |
+
if ($ratio > 0)
|
196 |
+
{
|
197 |
+
|
198 |
+
$width = floor($width / $ratio);
|
199 |
+
$height = floor($height / $ratio);
|
200 |
+
}
|
201 |
+
|
202 |
+
// SVG's without any helpers return around 0 for width / height. Fix preview.
|
203 |
|
204 |
|
205 |
+
// preview width, if source if found, should be set to source.
|
206 |
+
$this->preview_width = $width;
|
207 |
+
$this->preview_height = $height;
|
|
|
208 |
|
209 |
$image = "<img src='$url' width='$width' height='$height' class='image' style='max-width:100%; max-height: 100%;' />";
|
210 |
|
211 |
+
$defaults = array(
|
212 |
'width' => $width,
|
213 |
'height' => $height,
|
214 |
'image' => $image,
|
216 |
'file_size' => $file->getFileSize(),
|
217 |
);
|
218 |
|
219 |
+
$args = wp_parse_args($args, $defaults);
|
220 |
+
|
221 |
$output = $this->getPlaceHolder($args);
|
222 |
return $output;
|
223 |
}
|
224 |
|
225 |
protected function getImageSizes($attach_id, $size = 'thumbnail')
|
226 |
{
|
227 |
+
// We are not using this function, because depending on the theme, it can mess with the dimensions - https://wordpress.stackexchange.com/questions/167525/why-is-wp-get-attachment-image-src-returning-wrong-dimensions
|
228 |
+
// $data = wp_get_attachment_image_src($attach_id, $size);
|
229 |
+
$meta = wp_get_attachment_metadata($attach_id);
|
230 |
+
|
231 |
+
$data = false;
|
232 |
+
|
233 |
+
if (isset($meta['sizes']))
|
234 |
+
{
|
235 |
+
foreach($meta['sizes'] as $sizeName => $metaData)
|
236 |
+
{
|
237 |
+
if ($sizeName == $size)
|
238 |
+
{
|
239 |
+
$width = isset($metaData['width']) ? $metaData['width'] : 0;
|
240 |
+
$height = isset($metaData['height']) ? $metaData['height'] : 0;
|
241 |
+
$imgData = image_downsize($attach_id, $size); // return whole array w/ possible wrong dimensions.
|
242 |
+
$data = array($imgData[0], $width, $height);
|
243 |
+
}
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
if ($data === false)
|
248 |
+
{
|
249 |
+
$data = wp_get_attachment_image_src($attach_id, $size);
|
250 |
+
$width = isset($data[1]) ? $data[1] : 0;
|
251 |
+
}
|
252 |
+
|
253 |
+
$file = get_attached_file($attach_id, true);
|
254 |
+
if (! file_exists($file))
|
255 |
+
return $data;
|
256 |
+
|
257 |
$mime_type = wp_get_image_mime($file);
|
258 |
|
259 |
if (strpos($mime_type, 'svg') !== false && $width <= 5)
|
262 |
$data = $this->fixSVGSize($data, $file);
|
263 |
}
|
264 |
|
265 |
+
|
266 |
return $data;
|
267 |
}
|
268 |
|
307 |
$filename = false;
|
308 |
}
|
309 |
|
310 |
+
$mime_type = $file->getMime();
|
311 |
|
312 |
$args = array(
|
313 |
'width' => 300,
|
324 |
|
325 |
public function findImageSizeByMax($maxwidth)
|
326 |
{
|
327 |
+
$image_sizes = $this->wp_get_image_sizes();
|
328 |
|
329 |
$match_width = 0;
|
330 |
$match_height = 0;
|
356 |
'is_document' => false,
|
357 |
'mime_type' => false,
|
358 |
'file_size' => false,
|
359 |
+
'remove_bg_ui' => false, // In process icons et al when removing background, for preview pane.
|
360 |
+
|
361 |
);
|
362 |
|
363 |
$args = wp_parse_args($args, $defaults);
|
393 |
|
394 |
$filesize = ($args['file_size']) ? $args['file_size'] : '';
|
395 |
|
396 |
+
$background_remove_ui = (isset($args['remove_bg_ui']) && $args['remove_bg_ui'] == true) ? $this->getBgremoveUI() : '';
|
397 |
|
398 |
$output = "<div class='image_placeholder $placeholder_class' $filetype style='width:" . $w . "px; height:". $h ."px'> ";
|
399 |
$output .= $args['image'];
|
400 |
$output .= "<div class='dashicons $icon'> </div>";
|
401 |
$output .= "<span class='textlayer'>" . $args['layer'] . "</span>";
|
402 |
+
$output .= $background_remove_ui;
|
403 |
$output .= "<div class='image_size'>" . $this->convertFileSize($filesize). "</div>";
|
404 |
$output .= "</div>";
|
405 |
|
408 |
return $output;
|
409 |
}
|
410 |
|
411 |
+
public function isBackgroundRemovable($post)
|
412 |
+
{
|
413 |
+
if (false === wp_attachment_is_image($post))
|
414 |
+
return false;
|
415 |
+
|
416 |
+
$extensions = array('jpg', 'png','jpeg');
|
417 |
+
|
418 |
+
$mime = get_post_mime_type($post);
|
419 |
+
foreach($extensions as $extension)
|
420 |
+
{
|
421 |
+
if (strpos($mime, $extension) !== false )
|
422 |
+
return true;
|
423 |
+
}
|
424 |
+
|
425 |
+
return false;
|
426 |
+
|
427 |
+
}
|
428 |
+
|
429 |
+
private function getBgremoveUI()
|
430 |
+
{
|
431 |
+
$output = '<div class="overlay" id="overlay">
|
432 |
+
<div class="lds-spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>';
|
433 |
+
|
434 |
+
$output .= '<h3>' . esc_html__('Removing background...', 'enable-media-replace') . '</h3>';
|
435 |
+
$output .= '</div>';
|
436 |
+
|
437 |
+
return $output;
|
438 |
+
}
|
439 |
+
|
440 |
private function convertFileSize($filesize)
|
441 |
{
|
442 |
return size_format($filesize);
|
449 |
* @uses get_intermediate_image_sizes()
|
450 |
* @return array $sizes Data for all currently-registered image sizes.
|
451 |
*/
|
452 |
+
private function wp_get_image_sizes() {
|
453 |
global $_wp_additional_image_sizes;
|
454 |
|
455 |
$sizes = array();
|
479 |
return false;
|
480 |
}
|
481 |
|
482 |
+
public function featureNotice()
|
483 |
+
{
|
484 |
+
// @todo Remove in 2023.
|
485 |
+
$message = sprintf(__('%s New Beta Feature! %s %s Enable Media Replace now gives you the ability to remove the background of any image. Try it out in the Media Library: hover over an image and click on Remove Background. Or just click on Remove background from the image editing window! %s ', 'enable-media-replace' ), '<h3>', '</h3>',
|
486 |
+
'<p>', '</p>');
|
487 |
+
|
488 |
+
$notice = Notices::addNormal($message, true);
|
489 |
+
Notices::makePersistent($notice, self::NOTICE_NEW_FEATURE, 2 * YEAR_IN_SECONDS);
|
490 |
+
}
|
491 |
+
|
492 |
} // class
|
@@ -990,6 +990,9 @@
|
|
990 |
.emr_upload_form form .upsell-wrapper {
|
991 |
margin-left: 10px;
|
992 |
}
|
|
|
|
|
|
|
993 |
.emr_upload_form .wrapper {
|
994 |
padding: 18px;
|
995 |
border: 1px solid #ccc;
|
@@ -1052,7 +1055,6 @@
|
|
1052 |
margin-bottom: 10px;
|
1053 |
border: 1px solid #ddd;
|
1054 |
vertical-align: top;
|
1055 |
-
max-height: 500px;
|
1056 |
}
|
1057 |
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .textlayer {
|
1058 |
font-size: 25px;
|
990 |
.emr_upload_form form .upsell-wrapper {
|
991 |
margin-left: 10px;
|
992 |
}
|
993 |
+
.emr_upload_form .editor-wrapper {
|
994 |
+
width: 100%;
|
995 |
+
}
|
996 |
.emr_upload_form .wrapper {
|
997 |
padding: 18px;
|
998 |
border: 1px solid #ccc;
|
1055 |
margin-bottom: 10px;
|
1056 |
border: 1px solid #ddd;
|
1057 |
vertical-align: top;
|
|
|
1058 |
}
|
1059 |
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .textlayer {
|
1060 |
font-size: 25px;
|
@@ -1 +1 @@
|
|
1 |
-
{"version":3,"sourceRoot":"","sources":["../scss/_datepicker.scss","../scss/admin.scss"],"names":[],"mappings":"AAEA;EACC;EACA;EACA;;;AAID;EACC;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;EACA;EACA;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;;;AAGD;AACA;EACC;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAGD;AACA;EACC;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;;;AAED;AAAA;EAEC;EACA;;;AAGD;AACA;EACC;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;EAEC;;;AAED;AAAA;EAEC;;;AAGD;AACA;EAAiB;;;AACjB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAuB;;;AACvB;EAAuB;;;AACvB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAuB;;;AACvB;EAAyB;;;AACzB;EAAuB;;;AACvB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA4B;;;AAC5B;EAA8B;;;AAC9B;EAA4B;;;AAC5B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAAgC;;;AAChC;EAAgC;;;AAChC;EAAgC;;;AAChC;EAAgC;;;AAChC;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAAmB;;;AACnB;EAAwB;;;AACxB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAmB;;;AACnB;EAAmB;;;AACnB;EAAwB;;;AACxB;EAA6B;;;AAC7B;EAA4B;;;AAC5B;EAAuB;;;AACvB;EAAoB;;;AACpB;EAAsB;;;AACtB;EAAgB;;;AAChB;EAAuB;;;AACvB;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAe;;;AACf;EAAgB;;;AAChB;EAAgB;;;AAChB;EAAoB;;;AACpB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAsB;;;AACtB;EAAkB;;;AAClB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAe;;;AACf;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAqB;;;AACrB;EAAgB;;;AAChB;EAAmB;;;AACnB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAoB;;;AACpB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAsB;;;AACtB;AACA;EAAsB;;;AACtB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAuB;;;AACvB;EAAkB;;;AAClB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAuB;;;AACvB;EAAwB;;;AACxB;EAAwB;;;AACxB;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAAwB;;;AACxB;EAA4B;;;AAC5B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA4B;;;AAC5B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAAgC;;;AAChC;EAAkC;;;AAClC;EAA+B;;;AAC/B;EAAiC;;;AACjC;EAAiC;;;AACjC;EAA4B;;;AAE5B;AACA;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AC/ZC;EAEE;;AACA;EAEE;;
|
1 |
+
{"version":3,"sourceRoot":"","sources":["../scss/_datepicker.scss","../scss/admin.scss"],"names":[],"mappings":"AAEA;EACC;EACA;EACA;;;AAID;EACC;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;EACA;EACA;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;;;AAGD;AACA;EACC;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAGD;AACA;EACC;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;;;AAED;AAAA;EAEC;EACA;;;AAGD;AACA;EACC;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;EAEC;;;AAED;AAAA;EAEC;;;AAGD;AACA;EAAiB;;;AACjB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAuB;;;AACvB;EAAuB;;;AACvB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAuB;;;AACvB;EAAyB;;;AACzB;EAAuB;;;AACvB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA4B;;;AAC5B;EAA8B;;;AAC9B;EAA4B;;;AAC5B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAAgC;;;AAChC;EAAgC;;;AAChC;EAAgC;;;AAChC;EAAgC;;;AAChC;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAAmB;;;AACnB;EAAwB;;;AACxB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAmB;;;AACnB;EAAmB;;;AACnB;EAAwB;;;AACxB;EAA6B;;;AAC7B;EAA4B;;;AAC5B;EAAuB;;;AACvB;EAAoB;;;AACpB;EAAsB;;;AACtB;EAAgB;;;AAChB;EAAuB;;;AACvB;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAe;;;AACf;EAAgB;;;AAChB;EAAgB;;;AAChB;EAAoB;;;AACpB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAsB;;;AACtB;EAAkB;;;AAClB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAe;;;AACf;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAqB;;;AACrB;EAAgB;;;AAChB;EAAmB;;;AACnB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAoB;;;AACpB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAsB;;;AACtB;AACA;EAAsB;;;AACtB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAuB;;;AACvB;EAAkB;;;AAClB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAuB;;;AACvB;EAAwB;;;AACxB;EAAwB;;;AACxB;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAAwB;;;AACxB;EAA4B;;;AAC5B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA4B;;;AAC5B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAAgC;;;AAChC;EAAkC;;;AAClC;EAA+B;;;AAC/B;EAAiC;;;AACjC;EAAiC;;;AACjC;EAA4B;;;AAE5B;AACA;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AC/ZC;EAEE;;AACA;EAEE;;AAIL;EAEC;;AAGD;EAGG;EACA;;AAEA;EAEE;EAEA;EACA;EACA;;AAIJ;EAEE;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AACA;EAAK;;AACL;EAEE;;AAGF;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EAAgB;;AAGtB;EAEE;;AACA;EAEE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEG;EACA;EACA;EACA;;AAID;EAAiC;;AAMjC;EAAM;;AACN;EAAa;;AAEX;EACE;EACA;EACA;;AASZ;EAEE;EACA;EACA;EAEA;EACA;;AACA;EACI;EACA;EACA;;AAIN;EAEE;;AAGF;EAEE;;AAGF;EAEE;EACA;EACA;;AACA;EAEE;EACA;;AAKA;EAEE;;AAEF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAOR;EAEE;EACA;EACA;EACA;;AAGE;EACE;;AAEF;EAEE;;AAGN;EAEE;;AACA;EACC;EACA;;AAOG;EAEE;;AAMJ;EAAQ;;AAEV;EAEE;EACA;EACA;;AAEF;EAEE;EACA;EACA;;AACA;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;;AAIN;EAEE;EACA;;AACA;EAEE;EACA;;AAKN;EAEE;EACA;EACA;EACA;;AACA;EAEE;EACA;;AAIJ;EAEG;;AAEH;EAEE;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACF;;AACE;EACE;EACA;EACA;EACA;EACA;;AAEJ;EAEE;EACA;;AAEF;EAAO;;AACP;EAAQ;;AACR;EAAQ;;AACR;EAAS;;AACR;EACE;;AAED;EAEE;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACJ;;AAGF;EAAU;;AAER;EAEE;EACA;;AACA;EAAM;EAAkB;EAAmB;;AAS/C;EAEE;;AAIF;EAEI;IAEG;;EAEH;IACE;;EACA;IACE;;;AAGR;EAEE;IAAkB;;;AAErB;EAEE;IACE;IACA;IACA;;EAIA;IACE;IACD","file":"admin.css"}
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#remove-background-form form {
|
2 |
+
display: flex;
|
3 |
+
}
|
4 |
+
#remove-background-form .image_chooser.wrapper {
|
5 |
+
min-height: 0;
|
6 |
+
}
|
7 |
+
#remove-background-form .image_placeholder.is_image {
|
8 |
+
border: none;
|
9 |
+
width: 45%;
|
10 |
+
height: auto;
|
11 |
+
}
|
12 |
+
#remove-background-form .image_placeholder.is_image .textlayer, #remove-background-form .image_placeholder.is_image .image_size {
|
13 |
+
display: none;
|
14 |
+
}
|
15 |
+
#remove-background-form .bad-button {
|
16 |
+
text-align: right;
|
17 |
+
margin-right: 25px;
|
18 |
+
}
|
19 |
+
#remove-background-form .bad-button a {
|
20 |
+
visibility: hidden;
|
21 |
+
}
|
22 |
+
#remove-background-form .overlay {
|
23 |
+
visibility: hidden;
|
24 |
+
display: flex;
|
25 |
+
flex-direction: column;
|
26 |
+
justify-content: center;
|
27 |
+
align-items: center;
|
28 |
+
width: 100%;
|
29 |
+
height: 100%;
|
30 |
+
background-color: rgba(0, 0, 0, 0.2);
|
31 |
+
position: absolute;
|
32 |
+
top: 0;
|
33 |
+
}
|
34 |
+
#remove-background-form .lds-spinner {
|
35 |
+
color: official;
|
36 |
+
display: inline-block;
|
37 |
+
position: relative;
|
38 |
+
width: 80px;
|
39 |
+
height: 80px;
|
40 |
+
}
|
41 |
+
#remove-background-form .lds-spinner div {
|
42 |
+
transform-origin: 40px 40px;
|
43 |
+
animation: lds-spinner 1.2s linear infinite;
|
44 |
+
}
|
45 |
+
#remove-background-form .lds-spinner div:after {
|
46 |
+
content: " ";
|
47 |
+
display: block;
|
48 |
+
position: absolute;
|
49 |
+
top: 3px;
|
50 |
+
left: 37px;
|
51 |
+
width: 6px;
|
52 |
+
height: 18px;
|
53 |
+
border-radius: 20%;
|
54 |
+
background: #fff;
|
55 |
+
}
|
56 |
+
#remove-background-form .lds-spinner div:nth-child(1) {
|
57 |
+
transform: rotate(0deg);
|
58 |
+
animation-delay: -1.1s;
|
59 |
+
}
|
60 |
+
#remove-background-form .lds-spinner div:nth-child(2) {
|
61 |
+
transform: rotate(30deg);
|
62 |
+
animation-delay: -1s;
|
63 |
+
}
|
64 |
+
#remove-background-form .lds-spinner div:nth-child(3) {
|
65 |
+
transform: rotate(60deg);
|
66 |
+
animation-delay: -0.9s;
|
67 |
+
}
|
68 |
+
#remove-background-form .lds-spinner div:nth-child(4) {
|
69 |
+
transform: rotate(90deg);
|
70 |
+
animation-delay: -0.8s;
|
71 |
+
}
|
72 |
+
#remove-background-form .lds-spinner div:nth-child(5) {
|
73 |
+
transform: rotate(120deg);
|
74 |
+
animation-delay: -0.7s;
|
75 |
+
}
|
76 |
+
#remove-background-form .lds-spinner div:nth-child(6) {
|
77 |
+
transform: rotate(150deg);
|
78 |
+
animation-delay: -0.6s;
|
79 |
+
}
|
80 |
+
#remove-background-form .lds-spinner div:nth-child(7) {
|
81 |
+
transform: rotate(180deg);
|
82 |
+
animation-delay: -0.5s;
|
83 |
+
}
|
84 |
+
#remove-background-form .lds-spinner div:nth-child(8) {
|
85 |
+
transform: rotate(210deg);
|
86 |
+
animation-delay: -0.4s;
|
87 |
+
}
|
88 |
+
#remove-background-form .lds-spinner div:nth-child(9) {
|
89 |
+
transform: rotate(240deg);
|
90 |
+
animation-delay: -0.3s;
|
91 |
+
}
|
92 |
+
#remove-background-form .lds-spinner div:nth-child(10) {
|
93 |
+
transform: rotate(270deg);
|
94 |
+
animation-delay: -0.2s;
|
95 |
+
}
|
96 |
+
#remove-background-form .lds-spinner div:nth-child(11) {
|
97 |
+
transform: rotate(300deg);
|
98 |
+
animation-delay: -0.1s;
|
99 |
+
}
|
100 |
+
#remove-background-form .lds-spinner div:nth-child(12) {
|
101 |
+
transform: rotate(330deg);
|
102 |
+
animation-delay: 0s;
|
103 |
+
}
|
104 |
+
@keyframes lds-spinner {
|
105 |
+
0% {
|
106 |
+
opacity: 1;
|
107 |
+
}
|
108 |
+
100% {
|
109 |
+
opacity: 0;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
#remove-background-form * {
|
113 |
+
box-sizing: border-box;
|
114 |
+
}
|
115 |
+
#remove-background-form .img-comp-container {
|
116 |
+
position: relative;
|
117 |
+
height: 200px;
|
118 |
+
/*should be the same height as the images*/
|
119 |
+
}
|
120 |
+
#remove-background-form .img-comp-img {
|
121 |
+
position: absolute;
|
122 |
+
width: auto;
|
123 |
+
height: auto;
|
124 |
+
overflow: hidden;
|
125 |
+
}
|
126 |
+
#remove-background-form .img-comp-img img {
|
127 |
+
display: block;
|
128 |
+
}
|
129 |
+
#remove-background-form .img-comp-slider {
|
130 |
+
position: absolute;
|
131 |
+
z-index: 9;
|
132 |
+
cursor: ew-resize;
|
133 |
+
/*set the appearance of the slider:*/
|
134 |
+
width: 20px;
|
135 |
+
height: 20px;
|
136 |
+
background-color: #2196F3;
|
137 |
+
opacity: 0.7;
|
138 |
+
border-radius: 50%;
|
139 |
+
}
|
140 |
+
#remove-background-form .preview-area {
|
141 |
+
display: flex;
|
142 |
+
justify-content: center;
|
143 |
+
align-items: center;
|
144 |
+
width: 100%;
|
145 |
+
height: 100%;
|
146 |
+
}
|
147 |
+
#remove-background-form .preview-area h1 {
|
148 |
+
color: red !important;
|
149 |
+
}
|
150 |
+
|
151 |
+
/*# sourceMappingURL=remove_background.css.map */
|
@@ -0,0 +1 @@
|
|
|
1 |
+
{"version":3,"sourceRoot":"","sources":["../scss/remove_background.scss"],"names":[],"mappings":"AAEG;EACA;;AAGD;EACE;;AAEF;EAEE;EACA;EACA;;AACA;EACE;;AAIJ;EAEE;EACA;;AACA;EACC;;AAIH;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACC;IACC;;EAED;IACC;;;AAMH;EACC;;AAGD;EACC;EACA;AAAe;;AAGhB;EACC;EACA;EACA;EACA;;AAGD;EACC;;AAGD;EACC;EACA;EACA;AACA;EACA;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA;;AAED;EACC","file":"remove_background.css"}
|
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Enable Media Replace
|
4 |
* Plugin URI: https://wordpress.org/plugins/enable-media-replace/
|
5 |
* Description: Enable replacing media files by uploading a new file in the "Edit Media" section of the WordPress Media Library.
|
6 |
-
* Version:
|
7 |
* Author: ShortPixel
|
8 |
* Author URI: https://shortpixel.com
|
9 |
* GitHub Plugin URI: https://github.com/short-pixel-optimizer/enable-media-replace
|
@@ -20,14 +20,14 @@
|
|
20 |
*
|
21 |
* @author ShortPixel <https://shortpixel.com>
|
22 |
* @copyright ShortPixel 2018-2020
|
23 |
-
* @package
|
24 |
* @subpackage enable-media-replace
|
25 |
*
|
26 |
*/
|
27 |
|
28 |
namespace EnableMediaReplace;
|
29 |
|
30 |
-
define('EMR_VERSION', '
|
31 |
|
32 |
if ( ! defined( 'ABSPATH' ) ) {
|
33 |
exit; // Exit if accessed directly.
|
@@ -35,15 +35,15 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
35 |
|
36 |
/* Not sure why we define this?
|
37 |
if(!defined("S3_UPLOADS_AUTOENABLE")) {
|
38 |
-
|
39 |
} */
|
40 |
|
41 |
-
if (! defined(
|
42 |
-
define(
|
43 |
}
|
44 |
|
45 |
-
if(!defined(
|
46 |
-
define(
|
47 |
}
|
48 |
|
49 |
/** Usage:
|
@@ -55,34 +55,39 @@ if(!defined("SHORTPIXEL_AFFILIATE_CODE")) {
|
|
55 |
*
|
56 |
*
|
57 |
**/
|
58 |
-
if (! defined('EMR_CAPABILITY'))
|
59 |
-
|
|
|
60 |
|
61 |
/* if (! defined('EMR_CAPABILITY_USERONLY'))
|
62 |
define('EMR_CAPABILITY_USERONLY', false); */
|
63 |
|
64 |
-
$plugin_path = plugin_dir_path(EMR_ROOT_FILE);
|
65 |
-
|
66 |
-
require_once($plugin_path . 'build/shortpixel/autoload.php');
|
67 |
-
require_once($plugin_path . 'classes/compat.php');
|
68 |
-
require_once($plugin_path . 'classes/functions.php');
|
69 |
-
require_once($plugin_path . 'classes/replacer.php');
|
70 |
-
require_once($plugin_path . 'classes/uihelper.php');
|
71 |
-
require_once($plugin_path . 'classes/file.php');
|
72 |
-
require_once($plugin_path . 'classes/cache.php');
|
73 |
-
require_once($plugin_path . 'classes/emr-plugin.php');
|
74 |
-
require_once($plugin_path . 'classes/externals.php');
|
75 |
-
require_once($plugin_path . 'classes/external/elementor.php');
|
76 |
-
require_once($plugin_path . 'classes/external/wpbakery.php');
|
77 |
-
require_once($plugin_path . 'classes/external/upsell_installer.php');
|
78 |
-
require_once($plugin_path . 'thumbnail_updater.php');
|
79 |
|
80 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
-
|
|
|
|
|
|
|
|
|
83 |
|
84 |
-
function
|
85 |
{
|
86 |
-
|
87 |
-
delete_option('emr_news');
|
88 |
}
|
|
|
|
|
|
|
|
|
|
3 |
* Plugin Name: Enable Media Replace
|
4 |
* Plugin URI: https://wordpress.org/plugins/enable-media-replace/
|
5 |
* Description: Enable replacing media files by uploading a new file in the "Edit Media" section of the WordPress Media Library.
|
6 |
+
* Version: 4.0.0
|
7 |
* Author: ShortPixel
|
8 |
* Author URI: https://shortpixel.com
|
9 |
* GitHub Plugin URI: https://github.com/short-pixel-optimizer/enable-media-replace
|
20 |
*
|
21 |
* @author ShortPixel <https://shortpixel.com>
|
22 |
* @copyright ShortPixel 2018-2020
|
23 |
+
* @package WordPress
|
24 |
* @subpackage enable-media-replace
|
25 |
*
|
26 |
*/
|
27 |
|
28 |
namespace EnableMediaReplace;
|
29 |
|
30 |
+
define( 'EMR_VERSION', '4.0.0' );
|
31 |
|
32 |
if ( ! defined( 'ABSPATH' ) ) {
|
33 |
exit; // Exit if accessed directly.
|
35 |
|
36 |
/* Not sure why we define this?
|
37 |
if(!defined("S3_UPLOADS_AUTOENABLE")) {
|
38 |
+
define('S3_UPLOADS_AUTOENABLE', true);
|
39 |
} */
|
40 |
|
41 |
+
if ( ! defined( 'EMR_ROOT_FILE' ) ) {
|
42 |
+
define( 'EMR_ROOT_FILE', __FILE__ );
|
43 |
}
|
44 |
|
45 |
+
if ( ! defined( 'SHORTPIXEL_AFFILIATE_CODE' ) ) {
|
46 |
+
define( 'SHORTPIXEL_AFFILIATE_CODE', 'VKG6LYN28044' );
|
47 |
}
|
48 |
|
49 |
/** Usage:
|
55 |
*
|
56 |
*
|
57 |
**/
|
58 |
+
if ( ! defined( 'EMR_CAPABILITY' ) ) {
|
59 |
+
define( 'EMR_CAPABILITY', false );
|
60 |
+
}
|
61 |
|
62 |
/* if (! defined('EMR_CAPABILITY_USERONLY'))
|
63 |
define('EMR_CAPABILITY_USERONLY', false); */
|
64 |
|
65 |
+
$plugin_path = plugin_dir_path( EMR_ROOT_FILE );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
67 |
+
require_once( $plugin_path . 'build/shortpixel/autoload.php' );
|
68 |
+
require_once( $plugin_path . 'classes/compat.php' );
|
69 |
+
require_once( $plugin_path . 'classes/functions.php' );
|
70 |
+
require_once( $plugin_path . 'classes/replacer.php' );
|
71 |
+
require_once( $plugin_path . 'classes/uihelper.php' );
|
72 |
+
//require_once( $plugin_path . 'classes/file.php' );
|
73 |
+
require_once( $plugin_path . 'classes/cache.php' );
|
74 |
+
require_once( $plugin_path . 'classes/api.php' );
|
75 |
+
require_once( $plugin_path . 'classes/ajax.php' );
|
76 |
+
require_once( $plugin_path . 'classes/emr-plugin.php' );
|
77 |
+
require_once( $plugin_path . 'classes/installHelper.php' );
|
78 |
|
79 |
+
require_once( $plugin_path . 'classes/externals.php' );
|
80 |
+
require_once( $plugin_path . 'classes/external/elementor.php' );
|
81 |
+
require_once( $plugin_path . 'classes/external/wpbakery.php' );
|
82 |
+
require_once( $plugin_path . 'classes/external/upsell_installer.php' );
|
83 |
+
require_once( $plugin_path . 'thumbnail_updater.php' );
|
84 |
|
85 |
+
function emr()
|
86 |
{
|
87 |
+
return EnableMediaReplacePlugin::get();
|
|
|
88 |
}
|
89 |
+
emr(); // runtime.
|
90 |
+
|
91 |
+
//register_uninstall_hook( __FILE__, '\EnableMediaReplace\emr_uninstall' );
|
92 |
+
register_deactivation_hook( __FILE__, array('\EnableMediaReplace\InstallHelper','deactivatePlugin') );
|
93 |
+
register_uninstall_hook(__FILE__, array('\EnableMediaReplace\InstallHelper','uninstallPlugin') );
|
@@ -50,6 +50,7 @@
|
|
50 |
this.updateTextLayer(source, false);
|
51 |
this.showReplaceOptions();
|
52 |
|
|
|
53 |
}
|
54 |
this.loadDatePicker = function()
|
55 |
{
|
50 |
this.updateTextLayer(source, false);
|
51 |
this.showReplaceOptions();
|
52 |
|
53 |
+
|
54 |
}
|
55 |
this.loadDatePicker = function()
|
56 |
{
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function ($) {
|
2 |
+
|
3 |
+
// Init
|
4 |
+
$('input[type=radio][name=background_type]').on('change', backgroundInputs);
|
5 |
+
$('#bg_transparency').on('input', transparancyOptions);
|
6 |
+
|
7 |
+
backgroundInputs(); // init initial
|
8 |
+
transparancyOptions();
|
9 |
+
|
10 |
+
$('.replace_type.wrapper input').on('change', function () {
|
11 |
+
$('#replace_image_button').prop('disabled', 'disabled');
|
12 |
+
});
|
13 |
+
|
14 |
+
// Remove bg click
|
15 |
+
$('#remove_background_button').on('click', () => {
|
16 |
+
const method = 'POST'
|
17 |
+
const url = emrObject.ajax_url;
|
18 |
+
// const image = emrObject.base_url;
|
19 |
+
const nonce = emrObject.nonce;
|
20 |
+
const attachment_id = $('input[name="ID"]').val();
|
21 |
+
const action = 'emr_remove_background';
|
22 |
+
const bgType = $('input[type=radio][name=background_type]:checked').val();
|
23 |
+
const cLvl = $('input[type=radio][name=compression_level]:checked').val();
|
24 |
+
let background = {
|
25 |
+
type: "transparent"
|
26 |
+
}
|
27 |
+
|
28 |
+
background = {
|
29 |
+
type: bgType,
|
30 |
+
color: $('#bg_color').val(),
|
31 |
+
transparency: $('#bg_transparency').val()
|
32 |
+
}
|
33 |
+
|
34 |
+
$.ajax({
|
35 |
+
method,
|
36 |
+
url,
|
37 |
+
data: {
|
38 |
+
action,
|
39 |
+
nonce,
|
40 |
+
attachment_id,
|
41 |
+
background,
|
42 |
+
compression_level : cLvl
|
43 |
+
},
|
44 |
+
beforeSend: function () {
|
45 |
+
$('html, body').animate({
|
46 |
+
scrollTop: $(".emr_upload_form").offset().top
|
47 |
+
}, 1000);
|
48 |
+
$('input[type=radio][name=background_type]').attr('disabled', 'disabled')
|
49 |
+
$('input[type=radio][name=compression_level]').attr('disabled', 'disabled')
|
50 |
+
$('#remove_background_button').attr('disabled', 'disabled')
|
51 |
+
$('#overlay').css('visibility', 'visible');
|
52 |
+
var preview = $('.image_placeholder').last();
|
53 |
+
preview.find('img').remove();
|
54 |
+
// $('#preview-area').hide();
|
55 |
+
},
|
56 |
+
success: function (response) {
|
57 |
+
var preview = $('.image_placeholder').last();
|
58 |
+
|
59 |
+
if (response.success) {
|
60 |
+
|
61 |
+
|
62 |
+
$('#overlay').css('visibility', 'hidden');
|
63 |
+
preview.find('img').remove();
|
64 |
+
preview.removeClass('is_image not_image is_document');
|
65 |
+
|
66 |
+
$('#replace_image_button').prop('disabled', false);
|
67 |
+
|
68 |
+
var img = new Image();
|
69 |
+
img.src = response.image;
|
70 |
+
img.setAttribute('style', 'height: inherit;');
|
71 |
+
|
72 |
+
preview.prepend(img);
|
73 |
+
// preview.removeClass('not_image');
|
74 |
+
preview.addClass('is_image');
|
75 |
+
|
76 |
+
$('input[name="key"]').val(response.key);
|
77 |
+
$('input[type=radio][name=background_type]').attr('disabled', false);
|
78 |
+
$('input[type=radio][name=compression_level]').attr('disabled', false);
|
79 |
+
$('#remove_background_button').attr('disabled', false);
|
80 |
+
|
81 |
+
var badBg = document.getElementById('bad-background-link');
|
82 |
+
var href = badBg.dataset.link;
|
83 |
+
href = href.replace('{url}', response.url);
|
84 |
+
href = href.replace('{settings}', response.settings);
|
85 |
+
|
86 |
+
badBg.setAttribute('href', href);
|
87 |
+
|
88 |
+
badBg.style.visibility = 'visible';
|
89 |
+
/* $('#removed_image').html(`
|
90 |
+
<div class="img-comp-container">
|
91 |
+
<div class="img-comp-img">
|
92 |
+
<img src="${image}" width="${width}" height="${height}" />
|
93 |
+
</div>
|
94 |
+
|
95 |
+
</div>
|
96 |
+
`); */
|
97 |
+
// initComparisons();
|
98 |
+
}else{
|
99 |
+
|
100 |
+
preview.prepend(`<h1>${response.message}</h1>`);
|
101 |
+
$('#remove_background_button').attr('disabled', false)
|
102 |
+
$('input[type=radio][name=background_type]').attr('disabled', false)
|
103 |
+
$('input[type=radio][name=compression_level]').attr('disabled', false)
|
104 |
+
$('#overlay').css('visibility', 'hidden');
|
105 |
+
//$('#preview-area').show();
|
106 |
+
}
|
107 |
+
}
|
108 |
+
})
|
109 |
+
});
|
110 |
+
|
111 |
+
function backgroundInputs () {
|
112 |
+
const bgInputs = $('#solid_selecter');
|
113 |
+
var input = $('input[type=radio][name=background_type]:checked');
|
114 |
+
if (input.val() === 'solid') {
|
115 |
+
bgInputs.show();
|
116 |
+
} else {
|
117 |
+
bgInputs.hide();
|
118 |
+
}
|
119 |
+
|
120 |
+
};
|
121 |
+
|
122 |
+
$('#bg_display_picker').on('input', function () {
|
123 |
+
$('#color_range').html($(this).val());
|
124 |
+
$('#bg_color').val($(this).val());
|
125 |
+
});
|
126 |
+
|
127 |
+
function transparancyOptions() {
|
128 |
+
$('#transparency_range').html($('#bg_transparency').val());
|
129 |
+
};
|
130 |
+
|
131 |
+
});
|
@@ -1,52 +1,80 @@
|
|
1 |
=== Enable Media Replace ===
|
2 |
Contributors: ShortPixel
|
3 |
Donate link: https://www.paypal.me/resizeImage
|
4 |
-
Tags: replace, attachment, media, files, replace image, replace jpg, change media, replace media, image, file
|
5 |
Requires at least: 4.9.7
|
6 |
Tested up to: 6.0
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag:
|
9 |
|
10 |
Easily replace any attached image/file by simply uploading a new file in the Media Library edit view - a real time saver!
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
**A free, lightweight and easy to use plugin that allows you to seamlessly replace an image or file in your Media Library by uploading a new file in its place. No more deleting, renaming and re-uploading files!
|
|
|
15 |
Supported by the friendly team that created <a href="https://wordpress.org/plugins/shortpixel-image-optimiser/" target="_blank">ShortPixel</a> :)**
|
16 |
|
17 |
#### A real timesaver
|
18 |
|
19 |
-
Don't you find it tedious and complicated to
|
20 |
|
21 |
Well, no longer!
|
22 |
|
23 |
-
Now you
|
24 |
|
25 |
#### It's simple to replace a file
|
26 |
|
27 |
-
1.
|
28 |
-
|
29 |
|
30 |
-
This plugin is very powerful and a must-have for
|
31 |
|
32 |
-
####
|
|
|
|
|
33 |
|
34 |
-
|
|
|
|
|
35 |
`[file_modified id=XX format=XXXX]` where the "id" is required and the "format" is optional and defaults to your current WordPress settings for date and time format.
|
36 |
|
37 |
-
So `[file_modified id=870]` would
|
|
|
|
|
38 |
|
39 |
-
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
-
|
43 |
|
44 |
-
*
|
45 |
-
*
|
46 |
-
*
|
|
|
47 |
|
48 |
== Changelog ==
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
= 3.6.3 =
|
51 |
|
52 |
Release date: November 25th, 2021
|
1 |
=== Enable Media Replace ===
|
2 |
Contributors: ShortPixel
|
3 |
Donate link: https://www.paypal.me/resizeImage
|
4 |
+
Tags: replace, attachment, media, files, replace image, remove background, replace jpg, change media, replace media, image, file
|
5 |
Requires at least: 4.9.7
|
6 |
Tested up to: 6.0
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 4.0.0
|
9 |
|
10 |
Easily replace any attached image/file by simply uploading a new file in the Media Library edit view - a real time saver!
|
11 |
|
12 |
== Description ==
|
13 |
|
14 |
**A free, lightweight and easy to use plugin that allows you to seamlessly replace an image or file in your Media Library by uploading a new file in its place. No more deleting, renaming and re-uploading files!
|
15 |
+
New beta feature! You can now remove the background of your images for better integration with eCommerce solutions!
|
16 |
Supported by the friendly team that created <a href="https://wordpress.org/plugins/shortpixel-image-optimiser/" target="_blank">ShortPixel</a> :)**
|
17 |
|
18 |
#### A real timesaver
|
19 |
|
20 |
+
Don't you find it tedious and complicated to first delete a file and then upload another one with the exact same name every time you want to update an image or other uploaded file in the WordPress media library?
|
21 |
|
22 |
Well, no longer!
|
23 |
|
24 |
+
Now you can replace any uploaded file in the Edit Media view, where it should be. Replacing Media can be done in two ways:
|
25 |
|
26 |
#### It's simple to replace a file
|
27 |
|
28 |
+
1. Simply replace the file. This option requires you to upload a file of the same type as the file you want to replace. The attachment name remains the same regardless of what the file you upload is called.
|
29 |
+
2. Replace the file, use the new file name, and update all links. If you check this option, the old file will be replaced with the name and type of the file you are uploading. All links pointing to the current file will be updated to point to the new file name. Additional options for the folder to put the new file in or the date of the new file are also available on the replace screen.
|
30 |
|
31 |
+
This plugin is very powerful and a must-have for all major websites built with WordPress. It also offers a preview of the replaced image!
|
32 |
|
33 |
+
#### New beta feature: You can now remove the background of any image!
|
34 |
+
Similar to replacing media, you can also remove the background of the images from the Media Library! The background removal feature sends the images to ShortPixel's API, removes the background and sends them back in a preview window. If everything looks good, just replace the image with the one that has the background removed! If the source image is a PNG file, you will get a transparent background, while the other images default to a solid white background. You also have the option to choose a different color with an embedded color picker.
|
35 |
+
The background removal feature is still in beta and will be free of charge for a reasonable usage.
|
36 |
|
37 |
+
#### Show file modification time
|
38 |
+
|
39 |
+
There is a shortcode that takes the file modification date and displays it in a post or on a page. The code is:
|
40 |
`[file_modified id=XX format=XXXX]` where the "id" is required and the "format" is optional and defaults to your current WordPress settings for date and time format.
|
41 |
|
42 |
+
So `[file_modified id=870]` would show the last time the file with ID 870 was updated on your site. To get the ID for a file, check the URL when editing a file in the media library (see screenshot #4)
|
43 |
+
|
44 |
+
If you want more control over the format in which the time is shown, you can use the format option. So `[file_modified id=870 format=Y-m-d]` would show the date the file was modified but not the time. The format string uses [the standard PHP date() formatting tags](http://php.net/manual/en/function.date.php).
|
45 |
|
46 |
+
**Other plugins by [ShortPixel](https://shortpixel.com):**
|
47 |
|
48 |
+
* [ShortPixel Image Optimizer](https://wordpress.org/plugins/shortpixel-image-optimiser/) - Image optimization & compression for all the images on your website, including WebP & AVIF delivery
|
49 |
+
* [ShortPixel Adaptive Images](https://wordpress.org/plugins/shortpixel-adaptive-images/) - On-the-fly image optimization & CDN delivery
|
50 |
+
* [Resize Image After Upload](https://wordpress.org/plugins/resize-image-after-upload/) - Automatically resize each uploaded image
|
51 |
+
* [reGenerate Thumbnails Advanced](https://wordpress.org/plugins/regenerate-thumbnails-advanced/) - Easily regenerate thumbnails
|
52 |
+
* [WP SVG Images](https://wordpress.org/plugins/wp-svg-images/) - Secure upload of SVG files to Media Library
|
53 |
+
* [ShortPixel Critical CSS](https://wordpress.org/plugins/shortpixel-critical-css/) - Automatically generate above-the-fold CSS for fatster loading times and better SEO scores
|
54 |
|
55 |
+
**Get in touch!**
|
56 |
|
57 |
+
* Email <a href="https://shortpixel.com/contact" target="_blank">https://shortpixel.com/contact</a>
|
58 |
+
* Twitter <a href="https://twitter.com/shortpixel" target="_blank">https://twitter.com/shortpixel</a>
|
59 |
+
* Facebook <a href="https://www.facebook.com/ShortPixel" target="_blank">https://www.facebook.com/ShortPixel</a>
|
60 |
+
* LinkedIn <a href="https://www.linkedin.com/company/shortpixel" target="_blank">https://www.linkedin.com/company/shortpixel</a>
|
61 |
|
62 |
== Changelog ==
|
63 |
|
64 |
+
= 4.0.0 =
|
65 |
+
|
66 |
+
Release date: September 5th, 2022
|
67 |
+
* New: added the functionality to remove the background for any image;
|
68 |
+
* Fix: images added to the new block-style widgets were not replaced;
|
69 |
+
* Fix: the original file was not removed after replacement if a multilingual plugin was installed;
|
70 |
+
* Fix: additional checks were added to the new upload path for replacements, to avoid possible vulnerabilities, kudos to @soulseekah;
|
71 |
+
* Fix: an object cache flush was added after an image was replaced to prevent the content from still being cached in the post editor;
|
72 |
+
* Fix: if there was no `_wp_attached_file` in the postmeta table a fatal error was thrown;
|
73 |
+
* Fix: the time zone was not displayed correctly on the Replace Media screen;
|
74 |
+
* Fix: added some additional checks for file path to avoid `open_basedir` restrictions;
|
75 |
+
* Fix: added titles for the Replace Media and Remove Background screens;
|
76 |
+
* Fix: various small CSS/JS fixes, wording updates and code cleanups;
|
77 |
+
|
78 |
= 3.6.3 =
|
79 |
|
80 |
Release date: November 25th, 2021
|
@@ -11,7 +11,12 @@
|
|
11 |
}
|
12 |
}
|
13 |
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
15 |
{
|
16 |
// margin: 15px 0;
|
17 |
padding: 18px;
|
@@ -81,7 +86,7 @@
|
|
81 |
margin-bottom: 10px;
|
82 |
border: 1px solid #ddd;
|
83 |
vertical-align: top;
|
84 |
-
|
85 |
.textlayer
|
86 |
{
|
87 |
font-size: 25px;
|
11 |
}
|
12 |
}
|
13 |
|
14 |
+
.editor-wrapper
|
15 |
+
{
|
16 |
+
width: 100%;
|
17 |
+
}
|
18 |
+
|
19 |
+
.wrapper
|
20 |
{
|
21 |
// margin: 15px 0;
|
22 |
padding: 18px;
|
86 |
margin-bottom: 10px;
|
87 |
border: 1px solid #ddd;
|
88 |
vertical-align: top;
|
89 |
+
// max-height: 500px;
|
90 |
.textlayer
|
91 |
{
|
92 |
font-size: 25px;
|
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#remove-background-form
|
2 |
+
{
|
3 |
+
form {
|
4 |
+
display: flex;
|
5 |
+
|
6 |
+
}
|
7 |
+
.image_chooser.wrapper {
|
8 |
+
min-height: 0;
|
9 |
+
}
|
10 |
+
.image_placeholder.is_image
|
11 |
+
{
|
12 |
+
border:none;
|
13 |
+
width:45%;
|
14 |
+
height:auto;
|
15 |
+
.textlayer, .image_size {
|
16 |
+
display: none;
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
.bad-button
|
21 |
+
{
|
22 |
+
text-align: right;
|
23 |
+
margin-right: 25px;
|
24 |
+
a {
|
25 |
+
visibility: hidden;
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
.overlay{
|
30 |
+
visibility: hidden;
|
31 |
+
display: flex;
|
32 |
+
flex-direction: column;
|
33 |
+
justify-content: center;
|
34 |
+
align-items: center;
|
35 |
+
width: 100%;
|
36 |
+
height: 100%;
|
37 |
+
background-color: rgba(0,0,0,0.2);
|
38 |
+
position: absolute;
|
39 |
+
top: 0;
|
40 |
+
}
|
41 |
+
.lds-spinner {
|
42 |
+
color: official;
|
43 |
+
display: inline-block;
|
44 |
+
position: relative;
|
45 |
+
width: 80px;
|
46 |
+
height: 80px;
|
47 |
+
}
|
48 |
+
.lds-spinner div {
|
49 |
+
transform-origin: 40px 40px;
|
50 |
+
animation: lds-spinner 1.2s linear infinite;
|
51 |
+
}
|
52 |
+
.lds-spinner div:after {
|
53 |
+
content: " ";
|
54 |
+
display: block;
|
55 |
+
position: absolute;
|
56 |
+
top: 3px;
|
57 |
+
left: 37px;
|
58 |
+
width: 6px;
|
59 |
+
height: 18px;
|
60 |
+
border-radius: 20%;
|
61 |
+
background: #fff;
|
62 |
+
}
|
63 |
+
.lds-spinner div:nth-child(1) {
|
64 |
+
transform: rotate(0deg);
|
65 |
+
animation-delay: -1.1s;
|
66 |
+
}
|
67 |
+
.lds-spinner div:nth-child(2) {
|
68 |
+
transform: rotate(30deg);
|
69 |
+
animation-delay: -1s;
|
70 |
+
}
|
71 |
+
.lds-spinner div:nth-child(3) {
|
72 |
+
transform: rotate(60deg);
|
73 |
+
animation-delay: -0.9s;
|
74 |
+
}
|
75 |
+
.lds-spinner div:nth-child(4) {
|
76 |
+
transform: rotate(90deg);
|
77 |
+
animation-delay: -0.8s;
|
78 |
+
}
|
79 |
+
.lds-spinner div:nth-child(5) {
|
80 |
+
transform: rotate(120deg);
|
81 |
+
animation-delay: -0.7s;
|
82 |
+
}
|
83 |
+
.lds-spinner div:nth-child(6) {
|
84 |
+
transform: rotate(150deg);
|
85 |
+
animation-delay: -0.6s;
|
86 |
+
}
|
87 |
+
.lds-spinner div:nth-child(7) {
|
88 |
+
transform: rotate(180deg);
|
89 |
+
animation-delay: -0.5s;
|
90 |
+
}
|
91 |
+
.lds-spinner div:nth-child(8) {
|
92 |
+
transform: rotate(210deg);
|
93 |
+
animation-delay: -0.4s;
|
94 |
+
}
|
95 |
+
.lds-spinner div:nth-child(9) {
|
96 |
+
transform: rotate(240deg);
|
97 |
+
animation-delay: -0.3s;
|
98 |
+
}
|
99 |
+
.lds-spinner div:nth-child(10) {
|
100 |
+
transform: rotate(270deg);
|
101 |
+
animation-delay: -0.2s;
|
102 |
+
}
|
103 |
+
.lds-spinner div:nth-child(11) {
|
104 |
+
transform: rotate(300deg);
|
105 |
+
animation-delay: -0.1s;
|
106 |
+
}
|
107 |
+
.lds-spinner div:nth-child(12) {
|
108 |
+
transform: rotate(330deg);
|
109 |
+
animation-delay: 0s;
|
110 |
+
}
|
111 |
+
@keyframes lds-spinner {
|
112 |
+
0% {
|
113 |
+
opacity: 1;
|
114 |
+
}
|
115 |
+
100% {
|
116 |
+
opacity: 0;
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
|
121 |
+
|
122 |
+
* {
|
123 |
+
box-sizing: border-box;
|
124 |
+
}
|
125 |
+
|
126 |
+
.img-comp-container {
|
127 |
+
position: relative;
|
128 |
+
height: 200px; /*should be the same height as the images*/
|
129 |
+
}
|
130 |
+
|
131 |
+
.img-comp-img {
|
132 |
+
position: absolute;
|
133 |
+
width: auto;
|
134 |
+
height: auto;
|
135 |
+
overflow:hidden;
|
136 |
+
}
|
137 |
+
|
138 |
+
.img-comp-img img {
|
139 |
+
display:block;
|
140 |
+
}
|
141 |
+
|
142 |
+
.img-comp-slider {
|
143 |
+
position: absolute;
|
144 |
+
z-index:9;
|
145 |
+
cursor: ew-resize;
|
146 |
+
/*set the appearance of the slider:*/
|
147 |
+
width: 20px;
|
148 |
+
height: 20px;
|
149 |
+
background-color: #2196F3;
|
150 |
+
opacity: 0.7;
|
151 |
+
border-radius: 50%;
|
152 |
+
}
|
153 |
+
|
154 |
+
.preview-area{
|
155 |
+
display:flex;
|
156 |
+
justify-content: center;
|
157 |
+
align-items: center;
|
158 |
+
width: 100%;
|
159 |
+
height: 100%;
|
160 |
+
}
|
161 |
+
.preview-area h1{
|
162 |
+
color : red !important;
|
163 |
+
}
|
164 |
+
|
165 |
+
}
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace;
|
3 |
+
|
4 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
5 |
+
use EnableMediaReplace\Notices\NoticeController as Notices;
|
6 |
+
use \EnableMediaReplace\Replacer as Replacer;
|
7 |
+
|
8 |
+
|
9 |
+
if (! defined('ABSPATH')) {
|
10 |
+
exit; // Exit if accessed directly.
|
11 |
+
}
|
12 |
+
|
13 |
+
if (! check_admin_referer('do_background_replace'))
|
14 |
+
{
|
15 |
+
wp_die(esc_html__('Nonce in form failed. Go back, refresh and try again.', 'enable-media-replace'));
|
16 |
+
}
|
17 |
+
|
18 |
+
$key = isset($_POST['key']) ? sanitize_text_field($_POST['key']) : null;
|
19 |
+
|
20 |
+
if (is_null($key) || strlen($key) == 0)
|
21 |
+
{
|
22 |
+
wp_die(esc_html__('Error while sending form (no key). Please try again.', 'enable-media-replace'));
|
23 |
+
}
|
24 |
+
|
25 |
+
$post_id = isset($_POST['ID']) ? intval($_POST['ID']) : null; // sanitize, post_id.
|
26 |
+
if (is_null($post_id)) {
|
27 |
+
wp_die(esc_html__('Error in request. Please try again', 'enable-media-replace'));
|
28 |
+
}
|
29 |
+
|
30 |
+
$attachment = get_post($post_id);
|
31 |
+
|
32 |
+
if (! emr()->checkImagePermission($attachment->post_author, $attachment->ID)) {
|
33 |
+
wp_die(esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace'));
|
34 |
+
}
|
35 |
+
|
36 |
+
$uiHelper = emr()->uiHelper();
|
37 |
+
|
38 |
+
$replacer = new Replacer($post_id);
|
39 |
+
$replacer->setMode(\EnableMediaReplace\Replacer::MODE_REPLACE);
|
40 |
+
|
41 |
+
$datetime = current_time('mysql');
|
42 |
+
$replacer->setTimeMode( \EnableMediaReplace\Replacer::TIME_UPDATEMODIFIED, $datetime);
|
43 |
+
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
$api = new Api();
|
48 |
+
$result = $api->handleDownload($key);
|
49 |
+
|
50 |
+
if (! $result->success)
|
51 |
+
{
|
52 |
+
die($result->message);
|
53 |
+
}
|
54 |
+
|
55 |
+
// When are 1-1 replacing.
|
56 |
+
$source = $replacer->getSourceFile();
|
57 |
+
|
58 |
+
$redirect_error = $uiHelper->getFailedRedirect($post_id);
|
59 |
+
$redirect_success = $uiHelper->getSuccesRedirect($post_id);
|
60 |
+
|
61 |
+
if (! file_exists($result->image))
|
62 |
+
{
|
63 |
+
Log::addError('Download File not here', $result->image);
|
64 |
+
exit(__('Temp file does not exist', 'enable-media-replace'));
|
65 |
+
}
|
66 |
+
|
67 |
+
try {
|
68 |
+
$result = $replacer->replaceWith($result->image, $source->getFileName() , true);
|
69 |
+
} catch (\RunTimeException $e) {
|
70 |
+
print_r($e->getMessage());
|
71 |
+
Log::addError($e->getMessage());
|
72 |
+
die;
|
73 |
+
|
74 |
+
}
|
75 |
+
|
76 |
+
if (is_null($result)) {
|
77 |
+
wp_safe_redirect($redirect_error);
|
78 |
+
exit();
|
79 |
+
}
|
80 |
+
|
81 |
+
$noticeController = Notices::getInstance();
|
82 |
+
$notice = Notices::addSuccess('<p>' . __('File successfully replaced', 'enable-media-replace') . '</p>');
|
83 |
+
$notice->is_removable = false;
|
84 |
+
$noticeController->update();
|
85 |
+
|
86 |
+
wp_redirect($redirect_success);
|
87 |
+
exit();
|
@@ -24,13 +24,13 @@ if (!current_user_can('upload_files'))
|
|
24 |
|
25 |
global $wpdb;
|
26 |
|
27 |
-
|
28 |
|
29 |
$table_name = $wpdb->prefix . "posts";
|
30 |
$attachment_id = intval($_GET['attachment_id']);
|
31 |
$attachment = get_post($attachment_id);
|
32 |
|
33 |
-
if (!
|
34 |
{
|
35 |
wp_die( esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace') );
|
36 |
}
|
@@ -38,12 +38,12 @@ if (! $emr->checkImagePermission($attachment->post_author, $attachment_id))
|
|
38 |
$replacer = new Replacer($attachment_id);
|
39 |
|
40 |
$file = $replacer->getSourceFile();
|
41 |
-
$filepath = $file->
|
42 |
$filename = $file->getFileName();
|
43 |
-
$filetype = $file->
|
44 |
$source_mime = get_post_mime_type($attachment_id);
|
45 |
|
46 |
-
$uiHelper =
|
47 |
$uiHelper->setPreviewSizes();
|
48 |
$uiHelper->setSourceSizes($attachment_id);
|
49 |
|
@@ -58,6 +58,8 @@ $defaults = array(
|
|
58 |
);
|
59 |
$settings = get_option('enable_media_replace', $defaults);
|
60 |
|
|
|
|
|
61 |
?>
|
62 |
|
63 |
<div class="wrap emr_upload_form">
|
@@ -76,7 +78,7 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
76 |
|
77 |
<div class='editor-wrapper'>
|
78 |
<section class='image_chooser wrapper'>
|
79 |
-
<div class='section-header'> <?php _e('
|
80 |
|
81 |
<div id="message" class=""><strong><?php printf( esc_html__('NOTE: You are about to replace the media file "%s". There is no undo. Think about it!', "enable-media-replace"), $filename ); ?></strong></div>
|
82 |
|
@@ -87,11 +89,11 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
87 |
<div class='form-error filesize'><p><?php printf(__('%s f %s exceeds the maximum upload size for this site.', 'enable-media-replace'), '<span class="fn">', '</span>'); ?></p>
|
88 |
</div>
|
89 |
|
90 |
-
<div class='form-warning filetype'><p><?php printf(__('
|
91 |
|
92 |
</p></div>
|
93 |
|
94 |
-
<div class='form-warning mimetype'><p><?php printf(__('
|
95 |
|
96 |
<div class='emr_drop_area'>
|
97 |
<div class='drop-wrapper'>
|
@@ -122,12 +124,32 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
122 |
}
|
123 |
?>
|
124 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
</section>
|
127 |
|
128 |
<div class='option-flex-wrapper'>
|
129 |
<section class='replace_type wrapper'>
|
130 |
-
<div class='section-header'> <?php _e('
|
131 |
|
132 |
<?php
|
133 |
// these are also used in externals, for checks.
|
@@ -142,7 +164,7 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
142 |
</label>
|
143 |
|
144 |
<p class="howto">
|
145 |
-
<?php printf( esc_html__("Note: This option requires you to upload a file of the same type (%s) as the
|
146 |
</p>
|
147 |
|
148 |
<p class='form-warning filetype'><?php _e('If you replace the file with a different filetype, this file might become unreadable and / or cause unexpected issues', 'enable-media-replace'); ?>
|
@@ -156,12 +178,12 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
156 |
?>
|
157 |
|
158 |
<div class="option searchreplace <?php echo $searchreplace_disabled ?>">
|
159 |
-
<label for="replace_type_2"><input id="replace_type_2" <?php checked('replace_and_search', $settings['replace_type']) ?> type="radio" name="replace_type" value="replace_and_search" <?php echo $searchreplace_disabled ?> > <?php echo __("Replace the file, use new file name and update all links", "enable-media-replace"); ?>
|
160 |
</label>
|
161 |
|
162 |
-
<p class="howto"><?php printf( esc_html__("Note: If you
|
163 |
|
164 |
-
<!-- <p class="howto"><?php echo esc_html__("Please note that if you upload a new image, only embeds/links of the original size image will be replaced in your posts.", "enable-media-replace"); ?></p> -->
|
165 |
|
166 |
<?php do_action('emr_after_replace_type_options'); ?>
|
167 |
</div>
|
@@ -172,13 +194,13 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
172 |
<div class='option timestamp'>
|
173 |
<?php
|
174 |
$attachment_current_date = date_i18n('d/M/Y H:i', strtotime($attachment->post_date) );
|
175 |
-
$attachment_now_date = date_i18n('d/M/Y H:i'
|
|
|
176 |
$time = current_time('mysql');
|
177 |
$date = $nowDate = new \dateTime($time); // default to now.
|
178 |
-
// var_dump(strtotime($attachment->post_date));
|
179 |
-
// exit();
|
180 |
$attachmentDate = new \dateTime($attachment->post_date);
|
181 |
|
|
|
182 |
if ($settings['timestamp_replace'] == \EnableMediaReplace\Replacer::TIME_CUSTOM)
|
183 |
{
|
184 |
$date = new \dateTime($settings['custom_date']);
|
@@ -186,7 +208,7 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
186 |
?>
|
187 |
<p><?php _e('When replacing the media, do you want to:', 'enable-media-replace'); ?></p>
|
188 |
<ul>
|
189 |
-
<li><label><input type='radio' <?php checked('1', $settings['timestamp_replace']) ?> name='timestamp_replace' value='1' /><?php printf(__('Replace the date with current date %s(%s)%s', 'enable-media-replace'), "<span class='small'>", $attachment_now_date, "</span>") ; ?></label></li>
|
190 |
<li><label><input type='radio' <?php checked('2', $settings['timestamp_replace']) ?> name='timestamp_replace' value='2' /><?php printf(__('Keep the date %s(%s)%s', 'enable-media-replace'), "<span class='small'>", $attachment_current_date, "</span>"); ?></label></li>
|
191 |
<li><label><input type='radio' <?php checked('3', $settings['timestamp_replace']) ?> name='timestamp_replace' value='3' /><?php _e('Set a Custom Date', 'enable-media-replace'); ?></label></li>
|
192 |
</ul>
|
@@ -214,7 +236,7 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
214 |
$subdir = $settings['new_location_dir'];
|
215 |
?>
|
216 |
<div class='location_option'>
|
217 |
-
<label><input type="checkbox" name="new_location" value="1" <?php checked($settings['new_location'], 1); ?> /> <?php _e('
|
218 |
<input type="text" name="location_dir" value="<?php echo $subdir ?>" />
|
219 |
</div>
|
220 |
<?php endif; ?>
|
24 |
|
25 |
global $wpdb;
|
26 |
|
27 |
+
//$emr = EnableMediaReplacePlugin::get();
|
28 |
|
29 |
$table_name = $wpdb->prefix . "posts";
|
30 |
$attachment_id = intval($_GET['attachment_id']);
|
31 |
$attachment = get_post($attachment_id);
|
32 |
|
33 |
+
if (! emr()->checkImagePermission($attachment->post_author, $attachment_id))
|
34 |
{
|
35 |
wp_die( esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace') );
|
36 |
}
|
38 |
$replacer = new Replacer($attachment_id);
|
39 |
|
40 |
$file = $replacer->getSourceFile();
|
41 |
+
$filepath = $file->getFullPath();
|
42 |
$filename = $file->getFileName();
|
43 |
+
$filetype = $file->getExtension();
|
44 |
$source_mime = get_post_mime_type($attachment_id);
|
45 |
|
46 |
+
$uiHelper = emr()->uiHelper();
|
47 |
$uiHelper->setPreviewSizes();
|
48 |
$uiHelper->setSourceSizes($attachment_id);
|
49 |
|
58 |
);
|
59 |
$settings = get_option('enable_media_replace', $defaults);
|
60 |
|
61 |
+
$settings = array_merge($defaults, $settings); // might miss some
|
62 |
+
|
63 |
?>
|
64 |
|
65 |
<div class="wrap emr_upload_form">
|
78 |
|
79 |
<div class='editor-wrapper'>
|
80 |
<section class='image_chooser wrapper'>
|
81 |
+
<div class='section-header'> <?php _e('Select Replacement Media', 'enable-media-replace'); ?></div>
|
82 |
|
83 |
<div id="message" class=""><strong><?php printf( esc_html__('NOTE: You are about to replace the media file "%s". There is no undo. Think about it!', "enable-media-replace"), $filename ); ?></strong></div>
|
84 |
|
89 |
<div class='form-error filesize'><p><?php printf(__('%s f %s exceeds the maximum upload size for this site.', 'enable-media-replace'), '<span class="fn">', '</span>'); ?></p>
|
90 |
</div>
|
91 |
|
92 |
+
<div class='form-warning filetype'><p><?php printf(__('The replacement file does not have the same file type. This can lead to unexpected issues ( %s )', 'enable-media-replace'), '<span class="source_type"></span> - <span class="target_type"></span>'); ?>
|
93 |
|
94 |
</p></div>
|
95 |
|
96 |
+
<div class='form-warning mimetype'><p><?php printf(__('The replacement file type does not seem to be allowed by WordPress. This can lead to unexpected issues')); ?></p></div>
|
97 |
|
98 |
<div class='emr_drop_area'>
|
99 |
<div class='drop-wrapper'>
|
124 |
}
|
125 |
?>
|
126 |
</div>
|
127 |
+
<?php
|
128 |
+
$url = admin_url("upload.php");
|
129 |
+
$url = add_query_arg(array(
|
130 |
+
'page' => 'enable-media-replace/enable-media-replace.php',
|
131 |
+
'action' => 'emr_prepare_remove',
|
132 |
+
'attachment_id' => $attachment_id,
|
133 |
+
), $url);
|
134 |
+
?>
|
135 |
|
136 |
+
<p> </p>
|
137 |
+
<?php if ($uiHelper->isBackgroundRemovable($attachment)): ?>
|
138 |
+
<div>
|
139 |
+
|
140 |
+
<a href="<?php echo wp_nonce_url( $url , 'emr_prepare_remove' ); ?>">
|
141 |
+
<?php _e('New! Click here to remove the background of this image!', 'enable-media-replace'); ?></a>
|
142 |
+
<br>
|
143 |
+
<br>
|
144 |
+
<input type="checkbox" id="remove_after_progress" name="remove_after_progress" value="<?php echo $attachment_id;?>">
|
145 |
+
<label for="remove_after_progress"><?php _e('Remove the background after replacing this image!' ,'enable-media-replace'); ?> </label>
|
146 |
+
</div>
|
147 |
+
<?php endif; ?>
|
148 |
</section>
|
149 |
|
150 |
<div class='option-flex-wrapper'>
|
151 |
<section class='replace_type wrapper'>
|
152 |
+
<div class='section-header'> <?php _e('Replace Options', 'enable-media-replace'); ?></div>
|
153 |
|
154 |
<?php
|
155 |
// these are also used in externals, for checks.
|
164 |
</label>
|
165 |
|
166 |
<p class="howto">
|
167 |
+
<?php printf( esc_html__("Note: This option requires you to upload a file of the same type (%s) as the file you want to replace. The attachment name will remain the same (%s) regardless of what the file you upload is called. If a CDN is used, remember to clear the cache for this image!", "enable-media-replace"), $filetype, $filename ); ?>
|
168 |
</p>
|
169 |
|
170 |
<p class='form-warning filetype'><?php _e('If you replace the file with a different filetype, this file might become unreadable and / or cause unexpected issues', 'enable-media-replace'); ?>
|
178 |
?>
|
179 |
|
180 |
<div class="option searchreplace <?php echo $searchreplace_disabled ?>">
|
181 |
+
<label for="replace_type_2"><input id="replace_type_2" <?php checked('replace_and_search', $settings['replace_type']) ?> type="radio" name="replace_type" value="replace_and_search" <?php echo $searchreplace_disabled ?> > <?php echo __("Replace the file, use the new file name, and update all links", "enable-media-replace"); ?>
|
182 |
</label>
|
183 |
|
184 |
+
<p class="howto"><?php printf( esc_html__("Note: If you enable this option, the name and type of the file you are uploading will replace the old file. All links pointing to the current file (%s) will be updated to point to the new file name. (If other websites link directly to the file, those links will no longer work. Be careful!)", "enable-media-replace"), $filename ); ?></p>
|
185 |
|
186 |
+
<!-- <p class="howto"><?php echo esc_html__("Please note that if you upload a new image, only the embeds/links of the original size image will be replaced in your posts.", "enable-media-replace"); ?></p> -->
|
187 |
|
188 |
<?php do_action('emr_after_replace_type_options'); ?>
|
189 |
</div>
|
194 |
<div class='option timestamp'>
|
195 |
<?php
|
196 |
$attachment_current_date = date_i18n('d/M/Y H:i', strtotime($attachment->post_date) );
|
197 |
+
$attachment_now_date = date_i18n('d/M/Y H:i' );
|
198 |
+
|
199 |
$time = current_time('mysql');
|
200 |
$date = $nowDate = new \dateTime($time); // default to now.
|
|
|
|
|
201 |
$attachmentDate = new \dateTime($attachment->post_date);
|
202 |
|
203 |
+
|
204 |
if ($settings['timestamp_replace'] == \EnableMediaReplace\Replacer::TIME_CUSTOM)
|
205 |
{
|
206 |
$date = new \dateTime($settings['custom_date']);
|
208 |
?>
|
209 |
<p><?php _e('When replacing the media, do you want to:', 'enable-media-replace'); ?></p>
|
210 |
<ul>
|
211 |
+
<li><label><input type='radio' <?php checked('1', $settings['timestamp_replace']) ?> name='timestamp_replace' value='1' /><?php printf(__('Replace the date with the current date %s(%s)%s', 'enable-media-replace'), "<span class='small'>", $attachment_now_date, "</span>") ; ?></label></li>
|
212 |
<li><label><input type='radio' <?php checked('2', $settings['timestamp_replace']) ?> name='timestamp_replace' value='2' /><?php printf(__('Keep the date %s(%s)%s', 'enable-media-replace'), "<span class='small'>", $attachment_current_date, "</span>"); ?></label></li>
|
213 |
<li><label><input type='radio' <?php checked('3', $settings['timestamp_replace']) ?> name='timestamp_replace' value='3' /><?php _e('Set a Custom Date', 'enable-media-replace'); ?></label></li>
|
214 |
</ul>
|
236 |
$subdir = $settings['new_location_dir'];
|
237 |
?>
|
238 |
<div class='location_option'>
|
239 |
+
<label><input type="checkbox" name="new_location" value="1" <?php checked($settings['new_location'], 1); ?> /> <?php _e('Place the newly uploaded file in this folder: ', 'enable-media-replace'); ?></label>
|
240 |
<input type="text" name="location_dir" value="<?php echo $subdir ?>" />
|
241 |
</div>
|
242 |
<?php endif; ?>
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace;
|
3 |
+
|
4 |
+
use EnableMediaReplace\EnableMediaReplacePlugin;
|
5 |
+
use EnableMediaReplace\UIHelper;
|
6 |
+
|
7 |
+
if (! defined('ABSPATH')) {
|
8 |
+
exit; // Exit if accessed directly.
|
9 |
+
}
|
10 |
+
|
11 |
+
$date = new \dateTime();
|
12 |
+
$uiHelper = emr()->uiHelper();
|
13 |
+
|
14 |
+
$attachment_id = intval($_GET['attachment_id']);
|
15 |
+
$attachment = get_post($attachment_id);
|
16 |
+
|
17 |
+
$replacer = new Replacer($attachment_id);
|
18 |
+
|
19 |
+
$file = $replacer->getSourceFile();
|
20 |
+
|
21 |
+
$uiHelper->setPreviewSizes();
|
22 |
+
$uiHelper->setSourceSizes($attachment_id);
|
23 |
+
|
24 |
+
$base_image = $uiHelper->getPreviewImage($attachment_id, $file );
|
25 |
+
$replace_image = $uiHelper->getPreviewImage(-1, $file, array('remove_bg_ui' => true) );
|
26 |
+
|
27 |
+
$formurl = $uiHelper->getFormUrl($attachment_id, 'do_background_replace');
|
28 |
+
$formurl = wp_nonce_url( $formurl, "do_background_replace" );
|
29 |
+
|
30 |
+
$linebreak = '%0D%0A';
|
31 |
+
$linebreak_double = $linebreak . $linebreak;
|
32 |
+
$email_subject = __('Bad remove of background report', 'enable-media-replace');
|
33 |
+
$email_body = sprintf(__('Hello! %s This is a report of a background removal that did not go well %s Url: {url} %s Settings : {settings} %s Thank you! %s', 'enable-media-replace'), $linebreak_double, $linebreak_double, $linebreak, $linebreak_double, $linebreak_double);
|
34 |
+
|
35 |
+
|
36 |
+
$replace_url = add_query_arg(array(
|
37 |
+
'page' => 'enable-media-replace/enable-media-replace.php',
|
38 |
+
'action' => 'media_replace',
|
39 |
+
'attachment_id' => $attachment_id,
|
40 |
+
), admin_url("upload.php"));
|
41 |
+
|
42 |
+
$defaults = array(
|
43 |
+
'bg_type' => 'transparent',
|
44 |
+
'bg_color' => '#ffffff',
|
45 |
+
'bg_transparency' => 100,
|
46 |
+
);
|
47 |
+
$settings = get_option('enable_media_replace', $defaults);
|
48 |
+
|
49 |
+
$settings = array_merge($defaults, $settings); // might miss some
|
50 |
+
?>
|
51 |
+
<div class="wrap emr_upload_form" id="remove-background-form">
|
52 |
+
|
53 |
+
<form id="emr_replace_form" enctype="multipart/form-data" method="POST" action="<?php
|
54 |
+
echo $formurl; ?>" >
|
55 |
+
<input type="hidden" name="ID" value="<?php echo intval($attachment_id); ?>" />
|
56 |
+
<input type='hidden' name='key' value='' />
|
57 |
+
|
58 |
+
<div class="editor-wrapper" >
|
59 |
+
<section class='image_chooser wrapper'>
|
60 |
+
<div class='section-header'> <?php esc_html_e( 'Remove Media Background', 'enable-media-replace' ); ?></div>
|
61 |
+
<div class='image_previews'>
|
62 |
+
<?php echo $base_image; ?>
|
63 |
+
<?php echo $replace_image ?>
|
64 |
+
|
65 |
+
</div>
|
66 |
+
|
67 |
+
<div class='bad-button'>
|
68 |
+
<a href="" data-link="mailto:support@shortpixel.com?subject=<?php echo esc_attr($email_subject) ?>&body=<?php echo esc_attr($email_body) ?>" id="bad-background-link" class="button"><?php esc_html_e('Report bad background removal','enable-media-replace'); ?></a>
|
69 |
+
|
70 |
+
</div>
|
71 |
+
|
72 |
+
</section>
|
73 |
+
|
74 |
+
<p><a href="<?php echo esc_attr(wp_nonce_url($replace_url, 'media_replace')); ?>">Replace this image with another one instead!</a></p>
|
75 |
+
<div class="option-flex-wrapper">
|
76 |
+
<section class="replace_type wrapper">
|
77 |
+
<div class="section-header"><?php esc_html_e('Background Removal Options'); ?></div>
|
78 |
+
<div class="option replace ">
|
79 |
+
<p>
|
80 |
+
<?php esc_html_e('If a CDN is used, remember to clear the cache for this image!', 'enable-media-replace'); ?>
|
81 |
+
</p>
|
82 |
+
<label for="transparent_background">
|
83 |
+
<input id="transparent_background" type="radio" name="background_type" value="transparent" <?php checked('transparent', $settings['bg_type']); ?> >
|
84 |
+
<?php esc_html_e('Transparent/white background', 'enable-media-replace'); ?>
|
85 |
+
</label>
|
86 |
+
<p class="howto">
|
87 |
+
<?php esc_html_e('Returns a transparent background if it is a PNG image, or a white one if it is a JPG image.', 'enable-media-replace'); ?>
|
88 |
+
</p>
|
89 |
+
</div>
|
90 |
+
<div class="option searchreplace">
|
91 |
+
<label for="solid_background">
|
92 |
+
<input id="solid_background" type="radio" name="background_type" value="solid" <?php checked('solid', $settings['bg_type']); ?>>
|
93 |
+
<?php esc_html_e('Solid background', 'enable-media-replace'); ?>
|
94 |
+
</label>
|
95 |
+
<p class="howto">
|
96 |
+
<?php esc_html_e('If you select this option, the image will have a solid color background and you can choose the color code from the color picker below.', 'enable-media-replace'); ?>
|
97 |
+
</p>
|
98 |
+
<div id="solid_selecter" style="display:none;">
|
99 |
+
<label for="bg_display_picker">
|
100 |
+
<p><?php esc_html_e('Background Color:','enable-media-replace'); ?> <strong><span style="text-transform: uppercase;" id="color_range"><?php echo esc_attr($settings['bg_color']); ?></span></strong></p>
|
101 |
+
<input type="color" value="<?php echo esc_attr($settings['bg_color']); ?>" name="bg_display_picker" id="bg_display_picker" />
|
102 |
+
<input type="hidden" value="<?php echo esc_attr($settings['bg_color']); ?>" name="bg_color" id="bg_color" />
|
103 |
+
</label>
|
104 |
+
<hr>
|
105 |
+
<label for="bg_transparency">
|
106 |
+
<p><?php esc_html_e('Opacity:', 'enable-media-replace'); ?> <strong><span id="transparency_range"><?php echo esc_attr($settings['bg_transparency']); ?></span>%</strong></p>
|
107 |
+
<input type="range" min="0" max="100" value="<?php echo esc_attr($settings['bg_transparency']); ?>" id="bg_transparency" />
|
108 |
+
</label>
|
109 |
+
</div>
|
110 |
+
</div>
|
111 |
+
</section>
|
112 |
+
|
113 |
+
<!--
|
114 |
+
<section class="options wrapper">
|
115 |
+
|
116 |
+
|
117 |
+
<div class="section-header"><?php esc_html_e('Image Compression', 'enable-media-replace'); ?></div>
|
118 |
+
<div class="option replace">
|
119 |
+
<label for="lossy">
|
120 |
+
<input id="lossy" type="radio" name="compression_level" value="1">
|
121 |
+
<?php esc_html_e('Lossy compression','enable-media-replace'); ?>
|
122 |
+
</label>
|
123 |
+
<p class="howto">
|
124 |
+
<?php esc_html_e('Lossy has a better compression rate than lossless compression. The resulting image is not 100% identical with the original. Works well for photos taken with your camera.', 'enable-media-replace'); ?>
|
125 |
+
</p>
|
126 |
+
</div>
|
127 |
+
<div class="option searchreplace">
|
128 |
+
<label for="glossy">
|
129 |
+
<input id="glossy" type="radio" name="compression_level" value="2">
|
130 |
+
<?php esc_html_e('Glossy compression', 'enable-media-replace'); ?>
|
131 |
+
</label>
|
132 |
+
<p class="howto">
|
133 |
+
<?php esc_html_e('Creates images that are almost pixel-perfect identical to the originals. Best option for photographers and other professionals that use very high quality images on their sites and want best compression while keeping the quality untouched.', 'enable-media-replace'); ?>
|
134 |
+
</p>
|
135 |
+
</div>
|
136 |
+
<div class="option searchreplace">
|
137 |
+
<label for="lossless">
|
138 |
+
<input checked="checked" id="lossless" type="radio" name="compression_level" value="0">
|
139 |
+
<?php esc_html_e('Lossless compression', 'enable-media-replace'); ?>
|
140 |
+
</label>
|
141 |
+
<p class="howto">
|
142 |
+
<?php esc_html_e('The shrunk image will be identical with the original and smaller in size. Use this when you do not want to loose any of the original image\'s details. Works best for technical drawings, clip art and comics.', 'enable-media-replace'); ?>
|
143 |
+
</p>
|
144 |
+
</div>
|
145 |
+
</section> -->
|
146 |
+
</div>
|
147 |
+
<button type="button" class="button button-primary" id="remove_background_button"><?php esc_html_e('Preview', 'enable-media-replace'); ?></button>
|
148 |
+
<button type="submit" class="button button-primary" id="replace_image_button" disabled><?php esc_html_e('Replace', 'enable-media-replace'); ?></button>
|
149 |
+
<a class="button" href="javascript:history.back()"><?php esc_html_e('Cancel', 'enable-media-replace'); ?></a>
|
150 |
+
</div> <!--- editor wrapper -->
|
151 |
+
<?php include_once( 'upsell.php' ); ?>
|
152 |
+
</form>
|
153 |
+
</div>
|
@@ -1,192 +1,189 @@
|
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
|
4 |
-
if (
|
5 |
-
|
|
|
6 |
|
7 |
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
8 |
use EnableMediaReplace\Notices\NoticeController as Notices;
|
9 |
-
|
10 |
-
if (!current_user_can('upload_files'))
|
11 |
-
wp_die( esc_html__('You do not have permission to upload files.', 'enable-media-replace') );
|
12 |
-
|
13 |
-
/*require_once('classes/replacer.php');
|
14 |
-
require_once('classes/file.php'); */
|
15 |
-
|
16 |
use \EnableMediaReplace\Replacer as Replacer;
|
17 |
|
|
|
|
|
|
|
|
|
18 |
// Define DB table names
|
19 |
global $wpdb;
|
20 |
$table_name = $wpdb->prefix . "posts";
|
21 |
$postmeta_table_name = $wpdb->prefix . "postmeta";
|
22 |
|
23 |
// Starts processing.
|
24 |
-
$uihelper =
|
25 |
-
|
26 |
|
27 |
// Get old guid and filetype from DB
|
28 |
$post_id = isset($_POST['ID']) ? intval($_POST['ID']) : null; // sanitize, post_id.
|
29 |
-
if (is_null($post_id))
|
30 |
-
|
31 |
-
wp_die( esc_html__('Error in request. Please try again', 'enable-media-replace') );
|
32 |
}
|
33 |
$attachment = get_post($post_id);
|
34 |
|
35 |
-
if (!
|
36 |
-
|
|
|
37 |
|
38 |
$replacer = new Replacer($post_id);
|
39 |
|
40 |
// Massage a bunch of vars
|
41 |
$ID = intval($_POST["ID"]); // legacy
|
42 |
$replace_type = isset($_POST["replace_type"]) ? sanitize_text_field($_POST["replace_type"]) : false;
|
43 |
-
$timestamp_replace = intval($_POST['timestamp_replace']);
|
44 |
|
45 |
$redirect_error = $uihelper->getFailedRedirect($post_id);
|
46 |
$redirect_success = $uihelper->getSuccesRedirect($post_id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
$do_new_location = isset($_POST['new_location']) ? sanitize_text_field($_POST['new_location']) : false;
|
49 |
$new_location_dir = isset($_POST['location_dir']) ? sanitize_text_field($_POST['location_dir']) : null;
|
50 |
|
51 |
-
$settings = array(); // save settings and show last loaded.
|
52 |
$settings['replace_type'] = $replace_type;
|
53 |
$settings['timestamp_replace'] = $timestamp_replace;
|
54 |
$settings['new_location'] = $do_new_location;
|
55 |
$settings['new_location_dir'] = $new_location_dir;
|
56 |
|
57 |
-
switch($timestamp_replace)
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
}
|
86 |
-
$datetime = $custom_date->format("Y-m-d H:i:s");
|
87 |
-
$settings['custom_date'] = $datetime;
|
88 |
-
break;
|
89 |
}
|
90 |
|
91 |
update_option('enable_media_replace', $settings, false);
|
92 |
|
93 |
// We have two types: replace / replace_and_search
|
94 |
-
if ($replace_type == 'replace')
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
{
|
109 |
-
wp_safe_redirect($redirect_error);
|
110 |
-
exit();
|
111 |
-
}
|
112 |
-
}
|
113 |
}
|
114 |
|
115 |
$replacer->setTimeMode($timestamp_replace, $datetime);
|
116 |
|
117 |
/** Check if file is uploaded properly **/
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
$newdirfile = $replacer->newTargetLocation($new_location_dir);
|
155 |
-
}
|
156 |
*/
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
//
|
173 |
-
|
174 |
-
// Execute hook actions - thanks rubious for the suggestion!
|
175 |
-
|
176 |
} else {
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
}
|
185 |
|
186 |
-
Notices::
|
|
|
|
|
|
|
187 |
|
188 |
// Allow developers to override $returnurl
|
189 |
//$returnurl = apply_filters('emr_returnurl', $returnurl);
|
190 |
wp_redirect($redirect_success);
|
191 |
exit();
|
192 |
-
?>
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
|
4 |
+
if (! defined('ABSPATH')) {
|
5 |
+
exit; // Exit if accessed directly.
|
6 |
+
}
|
7 |
|
8 |
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
9 |
use EnableMediaReplace\Notices\NoticeController as Notices;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
use \EnableMediaReplace\Replacer as Replacer;
|
11 |
|
12 |
+
if (!current_user_can('upload_files')) {
|
13 |
+
wp_die(esc_html__('You do not have permission to upload files.', 'enable-media-replace'));
|
14 |
+
}
|
15 |
+
|
16 |
// Define DB table names
|
17 |
global $wpdb;
|
18 |
$table_name = $wpdb->prefix . "posts";
|
19 |
$postmeta_table_name = $wpdb->prefix . "postmeta";
|
20 |
|
21 |
// Starts processing.
|
22 |
+
$uihelper = emr()->uiHelper();
|
23 |
+
//$emr = EnableMediaReplacePlugin::get();
|
24 |
|
25 |
// Get old guid and filetype from DB
|
26 |
$post_id = isset($_POST['ID']) ? intval($_POST['ID']) : null; // sanitize, post_id.
|
27 |
+
if (is_null($post_id)) {
|
28 |
+
wp_die(esc_html__('Error in request. Please try again', 'enable-media-replace'));
|
|
|
29 |
}
|
30 |
$attachment = get_post($post_id);
|
31 |
|
32 |
+
if (! emr()->checkImagePermission($attachment->post_author, $attachment->ID)) {
|
33 |
+
wp_die(esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace'));
|
34 |
+
}
|
35 |
|
36 |
$replacer = new Replacer($post_id);
|
37 |
|
38 |
// Massage a bunch of vars
|
39 |
$ID = intval($_POST["ID"]); // legacy
|
40 |
$replace_type = isset($_POST["replace_type"]) ? sanitize_text_field($_POST["replace_type"]) : false;
|
41 |
+
$timestamp_replace = isset($_POST['timestamp_replace']) ? intval($_POST['timestamp_replace']) : Replacer::TIME_UPDATEMODIFIED;
|
42 |
|
43 |
$redirect_error = $uihelper->getFailedRedirect($post_id);
|
44 |
$redirect_success = $uihelper->getSuccesRedirect($post_id);
|
45 |
+
if ( isset( $_POST['remove_after_progress'] ) ) {
|
46 |
+
$url = admin_url("upload.php");
|
47 |
+
$url = add_query_arg(array(
|
48 |
+
'page' => 'enable-media-replace/enable-media-replace.php',
|
49 |
+
'action' => 'emr_prepare_remove',
|
50 |
+
'attachment_id' => $ID,
|
51 |
+
'_wpnonce' => wp_create_nonce('emr_prepare_remove')
|
52 |
+
), $url);
|
53 |
+
|
54 |
+
$redirect_success = $url;
|
55 |
+
}
|
56 |
|
57 |
$do_new_location = isset($_POST['new_location']) ? sanitize_text_field($_POST['new_location']) : false;
|
58 |
$new_location_dir = isset($_POST['location_dir']) ? sanitize_text_field($_POST['location_dir']) : null;
|
59 |
|
60 |
+
$settings = get_option('enable_media_replace', array()); // save settings and show last loaded.
|
61 |
$settings['replace_type'] = $replace_type;
|
62 |
$settings['timestamp_replace'] = $timestamp_replace;
|
63 |
$settings['new_location'] = $do_new_location;
|
64 |
$settings['new_location_dir'] = $new_location_dir;
|
65 |
|
66 |
+
switch ($timestamp_replace) {
|
67 |
+
case \EnableMediaReplace\Replacer::TIME_UPDATEALL:
|
68 |
+
case \EnableMediaReplace\Replacer::TIME_UPDATEMODIFIED:
|
69 |
+
$datetime = current_time('mysql');
|
70 |
+
break;
|
71 |
+
case \EnableMediaReplace\Replacer::TIME_CUSTOM:
|
72 |
+
$custom_date = $_POST['custom_date_formatted'];
|
73 |
+
$custom_hour = str_pad($_POST['custom_hour'], 2, 0, STR_PAD_LEFT);
|
74 |
+
$custom_minute = str_pad($_POST['custom_minute'], 2, 0, STR_PAD_LEFT);
|
75 |
+
|
76 |
+
// create a mysql time representation from what we have.
|
77 |
+
Log::addDebug($_POST);
|
78 |
+
Log::addDebug('Custom Date - ' . $custom_date . ' ' . $custom_hour . ':' . $custom_minute);
|
79 |
+
$custom_date = \DateTime::createFromFormat('Y-m-d G:i', $custom_date . ' ' . $custom_hour . ':' . $custom_minute);
|
80 |
+
if ($custom_date === false) {
|
81 |
+
wp_safe_redirect($redirect_error);
|
82 |
+
$errors = \DateTime::getLastErrors();
|
83 |
+
$error = '';
|
84 |
+
if (isset($errors['errors'])) {
|
85 |
+
$error = implode(',', $errors['errors']);
|
86 |
+
}
|
87 |
+
Notices::addError(sprintf(__('Invalid Custom Date. Please check the custom date values: (%s)', 'enable-media-replace'), $error));
|
88 |
+
|
89 |
+
exit();
|
90 |
+
}
|
91 |
+
$datetime = $custom_date->format("Y-m-d H:i:s");
|
92 |
+
$settings['custom_date'] = $datetime;
|
93 |
+
break;
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
|
96 |
update_option('enable_media_replace', $settings, false);
|
97 |
|
98 |
// We have two types: replace / replace_and_search
|
99 |
+
if ($replace_type == 'replace') {
|
100 |
+
$replacer->setMode(\EnableMediaReplace\Replacer::MODE_REPLACE);
|
101 |
+
$mode = \EnableMediaReplace\Replacer::MODE_REPLACE;
|
102 |
+
} elseif ('replace_and_search' == $replace_type && apply_filters('emr_enable_replace_and_search', true)) {
|
103 |
+
$replacer->setMode(\EnableMediaReplace\Replacer::MODE_SEARCHREPLACE);
|
104 |
+
$mode = \EnableMediaReplace\Replacer::MODE_SEARCHREPLACE;
|
105 |
+
|
106 |
+
if ($do_new_location && ! is_null($new_location_dir)) {
|
107 |
+
$result = $replacer->setNewTargetLocation($new_location_dir);
|
108 |
+
if (! $result) {
|
109 |
+
wp_safe_redirect($redirect_error);
|
110 |
+
exit();
|
111 |
+
}
|
112 |
+
}
|
|
|
|
|
|
|
|
|
|
|
113 |
}
|
114 |
|
115 |
$replacer->setTimeMode($timestamp_replace, $datetime);
|
116 |
|
117 |
/** Check if file is uploaded properly **/
|
118 |
+
// @todo Post remove Bg should be removed.
|
119 |
+
if (is_uploaded_file($_FILES["userfile"]["tmp_name"]) || isset($_POST["remove_bg"])) {
|
120 |
+
Log::addDebug($_FILES['userfile']);
|
121 |
+
|
122 |
+
// New method for validating that the uploaded file is allowed, using WP:s internal wp_check_filetype_and_ext() function.
|
123 |
+
$filedata = wp_check_filetype_and_ext($_FILES["userfile"]["tmp_name"], $_FILES["userfile"]["name"]);
|
124 |
+
|
125 |
+
Log::addDebug('Data after check', $filedata);
|
126 |
+
if (isset($_FILES['userfile']['error']) && $_FILES['userfile']['error'] > 0) {
|
127 |
+
$e = new RunTimeException('File Uploaded Failed');
|
128 |
+
Notices::addError($e->getMessage());
|
129 |
+
wp_safe_redirect($redirect_error);
|
130 |
+
exit();
|
131 |
+
}
|
132 |
+
|
133 |
+
|
134 |
+
if ($filedata["ext"] == false && ! current_user_can('unfiltered_upload') && ! isset($_POST["remove_bg"])) {
|
135 |
+
Notices::addError(esc_html__("File type does not meet security guidelines. Try another.", 'enable-media-replace'));
|
136 |
+
wp_safe_redirect($redirect_error);
|
137 |
+
exit();
|
138 |
+
}
|
139 |
+
|
140 |
+
// Here we have the uploaded file
|
141 |
+
$new_filename = $_FILES["userfile"]["name"];
|
142 |
+
//$new_filesize = $_FILES["userfile"]["size"]; // Seems not to be in use.
|
143 |
+
$new_filetype = $filedata["type"] ? $filedata["type"] : $_FILES['userfile']['type'];
|
144 |
+
|
145 |
+
// Gather all functions that both options do.
|
146 |
+
do_action('wp_handle_replace', array('post_id' => $post_id));
|
147 |
+
|
148 |
+
|
149 |
+
/* if ($mode = \EnableMediaReplace\Replacer::MODE_SEARCHREPLACE && $do_new_location && ! is_null($new_location_dir))
|
150 |
+
{
|
151 |
+
exit($new_filename);
|
152 |
+
$newdirfile = $replacer->newTargetLocation($new_location_dir);
|
153 |
+
}
|
|
|
|
|
154 |
*/
|
155 |
+
try {
|
156 |
+
$result = $replacer->replaceWith($_FILES["userfile"]["tmp_name"], $new_filename , isset($_POST["remove_bg"]));
|
157 |
+
} catch (\RunTimeException $e) {
|
158 |
+
var_dump($e->getMessage());
|
159 |
+
die;
|
160 |
+
Log::addError($e->getMessage());
|
161 |
+
// exit($e->getMessage());
|
162 |
+
}
|
163 |
+
|
164 |
+
if (is_null($result)) {
|
165 |
+
wp_safe_redirect($redirect_error);
|
166 |
+
exit();
|
167 |
+
}
|
168 |
+
// $returnurl = admin_url("/post.php?post={$_POST["ID"]}&action=edit&message=1");
|
169 |
+
|
170 |
+
// Execute hook actions - thanks rubious for the suggestion!
|
|
|
|
|
|
|
171 |
} else {
|
172 |
+
//TODO Better error handling when no file is selected.
|
173 |
+
//For now just go back to media management
|
174 |
+
//$returnurl = admin_url("upload.php");
|
175 |
+
Log::addInfo('Failed. Redirecting - '. $redirect_error);
|
176 |
+
Notices::addError(__('File Upload seems to have failed. No files were returned by system', 'enable-media-replace'));
|
177 |
+
wp_safe_redirect($redirect_error);
|
178 |
+
exit();
|
179 |
}
|
180 |
|
181 |
+
$noticeController = Notices::getInstance();
|
182 |
+
$notice = Notices::addSuccess('<p>' . __('File successfully replaced', 'enable-media-replace') . '</p>');
|
183 |
+
$notice->is_removable = false;
|
184 |
+
$noticeController->update();
|
185 |
|
186 |
// Allow developers to override $returnurl
|
187 |
//$returnurl = apply_filters('emr_returnurl', $returnurl);
|
188 |
wp_redirect($redirect_success);
|
189 |
exit();
|
|
@@ -36,7 +36,7 @@ if (! apply_filters('emr/upsell', current_user_can('install_plugins')))
|
|
36 |
|
37 |
<div class='shortpixel-offer spio'>
|
38 |
<div class='img-wrapper'>
|
39 |
-
<img width="40" height="40" src="<?php echo
|
40 |
</div>
|
41 |
<h4 class="grey">
|
42 |
<?php echo esc_html__("ShortPixel Image Optimizer", "enable-media-replace"); ?>
|
@@ -69,7 +69,7 @@ if (! apply_filters('emr/upsell', current_user_can('install_plugins')))
|
|
69 |
|
70 |
<div class='shortpixel-offer spai'>
|
71 |
<div class='img-wrapper'>
|
72 |
-
<img width="40" height="40" src="<?php echo
|
73 |
</div>
|
74 |
<h4 class="grey">
|
75 |
<?php echo esc_html__("ShortPixel Adaptive Images", "enable-media-replace"); ?>
|
@@ -100,7 +100,7 @@ if (! apply_filters('emr/upsell', current_user_can('install_plugins')))
|
|
100 |
|
101 |
<!--- WPSO -->
|
102 |
<div class='shortpixel-offer site-speed'>
|
103 |
-
<p class='img-wrapper'><img width="40" height="40" src="<?php echo
|
104 |
<h3><?php printf(__('GET AN ASSESSMENT FOR %s YOUR WEBSITE %s AND %s %s FIND OUT HOW TO MAKE IT FASTER %s', 'enable-media-replace'),'<br>', '<br>','<br>', '<span class="red">','</span>'); ?></h3>
|
105 |
|
106 |
<p class='button-wrapper'><a href='https://wso.shortpixel.com/?utm_source=EMR' target="_blank"><?php _e('FIND OUT MORE', 'enable-media-replace') ?></a></p>
|
@@ -111,7 +111,7 @@ if (! apply_filters('emr/upsell', current_user_can('install_plugins')))
|
|
111 |
<?php if (! $envira_pro_active): ?>
|
112 |
<div class='envira-shortpixel-install shortpixel-offer'>
|
113 |
|
114 |
-
<p class='img-wrapper'><img src="<?php echo
|
115 |
<p><?php esc_html_e('Create beautiful, fast-loading photo & video galleries for your site in minutes.', 'enable-media-replace' ); ?></p>
|
116 |
|
117 |
<?php
|
36 |
|
37 |
<div class='shortpixel-offer spio'>
|
38 |
<div class='img-wrapper'>
|
39 |
+
<img width="40" height="40" src="<?php echo emr()->getPluginURL('img/sp-logo-regular.svg') ?>" alt="ShortPixel">
|
40 |
</div>
|
41 |
<h4 class="grey">
|
42 |
<?php echo esc_html__("ShortPixel Image Optimizer", "enable-media-replace"); ?>
|
69 |
|
70 |
<div class='shortpixel-offer spai'>
|
71 |
<div class='img-wrapper'>
|
72 |
+
<img width="40" height="40" src="<?php echo emr()->getPluginURL('img/spai-logo.svg') ?>" alt="ShortPixel">
|
73 |
</div>
|
74 |
<h4 class="grey">
|
75 |
<?php echo esc_html__("ShortPixel Adaptive Images", "enable-media-replace"); ?>
|
100 |
|
101 |
<!--- WPSO -->
|
102 |
<div class='shortpixel-offer site-speed'>
|
103 |
+
<p class='img-wrapper'><img width="40" height="40" src="<?php echo emr()->getPluginURL('img/sp-logo-wink.svg'); ?>" alt='ShortPixel'></p>
|
104 |
<h3><?php printf(__('GET AN ASSESSMENT FOR %s YOUR WEBSITE %s AND %s %s FIND OUT HOW TO MAKE IT FASTER %s', 'enable-media-replace'),'<br>', '<br>','<br>', '<span class="red">','</span>'); ?></h3>
|
105 |
|
106 |
<p class='button-wrapper'><a href='https://wso.shortpixel.com/?utm_source=EMR' target="_blank"><?php _e('FIND OUT MORE', 'enable-media-replace') ?></a></p>
|
111 |
<?php if (! $envira_pro_active): ?>
|
112 |
<div class='envira-shortpixel-install shortpixel-offer'>
|
113 |
|
114 |
+
<p class='img-wrapper'><img src="<?php echo emr()->getPluginURL('img/envira-logo.png'); ?>" alt='Envira Gallery'></p>
|
115 |
<p><?php esc_html_e('Create beautiful, fast-loading photo & video galleries for your site in minutes.', 'enable-media-replace' ); ?></p>
|
116 |
|
117 |
<?php
|