Enable Media Replace - Version 3.3.8

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 Icon 128x128 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 CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "shortpixel/log",
3
  "description": "ShortPixel Logging",
4
- "version": "1.1.2",
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
- /* On Early init, this function might not exist, then queue it when needed */
92
- if (! function_exists('wp_get_current_user'))
93
- add_action('plugins_loaded', array($this, 'initView'));
94
- else
95
- $this->initView();
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 static function addLog($message, $level, $data = array())
136
  {
137
- $log = self::getInstance();
138
 
139
- // don't log anything too low.
140
- if ($log->logLevel < $level)
141
  {
142
  return;
143
  }
144
 
 
 
 
 
 
 
 
145
  $arg = array();
146
  $args['level'] = $level;
147
  $args['data'] = $data;
148
 
149
  $newItem = new DebugItem($message, $args);
150
- $log->items[] = $newItem;
151
 
152
- if ($log->is_active)
153
  {
154
- $log->write($newItem);
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
- static::addLog($message, $level, $args);
 
229
  }
230
  public static function addWarn($message, $args = array())
231
  {
232
  $level = DebugItem::LEVEL_WARN;
233
- static::addLog($message, $level, $args);
 
234
  }
235
  public static function addInfo($message, $args = array())
236
  {
237
  $level = DebugItem::LEVEL_INFO;
238
- static::addLog($message, $level, $args);
 
239
  }
240
  public static function addDebug($message, $args = array())
241
  {
242
  $level = DebugItem::LEVEL_DEBUG;
243
- static::addLog($message, $level, $args);
 
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.2",
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
- Log::addDebug('Notice Control - #num notices' . $cnotice);
54
- if ($notices !== false)
 
 
55
  {
56
  self::$notices = $notices;
57
  $this->has_stored = true;
@@ -64,7 +81,7 @@ class NoticeController //extends ShortPixelController
64
  }
65
 
66
 
67
- public function addNotice($message, $code, $unique)
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 false;
77
  }
78
  }
79
  self::$notices[] = $notice;
@@ -118,17 +135,97 @@ class NoticeController //extends ShortPixelController
118
 
119
  public function getNotices()
120
  {
121
- return self::$notices;
122
  }
123
 
124
- public static function getInstance()
125
  {
126
- if ( self::$instance === null)
127
- {
128
- self::$instance = new NoticeController();
129
- }
 
130
 
131
- return self::$instance;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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->getNotices() as $notice)
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
- protected $viewed = false;
10
- public $is_persistent = false; // This is a fatal issue, display until something was fixed.
 
 
 
 
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
- return "<div class='$class'>" . $icon . "<p>" . $this->message . "</p></div>";
 
 
 
 
 
 
 
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
- $uploaddir =wp_upload_dir();
25
- if (isset($uploaddir['basedir']))
26
- $log->setLogPath($uploaddir['basedir'] . "/emr_log");
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-eplace-box', __('Replace Image', 'enable-media-replace'), array($this, 'replace_meta_box'), 'attachment', 'side', 'low'); } );
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-replace-box', __('Replaced Thumbnails Preview', 'enable-media-replace'), array($this, 'show_thumbs_box'), 'attachment', 'side', 'low'); } );
67
- add_filter('postbox_classes_attachment_emr-replace-box', function($classes) { $classes[] = 'closed'; return $classes; });
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
- wp_register_script('emr_admin', plugins_url('js/emr_admin.js', EMR_ROOT_FILE), array('jquery'), false, true );
 
 
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
- $source_file = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )));
 
 
 
 
 
 
 
 
 
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
- $this->ThumbnailUpdater = new \ThumbnailUpdater($post_id);
50
- $this->ThumbnailUpdater->setOldMetadata($this->source_metadata);
 
 
 
 
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
- if(wp_attachment_is_image($this->post_id))
 
 
 
 
 
 
 
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
- $result = \wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $this->sourceFile->getFullFilePath() );
 
 
 
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
- global $wpdb;
 
 
 
 
 
 
293
 
294
  // Search-and-replace filename in post database
295
- $current_base_url = emr_get_match_url( $this->source_url);
 
 
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
- exit('Fail Safe :: Source Location seems to be a directory.');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- //INNER JOIN ' . $wpdb->posts . ' on ' . $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id
 
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
- $search_urls = emr_get_file_urls( $this->source_url, $this->source_metadata );
322
- $replace_urls = emr_get_file_urls( $this->target_url, $this->target_metadata );
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
- $post_content = str_replace( $search_urls, $replace_urls, $post_content );
333
-
334
- $sql = $wpdb->prepare(
335
- "UPDATE $wpdb->posts SET post_content = %s WHERE ID = %d;",
336
- array($post_content, $rows["ID"])
337
- );
338
- // echo "$sql <BR>";
339
- $wpdb->query( $sql );
 
 
 
 
 
 
 
 
340
  }
341
  }
342
  if (! empty($rsmeta))
@@ -345,14 +472,161 @@ class Replacer
345
  {
346
  $number_of_updates++;
347
  $content = $row['meta_value'];
348
- $content = str_replace($search_urls, $replace_urls, $content);
 
 
349
 
350
- $sql = $wpdb->prepare('UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d', $content, $row['meta_id'] );
351
- $wpdb->query($sql);
 
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
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
- jQuery(document).ready(function($)
2
- {
3
  // interface for emr.
4
- var emrIf = new function ()
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, img.naturalWidth + ' x ' + img.naturalHeight);
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
- window.enableMediaReplace = emrIf;
 
 
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.2
6
  Tested up to: 5.3
7
- Requires PHP: 5.4
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
- $filepath = get_attached_file($attachment_id); // fullpath
 
 
 
 
 
 
38
  $filetype = $attachment->post_mime_type;
39
  $filename = basename($filepath);
40
- $source_mime = get_post_mime_type($attachment_id);
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 Image', 'enable-replace-media'); ?></div>
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 replacer($post_id);
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
- if ($filedata["ext"] == "") {
 
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.