Version Description
Release date: 18th February 2020 * Fixes for WP 5.3+ -scaled images system. Will now replace those as well. * Updating and replacing images and thumbnails should now work for serialized (and such) metadata. - For Beaver Builder * Add extra warning if mimetype is not allowed by WordPress for upload * Put Javascript version in wp_register_script * Hidden double 'replace media' * Replace Image label to Replace Media * Removed constant S3_UPLOADS_AUTOENABLE * Improved detection of SVG image sizes * Fixed - Logger doesn't call wp_upload_dir when not debugging * Extra - Javascript tries to resume after external errors. * Language 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted
Download this release
Release Info
Developer | ShortPixel |
Plugin | Enable Media Replace |
Version | 3.3.8 |
Comparing to | |
See all releases |
Code changes from version 3.3.7 to 3.3.8
- build/shortpixel/log/composer.json +1 -1
- build/shortpixel/log/src/ShortPixelLogger.php +30 -23
- build/shortpixel/notices/composer.json +1 -1
- build/shortpixel/notices/src/NoticeController.php +134 -12
- build/shortpixel/notices/src/NoticeModel.php +79 -6
- classes/emr-plugin.php +34 -8
- classes/externals.php +2 -2
- classes/functions.php +1 -1
- classes/replacer.php +312 -38
- classes/uihelper.php +45 -3
- css/edit_attachment.css +3 -3
- enable-media-replace.php +4 -2
- js/emr_admin.js +43 -5
- readme.txt +18 -2
- scss/edit_attachment.scss +2 -1
- thumbnail_updater.php +0 -3
- views/popup.php +12 -4
- views/upload.php +3 -18
build/shortpixel/log/composer.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
{
|
2 |
"name": "shortpixel/log",
|
3 |
"description": "ShortPixel Logging",
|
4 |
-
"version": "1.1.
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
1 |
{
|
2 |
"name": "shortpixel/log",
|
3 |
"description": "ShortPixel Logging",
|
4 |
+
"version": "1.1.3",
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
build/shortpixel/log/src/ShortPixelLogger.php
CHANGED
@@ -49,12 +49,6 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
49 |
$ns = __NAMESPACE__;
|
50 |
$this->namespace = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
|
51 |
|
52 |
-
if ($this->logPath === false)
|
53 |
-
{
|
54 |
-
$upload_dir = wp_upload_dir(null,false,false);
|
55 |
-
$this->logPath = $this->setLogPath($upload_dir['basedir'] . '/' . $this->namespace . ".log");
|
56 |
-
}
|
57 |
-
|
58 |
if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants
|
59 |
{
|
60 |
$this->is_manual_request = true;
|
@@ -88,12 +82,14 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
88 |
|
89 |
}
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
97 |
|
98 |
if ($this->is_active && count($this->hooks) > 0)
|
99 |
$this->monitorHooks();
|
@@ -132,26 +128,33 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
132 |
{
|
133 |
$this->logPath = $logPath;
|
134 |
}
|
135 |
-
protected
|
136 |
{
|
137 |
-
|
138 |
|
139 |
-
// don't log anything too low.
|
140 |
-
if ($
|
141 |
{
|
142 |
return;
|
143 |
}
|
144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
$arg = array();
|
146 |
$args['level'] = $level;
|
147 |
$args['data'] = $data;
|
148 |
|
149 |
$newItem = new DebugItem($message, $args);
|
150 |
-
$
|
151 |
|
152 |
-
if ($
|
153 |
{
|
154 |
-
$
|
155 |
}
|
156 |
}
|
157 |
|
@@ -225,22 +228,26 @@ namespace EnableMediaReplace\ShortPixelLogger;
|
|
225 |
public static function addError($message, $args = array())
|
226 |
{
|
227 |
$level = DebugItem::LEVEL_ERROR;
|
228 |
-
|
|
|
229 |
}
|
230 |
public static function addWarn($message, $args = array())
|
231 |
{
|
232 |
$level = DebugItem::LEVEL_WARN;
|
233 |
-
|
|
|
234 |
}
|
235 |
public static function addInfo($message, $args = array())
|
236 |
{
|
237 |
$level = DebugItem::LEVEL_INFO;
|
238 |
-
|
|
|
239 |
}
|
240 |
public static function addDebug($message, $args = array())
|
241 |
{
|
242 |
$level = DebugItem::LEVEL_DEBUG;
|
243 |
-
|
|
|
244 |
}
|
245 |
|
246 |
public static function logLevel($level)
|
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;
|
82 |
|
83 |
}
|
84 |
|
85 |
+
if ($this->is_active)
|
86 |
+
{
|
87 |
+
/* On Early init, this function might not exist, then queue it when needed */
|
88 |
+
if (! function_exists('wp_get_current_user'))
|
89 |
+
add_action('init', array($this, 'initView'));
|
90 |
+
else
|
91 |
+
$this->initView();
|
92 |
+
}
|
93 |
|
94 |
if ($this->is_active && count($this->hooks) > 0)
|
95 |
$this->monitorHooks();
|
128 |
{
|
129 |
$this->logPath = $logPath;
|
130 |
}
|
131 |
+
protected function addLog($message, $level, $data = array())
|
132 |
{
|
133 |
+
// $log = self::getInstance();
|
134 |
|
135 |
+
// don't log anything too low or when not active.
|
136 |
+
if ($this->logLevel < $level || ! $this->is_active)
|
137 |
{
|
138 |
return;
|
139 |
}
|
140 |
|
141 |
+
// Check where to log to.
|
142 |
+
if ($this->logPath === false)
|
143 |
+
{
|
144 |
+
$upload_dir = wp_upload_dir(null,false,false);
|
145 |
+
$this->logPath = $this->setLogPath($upload_dir['basedir'] . '/' . $this->namespace . ".log");
|
146 |
+
}
|
147 |
+
|
148 |
$arg = array();
|
149 |
$args['level'] = $level;
|
150 |
$args['data'] = $data;
|
151 |
|
152 |
$newItem = new DebugItem($message, $args);
|
153 |
+
$this->items[] = $newItem;
|
154 |
|
155 |
+
if ($this->is_active)
|
156 |
{
|
157 |
+
$this->write($newItem);
|
158 |
}
|
159 |
}
|
160 |
|
228 |
public static function addError($message, $args = array())
|
229 |
{
|
230 |
$level = DebugItem::LEVEL_ERROR;
|
231 |
+
$log = self::getInstance();
|
232 |
+
$log->addLog($message, $level, $args);
|
233 |
}
|
234 |
public static function addWarn($message, $args = array())
|
235 |
{
|
236 |
$level = DebugItem::LEVEL_WARN;
|
237 |
+
$log = self::getInstance();
|
238 |
+
$log->addLog($message, $level, $args);
|
239 |
}
|
240 |
public static function addInfo($message, $args = array())
|
241 |
{
|
242 |
$level = DebugItem::LEVEL_INFO;
|
243 |
+
$log = self::getInstance();
|
244 |
+
$log->addLog($message, $level, $args);
|
245 |
}
|
246 |
public static function addDebug($message, $args = array())
|
247 |
{
|
248 |
$level = DebugItem::LEVEL_DEBUG;
|
249 |
+
$log = self::getInstance();
|
250 |
+
$log->addLog($message, $level, $args);
|
251 |
}
|
252 |
|
253 |
public static function logLevel($level)
|
build/shortpixel/notices/composer.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
{
|
2 |
"name": "shortpixel/notices",
|
3 |
"description": "ShortPixel WordPress Notice System",
|
4 |
-
"version": "1.
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
1 |
{
|
2 |
"name": "shortpixel/notices",
|
3 |
"description": "ShortPixel WordPress Notice System",
|
4 |
+
"version": "1.3",
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
build/shortpixel/notices/src/NoticeController.php
CHANGED
@@ -8,6 +8,8 @@ class NoticeController //extends ShortPixelController
|
|
8 |
protected static $instance = null;
|
9 |
protected static $cssHookLoaded = false; // prevent css output more than once.
|
10 |
|
|
|
|
|
11 |
public $notice_count = 0;
|
12 |
|
13 |
protected $has_stored = false;
|
@@ -22,16 +24,29 @@ class NoticeController //extends ShortPixelController
|
|
22 |
$ns = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
|
23 |
$this->notice_option = $ns . '-notices';
|
24 |
|
|
|
|
|
25 |
$this->loadNotices();
|
26 |
//$this->loadConfig();
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
/** Load Notices Config File, if any
|
30 |
*
|
31 |
* [ Future Use ]
|
32 |
*/
|
33 |
public function loadConfig()
|
34 |
{
|
|
|
35 |
if (file_exists('../notice_config.json'))
|
36 |
{
|
37 |
$config = file_get_contents('../notice_config.json');
|
@@ -50,8 +65,10 @@ class NoticeController //extends ShortPixelController
|
|
50 |
{
|
51 |
$notices = get_option($this->notice_option, false);
|
52 |
$cnotice = (is_array($notices)) ? count($notices) : 0;
|
53 |
-
|
54 |
-
|
|
|
|
|
55 |
{
|
56 |
self::$notices = $notices;
|
57 |
$this->has_stored = true;
|
@@ -64,7 +81,7 @@ class NoticeController //extends ShortPixelController
|
|
64 |
}
|
65 |
|
66 |
|
67 |
-
|
68 |
{
|
69 |
$notice = new NoticeModel($message, $code);
|
70 |
|
@@ -73,7 +90,7 @@ class NoticeController //extends ShortPixelController
|
|
73 |
foreach(self::$notices as $nitem)
|
74 |
{
|
75 |
if ($nitem->message == $notice->message && $nitem->code == $notice->code) // same message.
|
76 |
-
return
|
77 |
}
|
78 |
}
|
79 |
self::$notices[] = $notice;
|
@@ -118,17 +135,97 @@ class NoticeController //extends ShortPixelController
|
|
118 |
|
119 |
public function getNotices()
|
120 |
{
|
121 |
-
|
122 |
}
|
123 |
|
124 |
-
public
|
125 |
{
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
|
|
130 |
|
131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
}
|
133 |
|
134 |
/** Adds a notice, quick and fast method
|
@@ -170,6 +267,30 @@ class NoticeController //extends ShortPixelController
|
|
170 |
|
171 |
}
|
172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
public function admin_notices()
|
174 |
{
|
175 |
if ($this->countNotices() > 0)
|
@@ -179,7 +300,7 @@ class NoticeController //extends ShortPixelController
|
|
179 |
add_action('admin_print_footer_scripts', array($this, 'printNoticeStyle'));
|
180 |
self::$cssHookLoaded = true;
|
181 |
}
|
182 |
-
foreach($this->
|
183 |
{
|
184 |
echo $notice->getForDisplay();
|
185 |
}
|
@@ -187,6 +308,7 @@ class NoticeController //extends ShortPixelController
|
|
187 |
$this->update(); // puts views, and updates
|
188 |
}
|
189 |
|
|
|
190 |
public function printNoticeStyle()
|
191 |
{
|
192 |
if (file_exists(__DIR__ . '/css/notices.css'))
|
8 |
protected static $instance = null;
|
9 |
protected static $cssHookLoaded = false; // prevent css output more than once.
|
10 |
|
11 |
+
protected $notice_displayed = array();
|
12 |
+
|
13 |
public $notice_count = 0;
|
14 |
|
15 |
protected $has_stored = false;
|
24 |
$ns = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
|
25 |
$this->notice_option = $ns . '-notices';
|
26 |
|
27 |
+
add_action('wp_ajax_' . $this->notice_option, array($this, 'ajax_action'));
|
28 |
+
|
29 |
$this->loadNotices();
|
30 |
//$this->loadConfig();
|
31 |
}
|
32 |
|
33 |
+
public static function getInstance()
|
34 |
+
{
|
35 |
+
if ( self::$instance === null)
|
36 |
+
{
|
37 |
+
self::$instance = new NoticeController();
|
38 |
+
}
|
39 |
+
|
40 |
+
return self::$instance;
|
41 |
+
}
|
42 |
+
|
43 |
/** Load Notices Config File, if any
|
44 |
*
|
45 |
* [ Future Use ]
|
46 |
*/
|
47 |
public function loadConfig()
|
48 |
{
|
49 |
+
return;
|
50 |
if (file_exists('../notice_config.json'))
|
51 |
{
|
52 |
$config = file_get_contents('../notice_config.json');
|
65 |
{
|
66 |
$notices = get_option($this->notice_option, false);
|
67 |
$cnotice = (is_array($notices)) ? count($notices) : 0;
|
68 |
+
if ($cnotice > 0)
|
69 |
+
Log::addDebug('Notice Control - #num notices' . $cnotice);
|
70 |
+
|
71 |
+
if ($notices !== false && is_array($notices))
|
72 |
{
|
73 |
self::$notices = $notices;
|
74 |
$this->has_stored = true;
|
81 |
}
|
82 |
|
83 |
|
84 |
+
protected function addNotice($message, $code, $unique)
|
85 |
{
|
86 |
$notice = new NoticeModel($message, $code);
|
87 |
|
90 |
foreach(self::$notices as $nitem)
|
91 |
{
|
92 |
if ($nitem->message == $notice->message && $nitem->code == $notice->code) // same message.
|
93 |
+
return $notice; // return the notice with the same message.
|
94 |
}
|
95 |
}
|
96 |
self::$notices[] = $notice;
|
135 |
|
136 |
public function getNotices()
|
137 |
{
|
138 |
+
return self::$notices;
|
139 |
}
|
140 |
|
141 |
+
public function getNoticesForDisplay()
|
142 |
{
|
143 |
+
$newNotices = array();
|
144 |
+
foreach(self::$notices as $notice)
|
145 |
+
{
|
146 |
+
if ($notice->isDismissed()) // dismissed never displays.
|
147 |
+
continue;
|
148 |
|
149 |
+
if ($notice->isPersistent())
|
150 |
+
{
|
151 |
+
$id = $notice->getID();
|
152 |
+
if (! is_null($id) && ! in_array($id, $this->notice_displayed))
|
153 |
+
{
|
154 |
+
$notice->notice_action = $this->notice_option;
|
155 |
+
$newNotices[] = $notice;
|
156 |
+
$this->notice_displayed[] = $id;
|
157 |
+
}
|
158 |
+
|
159 |
+
}
|
160 |
+
else
|
161 |
+
$newNotices[] = $notice;
|
162 |
+
|
163 |
+
|
164 |
+
}
|
165 |
+
return $newNotices;
|
166 |
+
}
|
167 |
+
|
168 |
+
|
169 |
+
public function getNoticeByID($id)
|
170 |
+
{
|
171 |
+
foreach(self::$notices as $notice)
|
172 |
+
{
|
173 |
+
if ($notice->getID() == $id)
|
174 |
+
return $notice;
|
175 |
+
}
|
176 |
+
|
177 |
+
return false;
|
178 |
+
}
|
179 |
+
|
180 |
+
public static function removeNoticeByID($id)
|
181 |
+
{
|
182 |
+
$noticeController = self::getInstance();
|
183 |
+
|
184 |
+
for($i = 0; $i < count(self::$notices); $i++)
|
185 |
+
{
|
186 |
+
$item = self::$notices[$i];
|
187 |
+
if ($item->getID() == $id)
|
188 |
+
{
|
189 |
+
Log::addDebug('Removing notice with ID ' . $id);
|
190 |
+
unset(self::$notices[$i]);
|
191 |
+
}
|
192 |
+
//if ($notice_item )
|
193 |
+
}
|
194 |
+
$noticeController->update();
|
195 |
+
}
|
196 |
+
|
197 |
+
public function ajax_action()
|
198 |
+
{
|
199 |
+
$response = array('result' => false, 'reason' => '');
|
200 |
+
|
201 |
+
if ( wp_verify_nonce( $_POST['nonce'], 'dismiss') )
|
202 |
+
{
|
203 |
+
if ($_POST['plugin_action'] == 'dismiss')
|
204 |
+
{
|
205 |
+
$id = sanitize_text_field($_POST['id']);
|
206 |
+
$notice = $this->getNoticeByID($id);
|
207 |
+
|
208 |
+
if($notice)
|
209 |
+
{
|
210 |
+
$notice->dismiss();
|
211 |
+
$this->update();
|
212 |
+
$response['result'] = true;
|
213 |
+
}
|
214 |
+
else
|
215 |
+
{
|
216 |
+
Log::addError('Notice not found when dismissing -> ' . $id, self::$notices);
|
217 |
+
$response['result'] = ' Notice ' . $id . ' not found. ';
|
218 |
+
}
|
219 |
+
|
220 |
+
}
|
221 |
+
|
222 |
+
}
|
223 |
+
else
|
224 |
+
{
|
225 |
+
Log::addError('Wrong Nonce when dismissed notice. ');
|
226 |
+
$response['reason'] = 'wrong nonce';
|
227 |
+
}
|
228 |
+
wp_send_json($response);
|
229 |
}
|
230 |
|
231 |
/** Adds a notice, quick and fast method
|
267 |
|
268 |
}
|
269 |
|
270 |
+
public static function makePersistent($notice, $key, $suppress = -1)
|
271 |
+
{
|
272 |
+
$noticeController = self::getInstance();
|
273 |
+
$existing = $noticeController->getNoticeByID($key);
|
274 |
+
|
275 |
+
// if this key already exists, don't allow the new notice to be entered into the array. Remove it since it's already created.
|
276 |
+
if ($existing)
|
277 |
+
{
|
278 |
+
for($i = 0; $i < count(self::$notices); $i++)
|
279 |
+
{
|
280 |
+
$item = self::$notices[$i];
|
281 |
+
if ($item->message == $notice->message && $item->getID() == null)
|
282 |
+
unset(self::$notices[$i]);
|
283 |
+
//if ($notice_item )
|
284 |
+
}
|
285 |
+
}
|
286 |
+
else
|
287 |
+
{
|
288 |
+
$notice->setPersistent($key, $suppress); // set this notice persistent.
|
289 |
+
}
|
290 |
+
|
291 |
+
$noticeController->update();
|
292 |
+
}
|
293 |
+
|
294 |
public function admin_notices()
|
295 |
{
|
296 |
if ($this->countNotices() > 0)
|
300 |
add_action('admin_print_footer_scripts', array($this, 'printNoticeStyle'));
|
301 |
self::$cssHookLoaded = true;
|
302 |
}
|
303 |
+
foreach($this->getNoticesForDisplay() as $notice)
|
304 |
{
|
305 |
echo $notice->getForDisplay();
|
306 |
}
|
308 |
$this->update(); // puts views, and updates
|
309 |
}
|
310 |
|
311 |
+
|
312 |
public function printNoticeStyle()
|
313 |
{
|
314 |
if (file_exists(__DIR__ . '/css/notices.css'))
|
build/shortpixel/notices/src/NoticeModel.php
CHANGED
@@ -3,14 +3,20 @@ namespace EnableMediaReplace\Notices;
|
|
3 |
|
4 |
class NoticeModel //extends ShortPixelModel
|
5 |
{
|
6 |
-
public $message;
|
7 |
public $code;
|
8 |
|
9 |
-
|
10 |
-
|
|
|
|
|
|
|
|
|
11 |
public $is_removable = true; // if removable, display a notice dialog with red X or so.
|
12 |
public $messageType = self::NOTICE_NORMAL;
|
13 |
|
|
|
|
|
14 |
public static $icons = array();
|
15 |
|
16 |
const NOTICE_NORMAL = 1;
|
@@ -18,7 +24,7 @@ class NoticeModel //extends ShortPixelModel
|
|
18 |
const NOTICE_SUCCESS = 3;
|
19 |
const NOTICE_WARNING = 4;
|
20 |
|
21 |
-
|
22 |
public function __construct($message, $messageType = self::NOTICE_NORMAL)
|
23 |
{
|
24 |
$this->message = $message;
|
@@ -28,11 +34,53 @@ class NoticeModel //extends ShortPixelModel
|
|
28 |
|
29 |
public function isDone()
|
30 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
if ($this->viewed && ! $this->is_persistent)
|
32 |
return true;
|
33 |
else
|
34 |
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
}
|
37 |
|
38 |
public static function setIcon($notice_type, $icon)
|
@@ -96,12 +144,37 @@ class NoticeModel //extends ShortPixelModel
|
|
96 |
|
97 |
if ($this->is_persistent)
|
98 |
{
|
99 |
-
$class .= '';
|
100 |
}
|
101 |
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
}
|
105 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
}
|
3 |
|
4 |
class NoticeModel //extends ShortPixelModel
|
5 |
{
|
6 |
+
public $message; // The message we want to convey.
|
7 |
public $code;
|
8 |
|
9 |
+
private $id = null; // used for persistent messages.
|
10 |
+
protected $viewed = false; // was this notice viewed?
|
11 |
+
protected $is_persistent = false; // This is a fatal issue, display until something was fixed.
|
12 |
+
protected $is_dismissed = false; // for persistent notices,
|
13 |
+
protected $suppress_until = null;
|
14 |
+
protected $suppress_period = -1;
|
15 |
public $is_removable = true; // if removable, display a notice dialog with red X or so.
|
16 |
public $messageType = self::NOTICE_NORMAL;
|
17 |
|
18 |
+
public $notice_action; // empty unless for display. Ajax action to talk back to controller.
|
19 |
+
|
20 |
public static $icons = array();
|
21 |
|
22 |
const NOTICE_NORMAL = 1;
|
24 |
const NOTICE_SUCCESS = 3;
|
25 |
const NOTICE_WARNING = 4;
|
26 |
|
27 |
+
/** Use this model in conjunction with NoticeController, do not call directly */
|
28 |
public function __construct($message, $messageType = self::NOTICE_NORMAL)
|
29 |
{
|
30 |
$this->message = $message;
|
34 |
|
35 |
public function isDone()
|
36 |
{
|
37 |
+
// check suppressed
|
38 |
+
if ($this->is_dismissed && ! is_null($this->suppress_until))
|
39 |
+
{
|
40 |
+
if (time() >= $this->suppress_until)
|
41 |
+
{
|
42 |
+
//Log::addDebug('')
|
43 |
+
$this->is_persistent = false; // unpersist, so it will be cleaned and dropped.
|
44 |
+
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
if ($this->viewed && ! $this->is_persistent)
|
49 |
return true;
|
50 |
else
|
51 |
return false;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function getID()
|
55 |
+
{
|
56 |
+
return $this->id;
|
57 |
+
}
|
58 |
+
|
59 |
+
public function isPersistent()
|
60 |
+
{
|
61 |
+
return $this->is_persistent;
|
62 |
+
}
|
63 |
+
|
64 |
+
public function isDismissed()
|
65 |
+
{
|
66 |
+
return $this->is_dismissed;
|
67 |
+
}
|
68 |
|
69 |
+
public function dismiss()
|
70 |
+
{
|
71 |
+
$this->is_dismissed = true;
|
72 |
+
$this->suppress_until = time() + $this->suppress_period;
|
73 |
+
}
|
74 |
+
|
75 |
+
/** Set a notice persistent. Meaning it shows every page load until dismissed.
|
76 |
+
* @param $key Unique Key of this message. Required
|
77 |
+
* @param $suppress When dismissed do not show this message again for X amount of time. When -1 it will just be dropped from the Notices and not suppressed
|
78 |
+
*/
|
79 |
+
public function setPersistent($key, $suppress = -1)
|
80 |
+
{
|
81 |
+
$this->id = $key;
|
82 |
+
$this->is_persistent = true;
|
83 |
+
$this->suppress_period = $suppress;
|
84 |
}
|
85 |
|
86 |
public static function setIcon($notice_type, $icon)
|
144 |
|
145 |
if ($this->is_persistent)
|
146 |
{
|
147 |
+
$class .= 'is-persistent ';
|
148 |
}
|
149 |
|
150 |
+
$id = ! is_null($this->id) ? 'id="' . $this->id . '"' : '';
|
151 |
+
|
152 |
+
$output = "<div $id class='$class'><span class='icon'> " . $icon . "</span> <span class='content'>" . $this->message . "</span></div>";
|
153 |
+
if ($this->is_persistent && $this->is_removable)
|
154 |
+
{
|
155 |
+
$output .= "<script type='text/javascript'>\n" . $this->getDismissJS() . "\n</script>";
|
156 |
+
}
|
157 |
+
return $output;
|
158 |
|
159 |
}
|
160 |
|
161 |
+
private function getDismissJS()
|
162 |
+
{
|
163 |
+
$url = wp_json_encode(admin_url('admin-ajax.php'));
|
164 |
+
// $action = 'dismiss';
|
165 |
+
$nonce = wp_create_nonce('dismiss');
|
166 |
+
|
167 |
+
$data = wp_json_encode(array('action' => $this->notice_action, 'plugin_action' => 'dismiss', 'nonce' => $nonce, 'id' => $this->id, 'time' => $this->suppress_period));
|
168 |
+
|
169 |
+
// $data_string = "{action:'$this->notice_action'}";
|
170 |
+
|
171 |
+
$js = "jQuery(document).on('click','#$this->id button',
|
172 |
+
function() {
|
173 |
+
var data = $data;
|
174 |
+
var url = $url;
|
175 |
+
jQuery.post(url, data); }
|
176 |
+
);";
|
177 |
+
return "\n jQuery(document).ready(function(){ \n" . $js . "\n});";
|
178 |
+
}
|
179 |
|
180 |
}
|
classes/emr-plugin.php
CHANGED
@@ -21,10 +21,12 @@ class EnableMediaReplacePlugin
|
|
21 |
self::$instance = new EnableMediaReplacePlugin();
|
22 |
|
23 |
$log = Log::getInstance();
|
24 |
-
|
25 |
-
|
26 |
-
$
|
27 |
-
|
|
|
|
|
28 |
return self::$instance;
|
29 |
}
|
30 |
|
@@ -51,7 +53,7 @@ class EnableMediaReplacePlugin
|
|
51 |
add_action('wp_ajax_emr_dismiss_notices', array($this,'dismiss_notices'));
|
52 |
|
53 |
// editors
|
54 |
-
add_action( 'add_meta_boxes', function () { add_meta_box('emr-
|
55 |
add_filter('attachment_fields_to_edit', array($this, 'attachment_editor'), 10, 2);
|
56 |
|
57 |
// shortcode
|
@@ -63,10 +65,11 @@ class EnableMediaReplacePlugin
|
|
63 |
add_filter('wp_get_attachment_image_src',array($this, 'attempt_uncache_image'), 10, 4);
|
64 |
|
65 |
// adds a metabox to list thumbnails. This is a cache reset hidden as feature.
|
66 |
-
add_action( 'add_meta_boxes', function () { add_meta_box('emr-
|
67 |
-
add_filter('postbox_classes_attachment_emr-
|
68 |
}
|
69 |
|
|
|
70 |
}
|
71 |
|
72 |
/**
|
@@ -149,10 +152,13 @@ class EnableMediaReplacePlugin
|
|
149 |
|
150 |
wp_register_style('emr_edit-attachment', plugins_url('css/edit_attachment.css', EMR_ROOT_FILE));
|
151 |
|
152 |
-
|
|
|
|
|
153 |
$emr_options = array(
|
154 |
'dateFormat' => $this->convertdate(get_option( 'date_format' )),
|
155 |
'maxfilesize' => wp_max_upload_size(),
|
|
|
156 |
|
157 |
);
|
158 |
|
@@ -203,6 +209,7 @@ class EnableMediaReplacePlugin
|
|
203 |
|
204 |
public function replace_meta_box($post)
|
205 |
{
|
|
|
206 |
$url = $this->getMediaReplaceURL($post->ID);
|
207 |
|
208 |
$action = "media_replace";
|
@@ -229,6 +236,20 @@ class EnableMediaReplacePlugin
|
|
229 |
return false;
|
230 |
}
|
231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
foreach($meta['sizes'] as $size => $data)
|
233 |
{
|
234 |
$display_size = ucfirst(str_replace("_", " ", $size));
|
@@ -239,6 +260,10 @@ class EnableMediaReplacePlugin
|
|
239 |
|
240 |
public function attachment_editor($form_fields, $post)
|
241 |
{
|
|
|
|
|
|
|
|
|
242 |
$url = $this->getMediaReplaceURL($post->ID);
|
243 |
$action = "media_replace";
|
244 |
$editurl = wp_nonce_url( $url, $action );
|
@@ -249,6 +274,7 @@ class EnableMediaReplacePlugin
|
|
249 |
"input" => "html",
|
250 |
"html" => "<p><a class='button-secondary' $link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a></p>", "helps" => esc_html__("To replace the current file, click the link and upload a replacement.", "enable-media-replace")
|
251 |
);
|
|
|
252 |
return $form_fields;
|
253 |
}
|
254 |
|
21 |
self::$instance = new EnableMediaReplacePlugin();
|
22 |
|
23 |
$log = Log::getInstance();
|
24 |
+
if (Log::debugIsActive())
|
25 |
+
{
|
26 |
+
$uploaddir = wp_upload_dir(null, false, false);
|
27 |
+
if (isset($uploaddir['basedir']))
|
28 |
+
$log->setLogPath($uploaddir['basedir'] . "/emr_log");
|
29 |
+
}
|
30 |
return self::$instance;
|
31 |
}
|
32 |
|
53 |
add_action('wp_ajax_emr_dismiss_notices', array($this,'dismiss_notices'));
|
54 |
|
55 |
// editors
|
56 |
+
add_action( 'add_meta_boxes', function () { add_meta_box('emr-replace-box', __('Replace Media', 'enable-media-replace'), array($this, 'replace_meta_box'), 'attachment', 'side', 'low'); } );
|
57 |
add_filter('attachment_fields_to_edit', array($this, 'attachment_editor'), 10, 2);
|
58 |
|
59 |
// shortcode
|
65 |
add_filter('wp_get_attachment_image_src',array($this, 'attempt_uncache_image'), 10, 4);
|
66 |
|
67 |
// adds a metabox to list thumbnails. This is a cache reset hidden as feature.
|
68 |
+
add_action( 'add_meta_boxes', function () { add_meta_box('emr-showthumbs-box', __('Replaced Thumbnails Preview', 'enable-media-replace'), array($this, 'show_thumbs_box'), 'attachment', 'side', 'low'); } );
|
69 |
+
add_filter('postbox_classes_attachment_emr-showthumbs-box', function($classes) { $classes[] = 'closed'; return $classes; });
|
70 |
}
|
71 |
|
72 |
+
|
73 |
}
|
74 |
|
75 |
/**
|
152 |
|
153 |
wp_register_style('emr_edit-attachment', plugins_url('css/edit_attachment.css', EMR_ROOT_FILE));
|
154 |
|
155 |
+
$mimes = array_values(get_allowed_mime_types());
|
156 |
+
|
157 |
+
wp_register_script('emr_admin', plugins_url('js/emr_admin.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true );
|
158 |
$emr_options = array(
|
159 |
'dateFormat' => $this->convertdate(get_option( 'date_format' )),
|
160 |
'maxfilesize' => wp_max_upload_size(),
|
161 |
+
'allowed_mime' => $mimes,
|
162 |
|
163 |
);
|
164 |
|
209 |
|
210 |
public function replace_meta_box($post)
|
211 |
{
|
212 |
+
|
213 |
$url = $this->getMediaReplaceURL($post->ID);
|
214 |
|
215 |
$action = "media_replace";
|
236 |
return false;
|
237 |
}
|
238 |
|
239 |
+
if (function_exists('wp_get_original_image_url')) // indicating WP 5.3+
|
240 |
+
{
|
241 |
+
$source_url = wp_get_original_image_url($post->ID);
|
242 |
+
// oldway will give -scaled in case of scaling.
|
243 |
+
$source_url_oldway = wp_get_attachment_url($post->ID);
|
244 |
+
|
245 |
+
if ($source_url !== $source_url_oldway)
|
246 |
+
{
|
247 |
+
echo "<div class='original previewwrapper'><img src='" . $source_url_oldway . "'><span class='label'>" . __('Original') . "</span></div>";
|
248 |
+
}
|
249 |
+
|
250 |
+
}
|
251 |
+
|
252 |
+
|
253 |
foreach($meta['sizes'] as $size => $data)
|
254 |
{
|
255 |
$display_size = ucfirst(str_replace("_", " ", $size));
|
260 |
|
261 |
public function attachment_editor($form_fields, $post)
|
262 |
{
|
263 |
+
$screen = get_current_screen();
|
264 |
+
if(! is_null($screen) && $screen->id == 'attachment') // hide on edit attachment screen.
|
265 |
+
return $form_fields;
|
266 |
+
|
267 |
$url = $this->getMediaReplaceURL($post->ID);
|
268 |
$action = "media_replace";
|
269 |
$editurl = wp_nonce_url( $url, $action );
|
274 |
"input" => "html",
|
275 |
"html" => "<p><a class='button-secondary' $link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a></p>", "helps" => esc_html__("To replace the current file, click the link and upload a replacement.", "enable-media-replace")
|
276 |
);
|
277 |
+
|
278 |
return $form_fields;
|
279 |
}
|
280 |
|
classes/externals.php
CHANGED
@@ -25,11 +25,11 @@ class Externals
|
|
25 |
|
26 |
protected function check()
|
27 |
{
|
28 |
-
if (class_exists('FLBuilder'))
|
29 |
{
|
30 |
$this->replaceSearchType = false;
|
31 |
$this->messages[] = __('Replace and Search feature is not compatible with Beaver Builder.', 'enable-media-replace');
|
32 |
-
}
|
33 |
}
|
34 |
|
35 |
public function get_replace_type($bool)
|
25 |
|
26 |
protected function check()
|
27 |
{
|
28 |
+
/*if (class_exists('FLBuilder'))
|
29 |
{
|
30 |
$this->replaceSearchType = false;
|
31 |
$this->messages[] = __('Replace and Search feature is not compatible with Beaver Builder.', 'enable-media-replace');
|
32 |
+
} */
|
33 |
}
|
34 |
|
35 |
public function get_replace_type($bool)
|
classes/functions.php
CHANGED
@@ -57,7 +57,7 @@ function emr_remove_size_from_filename( $url, $remove_extension = false ) {
|
|
57 |
function emr_get_match_url($url) {
|
58 |
$url = emr_remove_scheme($url);
|
59 |
$url = emr_maybe_remove_query_string($url);
|
60 |
-
$url = emr_remove_size_from_filename($url, true);
|
61 |
$url = emr_remove_domain_from_filename($url);
|
62 |
return $url;
|
63 |
}
|
57 |
function emr_get_match_url($url) {
|
58 |
$url = emr_remove_scheme($url);
|
59 |
$url = emr_maybe_remove_query_string($url);
|
60 |
+
$url = emr_remove_size_from_filename($url, true); // and extension is removed.
|
61 |
$url = emr_remove_domain_from_filename($url);
|
62 |
return $url;
|
63 |
}
|
classes/replacer.php
CHANGED
@@ -15,7 +15,7 @@ class Replacer
|
|
15 |
protected $source_metadata;
|
16 |
protected $source_url;
|
17 |
|
18 |
-
// everything target is what will be.
|
19 |
protected $targetFile;
|
20 |
protected $targetName;
|
21 |
protected $target_metadata;
|
@@ -38,16 +38,28 @@ class Replacer
|
|
38 |
{
|
39 |
$this->post_id = $post_id;
|
40 |
|
41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
$this->sourceFile = new File($source_file);
|
43 |
|
44 |
$this->source_post = get_post($post_id);
|
45 |
$this->source_is_image = wp_attachment_is('image', $this->source_post);
|
46 |
$this->source_metadata = wp_get_attachment_metadata( $post_id );
|
47 |
-
$this->source_url = wp_get_attachment_url($post_id);
|
48 |
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
|
53 |
public function setMode($mode)
|
@@ -133,7 +145,6 @@ class Replacer
|
|
133 |
|
134 |
if ($this->replaceMode == self::MODE_SEARCHREPLACE)
|
135 |
{
|
136 |
-
|
137 |
// Write new image title.
|
138 |
$title = $this->getNewTitle();
|
139 |
$update_ar = array('ID' => $this->post_id);
|
@@ -155,17 +166,23 @@ class Replacer
|
|
155 |
echo $error;
|
156 |
}
|
157 |
}
|
158 |
-
$this->doSearchReplace();
|
159 |
|
160 |
} // SEARCH REPLACE MODE
|
161 |
|
162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
{
|
164 |
$this->ThumbnailUpdater->setNewMetadata($this->target_metadata);
|
165 |
$result = $this->ThumbnailUpdater->updateThumbnails();
|
166 |
if (false === $result)
|
167 |
Log::addWarn('Thumbnail Updater returned false');
|
168 |
-
}
|
169 |
|
170 |
// if all set and done, update the date.
|
171 |
// This must be done after wp_update_posts
|
@@ -207,6 +224,12 @@ class Replacer
|
|
207 |
return $title;
|
208 |
}
|
209 |
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
/** Returns a full target path to place to new file. Including the file name! **/
|
211 |
protected function getTargetFile()
|
212 |
{
|
@@ -250,7 +273,10 @@ class Replacer
|
|
250 |
{
|
251 |
$meta = \wp_get_attachment_metadata( $this->post_id );
|
252 |
$backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true );
|
253 |
-
|
|
|
|
|
|
|
254 |
|
255 |
}
|
256 |
|
@@ -278,65 +304,166 @@ class Replacer
|
|
278 |
|
279 |
wp_cache_delete($this->post_id, 'posts');
|
280 |
|
281 |
-
|
282 |
-
/* $sql = $wpdb->prepare(
|
283 |
-
"UPDATE $table_name SET post_date = '$post_date', post_date_gmt = '$post_date_gmt' WHERE ID = %d;",
|
284 |
-
$ID
|
285 |
-
);
|
286 |
-
$wpdb->query($sql); */
|
287 |
}
|
288 |
|
289 |
|
290 |
-
protected function doSearchReplace()
|
291 |
{
|
292 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
|
294 |
// Search-and-replace filename in post database
|
295 |
-
|
|
|
|
|
296 |
|
297 |
/** Fail-safe if base_url is a whole directory, don't go search/replace */
|
298 |
if (is_dir($current_base_url))
|
299 |
{
|
300 |
Log::addError('Search Replace tried to replace to directory - ' . $current_base_url);
|
301 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
302 |
}
|
303 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
/* Search and replace in WP_POSTS */
|
305 |
// Removed $wpdb->remove_placeholder_escape from here, not compatible with WP 4.8
|
306 |
$posts_sql = $wpdb->prepare(
|
307 |
"SELECT ID, post_content FROM $wpdb->posts WHERE post_status = 'publish' AND post_content LIKE %s;",
|
308 |
'%' . $current_base_url . '%');
|
309 |
|
310 |
-
//
|
|
|
311 |
|
312 |
-
$postmeta_sql = 'SELECT meta_id, post_id, meta_value FROM ' . $wpdb->postmeta . '
|
313 |
-
WHERE post_id in (SELECT ID from '. $wpdb->posts . ' where post_status = "publish") AND meta_value like %s
|
314 |
$postmeta_sql = $wpdb->prepare($postmeta_sql, '%' . $current_base_url . '%');
|
315 |
|
|
|
|
|
|
|
316 |
$rsmeta = $wpdb->get_results($postmeta_sql, ARRAY_A);
|
|
|
317 |
$rs = $wpdb->get_results( $posts_sql, ARRAY_A );
|
318 |
|
319 |
$number_of_updates = 0;
|
320 |
|
321 |
-
|
322 |
-
|
323 |
-
$replace_urls = array_values(emr_normalize_file_urls( $search_urls, $replace_urls ));
|
324 |
|
325 |
-
Log::addDebug('Replacing references', array($search_urls, $replace_urls));
|
326 |
|
327 |
if ( ! empty( $rs ) ) {
|
328 |
foreach ( $rs AS $rows ) {
|
329 |
$number_of_updates = $number_of_updates + 1;
|
330 |
// replace old URLs with new URLs.
|
331 |
$post_content = $rows["post_content"];
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
340 |
}
|
341 |
}
|
342 |
if (! empty($rsmeta))
|
@@ -345,14 +472,161 @@ class Replacer
|
|
345 |
{
|
346 |
$number_of_updates++;
|
347 |
$content = $row['meta_value'];
|
348 |
-
$
|
|
|
|
|
349 |
|
350 |
-
|
351 |
-
|
|
|
352 |
}
|
353 |
}
|
354 |
|
355 |
|
356 |
} // doSearchReplace
|
357 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
358 |
} // class
|
15 |
protected $source_metadata;
|
16 |
protected $source_url;
|
17 |
|
18 |
+
// everything target is what will be. This is set when the image is replace, the result. Used for replacing.
|
19 |
protected $targetFile;
|
20 |
protected $targetName;
|
21 |
protected $target_metadata;
|
38 |
{
|
39 |
$this->post_id = $post_id;
|
40 |
|
41 |
+
if (function_exists('wp_get_original_image_path')) // WP 5.3+
|
42 |
+
{
|
43 |
+
$source_file = wp_get_original_image_path($post_id);
|
44 |
+
if ($source_file === false) // if it's not an image, returns false, use the old way.
|
45 |
+
$source_file = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )));
|
46 |
+
}
|
47 |
+
else
|
48 |
+
$source_file = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )));
|
49 |
+
|
50 |
+
Log::addDebug('SourceFile ' . $source_file);
|
51 |
$this->sourceFile = new File($source_file);
|
52 |
|
53 |
$this->source_post = get_post($post_id);
|
54 |
$this->source_is_image = wp_attachment_is('image', $this->source_post);
|
55 |
$this->source_metadata = wp_get_attachment_metadata( $post_id );
|
|
|
56 |
|
57 |
+
if (function_exists('wp_get_original_image_url')) // WP 5.3+
|
58 |
+
$this->source_url = wp_get_original_image_url($post_id);
|
59 |
+
else
|
60 |
+
$this->source_url = wp_get_attachment_url($post_id);
|
61 |
+
// $this->ThumbnailUpdater = new \ThumbnailUpdater($post_id);
|
62 |
+
//$this->ThumbnailUpdater->setOldMetadata($this->source_metadata);
|
63 |
}
|
64 |
|
65 |
public function setMode($mode)
|
145 |
|
146 |
if ($this->replaceMode == self::MODE_SEARCHREPLACE)
|
147 |
{
|
|
|
148 |
// Write new image title.
|
149 |
$title = $this->getNewTitle();
|
150 |
$update_ar = array('ID' => $this->post_id);
|
166 |
echo $error;
|
167 |
}
|
168 |
}
|
|
|
169 |
|
170 |
} // SEARCH REPLACE MODE
|
171 |
|
172 |
+
$args = array(
|
173 |
+
'thumbnails_only' => ($this->replaceMode == self::MODE_SEARCHREPLACE) ? false : true,
|
174 |
+
);
|
175 |
+
|
176 |
+
// Search Replace will also update thumbnails.
|
177 |
+
$this->doSearchReplace($args);
|
178 |
+
|
179 |
+
/*if(wp_attachment_is_image($this->post_id))
|
180 |
{
|
181 |
$this->ThumbnailUpdater->setNewMetadata($this->target_metadata);
|
182 |
$result = $this->ThumbnailUpdater->updateThumbnails();
|
183 |
if (false === $result)
|
184 |
Log::addWarn('Thumbnail Updater returned false');
|
185 |
+
}*/
|
186 |
|
187 |
// if all set and done, update the date.
|
188 |
// This must be done after wp_update_posts
|
224 |
return $title;
|
225 |
}
|
226 |
|
227 |
+
/** Gets the source file after processing. Returns a file */
|
228 |
+
public function getSourceFile()
|
229 |
+
{
|
230 |
+
return $this->sourceFile;
|
231 |
+
}
|
232 |
+
|
233 |
/** Returns a full target path to place to new file. Including the file name! **/
|
234 |
protected function getTargetFile()
|
235 |
{
|
273 |
{
|
274 |
$meta = \wp_get_attachment_metadata( $this->post_id );
|
275 |
$backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true );
|
276 |
+
|
277 |
+
// 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.
|
278 |
+
$file = get_attached_file($this->post_id);
|
279 |
+
$result = \wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $file );
|
280 |
|
281 |
}
|
282 |
|
304 |
|
305 |
wp_cache_delete($this->post_id, 'posts');
|
306 |
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
}
|
308 |
|
309 |
|
310 |
+
protected function doSearchReplace($args = array())
|
311 |
{
|
312 |
+
$defaults = array(
|
313 |
+
'thumbnails_only' => false,
|
314 |
+
);
|
315 |
+
|
316 |
+
$args = wp_parse_args($args, $defaults);
|
317 |
+
|
318 |
+
global $wpdb;
|
319 |
|
320 |
// Search-and-replace filename in post database
|
321 |
+
// @todo Check this with scaled images.
|
322 |
+
$current_base_url = parse_url($this->source_url, PHP_URL_PATH);// emr_get_match_url( $this->source_url);
|
323 |
+
$current_base_url = str_replace('.' . pathinfo($current_base_url, PATHINFO_EXTENSION), '', $current_base_url);
|
324 |
|
325 |
/** Fail-safe if base_url is a whole directory, don't go search/replace */
|
326 |
if (is_dir($current_base_url))
|
327 |
{
|
328 |
Log::addError('Search Replace tried to replace to directory - ' . $current_base_url);
|
329 |
+
Notices::addError(__('Fail Safe :: Source Location seems to be a directory.', 'enable-media-replace'));
|
330 |
+
return;
|
331 |
+
}
|
332 |
+
|
333 |
+
//$search_files = $this->getFilesFromMetadata($this->source_metadata);
|
334 |
+
//$replace_files = $this->getFilesFromMetadata($this->target_metadata);
|
335 |
+
// $arr = $this->getRelativeURLS();
|
336 |
+
|
337 |
+
/*$search_urls = emr_get_file_urls( $this->source_url, $this->source_metadata );
|
338 |
+
$replace_urls = emr_get_file_urls( $this->target_url, $this->target_metadata );
|
339 |
+
$replace_urls = array_values(emr_normalize_file_urls( $search_urls, $replace_urls ));*/
|
340 |
+
|
341 |
+
// get relurls of both source and target.
|
342 |
+
$urls = $this->getRelativeURLS();
|
343 |
+
|
344 |
+
|
345 |
+
if ($args['thumbnails_only'])
|
346 |
+
{
|
347 |
+
foreach($urls as $side => $data)
|
348 |
+
{
|
349 |
+
if (isset($data['base']))
|
350 |
+
{
|
351 |
+
unset($urls[$side]['base']);
|
352 |
+
}
|
353 |
+
if (isset($data['file']))
|
354 |
+
{
|
355 |
+
unset($urls[$side]['file']);
|
356 |
+
}
|
357 |
+
}
|
358 |
+
}
|
359 |
+
|
360 |
+
$search_urls = $urls['source'];
|
361 |
+
$replace_urls = $urls['target'];
|
362 |
+
|
363 |
+
/* If the replacement is much larger than the source, there can be more thumbnails. This leads to disbalance in the search/replace arrays.
|
364 |
+
Remove those from the equation. If the size doesn't exist in the source, it shouldn't be in use either */
|
365 |
+
foreach($replace_urls as $size => $url)
|
366 |
+
{
|
367 |
+
if (! isset($search_urls[$size]))
|
368 |
+
{
|
369 |
+
Log::addDebug('Dropping size ' . $size . ' - not found in source urls');
|
370 |
+
unset($replace_urls[$size]);
|
371 |
+
}
|
372 |
+
}
|
373 |
+
|
374 |
+
/* If on the other hand, some sizes are available in source, but not in target, try to replace them with something closeby. */
|
375 |
+
foreach($search_urls as $size => $url)
|
376 |
+
{
|
377 |
+
if (! isset($replace_urls[$size]))
|
378 |
+
{
|
379 |
+
$closest = $this->findNearestSize($size);
|
380 |
+
if ($closest)
|
381 |
+
{
|
382 |
+
$sourceUrl = $search_urls[$size];
|
383 |
+
$baseurl = trailingslashit(str_replace(wp_basename($sourceUrl), '', $sourceUrl));
|
384 |
+
Log::addDebug('Nearest size of source ' . $size . ' for target is ' . $closest);
|
385 |
+
$replace_urls[$size] = $baseurl . $closest;
|
386 |
+
}
|
387 |
+
else
|
388 |
+
{
|
389 |
+
Log::addDebug('Unset size ' . $size . ' - no closest found in source');
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
/* If source and target are the same, remove them from replace. This happens when replacing a file with same name, and +/- same dimensions generated.
|
395 |
+
|
396 |
+
After previous loops, for every search there should be a replace size.
|
397 |
+
*/
|
398 |
+
foreach($search_urls as $size => $url)
|
399 |
+
{
|
400 |
+
$replace_url = $replace_urls[$size];
|
401 |
+
if ($url == $replace_url) // if source and target as the same, no need for replacing.
|
402 |
+
{
|
403 |
+
unset($search_urls[$size]);
|
404 |
+
unset($replace_urls[$size]);
|
405 |
+
}
|
406 |
}
|
407 |
|
408 |
+
// If the two sides are disbalanced, the str_replace part will cause everything that has an empty replace counterpart to replace it with empty. Unwanted.
|
409 |
+
if (count($search_urls) !== count($replace_urls))
|
410 |
+
{
|
411 |
+
|
412 |
+
Log::addError('Unbalanced Replace Arrays, aborting', array($search_urls, $replace_urls, count($search_urls), count($replace_urls) ));
|
413 |
+
Notices::addError(__('There was an issue with updating your image URLS: Search and replace have different amount of values. Aborting updating thumbnails', 'enable-media-replace'));
|
414 |
+
return;
|
415 |
+
}
|
416 |
+
|
417 |
+
Log::addDebug('Doing meta search and replace -', array($search_urls, $replace_urls) );
|
418 |
+
Log::addDebug('Searching with BaseuRL' . $current_base_url);
|
419 |
+
|
420 |
/* Search and replace in WP_POSTS */
|
421 |
// Removed $wpdb->remove_placeholder_escape from here, not compatible with WP 4.8
|
422 |
$posts_sql = $wpdb->prepare(
|
423 |
"SELECT ID, post_content FROM $wpdb->posts WHERE post_status = 'publish' AND post_content LIKE %s;",
|
424 |
'%' . $current_base_url . '%');
|
425 |
|
426 |
+
// json encodes it all differently. Catch json-like encoded urls
|
427 |
+
//$json_url = str_replace('/', '\/', ltrim($current_base_url, '/') );
|
428 |
|
429 |
+
$postmeta_sql = 'SELECT meta_id, post_id, meta_key, meta_value FROM ' . $wpdb->postmeta . '
|
430 |
+
WHERE post_id in (SELECT ID from '. $wpdb->posts . ' where post_status = "publish") AND meta_value like %s';
|
431 |
$postmeta_sql = $wpdb->prepare($postmeta_sql, '%' . $current_base_url . '%');
|
432 |
|
433 |
+
// 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.
|
434 |
+
// $postmeta_sql = str_replace('[JSON_URL]', $json_url, $postmeta_sql);
|
435 |
+
|
436 |
$rsmeta = $wpdb->get_results($postmeta_sql, ARRAY_A);
|
437 |
+
|
438 |
$rs = $wpdb->get_results( $posts_sql, ARRAY_A );
|
439 |
|
440 |
$number_of_updates = 0;
|
441 |
|
442 |
+
Log::addDebug('Queries', array($postmeta_sql, $posts_sql));
|
443 |
+
Log::addDebug('Queries found ' . count($rs) . ' post rows and ' . count($rsmeta) . ' meta rows');
|
|
|
444 |
|
|
|
445 |
|
446 |
if ( ! empty( $rs ) ) {
|
447 |
foreach ( $rs AS $rows ) {
|
448 |
$number_of_updates = $number_of_updates + 1;
|
449 |
// replace old URLs with new URLs.
|
450 |
$post_content = $rows["post_content"];
|
451 |
+
//$post_content = str_replace( $search_urls, $replace_urls, $post_content );
|
452 |
+
|
453 |
+
$post_id = $rows['ID'];
|
454 |
+
$post_ar = array('ID' => $post_id);
|
455 |
+
$post_ar['post_content'] = $this->replaceContent($post_content, $search_urls, $replace_urls);
|
456 |
+
|
457 |
+
if ($post_ar['post_content'] !== $post_content)
|
458 |
+
{
|
459 |
+
$result = wp_update_post($post_ar);
|
460 |
+
if (is_wp_error($result))
|
461 |
+
{
|
462 |
+
Notice::addError('Something went wrong while replacing' . $result->get_error_message() );
|
463 |
+
Log::addError('WP-Error during post update', $result);
|
464 |
+
}
|
465 |
+
}
|
466 |
+
|
467 |
}
|
468 |
}
|
469 |
if (! empty($rsmeta))
|
472 |
{
|
473 |
$number_of_updates++;
|
474 |
$content = $row['meta_value'];
|
475 |
+
$meta_key = $row['meta_key'];
|
476 |
+
$post_id = $row['post_id'];
|
477 |
+
$content = $this->replaceContent($content, $search_urls, $replace_urls); //str_replace($search_urls, $replace_urls, $content);
|
478 |
|
479 |
+
update_post_meta($post_id, $meta_key, $content);
|
480 |
+
// $sql = $wpdb->prepare('UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d', $content, $row['meta_id'] );
|
481 |
+
// $wpdb->query($sql);
|
482 |
}
|
483 |
}
|
484 |
|
485 |
|
486 |
} // doSearchReplace
|
487 |
|
488 |
+
private function replaceContent($content, $search, $replace)
|
489 |
+
{
|
490 |
+
//$is_serial = false;
|
491 |
+
$content = maybe_unserialize($content);
|
492 |
+
$isJson = $this->isJSON($content);
|
493 |
+
|
494 |
+
if ($isJson)
|
495 |
+
{
|
496 |
+
$content = json_decode($content);
|
497 |
+
}
|
498 |
+
|
499 |
+
if (is_string($content)) // let's check the normal one first.
|
500 |
+
{
|
501 |
+
return str_replace($search, $replace, $content);
|
502 |
+
}
|
503 |
+
elseif (is_wp_error($content)) // seen this.
|
504 |
+
{
|
505 |
+
return $content; // do nothing.
|
506 |
+
}
|
507 |
+
elseif (is_array($content) ) // array metadata and such.
|
508 |
+
{
|
509 |
+
foreach($content as $index => $value)
|
510 |
+
{
|
511 |
+
$content[$index] = $this->replaceContent($value, $search, $replace); //str_replace($value, $search, $replace);
|
512 |
+
}
|
513 |
+
return $content;
|
514 |
+
}
|
515 |
+
elseif(is_object($content)) // metadata objects, they exist.
|
516 |
+
{
|
517 |
+
foreach($content as $key => $value)
|
518 |
+
{
|
519 |
+
$content->{$key} = $this->replaceContent($value, $search, $replace); //str_replace($value, $search, $replace);
|
520 |
+
}
|
521 |
+
return $content;
|
522 |
+
}
|
523 |
+
|
524 |
+
if ($isJson) // convert back to JSON, if this was JSON. Different than serialize which does WP automatically.
|
525 |
+
{
|
526 |
+
$content = json_encode($content);
|
527 |
+
}
|
528 |
+
|
529 |
+
return $content;
|
530 |
+
}
|
531 |
+
|
532 |
+
private function getFilesFromMetadata($meta)
|
533 |
+
{
|
534 |
+
$fileArray = array();
|
535 |
+
if (isset($meta['file']))
|
536 |
+
$fileArray['file'] = $meta['file'];
|
537 |
+
|
538 |
+
if (isset($meta['sizes']))
|
539 |
+
{
|
540 |
+
foreach($meta['sizes'] as $name => $data)
|
541 |
+
{
|
542 |
+
if (isset($data['file']))
|
543 |
+
{
|
544 |
+
$fileArray[$name] = $data['file'];
|
545 |
+
}
|
546 |
+
}
|
547 |
+
}
|
548 |
+
return $fileArray;
|
549 |
+
}
|
550 |
+
|
551 |
+
/* Check if given content is JSON format. */
|
552 |
+
private function isJSON($content)
|
553 |
+
{
|
554 |
+
$json = is_string($content) && json_decode($content);
|
555 |
+
return $json && $content != $json;
|
556 |
+
}
|
557 |
+
|
558 |
+
// Get REL Urls of both source and target.
|
559 |
+
private function getRelativeURLS()
|
560 |
+
{
|
561 |
+
$dataArray = array(
|
562 |
+
'source' => array('url' => $this->source_url, 'metadata' => $this->getFilesFromMetadata($this->source_metadata) ),
|
563 |
+
'target' => array('url' => $this->target_url, 'metadata' => $this->getFilesFromMetadata($this->target_metadata) ),
|
564 |
+
);
|
565 |
+
|
566 |
+
// Log::addDebug('Source Metadata', $this->source_metadata);
|
567 |
+
// Log::addDebug('Target Metadata', $this->target_metadata);
|
568 |
+
|
569 |
+
$result = array();
|
570 |
+
|
571 |
+
foreach($dataArray as $index => $item)
|
572 |
+
{
|
573 |
+
$result[$index] = array();
|
574 |
+
$metadata = $item['metadata'];
|
575 |
+
|
576 |
+
$baseurl = parse_url($item['url'], PHP_URL_PATH);
|
577 |
+
$result[$index]['base'] = $baseurl; // this is the relpath of the mainfile.
|
578 |
+
$baseurl = trailingslashit(str_replace( wp_basename($item['url']), '', $baseurl)); // get the relpath of main file.
|
579 |
+
|
580 |
+
foreach($metadata as $name => $filename)
|
581 |
+
{
|
582 |
+
$result[$index][$name] = $baseurl . wp_basename($filename); // filename can have a path like 19/08 etc.
|
583 |
+
}
|
584 |
+
|
585 |
+
}
|
586 |
+
// Log::addDebug('Relative URLS', $result);
|
587 |
+
return $result;
|
588 |
+
}
|
589 |
+
|
590 |
+
|
591 |
+
/** FindNearestsize
|
592 |
+
* This works on the assumption that when the exact image size name is not available, find the nearest width with the smallest possible difference to impact the site the least.
|
593 |
+
*/
|
594 |
+
private function findNearestSize($sizeName)
|
595 |
+
{
|
596 |
+
|
597 |
+
$old_width = $this->source_metadata['sizes'][$sizeName]['width']; // the width from size not in new image
|
598 |
+
$new_width = $this->target_metadata['width']; // default check - the width of the main image
|
599 |
+
|
600 |
+
$diff = abs($old_width - $new_width);
|
601 |
+
// $closest_file = str_replace($this->relPath, '', $this->newMeta['file']);
|
602 |
+
$closest_file = wp_basename($this->target_metadata['file']); // mainfile as default
|
603 |
+
|
604 |
+
foreach($this->target_metadata['sizes'] as $sizeName => $data)
|
605 |
+
{
|
606 |
+
$thisdiff = abs($old_width - $data['width']);
|
607 |
+
|
608 |
+
if ( $thisdiff < $diff )
|
609 |
+
{
|
610 |
+
$closest_file = $data['file'];
|
611 |
+
if(is_array($closest_file)) { $closest_file = $closest_file[0];} // HelpScout case 709692915
|
612 |
+
if(!empty($closest_file)) {
|
613 |
+
$diff = $thisdiff;
|
614 |
+
$found_metasize = true;
|
615 |
+
}
|
616 |
+
}
|
617 |
+
}
|
618 |
+
|
619 |
+
|
620 |
+
if(empty($closest_file)) return false;
|
621 |
+
|
622 |
+
return $closest_file;
|
623 |
+
//$oldFile = $oldData['file'];
|
624 |
+
//if(is_array($oldFile)) { $oldFile = $oldFile[0];} // HelpScout case 709692915
|
625 |
+
/*if(empty($oldFile)) {
|
626 |
+
return false; //make sure we don't replace in this case as we will break the URLs for all the images in the folder.
|
627 |
+
} */
|
628 |
+
// $this->convertArray[] = array('imageFrom' => $this->relPath . $oldFile, 'imageTo' => $this->relPath . $closest_file);
|
629 |
+
|
630 |
+
}
|
631 |
+
|
632 |
} // class
|
classes/uihelper.php
CHANGED
@@ -64,7 +64,7 @@ class UIHelper
|
|
64 |
|
65 |
$url = add_query_arg('SHORTPIXEL_DEBUG', $spdebug, $url);
|
66 |
}
|
67 |
-
|
68 |
$url = apply_filters('emr_returnurl', $url);
|
69 |
Log::addDebug('Success URL- ' . $url);
|
70 |
|
@@ -97,12 +97,16 @@ class UIHelper
|
|
97 |
|
98 |
public function setSourceSizes($attach_id)
|
99 |
{
|
100 |
-
$data = wp_get_attachment_image_src($attach_id, 'full');
|
|
|
|
|
101 |
if (is_array($data))
|
102 |
{
|
|
|
103 |
$this->full_width = $data[1];
|
104 |
$this->full_height = $data[2];
|
105 |
}
|
|
|
106 |
}
|
107 |
|
108 |
// Returns Preview Image HTML Output.
|
@@ -112,10 +116,11 @@ class UIHelper
|
|
112 |
|
113 |
if ($attach_id > 0)
|
114 |
{
|
115 |
-
$data = wp_get_attachment_image_src($attach_id, $this->preview_size);
|
116 |
$file = get_attached_file($attach_id);
|
117 |
Log::addDebug('Attached File ' . $file, $data);
|
118 |
|
|
|
119 |
}
|
120 |
|
121 |
$mime_type = get_post_mime_type($attach_id);
|
@@ -146,10 +151,14 @@ class UIHelper
|
|
146 |
$url = $data[0];
|
147 |
$width = $data[1];
|
148 |
$height = $data[2];
|
|
|
|
|
|
|
149 |
// preview width, if source if found, should be set to source.
|
150 |
$this->preview_width = $width;
|
151 |
$this->preview_height = $height;
|
152 |
|
|
|
153 |
if ($width > $this->preview_max_width)
|
154 |
$width = $this->preview_max_width;
|
155 |
if ($height > $this->preview_max_height)
|
@@ -163,10 +172,43 @@ class UIHelper
|
|
163 |
'image' => $image,
|
164 |
'mime_type' => $mime_type,
|
165 |
);
|
|
|
166 |
$output = $this->getPlaceHolder($args);
|
167 |
return $output;
|
168 |
}
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
public function getPreviewError($attach_id)
|
171 |
{
|
172 |
$args = array(
|
64 |
|
65 |
$url = add_query_arg('SHORTPIXEL_DEBUG', $spdebug, $url);
|
66 |
}
|
67 |
+
|
68 |
$url = apply_filters('emr_returnurl', $url);
|
69 |
Log::addDebug('Success URL- ' . $url);
|
70 |
|
97 |
|
98 |
public function setSourceSizes($attach_id)
|
99 |
{
|
100 |
+
$data = $this->getImageSizes($attach_id, 'full'); // wp_get_attachment_image_src($attach_id, 'full');
|
101 |
+
$file = get_attached_file($attach_id);
|
102 |
+
|
103 |
if (is_array($data))
|
104 |
{
|
105 |
+
|
106 |
$this->full_width = $data[1];
|
107 |
$this->full_height = $data[2];
|
108 |
}
|
109 |
+
|
110 |
}
|
111 |
|
112 |
// Returns Preview Image HTML Output.
|
116 |
|
117 |
if ($attach_id > 0)
|
118 |
{
|
119 |
+
$data = $this->getImageSizes($attach_id, $this->preview_size); //wp_get_attachment_image_src($attach_id, $this->preview_size);
|
120 |
$file = get_attached_file($attach_id);
|
121 |
Log::addDebug('Attached File ' . $file, $data);
|
122 |
|
123 |
+
|
124 |
}
|
125 |
|
126 |
$mime_type = get_post_mime_type($attach_id);
|
151 |
$url = $data[0];
|
152 |
$width = $data[1];
|
153 |
$height = $data[2];
|
154 |
+
|
155 |
+
// SVG's without any helpers return around 0 for width / height. Fix preview.
|
156 |
+
|
157 |
// preview width, if source if found, should be set to source.
|
158 |
$this->preview_width = $width;
|
159 |
$this->preview_height = $height;
|
160 |
|
161 |
+
|
162 |
if ($width > $this->preview_max_width)
|
163 |
$width = $this->preview_max_width;
|
164 |
if ($height > $this->preview_max_height)
|
172 |
'image' => $image,
|
173 |
'mime_type' => $mime_type,
|
174 |
);
|
175 |
+
|
176 |
$output = $this->getPlaceHolder($args);
|
177 |
return $output;
|
178 |
}
|
179 |
|
180 |
+
protected function getImageSizes($attach_id, $size = 'thumbnail')
|
181 |
+
{
|
182 |
+
$data = wp_get_attachment_image_src($attach_id, $size);
|
183 |
+
$width = $data[1];
|
184 |
+
$mime_type = get_post_mime_type($attach_id);
|
185 |
+
|
186 |
+
if (strpos($mime_type, 'svg') !== false && $width <= 5)
|
187 |
+
{
|
188 |
+
$file = get_attached_file($attach_id);
|
189 |
+
$data = $this->fixSVGSize($data, $file);
|
190 |
+
}
|
191 |
+
|
192 |
+
return $data;
|
193 |
+
}
|
194 |
+
|
195 |
+
protected function fixSVGSize($data, $file)
|
196 |
+
{
|
197 |
+
if (! function_exists('simplexml_load_file'))
|
198 |
+
return $data;
|
199 |
+
|
200 |
+
$xml = simplexml_load_file($file);
|
201 |
+
if ($xml)
|
202 |
+
{ // stolen from SVG Upload plugin
|
203 |
+
$attr = $xml->attributes();
|
204 |
+
$viewbox = explode(' ', $attr->viewBox);
|
205 |
+
$data[1] = isset($attr->width) && preg_match('/\d+/', $attr->width, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[2] : null);
|
206 |
+
$data[2] = isset($attr->height) && preg_match('/\d+/', $attr->height, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[3] : null);
|
207 |
+
}
|
208 |
+
|
209 |
+
return $data;
|
210 |
+
}
|
211 |
+
|
212 |
public function getPreviewError($attach_id)
|
213 |
{
|
214 |
$args = array(
|
css/edit_attachment.css
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
/* Styling for the edit attachment screen */
|
2 |
-
#emr-replace-box .previewwrapper {
|
3 |
display: inline-block;
|
4 |
position: relative;
|
5 |
clear: both;
|
6 |
margin: 3px 0; }
|
7 |
-
#emr-replace-box .previewwrapper img {
|
8 |
max-width: 100%; }
|
9 |
-
#emr-replace-box .previewwrapper span.label {
|
10 |
font-size: 14px;
|
11 |
color: #fff;
|
12 |
position: absolute;
|
1 |
/* Styling for the edit attachment screen */
|
2 |
+
#emr-replace-box .previewwrapper, #emr-showthumbs-box .previewwrapper {
|
3 |
display: inline-block;
|
4 |
position: relative;
|
5 |
clear: both;
|
6 |
margin: 3px 0; }
|
7 |
+
#emr-replace-box .previewwrapper img, #emr-showthumbs-box .previewwrapper img {
|
8 |
max-width: 100%; }
|
9 |
+
#emr-replace-box .previewwrapper span.label, #emr-showthumbs-box .previewwrapper span.label {
|
10 |
font-size: 14px;
|
11 |
color: #fff;
|
12 |
position: absolute;
|
enable-media-replace.php
CHANGED
@@ -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: 3.3.
|
7 |
Author: ShortPixel
|
8 |
Author URI: https://shortpixel.com
|
9 |
Text Domain: enable-media-replace
|
@@ -25,14 +25,16 @@ http://www.gnu.org/licenses/gpl.html
|
|
25 |
*/
|
26 |
|
27 |
namespace EnableMediaReplace;
|
|
|
28 |
|
29 |
if ( ! defined( 'ABSPATH' ) ) {
|
30 |
exit; // Exit if accessed directly.
|
31 |
}
|
32 |
|
|
|
33 |
if(!defined("S3_UPLOADS_AUTOENABLE")) {
|
34 |
define('S3_UPLOADS_AUTOENABLE', true);
|
35 |
-
}
|
36 |
|
37 |
if (! defined("EMR_ROOT_FILE")) {
|
38 |
define("EMR_ROOT_FILE", __FILE__);
|
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: 3.3.8
|
7 |
Author: ShortPixel
|
8 |
Author URI: https://shortpixel.com
|
9 |
Text Domain: enable-media-replace
|
25 |
*/
|
26 |
|
27 |
namespace EnableMediaReplace;
|
28 |
+
define('EMR_VERSION', '3.3.8');
|
29 |
|
30 |
if ( ! defined( 'ABSPATH' ) ) {
|
31 |
exit; // Exit if accessed directly.
|
32 |
}
|
33 |
|
34 |
+
/* Not sure why we define this?
|
35 |
if(!defined("S3_UPLOADS_AUTOENABLE")) {
|
36 |
define('S3_UPLOADS_AUTOENABLE', true);
|
37 |
+
} */
|
38 |
|
39 |
if (! defined("EMR_ROOT_FILE")) {
|
40 |
define("EMR_ROOT_FILE", __FILE__);
|
js/emr_admin.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
-
|
2 |
-
{
|
3 |
// interface for emr.
|
4 |
-
var emrIf =
|
5 |
{
|
6 |
var source_type;
|
7 |
var source_is_image;
|
@@ -119,8 +118,15 @@ jQuery(document).ready(function($)
|
|
119 |
|
120 |
img.setAttribute('style', 'max-width:100%; max-height: 100%;');
|
121 |
img.addEventListener("load", function () {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
// $(preview).find('.textlayer').text(img.naturalWidth + ' x ' + img.naturalHeight );
|
123 |
-
self.updateTextLayer(preview,
|
124 |
});
|
125 |
|
126 |
$(preview).prepend(img);
|
@@ -147,6 +153,14 @@ jQuery(document).ready(function($)
|
|
147 |
this.debug(target_type + ' not ' + source_type);
|
148 |
this.warningFileType();
|
149 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
},
|
151 |
// replace the text, check if text is there ( or hide ), and fix the layout.
|
152 |
this.updateTextLayer = function (preview, newtext)
|
@@ -209,12 +223,36 @@ jQuery(document).ready(function($)
|
|
209 |
{
|
210 |
$('.form-warning.filetype').fadeIn();
|
211 |
}
|
|
|
|
|
|
|
|
|
212 |
this.debug = function(message)
|
213 |
{
|
214 |
console.debug(message);
|
215 |
}
|
216 |
} // emrIf
|
217 |
|
218 |
-
|
|
|
|
|
219 |
window.enableMediaReplace.init();
|
220 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
|
|
2 |
// interface for emr.
|
3 |
+
var emrIf = function ($)
|
4 |
{
|
5 |
var source_type;
|
6 |
var source_is_image;
|
118 |
|
119 |
img.setAttribute('style', 'max-width:100%; max-height: 100%;');
|
120 |
img.addEventListener("load", function () {
|
121 |
+
// with formats like svg it can be rough.
|
122 |
+
var width = img.naturalWidth;
|
123 |
+
var height = img.naturalHeight;
|
124 |
+
if (width == 0)
|
125 |
+
width = img.width;
|
126 |
+
if (height == 0)
|
127 |
+
height = img.height;
|
128 |
// $(preview).find('.textlayer').text(img.naturalWidth + ' x ' + img.naturalHeight );
|
129 |
+
self.updateTextLayer(preview, width + ' x ' + height);
|
130 |
});
|
131 |
|
132 |
$(preview).prepend(img);
|
153 |
this.debug(target_type + ' not ' + source_type);
|
154 |
this.warningFileType();
|
155 |
}
|
156 |
+
|
157 |
+
if (emr_options.allowed_mime.indexOf(target_type) == -1)
|
158 |
+
{
|
159 |
+
this.debug(target_type + ' not ' + ' in allowed types ');
|
160 |
+
this.warningMimeType();
|
161 |
+
}
|
162 |
+
// this.debug(emr_options.allowed_mime);
|
163 |
+
|
164 |
},
|
165 |
// replace the text, check if text is there ( or hide ), and fix the layout.
|
166 |
this.updateTextLayer = function (preview, newtext)
|
223 |
{
|
224 |
$('.form-warning.filetype').fadeIn();
|
225 |
}
|
226 |
+
this.warningMimeType = function(fileItem)
|
227 |
+
{
|
228 |
+
$('.form-warning.mimetype').fadeIn();
|
229 |
+
}
|
230 |
this.debug = function(message)
|
231 |
{
|
232 |
console.debug(message);
|
233 |
}
|
234 |
} // emrIf
|
235 |
|
236 |
+
jQuery(document).ready(function($)
|
237 |
+
{
|
238 |
+
window.enableMediaReplace = new emrIf($);
|
239 |
window.enableMediaReplace.init();
|
240 |
});
|
241 |
+
|
242 |
+
|
243 |
+
function emrDelayedInit() {
|
244 |
+
console.log('Checking delayed init ');
|
245 |
+
if(typeof window.enableMediaReplace == "undefined") {
|
246 |
+
console.log(emrIf);
|
247 |
+
window.enableMediaReplace = new emrIf(jQuery);
|
248 |
+
window.enableMediaReplace.init();
|
249 |
+
}
|
250 |
+
else if (typeof window.enableMediaReplace !== 'undefined')
|
251 |
+
{
|
252 |
+
// All fine.
|
253 |
+
}
|
254 |
+
else { // Nothing yet, try again.
|
255 |
+
setTimeout(emrdelayedInit, 3000);
|
256 |
+
}
|
257 |
+
}
|
258 |
+
setTimeout(emrDelayedInit, 3000);
|
readme.txt
CHANGED
@@ -2,9 +2,9 @@
|
|
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.
|
6 |
Tested up to: 5.3
|
7 |
-
Requires PHP: 5.
|
8 |
Stable tag: trunk
|
9 |
|
10 |
Easily replace any attached image/file by simply uploading a new file in the Media Library edit view - a real time saver!
|
@@ -47,6 +47,22 @@ If you want more control over the format used to display the time, you can use t
|
|
47 |
|
48 |
== Changelog ==
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
= 3.3.7 =
|
51 |
|
52 |
Release date: 13th November 2019
|
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: 5.3
|
7 |
+
Requires PHP: 5.6
|
8 |
Stable tag: trunk
|
9 |
|
10 |
Easily replace any attached image/file by simply uploading a new file in the Media Library edit view - a real time saver!
|
47 |
|
48 |
== Changelog ==
|
49 |
|
50 |
+
= 3.3.8 =
|
51 |
+
|
52 |
+
Release date: 18th February 2020
|
53 |
+
* Fixes for WP 5.3+ -scaled images system. Will now replace those as well.
|
54 |
+
* Updating and replacing images and thumbnails should now work for serialized (and such) metadata.
|
55 |
+
- For Beaver Builder
|
56 |
+
* Add extra warning if mimetype is not allowed by WordPress for upload
|
57 |
+
* Put Javascript version in wp_register_script
|
58 |
+
* Hidden double 'replace media'
|
59 |
+
* Replace Image label to Replace Media
|
60 |
+
* Removed constant S3_UPLOADS_AUTOENABLE
|
61 |
+
* Improved detection of SVG image sizes
|
62 |
+
* Fixed - Logger doesn't call wp_upload_dir when not debugging
|
63 |
+
* Extra - Javascript tries to resume after external errors.
|
64 |
+
* Language – 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted
|
65 |
+
|
66 |
= 3.3.7 =
|
67 |
|
68 |
Release date: 13th November 2019
|
scss/edit_attachment.scss
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
/* Styling for the edit attachment screen */
|
3 |
-
#emr-replace-box
|
4 |
{
|
5 |
.previewwrapper
|
6 |
{
|
@@ -23,6 +23,7 @@
|
|
23 |
text-align: center;
|
24 |
padding: 4px 0;
|
25 |
|
|
|
26 |
}
|
27 |
|
28 |
}
|
1 |
|
2 |
/* Styling for the edit attachment screen */
|
3 |
+
#emr-replace-box, #emr-showthumbs-box
|
4 |
{
|
5 |
.previewwrapper
|
6 |
{
|
23 |
text-align: center;
|
24 |
padding: 4px 0;
|
25 |
|
26 |
+
|
27 |
}
|
28 |
|
29 |
}
|
thumbnail_updater.php
CHANGED
@@ -6,9 +6,6 @@ use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
|
6 |
use EnableMediaReplace\Notices\NoticeController as Notices;
|
7 |
|
8 |
/* Simple class for updating thumbnails.
|
9 |
-
*
|
10 |
-
*
|
11 |
-
*
|
12 |
*/
|
13 |
class ThumbnailUpdater
|
14 |
{
|
6 |
use EnableMediaReplace\Notices\NoticeController as Notices;
|
7 |
|
8 |
/* Simple class for updating thumbnails.
|
|
|
|
|
|
|
9 |
*/
|
10 |
class ThumbnailUpdater
|
11 |
{
|
views/popup.php
CHANGED
@@ -33,17 +33,24 @@ Log::addDebug('Load Popup Form View');
|
|
33 |
|
34 |
$attachment_id = intval($_GET['attachment_id']);
|
35 |
$attachment = get_post($attachment_id);
|
|
|
36 |
|
37 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
$filetype = $attachment->post_mime_type;
|
39 |
$filename = basename($filepath);
|
40 |
-
|
41 |
|
42 |
$uiHelper = new UIHelper();
|
43 |
$uiHelper->setPreviewSizes();
|
44 |
$uiHelper->setSourceSizes($attachment_id);
|
45 |
|
46 |
-
Log::addDebug('Popup view Data', array('id' => $attachment_id, 'source_mime' => $source_mime, 'filepath' => $filepath));
|
47 |
|
48 |
?>
|
49 |
<style>
|
@@ -71,7 +78,7 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
71 |
|
72 |
<form enctype="multipart/form-data" method="POST" action="<?php echo $formurl; ?>">
|
73 |
<section class='image_chooser wrapper'>
|
74 |
-
<div class='section-header'> <?php _e('Choose Replacement
|
75 |
|
76 |
<?php
|
77 |
#wp_nonce_field('enable-media-replace');
|
@@ -113,6 +120,7 @@ $url = $uiHelper->getFormUrl($attachment_id);
|
|
113 |
|
114 |
<div class='form-warning filetype'><p><?php printf(__('Replacement file is not the same filetype. This might cause unexpected issues')); ?></p></div>
|
115 |
|
|
|
116 |
|
117 |
<input type="file" name="userfile" id="userfile" />
|
118 |
<div class='image_previews'>
|
33 |
|
34 |
$attachment_id = intval($_GET['attachment_id']);
|
35 |
$attachment = get_post($attachment_id);
|
36 |
+
$replacer = new Replacer($attachment_id);
|
37 |
|
38 |
+
$file = $replacer->getSourceFile();
|
39 |
+
$filepath = $file->getFullFilePath();
|
40 |
+
$filename = $file->getFileName();
|
41 |
+
$filetype = $file->getFileExtension();
|
42 |
+
$source_mime = get_post_mime_type($attachment_id);
|
43 |
+
|
44 |
+
/*$filepath = get_attached_file($attachment_id); // fullpath
|
45 |
$filetype = $attachment->post_mime_type;
|
46 |
$filename = basename($filepath);
|
47 |
+
*/
|
48 |
|
49 |
$uiHelper = new UIHelper();
|
50 |
$uiHelper->setPreviewSizes();
|
51 |
$uiHelper->setSourceSizes($attachment_id);
|
52 |
|
53 |
+
//Log::addDebug('Popup view Data', array('id' => $attachment_id, 'source_mime' => $source_mime, 'filepath' => $filepath));
|
54 |
|
55 |
?>
|
56 |
<style>
|
78 |
|
79 |
<form enctype="multipart/form-data" method="POST" action="<?php echo $formurl; ?>">
|
80 |
<section class='image_chooser wrapper'>
|
81 |
+
<div class='section-header'> <?php _e('Choose Replacement Media', 'enable-replace-media'); ?></div>
|
82 |
|
83 |
<?php
|
84 |
#wp_nonce_field('enable-media-replace');
|
120 |
|
121 |
<div class='form-warning filetype'><p><?php printf(__('Replacement file is not the same filetype. This might cause unexpected issues')); ?></p></div>
|
122 |
|
123 |
+
<div class='form-warning mimetype'><p><?php printf(__('Replacement file type doesn\'t seem to be allowed by WordPress. This might cause unexpected issues')); ?></p></div>
|
124 |
|
125 |
<input type="file" name="userfile" id="userfile" />
|
126 |
<div class='image_previews'>
|
views/upload.php
CHANGED
@@ -21,26 +21,18 @@ global $wpdb;
|
|
21 |
$table_name = $wpdb->prefix . "posts";
|
22 |
$postmeta_table_name = $wpdb->prefix . "postmeta";
|
23 |
|
24 |
-
|
25 |
// Starts processing.
|
26 |
$uihelper = new UIHelper();
|
27 |
|
28 |
// Get old guid and filetype from DB
|
29 |
$post_id = intval($_POST['ID']); // sanitize, post_id.
|
30 |
-
$replacer = new
|
31 |
|
32 |
// Massage a bunch of vars
|
33 |
$ID = intval($_POST["ID"]); // legacy
|
34 |
$replace_type = isset($_POST["replace_type"]) ? sanitize_text_field($_POST["replace_type"]) : false;
|
35 |
$timestamp_replace = intval($_POST['timestamp_replace']);
|
36 |
|
37 |
-
$current_file = get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true ));
|
38 |
-
$current_path = substr($current_file, 0, (strrpos($current_file, "/")));
|
39 |
-
$current_file = preg_replace("|(?<!:)/{2,}|", "/", $current_file); // @todo what does this mean?
|
40 |
-
$current_filename = wp_basename($current_file);
|
41 |
-
$current_metadata = wp_get_attachment_metadata( $post_id );
|
42 |
-
|
43 |
-
|
44 |
$redirect_error = $uihelper->getFailedRedirect($post_id);
|
45 |
$redirect_success = $uihelper->getSuccesRedirect($post_id);
|
46 |
|
@@ -106,7 +98,8 @@ if (is_uploaded_file($_FILES["userfile"]["tmp_name"])) {
|
|
106 |
exit();
|
107 |
}
|
108 |
|
109 |
-
|
|
|
110 |
|
111 |
Notices::addError(esc_html__("File type does not meet security guidelines. Try another.", 'enable-media-replace') );
|
112 |
wp_safe_redirect($redirect_error);
|
@@ -114,17 +107,10 @@ if (is_uploaded_file($_FILES["userfile"]["tmp_name"])) {
|
|
114 |
}
|
115 |
|
116 |
// Here we have the uploaded file
|
117 |
-
|
118 |
-
//$thumbUpdater = new ThumbnailUpdater($ID);
|
119 |
-
//$thumbUpdater->setOldMetadata($current_metadata);
|
120 |
-
|
121 |
$new_filename = $_FILES["userfile"]["name"];
|
122 |
//$new_filesize = $_FILES["userfile"]["size"]; // Seems not to be in use.
|
123 |
$new_filetype = $filedata["type"];
|
124 |
|
125 |
-
// save original file permissions
|
126 |
-
//$original_file_perms = fileperms($current_file) & 0777;
|
127 |
-
|
128 |
// Gather all functions that both options do.
|
129 |
do_action('wp_handle_replace', array('post_id' => $post_id));
|
130 |
|
@@ -141,7 +127,6 @@ if (is_uploaded_file($_FILES["userfile"]["tmp_name"])) {
|
|
141 |
$returnurl = admin_url("/post.php?post={$_POST["ID"]}&action=edit&message=1");
|
142 |
|
143 |
// Execute hook actions - thanks rubious for the suggestion!
|
144 |
-
//if (isset($new_guid)) { do_action("enable-media-replace-upload-done", $new_guid, $current_guid); }
|
145 |
|
146 |
} else {
|
147 |
//TODO Better error handling when no file is selected.
|
21 |
$table_name = $wpdb->prefix . "posts";
|
22 |
$postmeta_table_name = $wpdb->prefix . "postmeta";
|
23 |
|
|
|
24 |
// Starts processing.
|
25 |
$uihelper = new UIHelper();
|
26 |
|
27 |
// Get old guid and filetype from DB
|
28 |
$post_id = intval($_POST['ID']); // sanitize, post_id.
|
29 |
+
$replacer = new Replacer($post_id);
|
30 |
|
31 |
// Massage a bunch of vars
|
32 |
$ID = intval($_POST["ID"]); // legacy
|
33 |
$replace_type = isset($_POST["replace_type"]) ? sanitize_text_field($_POST["replace_type"]) : false;
|
34 |
$timestamp_replace = intval($_POST['timestamp_replace']);
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
$redirect_error = $uihelper->getFailedRedirect($post_id);
|
37 |
$redirect_success = $uihelper->getSuccesRedirect($post_id);
|
38 |
|
98 |
exit();
|
99 |
}
|
100 |
|
101 |
+
|
102 |
+
if ($filedata["ext"] == false) {
|
103 |
|
104 |
Notices::addError(esc_html__("File type does not meet security guidelines. Try another.", 'enable-media-replace') );
|
105 |
wp_safe_redirect($redirect_error);
|
107 |
}
|
108 |
|
109 |
// Here we have the uploaded file
|
|
|
|
|
|
|
|
|
110 |
$new_filename = $_FILES["userfile"]["name"];
|
111 |
//$new_filesize = $_FILES["userfile"]["size"]; // Seems not to be in use.
|
112 |
$new_filetype = $filedata["type"];
|
113 |
|
|
|
|
|
|
|
114 |
// Gather all functions that both options do.
|
115 |
do_action('wp_handle_replace', array('post_id' => $post_id));
|
116 |
|
127 |
$returnurl = admin_url("/post.php?post={$_POST["ID"]}&action=edit&message=1");
|
128 |
|
129 |
// Execute hook actions - thanks rubious for the suggestion!
|
|
|
130 |
|
131 |
} else {
|
132 |
//TODO Better error handling when no file is selected.
|