Version Description
Release date: 17th July 2019 * Check if medium size !> 400px, display that one, otherwise smallest. * Fixed: Links not updated when using Advanced Custom Fields * Fixed: Fails silently when file is too big for upload * When source file does not exist, show placeholder instead of failed image load * Fixed: Fatal error when replacing images * Fixed: Not the right time zone on replace * Fixed Beaver Builder incompatibility by not allowing replace with rename. * Fixed: Cannot replace non default Wordpress file types, even those allowed to upload [ Media Library Assistant compat ] * Fixed: error when trying to remove a file that doesn't exist - because the files are actually on another server
Download this release
Release Info
Developer | ShortPixel |
Plugin | ![]() |
Version | 3.3.2 |
Comparing to | |
See all releases |
Code changes from version 3.3.1 to 3.3.2
- build/shortpixel/PackageLoader.php +73 -0
- build/shortpixel/autoload.php +5 -0
- build/shortpixel/composer.json +1 -0
- build/shortpixel/log/composer.json +18 -0
- build/shortpixel/log/src/DebugItem.php +136 -0
- build/shortpixel/log/src/ShortPixelLogger.php +322 -0
- build/shortpixel/log/src/view-debug-box.php +57 -0
- build/shortpixel/notices/composer.json +31 -0
- build/shortpixel/notices/src/NoticeController.php +194 -0
- build/shortpixel/notices/src/NoticeModel.php +116 -0
- build/shortpixel/notices/src/css/notices.css +21 -0
- build/shortpixel/notices/src/css/notices.scss +39 -0
- classes/emr-plugin.php +33 -5
- classes/externals.php +64 -0
- classes/file.php +22 -1
- classes/replacer.php +61 -15
- classes/uihelper.php +297 -0
- composer.json +25 -0
- css/admin.css +68 -2
- enable-media-replace.php +7 -2
- js/emr_admin.js +164 -16
- readme.txt +31 -18
- scss/admin.scss +103 -4
- thumbnail_updater.php +22 -4
- views/popup.php +72 -61
- views/upload.php +67 -29
build/shortpixel/PackageLoader.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace\Build;
|
3 |
+
|
4 |
+
class PackageLoader
|
5 |
+
{
|
6 |
+
public $dir;
|
7 |
+
|
8 |
+
public function getComposerFile()
|
9 |
+
{
|
10 |
+
return json_decode(file_get_contents($this->dir."/composer.json"), 1);
|
11 |
+
}
|
12 |
+
|
13 |
+
public function load($dir)
|
14 |
+
{
|
15 |
+
$this->dir = $dir;
|
16 |
+
$composer = $this->getComposerFile();
|
17 |
+
if(isset($composer["autoload"]["psr-4"])){
|
18 |
+
$this->loadPSR4($composer['autoload']['psr-4']);
|
19 |
+
}
|
20 |
+
if(isset($composer["autoload"]["psr-0"])){
|
21 |
+
$this->loadPSR0($composer['autoload']['psr-0']);
|
22 |
+
}
|
23 |
+
if(isset($composer["autoload"]["files"])){
|
24 |
+
$this->loadFiles($composer["autoload"]["files"]);
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
public function loadFiles($files){
|
29 |
+
foreach($files as $file){
|
30 |
+
$fullpath = $this->dir."/".$file;
|
31 |
+
if(file_exists($fullpath)){
|
32 |
+
include_once($fullpath);
|
33 |
+
}
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
public function loadPSR4($namespaces)
|
38 |
+
{
|
39 |
+
$this->loadPSR($namespaces, true);
|
40 |
+
}
|
41 |
+
|
42 |
+
public function loadPSR0($namespaces)
|
43 |
+
{
|
44 |
+
$this->loadPSR($namespaces, false);
|
45 |
+
}
|
46 |
+
|
47 |
+
public function loadPSR($namespaces, $psr4)
|
48 |
+
{
|
49 |
+
$dir = $this->dir;
|
50 |
+
// Foreach namespace specified in the composer, load the given classes
|
51 |
+
foreach ($namespaces as $namespace => $classpaths) {
|
52 |
+
if (!is_array($classpaths)) {
|
53 |
+
$classpaths = array($classpaths);
|
54 |
+
}
|
55 |
+
spl_autoload_register(function ($classname) use ($namespace, $classpaths, $dir, $psr4) {
|
56 |
+
// Check if the namespace matches the class we are looking for
|
57 |
+
if (preg_match("#^".preg_quote($namespace)."#", $classname)) {
|
58 |
+
// Remove the namespace from the file path since it's psr4
|
59 |
+
if ($psr4) {
|
60 |
+
$classname = str_replace($namespace, "", $classname);
|
61 |
+
}
|
62 |
+
$filename = preg_replace("#\\\\#", "/", $classname).".php";
|
63 |
+
foreach ($classpaths as $classpath) {
|
64 |
+
$fullpath = $this->dir."/".$classpath."/$filename";
|
65 |
+
if (file_exists($fullpath)) {
|
66 |
+
include_once $fullpath;
|
67 |
+
}
|
68 |
+
}
|
69 |
+
}
|
70 |
+
});
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
build/shortpixel/autoload.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once "PackageLoader.php";
|
3 |
+
$loader = new EnableMediaReplace\Build\PackageLoader();
|
4 |
+
$loader->load(__DIR__);
|
5 |
+
|
build/shortpixel/composer.json
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
{"name":"EnableMediaReplace\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"EnableMediaReplace\\ShortPixelLogger\\":"log\/src\/","EnableMediaReplace\\Notices\\":"notices\/src\/"}}}
|
build/shortpixel/log/composer.json
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "shortpixel/log",
|
3 |
+
"description": "ShortPixel Logging",
|
4 |
+
"version": "1.1",
|
5 |
+
"type": "library",
|
6 |
+
"license": "MIT",
|
7 |
+
"authors": [
|
8 |
+
{
|
9 |
+
"name": "Bas",
|
10 |
+
"email": "bas@weblogmechanic.com"
|
11 |
+
}
|
12 |
+
],
|
13 |
+
"minimum-stability": "dev",
|
14 |
+
"require": {},
|
15 |
+
"autoload": {
|
16 |
+
"psr-4": { "ShortPixel\\ShortPixelLogger\\" : "src/" }
|
17 |
+
}
|
18 |
+
}
|
build/shortpixel/log/src/DebugItem.php
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// The data models.
|
3 |
+
namespace EnableMediaReplace\ShortPixelLogger;
|
4 |
+
|
5 |
+
|
6 |
+
class DebugItem
|
7 |
+
{
|
8 |
+
protected $time;
|
9 |
+
protected $level;
|
10 |
+
protected $message;
|
11 |
+
protected $data = array();
|
12 |
+
protected $caller = false; // array when filled
|
13 |
+
|
14 |
+
protected $model;
|
15 |
+
|
16 |
+
const LEVEL_ERROR = 1;
|
17 |
+
const LEVEL_WARN = 2;
|
18 |
+
const LEVEL_INFO = 3;
|
19 |
+
const LEVEL_DEBUG = 4;
|
20 |
+
|
21 |
+
public function __construct($message, $args)
|
22 |
+
{
|
23 |
+
$this->level = $args['level'];
|
24 |
+
$data = $args['data'];
|
25 |
+
|
26 |
+
$this->message = $message;
|
27 |
+
$this->time = microtime(true);
|
28 |
+
|
29 |
+
$this->setCaller();
|
30 |
+
|
31 |
+
// Add message to data if it seems to be some debug variable.
|
32 |
+
if (is_object($this->message) || is_array($this->message))
|
33 |
+
{
|
34 |
+
$data[] = $this->message;
|
35 |
+
$this->message = __('[Data]');
|
36 |
+
}
|
37 |
+
if (is_array($data) && count($data) > 0)
|
38 |
+
{
|
39 |
+
$dataType = $this->getDataType($data);
|
40 |
+
if ($dataType == 1) // singular
|
41 |
+
{
|
42 |
+
$this->data[] = print_r($data, true);
|
43 |
+
}
|
44 |
+
if ($dataType == 2) //array
|
45 |
+
{
|
46 |
+
foreach($data as $index => $item)
|
47 |
+
{
|
48 |
+
if (is_object($item) || is_array($item))
|
49 |
+
{
|
50 |
+
$this->data[] = print_r($item, true);
|
51 |
+
}
|
52 |
+
}
|
53 |
+
}
|
54 |
+
} // if
|
55 |
+
elseif (! is_array($data)) // this leaves out empty default arrays
|
56 |
+
{
|
57 |
+
$this->data[] = print_r($data, true);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
public function getData()
|
62 |
+
{
|
63 |
+
return array('time' => $this->time, 'level' => $this->level, 'message' => $this->message, 'data' => $this->data, 'caller' => $this->caller);
|
64 |
+
}
|
65 |
+
|
66 |
+
/** Test Data Array for possible values
|
67 |
+
*
|
68 |
+
* Data can be a collection of several debug vars, a single var, or just an normal array. Test if array has single types,
|
69 |
+
* which is a sign the array is not a collection.
|
70 |
+
*/
|
71 |
+
protected function getDataType($data)
|
72 |
+
{
|
73 |
+
$single_type = array('integer', 'boolean', 'string');
|
74 |
+
if (in_array(gettype(reset($data)), $single_type))
|
75 |
+
{
|
76 |
+
return 1;
|
77 |
+
}
|
78 |
+
else
|
79 |
+
{
|
80 |
+
return 2;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
public function getForFormat()
|
85 |
+
{
|
86 |
+
$data = $this->getData();
|
87 |
+
switch($this->level)
|
88 |
+
{
|
89 |
+
case self::LEVEL_ERROR:
|
90 |
+
$level = 'ERR';
|
91 |
+
$color = "\033[31m";
|
92 |
+
break;
|
93 |
+
case self::LEVEL_WARN:
|
94 |
+
$level = 'WRN';
|
95 |
+
$color = "\033[33m";
|
96 |
+
break;
|
97 |
+
case self::LEVEL_INFO:
|
98 |
+
$level = 'INF';
|
99 |
+
$color = "\033[37m";
|
100 |
+
break;
|
101 |
+
case self::LEVEL_DEBUG:
|
102 |
+
$level = 'DBG';
|
103 |
+
$color = "\033[37m";
|
104 |
+
break;
|
105 |
+
|
106 |
+
}
|
107 |
+
$color_end = "\033[0m";
|
108 |
+
|
109 |
+
$data['color'] = $color;
|
110 |
+
$data['color_end'] = $color_end;
|
111 |
+
$data['level'] = $level;
|
112 |
+
|
113 |
+
return $data;
|
114 |
+
|
115 |
+
//return array('time' => $this->time, 'level' => $level, 'message' => $this->message, 'data' => $this->data, 'color' => $color, 'color_end' => $color_end, 'caller' => $this->caller);
|
116 |
+
|
117 |
+
}
|
118 |
+
|
119 |
+
protected function setCaller()
|
120 |
+
{
|
121 |
+
$debug=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,5);
|
122 |
+
$i = 4;
|
123 |
+
if (isset($debug[$i]))
|
124 |
+
{
|
125 |
+
$info = $debug[$i];
|
126 |
+
$line = isset($info['line']) ? $info['line'] : 'Line unknown';
|
127 |
+
$file = isset($info['file']) ? basename($info['file']) : 'File not set';
|
128 |
+
|
129 |
+
$this->caller = array('line' => $line, 'file' => $file, 'function' => $info['function']);
|
130 |
+
}
|
131 |
+
|
132 |
+
|
133 |
+
}
|
134 |
+
|
135 |
+
|
136 |
+
}
|
build/shortpixel/log/src/ShortPixelLogger.php
ADDED
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace\ShortPixelLogger;
|
3 |
+
|
4 |
+
/*** Logger class
|
5 |
+
*
|
6 |
+
* Class uses the debug data model for keeping log entries.
|
7 |
+
* Logger should not be called before init hook!
|
8 |
+
*/
|
9 |
+
class ShortPixelLogger
|
10 |
+
{
|
11 |
+
static protected $instance = null;
|
12 |
+
protected $start_time;
|
13 |
+
|
14 |
+
protected $is_active = false;
|
15 |
+
protected $is_manual_request = false;
|
16 |
+
protected $show_debug_view = false;
|
17 |
+
|
18 |
+
protected $items = array();
|
19 |
+
protected $logPath = false;
|
20 |
+
protected $logMode = FILE_APPEND;
|
21 |
+
|
22 |
+
protected $logLevel;
|
23 |
+
protected $format = "[ %%time%% ] %%color%% %%level%% %%color_end%% \t %%message%% \t %%caller%% ( %%time_passed%% )";
|
24 |
+
protected $format_data = "\t %%data%% ";
|
25 |
+
|
26 |
+
protected $hooks = array();
|
27 |
+
/* protected $hooks = array(
|
28 |
+
'shortpixel_image_exists' => array('numargs' => 3),
|
29 |
+
'shortpixel_webp_image_base' => array('numargs' => 2),
|
30 |
+
'shortpixel_image_urls' => array('numargs' => 2),
|
31 |
+
); // @todo monitor hooks, but this should be more dynamic. Do when moving to module via config.
|
32 |
+
*/
|
33 |
+
|
34 |
+
// utility
|
35 |
+
private $namespace;
|
36 |
+
private $view;
|
37 |
+
|
38 |
+
protected $template = 'view-debug-box';
|
39 |
+
|
40 |
+
/** Debugger constructor
|
41 |
+
* Two ways to activate the debugger. 1) Define SHORTPIXEL_DEBUG in wp-config.php. Either must be true or a number corresponding to required LogLevel
|
42 |
+
* 2) Put SHORTPIXEL_DEBUG in the request. Either true or number.
|
43 |
+
*/
|
44 |
+
public function __construct()
|
45 |
+
{
|
46 |
+
$this->start_time = microtime(true);
|
47 |
+
$this->logLevel = DebugItem::LEVEL_WARN;
|
48 |
+
|
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 = $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;
|
61 |
+
$this->is_active = true;
|
62 |
+
|
63 |
+
if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true')
|
64 |
+
{
|
65 |
+
$this->logLevel = DebugItem::LEVEL_INFO;
|
66 |
+
}
|
67 |
+
else {
|
68 |
+
$this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']);
|
69 |
+
}
|
70 |
+
|
71 |
+
}
|
72 |
+
else if ( (defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG > 0) )
|
73 |
+
{
|
74 |
+
$this->is_active = true;
|
75 |
+
if (SHORTPIXEL_DEBUG === true)
|
76 |
+
$this->logLevel = DebugItem::LEVEL_INFO;
|
77 |
+
else {
|
78 |
+
$this->logLevel = intval(SHORTPIXEL_DEBUG);
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
if (defined('SHORTPIXEL_DEBUG_TARGET') && SHORTPIXEL_DEBUG_TARGET || $this->is_manual_request)
|
83 |
+
{
|
84 |
+
//$this->logPath = SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log";
|
85 |
+
//$this->logMode = defined('SHORTPIXEL_LOG_OVERWRITE') ? 0 : FILE_APPEND;
|
86 |
+
if (defined('SHORTPIXEL_LOG_OVERWRITE')) // if overwrite, do this on init once.
|
87 |
+
file_put_contents($this->logPath,'-- Log Reset -- ' .PHP_EOL);
|
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();
|
100 |
+
}
|
101 |
+
|
102 |
+
/** Init the view when needed. Private function ( public because of WP_HOOK )
|
103 |
+
* Never call directly */
|
104 |
+
public function initView()
|
105 |
+
{
|
106 |
+
$user_is_administrator = (current_user_can('manage_options')) ? true : false;
|
107 |
+
|
108 |
+
if ($this->is_active && $this->is_manual_request && $user_is_administrator )
|
109 |
+
{
|
110 |
+
$content_url = content_url();
|
111 |
+
$logPath = $this->logPath;
|
112 |
+
$pathpos = strpos($logPath, 'wp-content') + strlen('wp-content');
|
113 |
+
$logPart = substr($logPath, $pathpos);
|
114 |
+
$logLink = $content_url . $logPart;
|
115 |
+
|
116 |
+
$this->view = new \stdClass;
|
117 |
+
$this->view->logLink = $logLink;
|
118 |
+
add_action('admin_footer', array($this, 'loadView'));
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
public static function getInstance()
|
123 |
+
{
|
124 |
+
if ( self::$instance === null)
|
125 |
+
{
|
126 |
+
self::$instance = new ShortPixelLogger();
|
127 |
+
}
|
128 |
+
return self::$instance;
|
129 |
+
}
|
130 |
+
|
131 |
+
public function setLogPath($logPath)
|
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 |
+
|
158 |
+
/** Writes to log File. */
|
159 |
+
protected function write($debugItem, $mode = 'file')
|
160 |
+
{
|
161 |
+
$items = $debugItem->getForFormat();
|
162 |
+
$items['time_passed'] = round ( ($items['time'] - $this->start_time), 5);
|
163 |
+
$items['time'] = date('Y-m-d H:i:s', $items['time'] );
|
164 |
+
|
165 |
+
if ( ($items['caller']) && is_array($items['caller']) && count($items['caller']) > 0)
|
166 |
+
{
|
167 |
+
$caller = $items['caller'];
|
168 |
+
$items['caller'] = $caller['file'] . ' in ' . $caller['function'] . '(' . $caller['line'] . ')';
|
169 |
+
}
|
170 |
+
|
171 |
+
$line = $this->formatLine($items);
|
172 |
+
|
173 |
+
if ($this->logPath)
|
174 |
+
{
|
175 |
+
file_put_contents($this->logPath,$line, FILE_APPEND);
|
176 |
+
}
|
177 |
+
else {
|
178 |
+
error_log($line);
|
179 |
+
}
|
180 |
+
}
|
181 |
+
|
182 |
+
protected function formatLine($args = array() )
|
183 |
+
{
|
184 |
+
$line= $this->format;
|
185 |
+
foreach($args as $key => $value)
|
186 |
+
{
|
187 |
+
if (! is_array($value) && ! is_object($value))
|
188 |
+
$line = str_replace('%%' . $key . '%%', $value, $line);
|
189 |
+
}
|
190 |
+
|
191 |
+
$line .= PHP_EOL;
|
192 |
+
|
193 |
+
if (isset($args['data']))
|
194 |
+
{
|
195 |
+
$data = array_filter($args['data']);
|
196 |
+
if (count($data) > 0)
|
197 |
+
{
|
198 |
+
foreach($data as $item)
|
199 |
+
{
|
200 |
+
$line .= $item . PHP_EOL;
|
201 |
+
}
|
202 |
+
}
|
203 |
+
}
|
204 |
+
|
205 |
+
return $line;
|
206 |
+
}
|
207 |
+
|
208 |
+
protected function setLogLevel($level)
|
209 |
+
{
|
210 |
+
$this->logLevel = $level;
|
211 |
+
}
|
212 |
+
|
213 |
+
protected function getEnv($name)
|
214 |
+
{
|
215 |
+
if (isset($this->{$name}))
|
216 |
+
{
|
217 |
+
return $this->{$name};
|
218 |
+
}
|
219 |
+
else {
|
220 |
+
return false;
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
public static function addError($message, $args = array())
|
225 |
+
{
|
226 |
+
$level = DebugItem::LEVEL_ERROR;
|
227 |
+
static::addLog($message, $level, $args);
|
228 |
+
}
|
229 |
+
public static function addWarn($message, $args = array())
|
230 |
+
{
|
231 |
+
$level = DebugItem::LEVEL_WARN;
|
232 |
+
static::addLog($message, $level, $args);
|
233 |
+
}
|
234 |
+
public static function addInfo($message, $args = array())
|
235 |
+
{
|
236 |
+
$level = DebugItem::LEVEL_INFO;
|
237 |
+
static::addLog($message, $level, $args);
|
238 |
+
}
|
239 |
+
public static function addDebug($message, $args = array())
|
240 |
+
{
|
241 |
+
$level = DebugItem::LEVEL_DEBUG;
|
242 |
+
static::addLog($message, $level, $args);
|
243 |
+
}
|
244 |
+
|
245 |
+
public static function logLevel($level)
|
246 |
+
{
|
247 |
+
$log = self::getInstance();
|
248 |
+
static::addInfo('Changing Log level' . $level);
|
249 |
+
$log->setLogLevel($level);
|
250 |
+
}
|
251 |
+
|
252 |
+
public static function getLogLevel()
|
253 |
+
{
|
254 |
+
$log = self::getInstance();
|
255 |
+
return $log->getEnv('logLevel');
|
256 |
+
}
|
257 |
+
|
258 |
+
public static function isManualDebug()
|
259 |
+
{
|
260 |
+
$log = self::getInstance();
|
261 |
+
return $log->getEnv('is_manual_request');
|
262 |
+
}
|
263 |
+
|
264 |
+
public static function getLogPath()
|
265 |
+
{
|
266 |
+
$log = self::getInstance();
|
267 |
+
return $log->getEnv('logPath');
|
268 |
+
}
|
269 |
+
|
270 |
+
/** Function to test if the debugger is active
|
271 |
+
* @return boolean true when active.
|
272 |
+
*/
|
273 |
+
public static function debugIsActive()
|
274 |
+
{
|
275 |
+
$log = self::getInstance();
|
276 |
+
return $log->getEnv('is_active');
|
277 |
+
}
|
278 |
+
|
279 |
+
protected function monitorHooks()
|
280 |
+
{
|
281 |
+
|
282 |
+
foreach($this->hooks as $hook => $data)
|
283 |
+
{
|
284 |
+
$numargs = isset($data['numargs']) ? $data['numargs'] : 1;
|
285 |
+
$prio = isset($data['priority']) ? $data['priority'] : 10;
|
286 |
+
|
287 |
+
add_filter($hook, function($value) use ($hook) {
|
288 |
+
$args = func_get_args();
|
289 |
+
return $this->logHook($hook, $value, $args); }, $prio, $numargs);
|
290 |
+
}
|
291 |
+
}
|
292 |
+
|
293 |
+
public function logHook($hook, $value, $args)
|
294 |
+
{
|
295 |
+
array_shift($args);
|
296 |
+
self::addInfo('[Hook] - ' . $hook . ' with ' . var_export($value,true), $args);
|
297 |
+
return $value;
|
298 |
+
}
|
299 |
+
|
300 |
+
public function loadView()
|
301 |
+
{
|
302 |
+
// load either param or class template.
|
303 |
+
$template = $this->template;
|
304 |
+
|
305 |
+
$view = $this->view;
|
306 |
+
$view->namespace = $this->namespace;
|
307 |
+
$controller = $this;
|
308 |
+
|
309 |
+
$template_path = __DIR__ . '/' . $this->template . '.php';
|
310 |
+
if (file_exists($template_path))
|
311 |
+
{
|
312 |
+
|
313 |
+
include($template_path);
|
314 |
+
}
|
315 |
+
else {
|
316 |
+
self::addError("View $template could not be found in " . $template_path,
|
317 |
+
array('class' => get_class($this), 'req' => $_REQUEST));
|
318 |
+
}
|
319 |
+
}
|
320 |
+
|
321 |
+
|
322 |
+
} // class debugController
|
build/shortpixel/log/src/view-debug-box.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Debug Box to load Log File
|
3 |
+
namespace EnableMediaReplace\ShortPixelLogger;
|
4 |
+
wp_enqueue_script( 'jquery-ui-draggable' );
|
5 |
+
|
6 |
+
?>
|
7 |
+
|
8 |
+
<style>
|
9 |
+
.sp_debug_wrap
|
10 |
+
{
|
11 |
+
position: relative;
|
12 |
+
clear: both;
|
13 |
+
}
|
14 |
+
.sp_debug_box
|
15 |
+
{
|
16 |
+
position: absolute;
|
17 |
+
right: 0px;
|
18 |
+
top: 50px;
|
19 |
+
background-color: #fff;
|
20 |
+
width: 150px;
|
21 |
+
z-index: 1000000;
|
22 |
+
border: 1px solid #000;
|
23 |
+
|
24 |
+
}
|
25 |
+
.sp_debug_box .header
|
26 |
+
{
|
27 |
+
min-height: 10px;
|
28 |
+
background: #000;
|
29 |
+
color: #fff;
|
30 |
+
padding: 8px
|
31 |
+
}
|
32 |
+
.sp_debug_box .content_box
|
33 |
+
{
|
34 |
+
background: #ccc;
|
35 |
+
}
|
36 |
+
.content_box
|
37 |
+
{
|
38 |
+
padding: 8px;
|
39 |
+
}
|
40 |
+
</style>
|
41 |
+
|
42 |
+
<script language='javascript'>
|
43 |
+
jQuery(document).ready(function($)
|
44 |
+
{
|
45 |
+
$( ".sp_debug_box" ).draggable();
|
46 |
+
|
47 |
+
});
|
48 |
+
</script>
|
49 |
+
|
50 |
+
|
51 |
+
<div class='sp_debug_box'>
|
52 |
+
<div class='header'><?php echo $view->namespace ?> Debug Box </div>
|
53 |
+
<a target="_blank" href='<?php echo $view->logLink ?>'>Logfile</a>
|
54 |
+
<div class='content_box'>
|
55 |
+
|
56 |
+
</div>
|
57 |
+
</div>
|
build/shortpixel/notices/composer.json
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "shortpixel/notices",
|
3 |
+
"description": "ShortPixel WordPress Notice System",
|
4 |
+
"version": "1.1",
|
5 |
+
"type": "library",
|
6 |
+
"license": "MIT",
|
7 |
+
"authors": [
|
8 |
+
{
|
9 |
+
"name": "Bas",
|
10 |
+
"email": "bas@weblogmechanic.com"
|
11 |
+
}
|
12 |
+
],
|
13 |
+
"minimum-stability": "dev",
|
14 |
+
"require": {
|
15 |
+
"shortpixel/log" : "1.1.*"
|
16 |
+
},
|
17 |
+
"repositories": [
|
18 |
+
{
|
19 |
+
"packagist.org": false,
|
20 |
+
"type": "path",
|
21 |
+
"url": "../modules/",
|
22 |
+
"options": {
|
23 |
+
"symlink": true
|
24 |
+
}
|
25 |
+
}
|
26 |
+
],
|
27 |
+
|
28 |
+
"autoload": {
|
29 |
+
"psr-4": { "ShortPixel\\Notices\\" : "src/" }
|
30 |
+
}
|
31 |
+
}
|
build/shortpixel/notices/src/NoticeController.php
ADDED
@@ -0,0 +1,194 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace\Notices;
|
3 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
class NoticeController //extends ShortPixelController
|
6 |
+
{
|
7 |
+
protected static $notices = array();
|
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;
|
14 |
+
|
15 |
+
protected $notice_option = ''; // The wp_options name for notices here.
|
16 |
+
|
17 |
+
/** For backward compat. Never call constructor directly. */
|
18 |
+
public function __construct()
|
19 |
+
{
|
20 |
+
// $this->loadModel('notice');
|
21 |
+
$ns = __NAMESPACE__;
|
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');
|
38 |
+
$json_config = json_decode($config);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
public function loadIcons($icons)
|
43 |
+
{
|
44 |
+
foreach($icons as $name => $icon)
|
45 |
+
NoticeModel::setIcon($name, $icon);
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
protected function loadNotices()
|
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;
|
58 |
+
}
|
59 |
+
else {
|
60 |
+
self::$notices = array();
|
61 |
+
$this->has_stored = false;
|
62 |
+
}
|
63 |
+
$this->countNotices();
|
64 |
+
}
|
65 |
+
|
66 |
+
|
67 |
+
public function addNotice($message, $code)
|
68 |
+
{
|
69 |
+
$notice = new NoticeModel($message, $code);
|
70 |
+
self::$notices[] = $notice;
|
71 |
+
$this->countNotices();
|
72 |
+
Log::addDebug('Adding notice - ', $notice);
|
73 |
+
$this->update();
|
74 |
+
return $notice;
|
75 |
+
}
|
76 |
+
|
77 |
+
/** Update the notices to store, check what to remove, returns count. */
|
78 |
+
public function update()
|
79 |
+
{
|
80 |
+
if (! is_array(self::$notices) || count(self::$notices) == 0)
|
81 |
+
{
|
82 |
+
if ($this->has_stored)
|
83 |
+
delete_option($this->notice_option);
|
84 |
+
|
85 |
+
return 0;
|
86 |
+
}
|
87 |
+
|
88 |
+
$new_notices = array();
|
89 |
+
foreach(self::$notices as $item)
|
90 |
+
{
|
91 |
+
if (! $item->isDone() )
|
92 |
+
{
|
93 |
+
$new_notices[] = $item;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
update_option($this->notice_option, $new_notices);
|
98 |
+
self::$notices = $new_notices;
|
99 |
+
|
100 |
+
return $this->countNotices();
|
101 |
+
}
|
102 |
+
|
103 |
+
public function countNotices()
|
104 |
+
{
|
105 |
+
$this->notice_count = count(self::$notices);
|
106 |
+
return $this->notice_count;
|
107 |
+
}
|
108 |
+
|
109 |
+
|
110 |
+
public function getNotices()
|
111 |
+
{
|
112 |
+
return self::$notices;
|
113 |
+
}
|
114 |
+
|
115 |
+
public static function getInstance()
|
116 |
+
{
|
117 |
+
if ( self::$instance === null)
|
118 |
+
{
|
119 |
+
self::$instance = new NoticeController();
|
120 |
+
}
|
121 |
+
|
122 |
+
return self::$instance;
|
123 |
+
}
|
124 |
+
|
125 |
+
/** Adds a notice, quick and fast method
|
126 |
+
* @param String $message The Message you want to notify
|
127 |
+
* @param int $code A value of messageType as defined in model
|
128 |
+
* @returm Object Instance of noticeModel
|
129 |
+
*/
|
130 |
+
|
131 |
+
public static function addNormal($message)
|
132 |
+
{
|
133 |
+
$noticeController = self::getInstance();
|
134 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_NORMAL);
|
135 |
+
return $notice;
|
136 |
+
|
137 |
+
}
|
138 |
+
|
139 |
+
public static function addError($message)
|
140 |
+
{
|
141 |
+
$noticeController = self::getInstance();
|
142 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_ERROR);
|
143 |
+
return $notice;
|
144 |
+
|
145 |
+
}
|
146 |
+
|
147 |
+
public static function addWarning($message)
|
148 |
+
{
|
149 |
+
$noticeController = self::getInstance();
|
150 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_WARNING);
|
151 |
+
return $notice;
|
152 |
+
|
153 |
+
}
|
154 |
+
|
155 |
+
public static function addSuccess($message)
|
156 |
+
{
|
157 |
+
$noticeController = self::getInstance();
|
158 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_SUCCESS);
|
159 |
+
return $notice;
|
160 |
+
|
161 |
+
}
|
162 |
+
|
163 |
+
public function admin_notices()
|
164 |
+
{
|
165 |
+
if ($this->countNotices() > 0)
|
166 |
+
{
|
167 |
+
if (! self::$cssHookLoaded)
|
168 |
+
{
|
169 |
+
add_action('admin_print_footer_scripts', array($this, 'printNoticeStyle'));
|
170 |
+
self::$cssHookLoaded = true;
|
171 |
+
}
|
172 |
+
foreach($this->getNotices() as $notice)
|
173 |
+
{
|
174 |
+
echo $notice->getForDisplay();
|
175 |
+
}
|
176 |
+
}
|
177 |
+
$this->update(); // puts views, and updates
|
178 |
+
}
|
179 |
+
|
180 |
+
public function printNoticeStyle()
|
181 |
+
{
|
182 |
+
if (file_exists(__DIR__ . '/css/notices.css'))
|
183 |
+
{
|
184 |
+
echo '<style>' . file_get_contents(__DIR__ . '/css/notices.css') . '</style>';
|
185 |
+
}
|
186 |
+
else {
|
187 |
+
Log::addDebug('Notices : css/notices.css could not be loaded');
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
|
192 |
+
|
193 |
+
|
194 |
+
}
|
build/shortpixel/notices/src/NoticeModel.php
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace\Notices;
|
3 |
+
|
4 |
+
class NoticeModel //extends ShortPixelModel
|
5 |
+
{
|
6 |
+
protected $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;
|
17 |
+
const NOTICE_ERROR = 2;
|
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;
|
25 |
+
$this->messageType = $messageType;
|
26 |
+
|
27 |
+
}
|
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)
|
39 |
+
{
|
40 |
+
switch($notice_type)
|
41 |
+
{
|
42 |
+
case 'error':
|
43 |
+
$type = self::NOTICE_ERROR;
|
44 |
+
break;
|
45 |
+
case 'success':
|
46 |
+
$type = self::NOTICE_SUCCESS;
|
47 |
+
break;
|
48 |
+
case 'warning':
|
49 |
+
$type = self::NOTICE_WARNING;
|
50 |
+
break;
|
51 |
+
case 'normal':
|
52 |
+
default:
|
53 |
+
$type = self::NOTICE_NORMAL;
|
54 |
+
break;
|
55 |
+
}
|
56 |
+
self::$icons[$type] = $icon;
|
57 |
+
}
|
58 |
+
|
59 |
+
public function getForDisplay()
|
60 |
+
{
|
61 |
+
$this->viewed = true;
|
62 |
+
$class = 'shortpixel notice ';
|
63 |
+
|
64 |
+
$icon = '';
|
65 |
+
|
66 |
+
switch($this->messageType)
|
67 |
+
{
|
68 |
+
case self::NOTICE_ERROR:
|
69 |
+
$class .= 'notice-error ';
|
70 |
+
$icon = isset(self::$icons[self::NOTICE_ERROR]) ? self::$icons[self::NOTICE_ERROR] : '';
|
71 |
+
//$icon = 'scared';
|
72 |
+
break;
|
73 |
+
case self::NOTICE_SUCCESS:
|
74 |
+
$class .= 'notice-success ';
|
75 |
+
$icon = isset(self::$icons[self::NOTICE_SUCCESS]) ? self::$icons[self::NOTICE_SUCCESS] : '';
|
76 |
+
break;
|
77 |
+
case self::NOTICE_WARNING:
|
78 |
+
$class .= 'notice-warning ';
|
79 |
+
$icon = isset(self::$icons[self::NOTICE_WARNING]) ? self::$icons[self::NOTICE_WARNING] : '';
|
80 |
+
break;
|
81 |
+
case self::NOTICE_NORMAL:
|
82 |
+
$class .= 'notice-info ';
|
83 |
+
$icon = isset(self::$icons[self::NOTICE_NORMAL]) ? self::$icons[self::NOTICE_NORMAL] : '';
|
84 |
+
break;
|
85 |
+
default:
|
86 |
+
$class .= 'notice-info ';
|
87 |
+
$icon = '';
|
88 |
+
break;
|
89 |
+
}
|
90 |
+
|
91 |
+
/*$image = '<img src="' . plugins_url('/shortpixel-image-optimiser/res/img/robo-' . $icon . '.png') . '"
|
92 |
+
srcset="' . plugins_url( 'shortpixel-image-optimiser/res/img/robo-' . $icon . '.png' ) . ' 1x, ' . plugins_url( 'shortpixel-image-optimiser/res/img/robo-' . $icon . '@2x.png') . ' 2x" class="short-pixel-notice-icon">';
|
93 |
+
*/
|
94 |
+
|
95 |
+
if ($this->is_removable)
|
96 |
+
{
|
97 |
+
$class .= 'is-dismissible ';
|
98 |
+
}
|
99 |
+
|
100 |
+
if ($this->is_persistent)
|
101 |
+
{
|
102 |
+
$class .= '';
|
103 |
+
}
|
104 |
+
|
105 |
+
return "<div class='$class'>" . $icon . "<p>" . $this->message . "</p></div>";
|
106 |
+
|
107 |
+
}
|
108 |
+
|
109 |
+
|
110 |
+
|
111 |
+
// @todo Transient save, since that is used in some parts.
|
112 |
+
// save
|
113 |
+
// load
|
114 |
+
|
115 |
+
|
116 |
+
}
|
build/shortpixel/notices/src/css/notices.css
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.shortpixel.notice {
|
2 |
+
padding: 8px; }
|
3 |
+
.shortpixel.notice img {
|
4 |
+
display: inline-block;
|
5 |
+
margin: 0 25px 0 0;
|
6 |
+
max-height: 50px; }
|
7 |
+
.shortpixel.notice .notice-dismiss {
|
8 |
+
margin-top: 10px; }
|
9 |
+
|
10 |
+
/* In-view notice ( not on top, between the options ) - styled after WP notice */
|
11 |
+
.view-notice {
|
12 |
+
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
|
13 |
+
border: 4px solid #fff;
|
14 |
+
padding: 1px 12px; }
|
15 |
+
.view-notice p {
|
16 |
+
margin: 1em 0 !important; }
|
17 |
+
.view-notice.warning {
|
18 |
+
border-left-color: #ffb900; }
|
19 |
+
|
20 |
+
.view-notice-row {
|
21 |
+
display: none; }
|
build/shortpixel/notices/src/css/notices.scss
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
.shortpixel.notice
|
3 |
+
{
|
4 |
+
//padding: 18px;
|
5 |
+
//min-height: 50px;
|
6 |
+
padding: 8px;
|
7 |
+
img
|
8 |
+
{
|
9 |
+
display:inline-block;
|
10 |
+
margin: 0 25px 0 0;
|
11 |
+
max-height: 50px;
|
12 |
+
}
|
13 |
+
.notice-dismiss
|
14 |
+
{
|
15 |
+
margin-top: 10px;
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
/* In-view notice ( not on top, between the options ) - styled after WP notice */
|
20 |
+
.view-notice
|
21 |
+
{
|
22 |
+
|
23 |
+
box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
|
24 |
+
border: 4px solid #fff;
|
25 |
+
|
26 |
+
padding: 1px 12px;
|
27 |
+
p {
|
28 |
+
margin: 1em 0 !important;
|
29 |
+
}
|
30 |
+
&.warning
|
31 |
+
{
|
32 |
+
border-left-color: #ffb900;
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
.view-notice-row
|
37 |
+
{
|
38 |
+
display: none;
|
39 |
+
}
|
classes/emr-plugin.php
CHANGED
@@ -1,19 +1,29 @@
|
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
|
|
|
|
3 |
|
4 |
// Does what a plugin does.
|
5 |
class EnableMediaReplacePlugin
|
6 |
{
|
7 |
|
8 |
protected $plugin_path;
|
|
|
9 |
|
10 |
public function __construct()
|
11 |
{
|
12 |
$this->plugin_actions(); // init
|
|
|
13 |
|
|
|
|
|
|
|
|
|
14 |
|
|
|
15 |
}
|
16 |
|
|
|
17 |
public function plugin_actions()
|
18 |
{
|
19 |
$this->plugin_path = plugin_dir_path(EMR_ROOT_FILE);
|
@@ -51,11 +61,21 @@ class EnableMediaReplacePlugin
|
|
51 |
|
52 |
/**
|
53 |
* Initialize this plugin. Called by 'admin_init' hook.
|
54 |
-
*
|
55 |
*/
|
56 |
public function init()
|
57 |
{
|
58 |
load_plugin_textdomain( 'enable-media-replace', false, basename(dirname(EMR_ROOT_FILE) ) . '/languages' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
/** Load EMR views based on request */
|
@@ -109,7 +129,16 @@ class EnableMediaReplacePlugin
|
|
109 |
}
|
110 |
|
111 |
wp_register_script('emr_admin', plugins_url('js/emr_admin.js', EMR_ROOT_FILE), array('jquery'), false, true );
|
112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
|
114 |
}
|
115 |
|
@@ -170,7 +199,7 @@ class EnableMediaReplacePlugin
|
|
170 |
$form_fields["enable-media-replace"] = array(
|
171 |
"label" => esc_html__("Replace media", "enable-media-replace"),
|
172 |
"input" => "html",
|
173 |
-
"html" => "<p><a class='button-secondary
|
174 |
);
|
175 |
|
176 |
return $form_fields;
|
@@ -180,7 +209,6 @@ class EnableMediaReplacePlugin
|
|
180 |
* @param array $mime_types
|
181 |
* @return array
|
182 |
*/
|
183 |
-
|
184 |
public function add_mime_types($mime_types)
|
185 |
{
|
186 |
$mime_types['dat'] = 'text/plain'; // Adding .dat extension
|
@@ -202,7 +230,7 @@ class EnableMediaReplacePlugin
|
|
202 |
} */
|
203 |
$link = "href=\"$editurl\"";
|
204 |
|
205 |
-
$newaction['adddata'] = '<a ' . $link . ' aria-label="' .
|
206 |
return array_merge($actions,$newaction);
|
207 |
}
|
208 |
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
use EnableMediaReplace\Notices\NoticeController as Notices;
|
5 |
|
6 |
// Does what a plugin does.
|
7 |
class EnableMediaReplacePlugin
|
8 |
{
|
9 |
|
10 |
protected $plugin_path;
|
11 |
+
private static $instance;
|
12 |
|
13 |
public function __construct()
|
14 |
{
|
15 |
$this->plugin_actions(); // init
|
16 |
+
}
|
17 |
|
18 |
+
public static function get()
|
19 |
+
{
|
20 |
+
if (is_null(self::$instance))
|
21 |
+
self::$instance = new EnableMediaReplacePlugin();
|
22 |
|
23 |
+
return self::$instance;
|
24 |
}
|
25 |
|
26 |
+
|
27 |
public function plugin_actions()
|
28 |
{
|
29 |
$this->plugin_path = plugin_dir_path(EMR_ROOT_FILE);
|
61 |
|
62 |
/**
|
63 |
* Initialize this plugin. Called by 'admin_init' hook.
|
64 |
+
*
|
65 |
*/
|
66 |
public function init()
|
67 |
{
|
68 |
load_plugin_textdomain( 'enable-media-replace', false, basename(dirname(EMR_ROOT_FILE) ) . '/languages' );
|
69 |
+
|
70 |
+
// Load Submodules
|
71 |
+
Log::addDebug('Plugin Init');
|
72 |
+
$notices = Notices::getInstance();
|
73 |
+
|
74 |
+
// Enqueue notices
|
75 |
+
add_action('admin_notices', array($notices, 'admin_notices')); // previous page / init time
|
76 |
+
add_action('admin_footer', array($notices, 'admin_notices')); // fresh notices between init - end
|
77 |
+
|
78 |
+
new Externals();
|
79 |
}
|
80 |
|
81 |
/** Load EMR views based on request */
|
129 |
}
|
130 |
|
131 |
wp_register_script('emr_admin', plugins_url('js/emr_admin.js', EMR_ROOT_FILE), array('jquery'), false, true );
|
132 |
+
$emr_options = array(
|
133 |
+
'dateFormat' => $this->convertdate(get_option( 'date_format' )),
|
134 |
+
'maxfilesize' => wp_max_upload_size(),
|
135 |
+
|
136 |
+
);
|
137 |
+
|
138 |
+
if (Log::debugIsActive())
|
139 |
+
$emr_options['is_debug'] = true;
|
140 |
+
|
141 |
+
wp_localize_script('emr_admin', 'emr_options', $emr_options);
|
142 |
|
143 |
}
|
144 |
|
199 |
$form_fields["enable-media-replace"] = array(
|
200 |
"label" => esc_html__("Replace media", "enable-media-replace"),
|
201 |
"input" => "html",
|
202 |
+
"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")
|
203 |
);
|
204 |
|
205 |
return $form_fields;
|
209 |
* @param array $mime_types
|
210 |
* @return array
|
211 |
*/
|
|
|
212 |
public function add_mime_types($mime_types)
|
213 |
{
|
214 |
$mime_types['dat'] = 'text/plain'; // Adding .dat extension
|
230 |
} */
|
231 |
$link = "href=\"$editurl\"";
|
232 |
|
233 |
+
$newaction['adddata'] = '<a ' . $link . ' aria-label="' . esc_attr__("Replace media", "enable-media-replace") . '" rel="permalink">' . esc_html__("Replace media", "enable-media-replace") . '</a>';
|
234 |
return array_merge($actions,$newaction);
|
235 |
}
|
236 |
|
classes/externals.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace;
|
3 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
use EnableMediaReplace\Notices\NoticeController as Notices;
|
5 |
+
|
6 |
+
|
7 |
+
class Externals
|
8 |
+
{
|
9 |
+
protected $replaceType = null;
|
10 |
+
protected $replaceSearchType = null;
|
11 |
+
|
12 |
+
protected $messages = array();
|
13 |
+
|
14 |
+
|
15 |
+
public function __construct()
|
16 |
+
{
|
17 |
+
add_filter('emr_display_replace_type_options', array($this, 'get_replace_type'));
|
18 |
+
add_filter('emr_enable_replace_and_search', array($this, 'get_replacesearch_type'));
|
19 |
+
|
20 |
+
add_action('emr_after_replace_type_options', array($this, 'get_messages'));
|
21 |
+
|
22 |
+
|
23 |
+
$this->check();
|
24 |
+
}
|
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)
|
36 |
+
{
|
37 |
+
if ($this->replaceType === null)
|
38 |
+
return $bool;
|
39 |
+
|
40 |
+
return $this->replaceType;
|
41 |
+
}
|
42 |
+
|
43 |
+
public function get_replacesearch_type($bool)
|
44 |
+
{
|
45 |
+
if ($this->replaceSearchType === null)
|
46 |
+
return $bool;
|
47 |
+
|
48 |
+
return $this->replaceSearchType;
|
49 |
+
}
|
50 |
+
|
51 |
+
public function get_messages()
|
52 |
+
{
|
53 |
+
foreach($this->messages as $message)
|
54 |
+
{
|
55 |
+
echo '<span class="nofeature-notice"><p>'. $message . '</p></span>';
|
56 |
+
}
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
|
62 |
+
|
63 |
+
|
64 |
+
}
|
classes/file.php
CHANGED
@@ -1,6 +1,9 @@
|
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
|
|
|
|
|
|
|
4 |
class emrFile
|
5 |
{
|
6 |
|
@@ -36,7 +39,15 @@ class emrFile
|
|
36 |
// This will *not* be checked, is not meant for permission of validation!
|
37 |
$this->fileMime = (isset($filedata['type'])) ? $filedata['type'] : false;
|
38 |
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
}
|
41 |
|
42 |
public function getFullFilePath()
|
@@ -64,11 +75,21 @@ class emrFile
|
|
64 |
return $this->fileName;
|
65 |
}
|
66 |
|
|
|
|
|
|
|
|
|
|
|
67 |
public function getFileMime()
|
68 |
{
|
69 |
return $this->fileMime;
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
72 |
|
73 |
}
|
74 |
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
|
4 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
5 |
+
use EnableMediaReplace\Notices\NoticeController as Notices;
|
6 |
+
|
7 |
class emrFile
|
8 |
{
|
9 |
|
39 |
// This will *not* be checked, is not meant for permission of validation!
|
40 |
$this->fileMime = (isset($filedata['type'])) ? $filedata['type'] : false;
|
41 |
|
42 |
+
}
|
43 |
+
|
44 |
+
public function checkAndCreateFolder()
|
45 |
+
{
|
46 |
+
$path = $this->getFilePath();
|
47 |
+
if (! is_dir($path) && ! file_exists($path))
|
48 |
+
{
|
49 |
+
return wp_mkdir_p($path);
|
50 |
+
}
|
51 |
}
|
52 |
|
53 |
public function getFullFilePath()
|
75 |
return $this->fileName;
|
76 |
}
|
77 |
|
78 |
+
public function getFileExtension()
|
79 |
+
{
|
80 |
+
return $this->extension;
|
81 |
+
}
|
82 |
+
|
83 |
public function getFileMime()
|
84 |
{
|
85 |
return $this->fileMime;
|
86 |
}
|
87 |
|
88 |
+
public function exists()
|
89 |
+
{
|
90 |
+
return $this->exists;
|
91 |
+
}
|
92 |
+
|
93 |
|
94 |
}
|
95 |
|
classes/replacer.php
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
use \EnableMediaReplace\emrFile as File;
|
|
|
|
|
4 |
|
5 |
class Replacer
|
6 |
{
|
@@ -39,6 +41,7 @@ class Replacer
|
|
39 |
$source_file = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )));
|
40 |
|
41 |
$this->sourceFile = new File($source_file);
|
|
|
42 |
$this->source_post = get_post($post_id);
|
43 |
$this->source_is_image = wp_attachment_is('image', $this->source_post);
|
44 |
$this->source_metadata = wp_get_attachment_metadata( $post_id );
|
@@ -65,6 +68,7 @@ class Replacer
|
|
65 |
/** Replace the sourceFile with a target
|
66 |
* @param $file String Full Path to the Replacement File. This will usually be an uploaded file in /tmp/
|
67 |
* @param $fileName String The fileName of the uploaded file. This will be used if sourcefile is not to be overwritten.
|
|
|
68 |
*/
|
69 |
public function replaceWith($file, $fileName)
|
70 |
{
|
@@ -78,18 +82,25 @@ class Replacer
|
|
78 |
|
79 |
if (is_null($targetFile))
|
80 |
{
|
81 |
-
|
82 |
-
|
83 |
}
|
84 |
|
|
|
|
|
|
|
|
|
|
|
85 |
/* @todo See if wp_handle_sideload / wp_handle_upload can be more securely used for this */
|
86 |
$result_moved = move_uploaded_file($file,$targetFile);
|
87 |
|
88 |
if (false === $result_moved)
|
89 |
{
|
90 |
-
|
91 |
-
|
92 |
}
|
|
|
|
|
93 |
$this->targetFile = new File($targetFile);
|
94 |
|
95 |
if ($this->sourceFile->getPermissions() > 0)
|
@@ -114,6 +125,7 @@ class Replacer
|
|
114 |
{
|
115 |
update_attached_file($this->post_id, $filtered['file'] );
|
116 |
$this->targetFile = new File($filtered['file']); // handle as a new file
|
|
|
117 |
}
|
118 |
|
119 |
$metadata = wp_generate_attachment_metadata( $this->post_id, $this->targetFile->getFullFilePath() );
|
@@ -134,6 +146,8 @@ class Replacer
|
|
134 |
// update post doesn't update GUID on updates.
|
135 |
$wpdb->update( $wpdb->posts, array( 'guid' => $this->target_url), array('ID' => $this->post_id) );
|
136 |
//enable-media-replace-upload-done
|
|
|
|
|
137 |
if (is_wp_error($post_id))
|
138 |
{
|
139 |
$errors = $post_id->get_error_messages();
|
@@ -147,8 +161,10 @@ class Replacer
|
|
147 |
|
148 |
if(wp_attachment_is_image($this->post_id))
|
149 |
{
|
150 |
-
$this->ThumbnailUpdater->setNewMetadata($
|
151 |
-
$this->ThumbnailUpdater->updateThumbnails();
|
|
|
|
|
152 |
}
|
153 |
|
154 |
// if all set and done, update the date.
|
@@ -168,7 +184,8 @@ class Replacer
|
|
168 |
|
169 |
protected function getNewTitle()
|
170 |
{
|
171 |
-
|
|
|
172 |
$meta = $this->target_metadata;
|
173 |
|
174 |
if (isset($meta['image_meta']))
|
@@ -194,7 +211,7 @@ class Replacer
|
|
194 |
$targetPath = null;
|
195 |
if ($this->replaceMode == self::MODE_REPLACE)
|
196 |
{
|
197 |
-
$
|
198 |
}
|
199 |
elseif ($this->replaceMode == self::MODE_SEARCHREPLACE)
|
200 |
{
|
@@ -202,9 +219,26 @@ class Replacer
|
|
202 |
$unique = wp_unique_filename($path, $this->targetName);
|
203 |
|
204 |
$new_filename = apply_filters( 'emr_unique_filename', $unique, $path, $this->post_id );
|
205 |
-
$
|
206 |
}
|
207 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
}
|
209 |
|
210 |
/** Tries to remove all of the old image, without touching the metadata in database
|
@@ -212,9 +246,10 @@ class Replacer
|
|
212 |
*/
|
213 |
protected function removeCurrent()
|
214 |
{
|
215 |
-
$meta = wp_get_attachment_metadata( $this->post_id );
|
216 |
$backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true );
|
217 |
-
$result = wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $this->sourceFile->getFullFilePath() );
|
|
|
218 |
}
|
219 |
|
220 |
/** Handle new dates for the replacement */
|
@@ -255,7 +290,14 @@ class Replacer
|
|
255 |
global $wpdb;
|
256 |
|
257 |
// Search-and-replace filename in post database
|
258 |
-
$current_base_url = emr_get_match_url( $this->source_url
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
|
260 |
/* Search and replace in WP_POSTS */
|
261 |
$posts_sql = $wpdb->remove_placeholder_escape($wpdb->prepare(
|
@@ -277,8 +319,9 @@ class Replacer
|
|
277 |
$replace_urls = emr_get_file_urls( $this->target_url, $this->target_metadata );
|
278 |
$replace_urls = array_values(emr_normalize_file_urls( $search_urls, $replace_urls ));
|
279 |
|
280 |
-
|
281 |
|
|
|
282 |
foreach ( $rs AS $rows ) {
|
283 |
$number_of_updates = $number_of_updates + 1;
|
284 |
// replace old URLs with new URLs.
|
@@ -292,6 +335,9 @@ class Replacer
|
|
292 |
// echo "$sql <BR>";
|
293 |
$wpdb->query( $sql );
|
294 |
}
|
|
|
|
|
|
|
295 |
foreach ($rsmeta as $row)
|
296 |
{
|
297 |
$number_of_updates++;
|
@@ -301,8 +347,8 @@ class Replacer
|
|
301 |
$sql = $wpdb->prepare('UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d', $content, $row['meta_id'] );
|
302 |
$wpdb->query($sql);
|
303 |
}
|
|
|
304 |
|
305 |
-
}
|
306 |
|
307 |
} // doSearchReplace
|
308 |
|
1 |
<?php
|
2 |
namespace EnableMediaReplace;
|
3 |
use \EnableMediaReplace\emrFile as File;
|
4 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
5 |
+
use EnableMediaReplace\Notices\NoticeController as Notices;
|
6 |
|
7 |
class Replacer
|
8 |
{
|
41 |
$source_file = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )));
|
42 |
|
43 |
$this->sourceFile = new File($source_file);
|
44 |
+
|
45 |
$this->source_post = get_post($post_id);
|
46 |
$this->source_is_image = wp_attachment_is('image', $this->source_post);
|
47 |
$this->source_metadata = wp_get_attachment_metadata( $post_id );
|
68 |
/** Replace the sourceFile with a target
|
69 |
* @param $file String Full Path to the Replacement File. This will usually be an uploaded file in /tmp/
|
70 |
* @param $fileName String The fileName of the uploaded file. This will be used if sourcefile is not to be overwritten.
|
71 |
+
* @throws RunTimeException Can throw exception if something went wrong with the files.
|
72 |
*/
|
73 |
public function replaceWith($file, $fileName)
|
74 |
{
|
82 |
|
83 |
if (is_null($targetFile))
|
84 |
{
|
85 |
+
$ex = __('Target File could not be set. The source file might not be there. In case of search and replace, a filter might prevent this', "enable-media-replace");
|
86 |
+
throw new \RuntimeException($ex);
|
87 |
}
|
88 |
|
89 |
+
$targetFileObj = new File($targetFile);
|
90 |
+
$result = $targetFileObj->checkAndCreateFolder();
|
91 |
+
if ($result === false)
|
92 |
+
Log::addError('Directory creation for targetFile failed');
|
93 |
+
|
94 |
/* @todo See if wp_handle_sideload / wp_handle_upload can be more securely used for this */
|
95 |
$result_moved = move_uploaded_file($file,$targetFile);
|
96 |
|
97 |
if (false === $result_moved)
|
98 |
{
|
99 |
+
$ex = sprintf( esc_html__('The uploaded file could not be moved to %1$s. This is most likely an issue with permissions, or upload failed.', "enable-media-replace"), $targetFile );
|
100 |
+
throw new \RuntimeException($ex);
|
101 |
}
|
102 |
+
|
103 |
+
// init targetFile.
|
104 |
$this->targetFile = new File($targetFile);
|
105 |
|
106 |
if ($this->sourceFile->getPermissions() > 0)
|
125 |
{
|
126 |
update_attached_file($this->post_id, $filtered['file'] );
|
127 |
$this->targetFile = new File($filtered['file']); // handle as a new file
|
128 |
+
Log::addInfo('WP_Handle_upload filter returned different file', $filtered);
|
129 |
}
|
130 |
|
131 |
$metadata = wp_generate_attachment_metadata( $this->post_id, $this->targetFile->getFullFilePath() );
|
146 |
// update post doesn't update GUID on updates.
|
147 |
$wpdb->update( $wpdb->posts, array( 'guid' => $this->target_url), array('ID' => $this->post_id) );
|
148 |
//enable-media-replace-upload-done
|
149 |
+
|
150 |
+
// @todo Replace this one with proper Notices:addError;
|
151 |
if (is_wp_error($post_id))
|
152 |
{
|
153 |
$errors = $post_id->get_error_messages();
|
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.
|
184 |
|
185 |
protected function getNewTitle()
|
186 |
{
|
187 |
+
// get basename without extension
|
188 |
+
$title = basename($this->targetFile->getFileName(), '.' . $this->targetFile->getFileExtension());
|
189 |
$meta = $this->target_metadata;
|
190 |
|
191 |
if (isset($meta['image_meta']))
|
211 |
$targetPath = null;
|
212 |
if ($this->replaceMode == self::MODE_REPLACE)
|
213 |
{
|
214 |
+
$targetFile = $this->sourceFile->getFullFilePath(); // overwrite source
|
215 |
}
|
216 |
elseif ($this->replaceMode == self::MODE_SEARCHREPLACE)
|
217 |
{
|
219 |
$unique = wp_unique_filename($path, $this->targetName);
|
220 |
|
221 |
$new_filename = apply_filters( 'emr_unique_filename', $unique, $path, $this->post_id );
|
222 |
+
$targetFile = trailingslashit($path) . $new_filename;
|
223 |
}
|
224 |
+
if (is_dir($targetFile)) // this indicates an error with the source.
|
225 |
+
{
|
226 |
+
Log::addWarn('TargetFile is directory ' . $targetFile );
|
227 |
+
$upload_dir = wp_upload_dir();
|
228 |
+
if (isset($upload_dir['path']))
|
229 |
+
{
|
230 |
+
$targetFile = trailingslashit($upload_dir['path']) . wp_unique_filename($targetFile, $this->targetName);
|
231 |
+
}
|
232 |
+
else {
|
233 |
+
$err = 'EMR could not establish a proper destination for replacement';
|
234 |
+
Log::addError($err);
|
235 |
+
throw new \RuntimeException($err);
|
236 |
+
exit($err); // fallback
|
237 |
+
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
return $targetFile;
|
242 |
}
|
243 |
|
244 |
/** Tries to remove all of the old image, without touching the metadata in database
|
246 |
*/
|
247 |
protected function removeCurrent()
|
248 |
{
|
249 |
+
$meta = \wp_get_attachment_metadata( $this->post_id );
|
250 |
$backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true );
|
251 |
+
$result = \wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $this->sourceFile->getFullFilePath() );
|
252 |
+
|
253 |
}
|
254 |
|
255 |
/** Handle new dates for the replacement */
|
290 |
global $wpdb;
|
291 |
|
292 |
// Search-and-replace filename in post database
|
293 |
+
$current_base_url = emr_get_match_url( $this->source_url);
|
294 |
+
|
295 |
+
/** Fail-safe if base_url is a whole directory, don't go search/replace */
|
296 |
+
if (is_dir($current_base_url))
|
297 |
+
{
|
298 |
+
Log::addError('Search Replace tried to replace to directory - ' . $current_base_url);
|
299 |
+
exit('Fail Safe :: Source Location seems to be a directory.');
|
300 |
+
}
|
301 |
|
302 |
/* Search and replace in WP_POSTS */
|
303 |
$posts_sql = $wpdb->remove_placeholder_escape($wpdb->prepare(
|
319 |
$replace_urls = emr_get_file_urls( $this->target_url, $this->target_metadata );
|
320 |
$replace_urls = array_values(emr_normalize_file_urls( $search_urls, $replace_urls ));
|
321 |
|
322 |
+
Log::addDebug('Replacing references', array($search_urls, $replace_urls));
|
323 |
|
324 |
+
if ( ! empty( $rs ) ) {
|
325 |
foreach ( $rs AS $rows ) {
|
326 |
$number_of_updates = $number_of_updates + 1;
|
327 |
// replace old URLs with new URLs.
|
335 |
// echo "$sql <BR>";
|
336 |
$wpdb->query( $sql );
|
337 |
}
|
338 |
+
}
|
339 |
+
if (! empty($rsmeta))
|
340 |
+
{
|
341 |
foreach ($rsmeta as $row)
|
342 |
{
|
343 |
$number_of_updates++;
|
347 |
$sql = $wpdb->prepare('UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d', $content, $row['meta_id'] );
|
348 |
$wpdb->query($sql);
|
349 |
}
|
350 |
+
}
|
351 |
|
|
|
352 |
|
353 |
} // doSearchReplace
|
354 |
|
classes/uihelper.php
ADDED
@@ -0,0 +1,297 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EnableMediaReplace;
|
3 |
+
use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
use EnableMediaReplace\Notices\NoticeController as Notices;
|
5 |
+
|
6 |
+
/* Collection of functions helping the interface being cleaner. */
|
7 |
+
class UIHelper
|
8 |
+
{
|
9 |
+
protected $preview_size = '';
|
10 |
+
protected $preview_width = 0;
|
11 |
+
protected $preview_height = 0;
|
12 |
+
|
13 |
+
protected $preview_max_height = 500;
|
14 |
+
protected $preview_max_width = 400;
|
15 |
+
|
16 |
+
protected $full_width = 0;
|
17 |
+
protected $full_height = 0;
|
18 |
+
|
19 |
+
public function __construct()
|
20 |
+
{
|
21 |
+
|
22 |
+
}
|
23 |
+
|
24 |
+
|
25 |
+
public function getFormUrl($attach_id)
|
26 |
+
{
|
27 |
+
$url = admin_url('upload.php');
|
28 |
+
$url = add_query_arg(array(
|
29 |
+
'page' => 'enable-media-replace/enable-media-replace.php',
|
30 |
+
'noheader' => true,
|
31 |
+
'action' => 'media_replace_upload',
|
32 |
+
'attachment_id' => $attach_id,
|
33 |
+
));
|
34 |
+
|
35 |
+
if (isset($_REQUEST['SHORTPIXEL_DEBUG']))
|
36 |
+
{
|
37 |
+
$spdebug = $_REQUEST['SHORTPIXEL_DEBUG'];
|
38 |
+
if (is_numeric($spdebug))
|
39 |
+
$spdebug = intval($spdebug);
|
40 |
+
else {
|
41 |
+
$spdebug = sanitize_text_field($spdebug);
|
42 |
+
}
|
43 |
+
|
44 |
+
$url = add_query_arg('SHORTPIXEL_DEBUG', $spdebug, $url);
|
45 |
+
}
|
46 |
+
|
47 |
+
return $url;
|
48 |
+
|
49 |
+
}
|
50 |
+
|
51 |
+
public function getSuccesRedirect($post_id)
|
52 |
+
{
|
53 |
+
$url = admin_url('post.php');
|
54 |
+
$url = add_query_arg(array('action' => 'edit', 'post' => $post_id), $url);
|
55 |
+
|
56 |
+
$url = apply_filters('emr_returnurl', $url);
|
57 |
+
Log::addDebug('Success URL- ' . $url);
|
58 |
+
|
59 |
+
return $url;
|
60 |
+
|
61 |
+
}
|
62 |
+
|
63 |
+
public function getFailedRedirect($attach_id)
|
64 |
+
{
|
65 |
+
$url = admin_url('upload.php');
|
66 |
+
$url = add_query_arg(array(
|
67 |
+
'page' => 'enable-media-replace/enable-media-replace.php',
|
68 |
+
'action' => 'media_replace',
|
69 |
+
'attachment_id' => $attach_id,
|
70 |
+
'_wpnonce' => wp_create_nonce('media_replace'),
|
71 |
+
), $url
|
72 |
+
);
|
73 |
+
|
74 |
+
$url = apply_filters('emr_returnurl_failed', $url);
|
75 |
+
Log::addDebug('Failed URL- ' . $url);
|
76 |
+
return $url;
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
|
81 |
+
public function setPreviewSizes()
|
82 |
+
{
|
83 |
+
list($this->preview_size, $this->preview_width, $this->preview_height) = $this->findImageSizeByMax($this->preview_max_width);
|
84 |
+
}
|
85 |
+
|
86 |
+
public function setSourceSizes($attach_id)
|
87 |
+
{
|
88 |
+
$data = wp_get_attachment_image_src($attach_id, 'full');
|
89 |
+
if (is_array($data))
|
90 |
+
{
|
91 |
+
$this->full_width = $data[1];
|
92 |
+
$this->full_height = $data[2];
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
// Returns Preview Image HTML Output.
|
97 |
+
public function getPreviewImage($attach_id)
|
98 |
+
{
|
99 |
+
$data = false;
|
100 |
+
|
101 |
+
if ($attach_id > 0)
|
102 |
+
{
|
103 |
+
$data = wp_get_attachment_image_src($attach_id, $this->preview_size);
|
104 |
+
$file = get_attached_file($attach_id);
|
105 |
+
Log::addDebug('Attached File ' . $file, $data);
|
106 |
+
|
107 |
+
}
|
108 |
+
|
109 |
+
$mime_type = get_post_mime_type($attach_id);
|
110 |
+
|
111 |
+
if (! is_array($data) || ! file_exists($file) )
|
112 |
+
{
|
113 |
+
// if attachid higher than zero ( exists ) but not the image, fail, that's an error state.
|
114 |
+
$icon = ($attach_id < 0) ? '' : 'dashicons-no';
|
115 |
+
$is_document = false;
|
116 |
+
|
117 |
+
$args = array(
|
118 |
+
'width' => $this->preview_width,
|
119 |
+
'height' => $this->preview_height,
|
120 |
+
'is_image' => false,
|
121 |
+
'is_document' => $is_document,
|
122 |
+
'icon' => $icon,
|
123 |
+
);
|
124 |
+
|
125 |
+
// failed, it might be this server doens't support PDF thumbnails. Fallback to File preview.
|
126 |
+
if ($mime_type == 'application/pdf')
|
127 |
+
{
|
128 |
+
return $this->getPreviewFile($attach_id);
|
129 |
+
}
|
130 |
+
|
131 |
+
return $this->getPlaceHolder($args);
|
132 |
+
}
|
133 |
+
|
134 |
+
$url = $data[0];
|
135 |
+
$width = $data[1];
|
136 |
+
$height = $data[2];
|
137 |
+
// preview width, if source if found, should be set to source.
|
138 |
+
$this->preview_width = $width;
|
139 |
+
$this->preview_height = $height;
|
140 |
+
|
141 |
+
if ($width > $this->preview_max_width)
|
142 |
+
$width = $this->preview_max_width;
|
143 |
+
if ($height > $this->preview_max_height)
|
144 |
+
$height = $this->preview_max_height;
|
145 |
+
|
146 |
+
$image = "<img src='$url' width='$width' height='$height' class='image' style='max-width:100%; max-height: 100%;' />";
|
147 |
+
|
148 |
+
$args = array(
|
149 |
+
'width' => $width,
|
150 |
+
'height' => $height,
|
151 |
+
'image' => $image,
|
152 |
+
'mime_type' => $mime_type,
|
153 |
+
);
|
154 |
+
$output = $this->getPlaceHolder($args);
|
155 |
+
return $output;
|
156 |
+
}
|
157 |
+
|
158 |
+
public function getPreviewError($attach_id)
|
159 |
+
{
|
160 |
+
$args = array(
|
161 |
+
'width' => $this->preview_width,
|
162 |
+
'height' => $this->preview_height,
|
163 |
+
'icon' => 'dashicons-no',
|
164 |
+
'is_image' => false,
|
165 |
+
);
|
166 |
+
$output = $this->getPlaceHolder($args);
|
167 |
+
return $output;
|
168 |
+
}
|
169 |
+
|
170 |
+
public function getPreviewFile($attach_id)
|
171 |
+
{
|
172 |
+
if ($attach_id > 0)
|
173 |
+
{
|
174 |
+
$filepath = get_attached_file($attach_id);
|
175 |
+
$filename = basename($filepath);
|
176 |
+
}
|
177 |
+
else {
|
178 |
+
$filename = false;
|
179 |
+
}
|
180 |
+
|
181 |
+
$mime_type = get_post_mime_type($attach_id);
|
182 |
+
|
183 |
+
$args = array(
|
184 |
+
'width' => 300,
|
185 |
+
'height' => 300,
|
186 |
+
'is_image' => false,
|
187 |
+
'is_document' => true,
|
188 |
+
'layer' => $filename,
|
189 |
+
'mime_type' => $mime_type,
|
190 |
+
);
|
191 |
+
$output = $this->getPlaceHolder($args);
|
192 |
+
return $output;
|
193 |
+
}
|
194 |
+
|
195 |
+
public function findImageSizeByMax($maxwidth)
|
196 |
+
{
|
197 |
+
$image_sizes = $this->get_image_sizes();
|
198 |
+
|
199 |
+
$match_width = 0;
|
200 |
+
$match_height = 0;
|
201 |
+
$match = '';
|
202 |
+
|
203 |
+
foreach($image_sizes as $sizeName => $sizeItem)
|
204 |
+
{
|
205 |
+
|
206 |
+
$width = $sizeItem['width'];
|
207 |
+
if ($width > $match_width && $width <= $maxwidth)
|
208 |
+
{
|
209 |
+
$match = $sizeName;
|
210 |
+
$match_width = $width;
|
211 |
+
$match_height = $sizeItem['height'];
|
212 |
+
}
|
213 |
+
}
|
214 |
+
return array($match, $match_width, $match_height);
|
215 |
+
}
|
216 |
+
|
217 |
+
public function getPlaceHolder($args)
|
218 |
+
{
|
219 |
+
$defaults = array(
|
220 |
+
'width' => 150,
|
221 |
+
'height' => 150,
|
222 |
+
'image' => '',
|
223 |
+
'icon' => 'dashicons-media-document',
|
224 |
+
'layer' => $this->full_width . ' x ' . $this->full_height,
|
225 |
+
'is_image' => true,
|
226 |
+
'is_document' => false,
|
227 |
+
'mime_type' => false,
|
228 |
+
);
|
229 |
+
|
230 |
+
$args = wp_parse_args($args, $defaults);
|
231 |
+
$w = $args['width'];
|
232 |
+
$h = $args['height'];
|
233 |
+
|
234 |
+
if ($w < 150) // minimum
|
235 |
+
$w = 150;
|
236 |
+
if ($h < 150)
|
237 |
+
$h = 150;
|
238 |
+
|
239 |
+
$icon = $args['icon'];
|
240 |
+
|
241 |
+
if ($args['is_image'])
|
242 |
+
{
|
243 |
+
$placeholder_class = 'is_image';
|
244 |
+
}
|
245 |
+
else {
|
246 |
+
$placeholder_class = 'not_image';
|
247 |
+
}
|
248 |
+
|
249 |
+
if ($args['is_document'])
|
250 |
+
{
|
251 |
+
$placeholder_class .= ' is_document';
|
252 |
+
}
|
253 |
+
|
254 |
+
$filetype = '';
|
255 |
+
if ($args['mime_type'])
|
256 |
+
{
|
257 |
+
$filetype = 'data-filetype="' . $args['mime_type'] . '"';
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
$output = "<div class='image_placeholder $placeholder_class' $filetype style='width:" . $w . "px; height:". $h ."px'> ";
|
262 |
+
$output .= $args['image'];
|
263 |
+
$output .= "<div class='dashicons $icon'> </div>";
|
264 |
+
$output .= "<span class='textlayer'>" . $args['layer'] . "</span>";
|
265 |
+
$output .= "</div>";
|
266 |
+
|
267 |
+
return $output;
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Get size information for all currently-registered image sizes.
|
272 |
+
* Directly stolen from - https://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes
|
273 |
+
* @global $_wp_additional_image_sizes
|
274 |
+
* @uses get_intermediate_image_sizes()
|
275 |
+
* @return array $sizes Data for all currently-registered image sizes.
|
276 |
+
*/
|
277 |
+
private function get_image_sizes() {
|
278 |
+
global $_wp_additional_image_sizes;
|
279 |
+
|
280 |
+
$sizes = array();
|
281 |
+
|
282 |
+
foreach ( get_intermediate_image_sizes() as $_size ) {
|
283 |
+
if ( in_array( $_size, array('thumbnail', 'medium', 'medium_large', 'large') ) ) {
|
284 |
+
$sizes[ $_size ]['width'] = get_option( "{$_size}_size_w" );
|
285 |
+
$sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" );
|
286 |
+
} elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
|
287 |
+
$sizes[ $_size ] = array(
|
288 |
+
'width' => $_wp_additional_image_sizes[ $_size ]['width'],
|
289 |
+
'height' => $_wp_additional_image_sizes[ $_size ]['height'],
|
290 |
+
);
|
291 |
+
}
|
292 |
+
}
|
293 |
+
|
294 |
+
return $sizes;
|
295 |
+
}
|
296 |
+
|
297 |
+
} // class
|
composer.json
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"repositories": [
|
3 |
+
{
|
4 |
+
"packagist.org": false,
|
5 |
+
"type": "path",
|
6 |
+
"url": "../modules/*",
|
7 |
+
"options": {
|
8 |
+
"symlink": true
|
9 |
+
}
|
10 |
+
}
|
11 |
+
],
|
12 |
+
"require": {
|
13 |
+
"shortpixel/notices":"@dev",
|
14 |
+
"shortpixel/build" : "@dev"
|
15 |
+
},
|
16 |
+
|
17 |
+
"scripts": {
|
18 |
+
"post-update-cmd" : "\\ShortPixel\\Build\\Build::BuildIt",
|
19 |
+
"buildSP" : "\\ShortPixel\\Build\\Build::BuildIt"
|
20 |
+
},
|
21 |
+
"extra": {
|
22 |
+
"targetNamespace" : "EnableMediaReplace"
|
23 |
+
}
|
24 |
+
|
25 |
+
}
|
css/admin.css
CHANGED
@@ -772,14 +772,80 @@
|
|
772 |
min-height: 350px; }
|
773 |
.emr_upload_form .image_chooser.wrapper .image_previews {
|
774 |
margin: 15px 0; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
775 |
.emr_upload_form .option-flex-wrapper {
|
776 |
display: flex; }
|
777 |
.emr_upload_form .replace_type.wrapper {
|
778 |
flex: 1;
|
779 |
border: 1px solid #ccc;
|
780 |
margin: 15px 0; }
|
781 |
-
.emr_upload_form .replace_type.wrapper
|
782 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
783 |
.emr_upload_form .options.wrapper {
|
784 |
flex: 1;
|
785 |
border: 1px solid #ccc;
|
772 |
min-height: 350px; }
|
773 |
.emr_upload_form .image_chooser.wrapper .image_previews {
|
774 |
margin: 15px 0; }
|
775 |
+
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder {
|
776 |
+
position: relative;
|
777 |
+
display: inline-block;
|
778 |
+
margin-right: 25px;
|
779 |
+
border: 1px solid #ddd;
|
780 |
+
vertical-align: top;
|
781 |
+
max-height: 500px; }
|
782 |
+
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .textlayer {
|
783 |
+
font-size: 25px;
|
784 |
+
line-height: 25px;
|
785 |
+
opacity: 0.7;
|
786 |
+
position: absolute;
|
787 |
+
color: #ccc;
|
788 |
+
left: 48%;
|
789 |
+
top: 50%;
|
790 |
+
transform: translate(-50%, -50%);
|
791 |
+
border: 1px dashed #eee;
|
792 |
+
background-color: #333;
|
793 |
+
padding: 8px; }
|
794 |
+
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .dashicons {
|
795 |
+
font-size: 60px;
|
796 |
+
position: absolute;
|
797 |
+
top: 50%;
|
798 |
+
margin-top: -30px;
|
799 |
+
left: 50%;
|
800 |
+
margin-left: -30px;
|
801 |
+
opacity: 0.5; }
|
802 |
+
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.is_image .dashicons::before, .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.is_image .dashicons {
|
803 |
+
display: none; }
|
804 |
+
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image img {
|
805 |
+
display: none; }
|
806 |
+
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image .textlayer {
|
807 |
+
display: none; }
|
808 |
+
.emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image.is_document .textlayer {
|
809 |
+
font-size: 18px;
|
810 |
+
line-height: 20px;
|
811 |
+
display: block; }
|
812 |
+
.emr_upload_form .form-error, .emr_upload_form .form-warning {
|
813 |
+
background: #fff;
|
814 |
+
padding: 8px;
|
815 |
+
border-left: 4px solid #ff0000;
|
816 |
+
margin: 10px 0;
|
817 |
+
display: none; }
|
818 |
+
.emr_upload_form .form-error p, .emr_upload_form .form-warning p {
|
819 |
+
margin: 0; }
|
820 |
+
.emr_upload_form .form-warning {
|
821 |
+
border-left: 4px solid #ffb900; }
|
822 |
.emr_upload_form .option-flex-wrapper {
|
823 |
display: flex; }
|
824 |
.emr_upload_form .replace_type.wrapper {
|
825 |
flex: 1;
|
826 |
border: 1px solid #ccc;
|
827 |
margin: 15px 0; }
|
828 |
+
.emr_upload_form .replace_type.wrapper .option {
|
829 |
+
position: relative;
|
830 |
+
z-index: 1; }
|
831 |
+
.emr_upload_form .replace_type.wrapper .option label {
|
832 |
+
font-size: 1.2em; }
|
833 |
+
.emr_upload_form .replace_type.wrapper .option .nofeature-notice {
|
834 |
+
border: 1px solid #ccc;
|
835 |
+
padding: 8px;
|
836 |
+
margin: 0;
|
837 |
+
position: absolute;
|
838 |
+
left: 0;
|
839 |
+
right: 0;
|
840 |
+
top: 0;
|
841 |
+
bottom: 0;
|
842 |
+
opacity: 0.8;
|
843 |
+
z-index: 9;
|
844 |
+
background: #444; }
|
845 |
+
.emr_upload_form .replace_type.wrapper .option .nofeature-notice p {
|
846 |
+
text-align: center;
|
847 |
+
color: #fff;
|
848 |
+
margin: 15px 0; }
|
849 |
.emr_upload_form .options.wrapper {
|
850 |
flex: 1;
|
851 |
border: 1px solid #ccc;
|
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
|
@@ -24,6 +24,8 @@ http://www.gnu.org/licenses/gpl.html
|
|
24 |
*
|
25 |
*/
|
26 |
|
|
|
|
|
27 |
if ( ! defined( 'ABSPATH' ) ) {
|
28 |
exit; // Exit if accessed directly.
|
29 |
}
|
@@ -40,10 +42,13 @@ if(!defined("SHORTPIXEL_AFFILIATE_CODE")) {
|
|
40 |
define("SHORTPIXEL_AFFILIATE_CODE", 'VKG6LYN28044');
|
41 |
}
|
42 |
|
|
|
43 |
require_once('classes/replacer.php');
|
|
|
44 |
require_once('classes/file.php');
|
45 |
require_once('classes/cache.php');
|
46 |
require_once('classes/emr-plugin.php');
|
|
|
47 |
require_once('thumbnail_updater.php');
|
48 |
|
49 |
-
$emr_plugin =
|
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.2
|
7 |
Author: ShortPixel
|
8 |
Author URI: https://shortpixel.com
|
9 |
Text Domain: enable-media-replace
|
24 |
*
|
25 |
*/
|
26 |
|
27 |
+
namespace EnableMediaReplace;
|
28 |
+
|
29 |
if ( ! defined( 'ABSPATH' ) ) {
|
30 |
exit; // Exit if accessed directly.
|
31 |
}
|
42 |
define("SHORTPIXEL_AFFILIATE_CODE", 'VKG6LYN28044');
|
43 |
}
|
44 |
|
45 |
+
require_once('build/shortpixel/autoload.php');
|
46 |
require_once('classes/replacer.php');
|
47 |
+
require_once('classes/uihelper.php');
|
48 |
require_once('classes/file.php');
|
49 |
require_once('classes/cache.php');
|
50 |
require_once('classes/emr-plugin.php');
|
51 |
+
require_once('classes/externals.php');
|
52 |
require_once('thumbnail_updater.php');
|
53 |
|
54 |
+
$emr_plugin = EnableMediaReplacePlugin::get();
|
js/emr_admin.js
CHANGED
@@ -3,12 +3,39 @@ jQuery(document).ready(function($)
|
|
3 |
// interface for emr.
|
4 |
var emrIf = new function ()
|
5 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
this.init = function()
|
8 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
$('input[name="timestamp_replace"]').on('change', $.proxy(this.checkCustomDate, this));
|
|
|
10 |
this.checkCustomDate();
|
11 |
this.loadDatePicker();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
},
|
13 |
this.loadDatePicker = function()
|
14 |
{
|
@@ -28,7 +55,6 @@ jQuery(document).ready(function($)
|
|
28 |
},
|
29 |
this.checkCustomDate = function()
|
30 |
{
|
31 |
-
console.log('check');
|
32 |
if ($('input[name="timestamp_replace"]:checked').val() == 3)
|
33 |
this.showCustomDate();
|
34 |
else
|
@@ -46,26 +72,148 @@ jQuery(document).ready(function($)
|
|
46 |
$('.custom_date').css('visibility', 'hidden');
|
47 |
});
|
48 |
}
|
49 |
-
|
|
|
|
|
|
|
|
|
50 |
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
{
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
}
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
});
|
67 |
}
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
< |