a1c60821 by Jeff Balicki

ee

1 parent 2d193652
Showing 81 changed files with 12164 additions and 4 deletions
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12 freedom to share and change it. By contrast, the GNU General Public
13 License is intended to guarantee your freedom to share and change free
14 software--to make sure the software is free for all its users. This
15 General Public License applies to most of the Free Software
16 Foundation's software and to any other program whose authors commit to
17 using it. (Some other Free Software Foundation software is covered by
18 the GNU Lesser General Public License instead.) You can apply it to
19 your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22 price. Our General Public Licenses are designed to make sure that you
23 have the freedom to distribute copies of free software (and charge for
24 this service if you wish), that you receive source code or can get it
25 if you want it, that you can change the software or use pieces of it
26 in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29 anyone to deny you these rights or to ask you to surrender the rights.
30 These restrictions translate to certain responsibilities for you if you
31 distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34 gratis or for a fee, you must give the recipients all the rights that
35 you have. You must make sure that they, too, receive or can get the
36 source code. And you must show them these terms so they know their
37 rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40 (2) offer you this license which gives you legal permission to copy,
41 distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44 that everyone understands that there is no warranty for this free
45 software. If the software is modified by someone else and passed on, we
46 want its recipients to know that what they have is not the original, so
47 that any problems introduced by others will not reflect on the original
48 authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51 patents. We wish to avoid the danger that redistributors of a free
52 program will individually obtain patent licenses, in effect making the
53 program proprietary. To prevent this, we have made it clear that any
54 patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57 modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63 a notice placed by the copyright holder saying it may be distributed
64 under the terms of this General Public License. The "Program", below,
65 refers to any such program or work, and a "work based on the Program"
66 means either the Program or any derivative work under copyright law:
67 that is to say, a work containing the Program or a portion of it,
68 either verbatim or with modifications and/or translated into another
69 language. (Hereinafter, translation is included without limitation in
70 the term "modification".) Each licensee is addressed as "you".
71
72 Activities other than copying, distribution and modification are not
73 covered by this License; they are outside its scope. The act of
74 running the Program is not restricted, and the output from the Program
75 is covered only if its contents constitute a work based on the
76 Program (independent of having been made by running the Program).
77 Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80 source code as you receive it, in any medium, provided that you
81 conspicuously and appropriately publish on each copy an appropriate
82 copyright notice and disclaimer of warranty; keep intact all the
83 notices that refer to this License and to the absence of any warranty;
84 and give any other recipients of the Program a copy of this License
85 along with the Program.
86
87 You may charge a fee for the physical act of transferring a copy, and
88 you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91 of it, thus forming a work based on the Program, and copy and
92 distribute such modifications or work under the terms of Section 1
93 above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114 These requirements apply to the modified work as a whole. If
115 identifiable sections of that work are not derived from the Program,
116 and can be reasonably considered independent and separate works in
117 themselves, then this License, and its terms, do not apply to those
118 sections when you distribute them as separate works. But when you
119 distribute the same sections as part of a whole which is a work based
120 on the Program, the distribution of the whole must be on the terms of
121 this License, whose permissions for other licensees extend to the
122 entire whole, and thus to each and every part regardless of who wrote it.
123
124 Thus, it is not the intent of this section to claim rights or contest
125 your rights to work written entirely by you; rather, the intent is to
126 exercise the right to control the distribution of derivative or
127 collective works based on the Program.
128
129 In addition, mere aggregation of another work not based on the Program
130 with the Program (or with a work based on the Program) on a volume of
131 a storage or distribution medium does not bring the other work under
132 the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135 under Section 2) in object code or executable form under the terms of
136 Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155 The source code for a work means the preferred form of the work for
156 making modifications to it. For an executable work, complete source
157 code means all the source code for all modules it contains, plus any
158 associated interface definition files, plus the scripts used to
159 control compilation and installation of the executable. However, as a
160 special exception, the source code distributed need not include
161 anything that is normally distributed (in either source or binary
162 form) with the major components (compiler, kernel, and so on) of the
163 operating system on which the executable runs, unless that component
164 itself accompanies the executable.
165
166 If distribution of executable or object code is made by offering
167 access to copy from a designated place, then offering equivalent
168 access to copy the source code from the same place counts as
169 distribution of the source code, even though third parties are not
170 compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173 except as expressly provided under this License. Any attempt
174 otherwise to copy, modify, sublicense or distribute the Program is
175 void, and will automatically terminate your rights under this License.
176 However, parties who have received copies, or rights, from you under
177 this License will not have their licenses terminated so long as such
178 parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181 signed it. However, nothing else grants you permission to modify or
182 distribute the Program or its derivative works. These actions are
183 prohibited by law if you do not accept this License. Therefore, by
184 modifying or distributing the Program (or any work based on the
185 Program), you indicate your acceptance of this License to do so, and
186 all its terms and conditions for copying, distributing or modifying
187 the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190 Program), the recipient automatically receives a license from the
191 original licensor to copy, distribute or modify the Program subject to
192 these terms and conditions. You may not impose any further
193 restrictions on the recipients' exercise of the rights granted herein.
194 You are not responsible for enforcing compliance by third parties to
195 this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198 infringement or for any other reason (not limited to patent issues),
199 conditions are imposed on you (whether by court order, agreement or
200 otherwise) that contradict the conditions of this License, they do not
201 excuse you from the conditions of this License. If you cannot
202 distribute so as to satisfy simultaneously your obligations under this
203 License and any other pertinent obligations, then as a consequence you
204 may not distribute the Program at all. For example, if a patent
205 license would not permit royalty-free redistribution of the Program by
206 all those who receive copies directly or indirectly through you, then
207 the only way you could satisfy both it and this License would be to
208 refrain entirely from distribution of the Program.
209
210 If any portion of this section is held invalid or unenforceable under
211 any particular circumstance, the balance of the section is intended to
212 apply and the section as a whole is intended to apply in other
213 circumstances.
214
215 It is not the purpose of this section to induce you to infringe any
216 patents or other property right claims or to contest validity of any
217 such claims; this section has the sole purpose of protecting the
218 integrity of the free software distribution system, which is
219 implemented by public license practices. Many people have made
220 generous contributions to the wide range of software distributed
221 through that system in reliance on consistent application of that
222 system; it is up to the author/donor to decide if he or she is willing
223 to distribute software through any other system and a licensee cannot
224 impose that choice.
225
226 This section is intended to make thoroughly clear what is believed to
227 be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230 certain countries either by patents or by copyrighted interfaces, the
231 original copyright holder who places the Program under this License
232 may add an explicit geographical distribution limitation excluding
233 those countries, so that distribution is permitted only in or among
234 countries not thus excluded. In such case, this License incorporates
235 the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238 of the General Public License from time to time. Such new versions will
239 be similar in spirit to the present version, but may differ in detail to
240 address new problems or concerns.
241
242 Each version is given a distinguishing version number. If the Program
243 specifies a version number of this License which applies to it and "any
244 later version", you have the option of following the terms and conditions
245 either of that version or of any later version published by the Free
246 Software Foundation. If the Program does not specify a version number of
247 this License, you may choose any version ever published by the Free Software
248 Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251 programs whose distribution conditions are different, write to the author
252 to ask for permission. For software which is copyrighted by the Free
253 Software Foundation, write to the Free Software Foundation; we sometimes
254 make exceptions for this. Our decision will be guided by the two goals
255 of preserving the free status of all derivatives of our free software and
256 of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
281
282 How to Apply These Terms to Your New Programs
283
284 If you develop a new program, and you want it to be of the greatest
285 possible use to the public, the best way to achieve this is to make it
286 free software which everyone can redistribute and change under these terms.
287
288 To do so, attach the following notices to the program. It is safest
289 to attach them to the start of each source file to most effectively
290 convey the exclusion of warranty; and each file should have at least
291 the "copyright" line and a pointer to where the full notice is found.
292
293 {description}
294 Copyright (C) {year} {fullname}
295
296 This program is free software; you can redistribute it and/or modify
297 it under the terms of the GNU General Public License as published by
298 the Free Software Foundation; either version 2 of the License, or
299 (at your option) any later version.
300
301 This program is distributed in the hope that it will be useful,
302 but WITHOUT ANY WARRANTY; without even the implied warranty of
303 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 GNU General Public License for more details.
305
306 You should have received a copy of the GNU General Public License along
307 with this program; if not, write to the Free Software Foundation, Inc.,
308 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
310 Also add information on how to contact you by electronic and paper mail.
311
312 If the program is interactive, make it output a short notice like this
313 when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) year name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320 The hypothetical commands `show w' and `show c' should show the appropriate
321 parts of the General Public License. Of course, the commands you use may
322 be called something other than `show w' and `show c'; they could even be
323 mouse-clicks or menu items--whatever suits your program.
324
325 You should also get your employer (if you work as a programmer) or your
326 school, if any, to sign a "copyright disclaimer" for the program, if
327 necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 {signature of Ty Coon}, 1 April 1989
333 Ty Coon, President of Vice
334
335 This General Public License does not permit incorporating your program into
336 proprietary programs. If your program is a subroutine library, you may
337 consider it more useful to permit linking proprietary applications with the
338 library. If this is what you want to do, use the GNU Lesser General
339 Public License instead of this License.
...\ No newline at end of file ...\ No newline at end of file
1 # Enable Media Replace
2
3 This plugin allows you to replace a file in your media library by uploading a new file in its place. No more deleting, renaming and re-uploading files!
4
5 ## A real timesaver
6
7 Don't you find it tedious and complicated to have to first delete a file and then upload one with the exact same name every time you want to update an image or any uploaded file inside the WordPress media library?
8
9 Well, no longer!
10
11 Now you'll be able to replace any uploaded file from the media "edit" view, where it should be. Media replacement can be done in one of two ways:
12
13 ## It's simple to replace a file
14
15 1. Just replace the file. This option requires you to upload a file of the same type as the one you are replacing. The name of the attachment will stay the same no matter what the file you upload is called.
16 1. Replace the file, use new file name and update all links. If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file will be updated to point to the new file name.
17
18 This plugin is very powerful and a must-have for any larger sites built with WordPress.
19
20 ## Display file modification time
21
22 There is a shortcode available which picks up the file modification date and displays it in a post or a page. The code is:
23 `[file_modified id=XX format=XXXX]` where the "id" is required and the "format" is optional and defaults to your current WordPress settings for date and time format.
24
25 So `[file_modified id=870]` would display the last time the file with ID 870 was updated on your site. To get the ID for a file, check the URL when editing a file in the media library (see screenshot #4)
26
27 If you want more control over the format used to display the time, you can use the format option, so `[file_modified id=870 format=Y-m-d]` would display the file modification date but not the time. The format string uses [standard PHP date() formatting tags](http://php.net/manual/en/function.date.php).
28
29 ***
30
31 See [Enable Media Replace](http://wordpress.org/plugins/enable-media-replace/) at WordPress.org for more information.
1 <?php
2 namespace EnableMediaReplace\Build;
3
4 class PackageLoader
5 {
6 public $dir;
7 public $composerFile = false;
8
9 public function __construct()
10 {
11
12 }
13
14 public function setComposerFile($filePath)
15 {
16 $this->composerFile = json_decode(file_get_contents($filePath),1);
17 }
18
19 public function getComposerFile($filePath = false )
20 {
21 if (! $this->composerFile)
22 $this->composerFile = json_decode(file_get_contents($this->dir."/composer.json"), 1);
23
24 return $this->composerFile;
25 }
26
27 public function load($dir)
28 {
29 $this->dir = $dir;
30 $composer = $this->getComposerFile();
31
32
33 if(isset($composer["autoload"]["psr-4"])){
34 $this->loadPSR4($composer['autoload']['psr-4']);
35 }
36 if(isset($composer["autoload"]["psr-0"])){
37 $this->loadPSR0($composer['autoload']['psr-0']);
38 }
39 if(isset($composer["autoload"]["files"])){
40 $this->loadFiles($composer["autoload"]["files"]);
41 }
42 }
43
44 public function loadFiles($files){
45 foreach($files as $file){
46 $fullpath = $this->dir."/".$file;
47 if(file_exists($fullpath)){
48 include_once($fullpath);
49 }
50 }
51 }
52
53 public function loadPSR4($namespaces)
54 {
55 $this->loadPSR($namespaces, true);
56 }
57
58 public function loadPSR0($namespaces)
59 {
60 $this->loadPSR($namespaces, false);
61 }
62
63 public function loadPSR($namespaces, $psr4)
64 {
65 $dir = $this->dir;
66 // Foreach namespace specified in the composer, load the given classes
67 foreach ($namespaces as $namespace => $classpaths) {
68 if (!is_array($classpaths)) {
69 $classpaths = array($classpaths);
70 }
71 spl_autoload_register(function ($classname) use ($namespace, $classpaths, $dir, $psr4) {
72 // Check if the namespace matches the class we are looking for
73 if (preg_match("#^".preg_quote($namespace)."#", $classname)) {
74 // Remove the namespace from the file path since it's psr4
75 if ($psr4) {
76 $classname = str_replace($namespace, "", $classname);
77 }
78
79 // $filename = preg_replace("#\\\\#", "", $classname).".php";
80 // This is fix for nested classes which were losing a /
81 $filename = ltrim($classname .'.php', '\\');
82 $filename = str_replace('\\','/', $filename);
83
84 foreach ($classpaths as $classpath) {
85 $fullpath = trailingslashit($dir) . trailingslashit($classpath) .$filename;
86 if (file_exists($fullpath)) {
87 include_once $fullpath;
88 }
89 }
90 }
91 });
92 }
93 }
94 }
1 <?php
2 require_once (dirname(__FILE__) . "/PackageLoader.php");
3 $loader = new EnableMediaReplace\Build\PackageLoader();
4 $loader->load(__DIR__);
5
...\ No newline at end of file ...\ No newline at end of file
1 {"name":"EnableMediaReplace\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"EnableMediaReplace\\ShortPixelLogger":"log\/src","EnableMediaReplace\\Notices":"notices\/src"}}}
...\ No newline at end of file ...\ No newline at end of file
1 {
2 "name": "shortpixel/log",
3 "description": "ShortPixel Logging",
4 "version": "1.1.3",
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 }
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 if(PHP_VERSION_ID < 50400) {
122 $debug=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
123 } else {
124 $debug=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,5);
125 }
126
127 $i = 4;
128 if (isset($debug[$i]))
129 {
130 $info = $debug[$i];
131 $line = isset($info['line']) ? $info['line'] : 'Line unknown';
132 $file = isset($info['file']) ? basename($info['file']) : 'File not set';
133
134 $this->caller = array('line' => $line, 'file' => $file, 'function' => $info['function']);
135 }
136
137
138 }
139
140
141 }
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 (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants
53 {
54 $this->is_manual_request = true;
55 $this->is_active = true;
56
57 if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true')
58 {
59 $this->logLevel = DebugItem::LEVEL_INFO;
60 }
61 else {
62 $this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']);
63 }
64
65 }
66 else if ( (defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG > 0) )
67 {
68 $this->is_active = true;
69 if (SHORTPIXEL_DEBUG === true)
70 $this->logLevel = DebugItem::LEVEL_INFO;
71 else {
72 $this->logLevel = intval(SHORTPIXEL_DEBUG);
73 }
74 }
75
76 if (defined('SHORTPIXEL_DEBUG_TARGET') && SHORTPIXEL_DEBUG_TARGET || $this->is_manual_request)
77 {
78 //$this->logPath = SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log";
79 //$this->logMode = defined('SHORTPIXEL_LOG_OVERWRITE') ? 0 : FILE_APPEND;
80 if (defined('SHORTPIXEL_LOG_OVERWRITE')) // if overwrite, do this on init once.
81 file_put_contents($this->logPath,'-- Log Reset -- ' .PHP_EOL);
82
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();
96 }
97
98 /** Init the view when needed. Private function ( public because of WP_HOOK )
99 * Never call directly */
100 public function initView()
101 {
102 $user_is_administrator = (current_user_can('manage_options')) ? true : false;
103
104 if ($this->is_active && $this->is_manual_request && $user_is_administrator )
105 {
106 $content_url = content_url();
107 $logPath = $this->logPath;
108 $pathpos = strpos($logPath, 'wp-content') + strlen('wp-content');
109 $logPart = substr($logPath, $pathpos);
110 $logLink = $content_url . $logPart;
111
112 $this->view = new \stdClass;
113 $this->view->logLink = $logLink;
114 add_action('admin_footer', array($this, 'loadView'));
115 }
116 }
117
118 public static function getInstance()
119 {
120 if ( self::$instance === null)
121 {
122 self::$instance = new ShortPixelLogger();
123 }
124 return self::$instance;
125 }
126
127 public function setLogPath($logPath)
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 // Force administrator on manuals.
142 if ( $this->is_manual_request )
143 {
144 if (! function_exists('wp_get_current_user')) // not loaded yet
145 return false;
146
147 $user_is_administrator = (current_user_can('manage_options')) ? true : false;
148 if (! $user_is_administrator)
149 return false;
150 }
151
152 // Check where to log to.
153 if ($this->logPath === false)
154 {
155 $upload_dir = wp_upload_dir(null,false,false);
156 $this->logPath = $this->setLogPath($upload_dir['basedir'] . '/' . $this->namespace . ".log");
157 }
158
159 $arg = array();
160 $args['level'] = $level;
161 $args['data'] = $data;
162
163 $newItem = new DebugItem($message, $args);
164 $this->items[] = $newItem;
165
166 if ($this->is_active)
167 {
168 $this->write($newItem);
169 }
170 }
171
172 /** Writes to log File. */
173 protected function write($debugItem, $mode = 'file')
174 {
175 $items = $debugItem->getForFormat();
176 $items['time_passed'] = round ( ($items['time'] - $this->start_time), 5);
177 $items['time'] = date('Y-m-d H:i:s', $items['time'] );
178
179 if ( ($items['caller']) && is_array($items['caller']) && count($items['caller']) > 0)
180 {
181 $caller = $items['caller'];
182 $items['caller'] = $caller['file'] . ' in ' . $caller['function'] . '(' . $caller['line'] . ')';
183 }
184
185 $line = $this->formatLine($items);
186
187 // try to write to file. Don't write if directory doesn't exists (leads to notices)
188 if ($this->logPath && is_dir(dirname($this->logPath)) )
189 {
190 file_put_contents($this->logPath,$line, FILE_APPEND);
191 }
192 else {
193 error_log($line);
194 }
195 }
196
197 protected function formatLine($args = array() )
198 {
199 $line= $this->format;
200 foreach($args as $key => $value)
201 {
202 if (! is_array($value) && ! is_object($value))
203 $line = str_replace('%%' . $key . '%%', $value, $line);
204 }
205
206 $line .= PHP_EOL;
207
208 if (isset($args['data']))
209 {
210 $data = array_filter($args['data']);
211 if (count($data) > 0)
212 {
213 foreach($data as $item)
214 {
215 $line .= $item . PHP_EOL;
216 }
217 }
218 }
219
220 return $line;
221 }
222
223 protected function setLogLevel($level)
224 {
225 $this->logLevel = $level;
226 }
227
228 protected function getEnv($name)
229 {
230 if (isset($this->{$name}))
231 {
232 return $this->{$name};
233 }
234 else {
235 return false;
236 }
237 }
238
239 public static function addError($message, $args = array())
240 {
241 $level = DebugItem::LEVEL_ERROR;
242 $log = self::getInstance();
243 $log->addLog($message, $level, $args);
244 }
245 public static function addWarn($message, $args = array())
246 {
247 $level = DebugItem::LEVEL_WARN;
248 $log = self::getInstance();
249 $log->addLog($message, $level, $args);
250 }
251 // Alias, since it goes wrong so often.
252 public static function addWarning($message, $args = array())
253 {
254 self::addWarn($message, $args);
255 }
256 public static function addInfo($message, $args = array())
257 {
258 $level = DebugItem::LEVEL_INFO;
259 $log = self::getInstance();
260 $log->addLog($message, $level, $args);
261 }
262 public static function addDebug($message, $args = array())
263 {
264 $level = DebugItem::LEVEL_DEBUG;
265 $log = self::getInstance();
266 $log->addLog($message, $level, $args);
267 }
268
269 /** These should be removed every release. They are temporary only for d'bugging the current release */
270 public static function addTemp($message, $args = array())
271 {
272 self::addDebug($message, $args);
273 }
274
275 public static function logLevel($level)
276 {
277 $log = self::getInstance();
278 static::addInfo('Changing Log level' . $level);
279 $log->setLogLevel($level);
280 }
281
282 public static function getLogLevel()
283 {
284 $log = self::getInstance();
285 return $log->getEnv('logLevel');
286 }
287
288 public static function isManualDebug()
289 {
290 $log = self::getInstance();
291 return $log->getEnv('is_manual_request');
292 }
293
294 public static function getLogPath()
295 {
296 $log = self::getInstance();
297 return $log->getEnv('logPath');
298 }
299
300 /** Function to test if the debugger is active
301 * @return boolean true when active.
302 */
303 public static function debugIsActive()
304 {
305 $log = self::getInstance();
306 return $log->getEnv('is_active');
307 }
308
309 protected function monitorHooks()
310 {
311
312 foreach($this->hooks as $hook => $data)
313 {
314 $numargs = isset($data['numargs']) ? $data['numargs'] : 1;
315 $prio = isset($data['priority']) ? $data['priority'] : 10;
316
317 add_filter($hook, function($value) use ($hook) {
318 $args = func_get_args();
319 return $this->logHook($hook, $value, $args); }, $prio, $numargs);
320 }
321 }
322
323 public function logHook($hook, $value, $args)
324 {
325 array_shift($args);
326 self::addInfo('[Hook] - ' . $hook . ' with ' . var_export($value,true), $args);
327 return $value;
328 }
329
330 public function loadView()
331 {
332 // load either param or class template.
333 $template = $this->template;
334
335 $view = $this->view;
336 $view->namespace = $this->namespace;
337 $controller = $this;
338
339 $template_path = __DIR__ . '/' . $this->template . '.php';
340 // var_dump( $template_path);
341 if (file_exists($template_path))
342 {
343
344 include($template_path);
345 }
346 else {
347 self::addError("View $template could not be found in " . $template_path,
348 array('class' => get_class($this), 'req' => $_REQUEST));
349 }
350 }
351
352
353 } // class debugController
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>
1 {
2 "name": "shortpixel/notices",
3 "description": "ShortPixel WordPress Notice System",
4 "version": "1.5",
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 }
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 protected $notice_displayed = array();
12
13 public $notice_count = 0;
14
15 protected $has_stored = false;
16
17 protected $notice_option = ''; // The wp_options name for notices here.
18
19 /** For backward compat. Never call constructor directly. */
20 public function __construct()
21 {
22 $ns = __NAMESPACE__;
23 $ns = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
24 $this->notice_option = $ns . '-notices';
25
26 add_action('wp_ajax_' . $this->notice_option, array($this, 'ajax_action'));
27
28 $this->loadNotices();
29 //$this->loadConfig();
30 }
31
32 public static function getInstance()
33 {
34 if ( self::$instance === null)
35 {
36 self::$instance = new NoticeController();
37 }
38
39 return self::$instance;
40 }
41
42 /** Reset all notices, before loading them, to ensure on updates / activations one starts fresh */
43 public static function resetNotices()
44 {
45 $ns = __NAMESPACE__;
46 $ns = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
47 $result = delete_option($ns . '-notices');
48 }
49
50 /** Load Notices Config File, if any
51 *
52 * [ Future Use ]
53 */
54 public function loadConfig()
55 {
56 return;
57 if (file_exists('../notice_config.json'))
58 {
59 $config = file_get_contents('../notice_config.json');
60 $json_config = json_decode($config);
61 }
62 }
63
64 public function loadIcons($icons)
65 {
66 foreach($icons as $name => $icon)
67 NoticeModel::setIcon($name, $icon);
68 }
69
70
71 protected function loadNotices()
72 {
73 $notices = get_option($this->notice_option, false);
74 $cnotice = (is_array($notices)) ? count($notices) : 0;
75
76 if ($notices !== false && is_array($notices))
77 {
78 $checked = array();
79 foreach($notices as $noticeObj)
80 {
81 if (is_object($noticeObj) && $noticeObj instanceOf NoticeModel)
82 {
83 $checked[] = $noticeObj;
84 }
85 }
86 self::$notices = $checked;
87 $this->has_stored = true;
88 }
89 else {
90 self::$notices = array();
91 $this->has_stored = false;
92 }
93 $this->countNotices();
94 }
95
96
97 protected function addNotice($message, $code, $unique)
98 {
99 $notice = new NoticeModel($message, $code);
100
101 if ($unique)
102 {
103 foreach(self::$notices as $nitem)
104 {
105 if ($nitem->message == $notice->message && $nitem->code == $notice->code) // same message.
106 return $nitem; // return the notice with the same message.
107 }
108 }
109 self::$notices[] = $notice;
110 $this->countNotices();
111 Log::addDebug('Adding notice - ', $notice);
112 $this->update();
113 return $notice;
114 }
115
116 /** Update the notices to store, check what to remove, returns count. */
117 public function update()
118 {
119 if (! is_array(self::$notices) || count(self::$notices) == 0)
120 {
121 if ($this->has_stored)
122 delete_option($this->notice_option);
123
124 return 0;
125 }
126
127 $new_notices = array();
128 foreach(self::$notices as $item)
129 {
130 if (! $item->isDone() )
131 {
132 $new_notices[] = $item;
133 }
134 }
135
136 update_option($this->notice_option, $new_notices);
137 self::$notices = $new_notices;
138
139 return $this->countNotices();
140 }
141
142 public function countNotices()
143 {
144 $this->notice_count = count(self::$notices);
145 return $this->notice_count;
146 }
147
148
149 public function getNotices()
150 {
151 return self::$notices;
152 }
153
154 public function getNoticesForDisplay()
155 {
156 $newNotices = array();
157
158 foreach(self::$notices as $notice)
159 {
160 if ($notice->isDismissed()) // dismissed never displays.
161 continue;
162
163 if ($notice->isPersistent())
164 {
165 $id = $notice->getID();
166 if (! is_null($id) && ! in_array($id, $this->notice_displayed))
167 {
168 $notice->notice_action = $this->notice_option;
169 $newNotices[] = $notice;
170 $this->notice_displayed[] = $id;
171 }
172
173 }
174 else
175 $newNotices[] = $notice;
176
177
178 }
179 return $newNotices;
180 }
181
182
183 public function getNoticeByID($id)
184 {
185 foreach(self::$notices as $notice)
186 {
187 if ($notice->getID() == $id)
188 return $notice;
189 }
190
191 return false;
192 }
193
194 public static function removeNoticeByID($id)
195 {
196 $noticeController = self::getInstance();
197
198 for($i = 0; $i < count(self::$notices); $i++)
199 {
200 $item = self::$notices[$i];
201 if (is_object($item) && $item->getID() == $id)
202 {
203 Log::addDebug('Removing notice with ID ' . $id);
204 unset(self::$notices[$i]);
205 }
206 //if ($notice_item )
207 }
208 $noticeController->update();
209 }
210
211 public function ajax_action()
212 {
213 $response = array('result' => false, 'reason' => '');
214
215 if ( wp_verify_nonce( $_POST['nonce'], 'dismiss') )
216 {
217 if ($_POST['plugin_action'] == 'dismiss')
218 {
219 $id = sanitize_text_field($_POST['id']);
220 $notice = $this->getNoticeByID($id);
221
222 if($notice)
223 {
224 $notice->dismiss();
225 $this->update();
226 $response['result'] = true;
227 }
228 else
229 {
230 Log::addError('Notice not found when dismissing -> ' . $id, self::$notices);
231 $response['result'] = ' Notice ' . $id . ' not found. ';
232 }
233
234 }
235
236 }
237 else
238 {
239 Log::addError('Wrong Nonce when dismissed notice. ');
240 $response['reason'] = 'wrong nonce';
241 }
242 wp_send_json($response);
243 }
244
245 /** Adds a notice, quick and fast method
246 * @param String $message The Message you want to notify
247 * @param Boolean $unique If unique, check to not repeat notice exact same text in notices. Discard if so
248 * @param int $code A value of messageType as defined in model
249 * @returm Object Instance of noticeModel
250 */
251
252 public static function addNormal($message, $unique = false)
253 {
254 $noticeController = self::getInstance();
255 $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_NORMAL, $unique);
256 return $notice;
257
258 }
259
260 public static function addError($message, $unique = false)
261 {
262 $noticeController = self::getInstance();
263 $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_ERROR, $unique);
264 return $notice;
265
266 }
267
268 public static function addWarning($message, $unique = false)
269 {
270 $noticeController = self::getInstance();
271 $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_WARNING, $unique);
272 return $notice;
273 }
274
275 public static function addSuccess($message, $unique = false)
276 {
277 $noticeController = self::getInstance();
278 $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_SUCCESS, $unique);
279 return $notice;
280
281 }
282
283 public static function addDetail($notice, $detail)
284 {
285 $noticeController = self::getInstance();
286 $notice->addDetail($detail);
287
288 // $notice_id = spl_object_id($notice);
289
290 $noticeController->update();
291 }
292
293 /** Make a regular notice persistent across multiple page loads
294 * @param $notice NoticeModel The Notice to make Persistent
295 * @param $key String Identifier of the persistent notice.
296 * @param $suppress Int When dismissed, time to stay dismissed
297 * @param $callback Function Callable function
298 */
299 public static function makePersistent($notice, $key, $suppress = -1, $callback = null)
300 {
301 $noticeController = self::getInstance();
302 $existing = $noticeController->getNoticeByID($key);
303
304 // if this key already exists, don't allow the new notice to be entered into the array. Remove it since it's already created.
305 if ($existing)
306 {
307 for($i = 0; $i < count(self::$notices); $i++)
308 {
309 $item = self::$notices[$i];
310
311 if ($item->message == $notice->message && $item->getID() == null)
312 {
313 if ($item->message != $existing->message) // allow the persistent message to be updated, if something else is served on this ID
314 {
315 $existing->message = $item->message;
316 }
317 unset(self::$notices[$i]);
318 }
319 //if ($notice_item )
320 }
321 }
322 else
323 {
324 $notice->setPersistent($key, $suppress, $callback); // set this notice persistent.
325 }
326
327 $noticeController->update();
328 }
329
330 public function admin_notices()
331 {
332 if ($this->countNotices() > 0)
333 {
334 if (! self::$cssHookLoaded)
335 {
336 add_action('admin_print_footer_scripts', array($this, 'printNoticeStyle'));
337 self::$cssHookLoaded = true;
338 }
339 foreach($this->getNoticesForDisplay() as $notice)
340 {
341 echo $notice->getForDisplay();
342 }
343 }
344 $this->update(); // puts views, and updates
345 }
346
347
348 public function printNoticeStyle()
349 {
350 if (file_exists(__DIR__ . '/css/notices.css'))
351 {
352 echo '<style>' . file_get_contents(__DIR__ . '/css/notices.css') . '</style>';
353 }
354 else {
355 Log::addDebug('Notices : css/notices.css could not be loaded');
356 }
357 }
358
359
360
361
362 }
1 <?php
2 namespace EnableMediaReplace\Notices;
3
4 class NoticeModel //extends ShortPixelModel
5 {
6 public $message; // The message we want to convey.
7 public $details = array(); // extra details, like the files involved. Something could be hideable in the future.
8 public $code;
9
10 private $id = null; // used for persistent messages.
11 protected $viewed = false; // was this notice viewed?
12 protected $is_persistent = false; // This is a fatal issue, display until something was fixed.
13 protected $is_dismissed = false; // for persistent notices,
14 protected $suppress_until = null;
15 protected $suppress_period = -1;
16 public $is_removable = true; // if removable, display a notice dialog with red X or so.
17 public $messageType = self::NOTICE_NORMAL;
18
19 public $notice_action; // empty unless for display. Ajax action to talk back to controller.
20 protected $callback; // empty unless callback is needed
21
22 public static $icons = array();
23
24 const NOTICE_NORMAL = 1;
25 const NOTICE_ERROR = 2;
26 const NOTICE_SUCCESS = 3;
27 const NOTICE_WARNING = 4;
28
29 /** Use this model in conjunction with NoticeController, do not call directly */
30 public function __construct($message, $messageType = self::NOTICE_NORMAL)
31 {
32 $this->message = $message;
33 $this->messageType = $messageType;
34
35 }
36
37 public function isDone()
38 {
39 // check suppressed
40 if ($this->is_dismissed && ! is_null($this->suppress_until))
41 {
42 if (time() >= $this->suppress_until)
43 {
44 //Log::addDebug('')
45 $this->is_persistent = false; // unpersist, so it will be cleaned and dropped.
46
47 }
48 }
49
50 if ($this->viewed && ! $this->is_persistent)
51 return true;
52 else
53 return false;
54 }
55
56 public function getID()
57 {
58 return $this->id;
59 }
60
61 public function isPersistent()
62 {
63 return $this->is_persistent;
64 }
65
66 public function isDismissed()
67 {
68 return $this->is_dismissed;
69 }
70
71 public function dismiss()
72 {
73 $this->is_dismissed = true;
74 $this->suppress_until = time() + $this->suppress_period;
75 }
76
77 public function unDismiss()
78 {
79 $this->is_dismissed = false;
80 }
81
82 public function setDismissedUntil($timestamp)
83 {
84 $this->suppress_until = $timestamp;
85 }
86
87 /** Support for extra information beyond the message.
88 * Can help to not overwhelm users w/ the same message but different file /circumstances.
89 */
90 public function addDetail($detail, $clean = false)
91 {
92 if ($clean)
93 $this->details = array();
94
95 if (! in_array($detail, $this->details) )
96 $this->details[] = $detail;
97 }
98
99
100
101 /** Set a notice persistent. Meaning it shows every page load until dismissed.
102 * @param $key Unique Key of this message. Required
103 * @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
104 */
105 public function setPersistent($key, $suppress = -1, $callback = null)
106 {
107 $this->id = $key;
108 $this->is_persistent = true;
109 $this->suppress_period = $suppress;
110 if ( ! is_null($callback) && is_callable($callback))
111 {
112 $this->callback = $callback;
113 }
114 }
115
116 public static function setIcon($notice_type, $icon)
117 {
118 switch($notice_type)
119 {
120 case 'error':
121 $type = self::NOTICE_ERROR;
122 break;
123 case 'success':
124 $type = self::NOTICE_SUCCESS;
125 break;
126 case 'warning':
127 $type = self::NOTICE_WARNING;
128 break;
129 case 'normal':
130 default:
131 $type = self::NOTICE_NORMAL;
132 break;
133 }
134 self::$icons[$type] = $icon;
135 }
136
137 private function checkIncomplete($var)
138 {
139 return ($var instanceof \__PHP_Incomplete_Class);
140 }
141
142 public function getForDisplay()
143 {
144 $this->viewed = true;
145 $class = 'shortpixel notice ';
146
147 $icon = '';
148
149 if ($this->callback)
150 {
151 if (is_array($this->callback))
152 {
153 foreach($this->callback as $part)
154 {
155 if ($this->checkIncomplete($part) === true)
156 {
157 return false;
158 }
159 }
160 } elseif (is_object($this->callback))
161 {
162 if ($this->checkIncomplete($part) === true)
163 return false;
164 }
165
166 $return = call_user_func($this->callback, $this);
167 if ($return === false) // don't display is callback returns false explicitly.
168 return;
169 }
170
171 switch($this->messageType)
172 {
173 case self::NOTICE_ERROR:
174 $class .= 'notice-error ';
175 $icon = isset(self::$icons[self::NOTICE_ERROR]) ? self::$icons[self::NOTICE_ERROR] : '';
176 //$icon = 'scared';
177 break;
178 case self::NOTICE_SUCCESS:
179 $class .= 'notice-success ';
180 $icon = isset(self::$icons[self::NOTICE_SUCCESS]) ? self::$icons[self::NOTICE_SUCCESS] : '';
181 break;
182 case self::NOTICE_WARNING:
183 $class .= 'notice-warning ';
184 $icon = isset(self::$icons[self::NOTICE_WARNING]) ? self::$icons[self::NOTICE_WARNING] : '';
185 break;
186 case self::NOTICE_NORMAL:
187 $class .= 'notice-info ';
188 $icon = isset(self::$icons[self::NOTICE_NORMAL]) ? self::$icons[self::NOTICE_NORMAL] : '';
189 break;
190 default:
191 $class .= 'notice-info ';
192 $icon = '';
193 break;
194 }
195
196
197 if ($this->is_removable)
198 {
199 $class .= 'is-dismissible ';
200 }
201
202 if ($this->is_persistent)
203 {
204 $class .= 'is-persistent ';
205 }
206
207 $id = ! is_null($this->id) ? $this->id : uniqid();
208 //'id="' . $this->id . '"'
209 $output = "<div id='$id' class='$class'><span class='icon'> " . $icon . "</span> <span class='content'>" . $this->message;
210 if ($this->hasDetails())
211 {
212 $output .= '<div class="details-wrapper">
213 <input type="checkbox" name="detailhider" id="check-' . $id .'">
214 <label for="check-' . $id . '" class="show-details"><span>' . __('See Details', 'shortpixel-image-optimiser') . '</span>
215 </label>';
216
217 $output .= "<div class='detail-content-wrapper'><p class='detail-content'>" . $this->parseDetails() . "</p></div>";
218 $output .= '<label for="check-' . $id . '" class="hide-details"><span>' . __('Hide Details', 'shortpixel-image-optimiser') . '</span></label>';
219
220 $output .= '</div>'; // detail rapper
221
222 }
223 $output .= "</span></div>";
224
225 if ($this->is_persistent && $this->is_removable)
226 {
227 $output .= "<script type='text/javascript'>\n" . $this->getDismissJS() . "\n</script>";
228 }
229 return $output;
230
231 }
232
233 protected function hasDetails()
234 {
235 if (is_array($this->details) && count($this->details) > 0)
236 return true;
237 else
238 return false;
239 }
240
241 protected function parseDetails()
242 {
243 return implode('<BR>', $this->details);
244 }
245
246 private function getDismissJS()
247 {
248 $url = wp_json_encode(admin_url('admin-ajax.php'));
249 // $action = 'dismiss';
250 $nonce = wp_create_nonce('dismiss');
251
252 $data = wp_json_encode(array('action' => $this->notice_action, 'plugin_action' => 'dismiss', 'nonce' => $nonce, 'id' => $this->id, 'time' => $this->suppress_period));
253
254 // $data_string = "{action:'$this->notice_action'}";
255
256 $js = "jQuery(document).on('click','#$this->id button.notice-dismiss',
257 function() {
258 var data = $data;
259 var url = $url;
260 jQuery.post(url, data); }
261 );";
262 return "\n jQuery(document).ready(function(){ \n" . $js . "\n});";
263 }
264
265 }
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; }
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 }
1 <?php
2 namespace EnableMediaReplace;
3
4 use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
5
6 class emrCache
7 {
8 protected $has_supercache = false; // supercache seems to replace quite fine, without our help. @todo Test if this is needed
9 protected $has_w3tc = false;
10 protected $has_wpengine = false;
11 protected $has_fastestcache = false;
12 protected $has_siteground = false;
13 protected $has_litespeed = false;
14
15 public function __construct()
16 {
17
18 }
19
20 /** Checks which cache plugins are active on the moment a flush is needed */
21 public function checkCaches()
22 {
23 if ( function_exists( 'w3tc_pgcache_flush' ) )
24 $this->has_w3tc = true;
25
26 if ( function_exists('wp_cache_clean_cache') )
27 $this->has_supercache = true;
28
29 if ( class_exists( 'WpeCommon' ) )
30 $this->has_wpengine = true;
31
32 global $wp_fastest_cache;
33 if ( method_exists( 'WpFastestCache', 'deleteCache' ) && !empty( $wp_fastest_cache ) )
34 $this->has_fastestcache = true;
35
36 // SG SuperCacher
37 if (function_exists('sg_cachepress_purge_cache')) {
38 $this->has_siteground = true;
39 }
40
41 if (defined( 'LSCWP_DIR' ))
42 {
43 $this->has_litespeed = true;
44 }
45
46 // @todo WpRocket?
47 // @todo BlueHost Caching?
48 }
49
50 /* Tries to flush cache there were we have issues
51 *
52 * @param Array $args Argument Array to provide data.
53 */
54 public function flushCache($args)
55 {
56 $defaults = array(
57 'flush_mode' => 'post',
58 'post_id' => 0,
59 );
60
61 $args = wp_parse_args($args, $defaults);
62 $post_id = $args['post_id']; // can be zero!
63
64 // important - first check the available cache plugins
65 $this->checkCaches();
66
67 // general WP
68 if ($post_id > 0)
69 clean_post_cache($post_id);
70 else
71 wp_cache_flush();
72
73 /* Verified working without.
74 if ($this->has_supercache)
75 $this->removeSuperCache();
76 */
77 if ($this->has_w3tc)
78 $this->removeW3tcCache();
79
80 if ($this->has_wpengine)
81 $this->removeWpeCache();
82
83 if ($this->has_siteground)
84 $this->removeSiteGround();
85
86 if ($this->has_fastestcache)
87 $this->removeFastestCache();
88
89 if ($this->has_litespeed)
90 $this->litespeedReset($post_id);
91
92 do_action('emr/cache/flush', $post_id);
93 }
94
95 protected function removeSuperCache()
96 {
97 global $file_prefix, $supercachedir;
98 if ( empty( $supercachedir ) && function_exists( 'get_supercache_dir' ) ) {
99 $supercachedir = get_supercache_dir();
100 }
101 wp_cache_clean_cache( $file_prefix );
102 }
103
104 protected function removeW3tcCache()
105 {
106 w3tc_pgcache_flush();
107 }
108
109 protected function removeWpeCache()
110 {
111 if ( method_exists( 'WpeCommon', 'purge_memcached' ) ) {
112 \WpeCommon::purge_memcached();
113 }
114 if ( method_exists( 'WpeCommon', 'clear_maxcdn_cache' ) ) {
115 \WpeCommon::clear_maxcdn_cache();
116 }
117 if ( method_exists( 'WpeCommon', 'purge_varnish_cache' ) ) {
118 \WpeCommon::purge_varnish_cache();
119 }
120 }
121
122 protected function removeFastestCache()
123 {
124 global $wp_fastest_cache;
125 $wp_fastest_cache->deleteCache();
126 }
127
128 protected function removeSiteGround()
129 {
130 sg_cachepress_purge_cache();
131 }
132
133 protected function litespeedReset($post_id)
134 {
135 do_action('litespeed_media_reset', $post_id);
136 }
137
138 }
1 <?php
2
3 // Compatibility functions for old version of WordPress / PHP / Other
4
5
6 /*
7 * Introduced in WP 4.9.7 - https://developer.wordpress.org/reference/functions/wp_delete_attachment_files/
8 * Compat for previous versions.
9 */
10 if (! function_exists('wp_delete_attachment_files'))
11 {
12 function wp_delete_attachment_files($post_id, $meta, $backup_sizes, $file )
13 {
14 global $wpdb;
15 $uploadpath = wp_get_upload_dir();
16 $deleted = true;
17
18 if ( ! empty( $meta['thumb'] ) ) {
19 // Don't delete the thumb if another attachment uses it.
20 if ( ! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $wpdb->esc_like( $meta['thumb'] ) . '%', $post_id ) ) ) {
21 $thumbfile = str_replace( wp_basename( $file ), $meta['thumb'], $file );
22 if ( ! empty( $thumbfile ) ) {
23 $thumbfile = path_join( $uploadpath['basedir'], $thumbfile );
24 $thumbdir = path_join( $uploadpath['basedir'], dirname( $file ) );
25
26 if ( ! wp_delete_file_from_directory( $thumbfile, $thumbdir ) ) {
27 $deleted = false;
28 }
29 }
30 }
31 }
32
33 // Remove intermediate and backup images if there are any.
34 if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
35 $intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
36 foreach ( $meta['sizes'] as $size => $sizeinfo ) {
37 $intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
38 if ( ! empty( $intermediate_file ) ) {
39 $intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
40
41 if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
42 $deleted = false;
43 }
44 }
45 }
46 }
47
48 if ( is_array( $backup_sizes ) ) {
49 $del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
50 foreach ( $backup_sizes as $size ) {
51 $del_file = path_join( dirname( $meta['file'] ), $size['file'] );
52 if ( ! empty( $del_file ) ) {
53 $del_file = path_join( $uploadpath['basedir'], $del_file );
54
55 if ( ! wp_delete_file_from_directory( $del_file, $del_dir ) ) {
56 $deleted = false;
57 }
58 }
59 }
60 }
61
62 if ( ! wp_delete_file_from_directory( $file, $uploadpath['basedir'] ) ) {
63 $deleted = false;
64 }
65
66 return $deleted;
67
68 }
69 } // end function
70
71
72 /*
73 * Introduced in WP 4.9.7 - https://developer.wordpress.org/reference/functions/wp_delete_attachment_files/
74 * Compat for previous versions.
75 */
76 if (! function_exists('wp_delete_file_from_directory'))
77 {
78 function wp_delete_file_from_directory( $file, $directory ) {
79 if ( wp_is_stream( $file ) ) {
80 $real_file = wp_normalize_path( $file );
81 $real_directory = wp_normalize_path( $directory );
82 } else {
83 $real_file = realpath( wp_normalize_path( $file ) );
84 $real_directory = realpath( wp_normalize_path( $directory ) );
85 }
86
87 if ( false === $real_file || false === $real_directory || strpos( $real_file, trailingslashit( $real_directory ) ) !== 0 ) {
88 return false;
89 }
90
91 wp_delete_file( $file );
92
93 return true;
94 }
95
96 } // end function
97
98
99 /*
100 * Introduced in WP 4.5.0 - needed for compat function of wp_delete_attachment_files
101 */
102 if (! function_exists('wp_get_upload_dir'))
103 {
104 function wp_get_upload_dir() {
105 return wp_upload_dir( null, false );
106 }
107 }
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 private $user_cap = false;
14 private $general_cap = false;
15
16 public function __construct()
17 {
18 add_action('plugins_loaded', array($this, 'runtime'));
19 }
20
21 public function runtime()
22 {
23 $this->nopriv_plugin_actions();
24
25 if (EMR_CAPABILITY !== false)
26 {
27 if (is_array(EMR_CAPABILITY))
28 {
29 $this->general_cap = EMR_CAPABILITY[0];
30 $this->user_cap = EMR_CAPABILITY[1];
31
32 if (! current_user_can($this->general_cap) && ! current_user_can($this->user_cap))
33 return;
34 }
35 else
36 {
37 $this->general_cap = EMR_CAPABILITY;
38 if (! current_user_can($this->general_cap))
39 return;
40 }
41 }
42 elseif (! current_user_can('upload_files'))
43 return;
44
45 $this->plugin_actions(); // init
46 }
47
48 public static function get()
49 {
50 if (is_null(self::$instance))
51 self::$instance = new EnableMediaReplacePlugin();
52
53 $log = Log::getInstance();
54 if (Log::debugIsActive())
55 {
56 $uploaddir = wp_upload_dir(null, false, false);
57 if (isset($uploaddir['basedir']))
58 $log->setLogPath($uploaddir['basedir'] . "/emr_log");
59 }
60 return self::$instance;
61 }
62
63 // Actions for EMR that always need to hook
64 protected function nopriv_plugin_actions()
65 {
66 // shortcode
67 add_shortcode('file_modified', array($this, 'get_modified_date'));
68 }
69
70 public function plugin_actions()
71 {
72 $this->plugin_path = plugin_dir_path(EMR_ROOT_FILE);
73 $this->plugin_url = plugin_dir_url(EMR_ROOT_FILE);
74
75 // init plugin
76 add_action('admin_menu', array($this,'menu'));
77 add_action('admin_init', array($this,'init'));
78 add_action('admin_enqueue_scripts', array($this,'admin_scripts'));
79
80
81 // content filters
82 add_filter('media_row_actions', array($this,'add_media_action'), 10, 2);
83 add_action('attachment_submitbox_misc_actions', array($this,'admin_date_replaced_media_on_edit_media_screen'), 91 );
84 //add_filter('upload_mimes', array($this,'add_mime_types'), 1, 1);
85
86 // notices
87 add_action('admin_notices', array($this,'display_notices'));
88 add_action('network_admin_notices', array($this,'display_network_notices'));
89 add_action('wp_ajax_emr_dismiss_notices', array($this,'dismiss_notices'));
90
91 // editors
92 add_action( 'add_meta_boxes', array($this, 'add_meta_boxes'),10,2 );
93 add_filter('attachment_fields_to_edit', array($this, 'attachment_editor'), 10, 2);
94
95 /** Just after an image is replaced, try to browser decache the images */
96 if (isset($_GET['emr_replaced']) && intval($_GET['emr_replaced'] == 1))
97 {
98 add_filter('wp_get_attachment_image_src',array($this, 'attempt_uncache_image'), 10, 4);
99
100 // adds a metabox to list thumbnails. This is a cache reset hidden as feature.
101 //add_action( 'add_meta_boxes', function () { );
102 add_filter('postbox_classes_attachment_emr-showthumbs-box', function($classes) { $classes[] = 'closed'; return $classes; });
103 }
104
105
106 }
107
108 /**
109 * Register this file in WordPress so we can call it with a ?page= GET var.
110 * To suppress it in the menu we give it an empty menu title.
111 */
112 public function menu()
113 {
114 /* add_submenu_page(null, esc_html__("Replace media", "enable-media-replace"), esc_html__("Replace media", "enable-media-replace"), 'upload_files', 'enable-media-replace/enable-media-replace', array($this, 'route')); */
115 add_submenu_page(null, esc_html__("Replace media", "enable-media-replace"), esc_html__("Replace media", "enable-media-replace"), 'upload_files', 'enable-media-replace/enable-media-replace', array($this, 'route'));
116 }
117
118 /**
119 * Initialize this plugin. Called by 'admin_init' hook.
120 *
121 */
122 public function init()
123 {
124 load_plugin_textdomain( 'enable-media-replace', false, basename(dirname(EMR_ROOT_FILE) ) . '/languages' );
125
126 // Load Submodules
127
128 $notices = Notices::getInstance();
129
130 // Enqueue notices
131 add_action('admin_notices', array($notices, 'admin_notices')); // previous page / init time
132 add_action('admin_footer', array($notices, 'admin_notices')); // fresh notices between init - end
133
134 new Externals();
135 }
136
137 /** Load EMR views based on request */
138 public function route()
139 {
140 global $plugin_page;
141 switch($plugin_page)
142 {
143 case 'enable-media-replace/enable-media-replace.php':
144 $action = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : '';
145 wp_enqueue_style('emr_style');
146 wp_enqueue_script('jquery-ui-datepicker');
147 wp_enqueue_style('jquery-ui-datepicker');
148 wp_enqueue_script('emr_admin');
149
150 if (! check_admin_referer( $action, '_wpnonce') )
151 {
152 die('Invalid Nonce');
153 }
154
155 // @todo Later this should be move to it's own controller, and built view from there.
156 if ( $action == 'media_replace' ) {
157 if ( array_key_exists("attachment_id", $_GET) && intval($_GET["attachment_id"]) > 0) {
158 wp_enqueue_script('emr_upsell');
159 require_once($this->plugin_path . "views/popup.php"); // warning variables like $action be overwritten here.
160 }
161 }
162 elseif ( $action == 'media_replace_upload' ) {
163 require_once($this->plugin_path . 'views/upload.php');
164 }
165 else {
166 exit('Something went wrong loading page, please try again');
167 }
168
169 break;
170 }
171
172 }
173
174 public function getPluginURL($path = '')
175 {
176 return plugins_url($path, EMR_ROOT_FILE);
177 }
178
179 /** register styles and scripts
180 *
181 * Nothing should ever by -enqueued- here, just registered.
182 */
183 public function admin_scripts()
184 {
185 if (is_rtl())
186 {
187 wp_register_style('emr_style', plugins_url('css/admin.rtl.css', EMR_ROOT_FILE) );
188 }
189 else {
190 wp_register_style('emr_style', plugins_url('css/admin.css', EMR_ROOT_FILE) );
191 }
192
193 wp_register_style('emr_edit-attachment', plugins_url('css/edit_attachment.css', EMR_ROOT_FILE));
194
195 $mimes = array_values(get_allowed_mime_types());
196
197 wp_register_script('emr_admin', plugins_url('js/emr_admin.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true );
198 $emr_options = array(
199 'dateFormat' => $this->convertdate(get_option( 'date_format' )),
200 'maxfilesize' => wp_max_upload_size(),
201 'allowed_mime' => $mimes,
202 );
203
204 wp_register_script('emr_upsell', plugins_url('js/upsell.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true );
205
206 wp_localize_script('emr_upsell', 'emr_upsell', array(
207 'ajax' => admin_url('admin-ajax.php'),
208 'installing' => __('Installing ...', 'enable-media-replace'),
209
210 ));
211
212 if (Log::debugIsActive())
213 $emr_options['is_debug'] = true;
214
215 wp_localize_script('emr_admin', 'emr_options', $emr_options);
216 }
217
218 /** Utility function for the Jquery UI Datepicker */
219 public function convertdate( $sFormat ) {
220 switch( $sFormat ) {
221 //Predefined WP date formats
222 case 'F j, Y':
223 return( 'MM dd, yy' );
224 break;
225 case 'Y/m/d':
226 return( 'yy/mm/dd' );
227 break;
228 case 'm/d/Y':
229 return( 'mm/dd/yy' );
230 break;
231 case 'd/m/Y':
232 default:
233 return( 'dd/mm/yy' );
234 break;
235 }
236 }
237
238 public function checkImagePermission($author_id, $post_id)
239 {
240 if ($this->general_cap === false && $this->user_cap === false)
241 {
242 if ( current_user_can('edit_post', $post_id) === true)
243 return true;
244 }
245 elseif (current_user_can($this->general_cap))
246 return true;
247 elseif (current_user_can($this->user_cap) && $author_id == get_current_user_id())
248 return true;
249
250 return false;
251 }
252
253 /** Get the URL to the media replace page
254 * @param $attach_id The attachment ID to replace
255 * @return Admin URL to the page.
256 */
257 protected function getMediaReplaceURL($attach_id)
258 {
259 $url = admin_url( "upload.php");
260 $url = add_query_arg(array(
261 'page' => 'enable-media-replace/enable-media-replace.php',
262 'action' => 'media_replace',
263 'attachment_id' => $attach_id,
264 ), $url);
265
266 return $url;
267
268 }
269
270 public function add_meta_boxes($post_type, $post)
271 {
272 // Because some plugins don't like to play by the rules.
273 if (is_null($post_type) || is_null($post))
274 return false;
275
276 if (! $this->checkImagePermission($post->post_author, $post->ID))
277 { return; }
278
279 add_meta_box('emr-replace-box', __('Replace Media', 'enable-media-replace'), array($this, 'replace_meta_box'), 'attachment', 'side', 'low');
280
281 if (isset($_GET['emr_replaced']) && intval($_GET['emr_replaced'] == 1))
282 {
283 add_meta_box('emr-showthumbs-box', __('Replaced Thumbnails Preview', 'enable-media-replace'), array($this, 'show_thumbs_box'), 'attachment', 'side', 'low');
284 }
285
286 }
287
288 public function replace_meta_box($post)
289 {
290
291 $url = $this->getMediaReplaceURL($post->ID);
292
293 $action = "media_replace";
294 $editurl = wp_nonce_url( $url, $action );
295
296 /* Unneeded - admin_url already checks for force_ssl_admin ( in set_scheme function )
297 if (FORCE_SSL_ADMIN) {
298 $editurl = str_replace("http:", "https:", $editurl);
299 } */
300 $link = "href=\"$editurl\"";
301
302
303 echo "<p><a class='button-secondary' $link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a></p><p>" . esc_html__("To replace the current file, click the link and upload a replacement.", "enable-media-replace") . "</p>";
304 }
305
306 public function show_thumbs_box($post)
307 {
308 if (! $this->checkImagePermission($post->post_author, $post->ID))
309 { return; }
310
311 wp_enqueue_style('emr_edit-attachment');
312
313 $meta = wp_get_attachment_metadata($post->ID);
314
315 if (! isset($meta['sizes']) )
316 { echo __('Thumbnails were not generated', 'enable-media-replace');
317 return false;
318 }
319
320 if (function_exists('wp_get_original_image_url')) // indicating WP 5.3+
321 {
322 $source_url = wp_get_original_image_url($post->ID);
323 // oldway will give -scaled in case of scaling.
324 $source_url_oldway = wp_get_attachment_url($post->ID);
325
326 if ($source_url !== $source_url_oldway)
327 {
328 echo "<div class='original previewwrapper'><img src='" . $source_url_oldway . "'><span class='label'>" . __('Original') . "</span></div>";
329 }
330
331 }
332
333
334 foreach($meta['sizes'] as $size => $data)
335 {
336 $display_size = ucfirst(str_replace("_", " ", $size));
337 $img = wp_get_attachment_image_src($post->ID, $size);
338 echo "<div class='$size previewwrapper'><img src='" . $img[0] . "'><span class='label'>$display_size</span></div>";
339 }
340 }
341
342 public function attachment_editor($form_fields, $post)
343 {
344 $screen = null;
345
346 if (! $this->checkImagePermission($post->post_author, $post->ID))
347 { return $form_fields; }
348
349 if (function_exists('get_current_screen'))
350 {
351 $screen = get_current_screen();
352
353 if(! is_null($screen) && $screen->id == 'attachment') // hide on edit attachment screen.
354 return $form_fields;
355 }
356
357 $url = $this->getMediaReplaceURL($post->ID);
358 $action = "media_replace";
359 $editurl = wp_nonce_url( $url, $action );
360
361 $link = "href=\"$editurl\"";
362 $form_fields["enable-media-replace"] = array(
363 "label" => esc_html__("Replace media", "enable-media-replace"),
364 "input" => "html",
365 "html" => "<a class='button-secondary' $link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a>", "helps" => esc_html__("To replace the current file, click the link and upload a replacement.", "enable-media-replace")
366 );
367
368 return $form_fields;
369 }
370
371 /**
372 * @param array $mime_types
373 * @return array
374 */
375 /* Off, no clue why this is here.
376 public function add_mime_types($mime_types)
377 {
378 $mime_types['dat'] = 'text/plain'; // Adding .dat extension
379 return $mime_types;
380 }
381 */
382 /**
383 * Function called by filter 'media_row_actions'
384 * Enables linking to EMR straight from the media library
385 */
386 public function add_media_action( $actions, $post) {
387
388
389 if (! $this->checkImagePermission($post->post_author, $post->ID))
390 { return $actions; }
391
392 $url = $this->getMediaReplaceURL($post->ID);
393 $action = "media_replace";
394 $editurl = wp_nonce_url( $url, $action );
395
396 /* See above, not needed.
397 if (FORCE_SSL_ADMIN) {
398 $editurl = str_replace("http:", "https:", $editurl);
399 } */
400 $link = "href=\"$editurl\"";
401
402 $newaction['adddata'] = '<a ' . $link . ' aria-label="' . esc_attr__("Replace media", "enable-media-replace") . '" rel="permalink">' . esc_html__("Replace media", "enable-media-replace") . '</a>';
403 return array_merge($actions,$newaction);
404 }
405
406
407 public function display_notices() {
408 $current_screen = get_current_screen();
409
410 $crtScreen = function_exists("get_current_screen") ? get_current_screen() : (object)array("base" => false);
411 /*
412 if(current_user_can( 'activate_plugins' ) && !get_option( 'emr_news') && !is_plugin_active('shortpixel-image-optimiser/wp-shortpixel.php')
413 && ($crtScreen->base == "upload" || $crtScreen->base == "plugins")
414 //for network installed plugins, don't display the message on subsites.
415 && !(function_exists('is_multisite') && is_multisite() && is_plugin_active_for_network('enable-media-replace/enable-media-replace.php') && !is_main_site()))
416 {
417 require_once($this->plugin_path . '/views/notice.php');
418 } */
419 }
420
421 public function display_network_notices() {
422 if(current_user_can( 'activate_plugins' ) && !get_option( 'emr_news') && !is_plugin_active_for_network('shortpixel-image-optimiser/wp-shortpixel.php')) {
423 require_once( str_replace("enable-media-replace.php", "notice.php", __FILE__) );
424 }
425 }
426
427 /* Ajax function to dismiss notice */
428 public function dismiss_notices() {
429 update_option( 'emr_news', true);
430 exit(json_encode(array("Status" => 0)));
431 }
432
433 /** Outputs the replaced date of the media on the edit_attachment screen
434 *
435 * @param $post Obj Post Object
436 */
437 function admin_date_replaced_media_on_edit_media_screen($post) {
438
439 // Fallback for before version 4.9, doens't pass post.
440 if (! is_object($post))
441 global $post;
442
443 if (! is_object($post)) // try to global, if it doesn't work - return.
444 return false;
445
446 $post_id = $post->ID;
447 if ( $post->post_modified !== $post->post_date ) {
448
449 $modified = date_i18n( __( 'M j, Y @ H:i' ) , strtotime( $post->post_modified ) );
450 ?>
451 <div class="misc-pub-section curtime">
452 <span id="timestamp"><?php echo esc_html__( 'Revised', 'enable-media-replace' ); ?>: <b><?php echo $modified; ?></b></span>
453 </div>
454
455 <?php
456 }
457 $author_id = get_post_meta($post_id, '_emr_replace_author', true);
458
459 if ($author_id)
460 {
461 $display_name = get_the_author_meta('display_name', $author_id);
462 ?>
463 <div class="misc-pub-section replace_author">
464 <span><?php echo esc_html__( 'Replaced By', 'enable-media-replace' ); ?>: <b><?php echo $display_name; ?></b></span>
465 </div>
466 <?php
467 }
468
469 }
470
471 /** When an image is just replaced, it can stuck in the browser cache making a look like it was not replaced. Try
472 * undo that effect by adding a timestamp to the query string */
473 public function attempt_uncache_image($image, $attachment_id, $size, $icon)
474 {
475 if ($image === false)
476 return $image;
477
478 // array with image src on 0
479 $image[0] = add_query_arg('time', time(), $image[0]);
480 return $image;
481 }
482
483 /**
484 * Shorttag function to show the media file modification date/time.
485 * @param array shorttag attributes
486 * @return string content / replacement shorttag
487 * @todo Note this returns the wrong date, ie. server date not corrected for timezone. Function could be removed altogether, not sure about purpose.
488 */
489 public function get_modified_date($atts) {
490 $id=0;
491 $format= '';
492
493 extract(shortcode_atts(array(
494 'id' => '',
495 'format' => get_option('date_format') . " " . get_option('time_format'),
496 ), $atts));
497
498 if ($id == '') return false;
499
500 // Get path to file
501 $current_file = get_attached_file($id);
502
503 if ( ! file_exists( $current_file ) ) {
504 return false;
505 }
506
507 // Get file modification time
508 $filetime = filemtime($current_file);
509
510 if ( false !== $filetime ) {
511 // do date conversion
512 return date( $format, $filetime );
513 }
514
515 return false;
516 }
517
518
519
520 } // class
1 <?php
2 namespace EnableMediaReplace\Externals;
3
4 class Elementor
5 {
6 private static $instance;
7
8 protected $queryKey = 'elementor';
9
10 public static function getInstance()
11 {
12 if (is_null(self::$instance))
13 self::$instance = new Elementor();
14
15 return self::$instance;
16 }
17
18 public function __construct()
19 {
20 if ($this->elementor_is_active()) // elementor is active
21 {
22 add_filter('emr/replacer/custom_replace_query', array($this, 'addElementor'), 10, 4); // custom query for elementor \ // problem
23 add_action('enable-media-replace-upload-done', array($this, 'removeCache') );
24 }
25 }
26
27 public function addElementor($items, $base_url, $search_urls, $replace_urls)
28 {
29 $base_url = $this->addSlash($base_url);
30 $el_search_urls = $search_urls; //array_map(array($this, 'addslash'), $search_urls);
31 $el_replace_urls = $replace_urls; //array_map(array($this, 'addslash'), $replace_urls);
32 $items[$this->queryKey] = array('base_url' => $base_url, 'search_urls' => $el_search_urls, 'replace_urls' => $el_replace_urls);
33 return $items;
34 }
35
36 public function addSlash($value)
37 {
38 global $wpdb;
39 $value= ltrim($value, '/'); // for some reason the left / isn't picked up by Mysql.
40 $value= str_replace('/', '\/', $value);
41 $value = $wpdb->esc_like(($value)); //(wp_slash) / str_replace('/', '\/', $value);
42
43 return $value;
44 }
45
46 protected function elementor_is_active()
47 {
48 $bool = false;
49
50 if (defined('ELEMENTOR_VERSION'))
51 $bool = true;
52
53 return apply_filters('emr/externals/elementor_is_active', $bool); // manual override
54 }
55
56 public function removeCache()
57 {
58 \Elementor\Plugin::$instance->files_manager->clear_cache();
59 }
60 }
1 <?php
2
3
4 /**
5 * Skin class.
6 *
7 * @since 1.0.0
8 *
9 * @package Envira_Gallery
10 * @author Envira Team
11 */
12 class EMR_Envira_Gallery_Skin extends WP_Upgrader_Skin {
13
14 /**
15 * Primary class constructor.
16 *
17 * @since 1.0.0
18 *
19 * @param array $args Empty array of args (we will use defaults).
20 */
21 public function __construct( $args = array() ) {
22
23 parent::__construct();
24
25 }
26
27 /**
28 * Set the upgrader object and store it as a property in the parent class.
29 *
30 * @since 1.0.0
31 *
32 * @param object $upgrader The upgrader object (passed by reference).
33 */
34 public function set_upgrader( &$upgrader ) {
35
36 if ( is_object( $upgrader ) ) {
37 $this->upgrader =& $upgrader;
38 }
39
40 }
41
42 /**
43 * Set the upgrader result and store it as a property in the parent class.
44 *
45 * @since 1.0.0
46 *
47 * @param object $result The result of the install process.
48 */
49 public function set_result( $result ) {
50
51 $this->result = $result;
52
53 }
54
55 /**
56 * Empty out the header of its HTML content and only check to see if it has
57 * been performed or not.
58 *
59 * @since 1.0.0
60 */
61 public function header() {}
62
63 /**
64 * Empty out the footer of its HTML contents.
65 *
66 * @since 1.0.0
67 */
68 public function footer() {}
69
70 /**
71 * Instead of outputting HTML for errors, json_encode the errors and send them
72 * back to the Ajax script for processing.
73 *
74 * @since 1.0.0
75 *
76 * @param array $errors Array of errors with the install process.
77 */
78 public function error( $errors ) {
79
80 if ( ! empty( $errors ) ) {
81 echo wp_json_encode( array( 'error' => __( 'There was an error installing the addon. Please try again.', 'envira-gallery' ) ) );
82 /* log this for API issues */
83
84 error_log( 'Envira: There was an error installing the addon' );
85 error_log( print_r( $errors, true ) );
86
87 die;
88 }
89
90 }
91
92 /**
93 * Empty out the feedback method to prevent outputting HTML strings as the install
94 * is progressing.
95 *
96 * @since 1.0.0
97 *
98 * @param string $string The feedback string.
99 * @param array ...$args The args.
100 */
101 public function feedback( $string, ...$args ) {}
102
103 }
1 <?php
2
3 add_action( 'wp_ajax_emr_plugin_install', 'emr_plugin_install' );
4
5 function emr_plugin_install() {
6
7 // Run a security check first.
8 check_admin_referer( 'emr-plugin-install', 'nonce' );
9
10 $plugin = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : null;
11
12 switch($plugin)
13 {
14 case "envira":
15 $download_url = 'https://downloads.wordpress.org/plugin/envira-gallery-lite.zip';
16 break;
17 case 'spio':
18 $download_url = 'https://downloads.wordpress.org/plugin/shortpixel-image-optimiser.zip';
19 break;
20 case 'spai':
21 $download_url = 'https://downloads.wordpress.org/plugin/shortpixel-adaptive-images.zip';
22 break;
23 }
24
25 // Install the addon.
26 if ( ! is_null($download_url ) ) {
27
28 //$download_url = esc_url_raw( wp_unslash( $_POST['plugin'] ) );
29 global $hook_suffix;
30
31 // Set the current screen to avoid undefined notices.
32 set_current_screen();
33
34 // Prepare variables.
35 $method = '';
36 $url = add_query_arg(
37 array(
38 // 'page' => 'envira-gallery-settings',
39 ),
40 admin_url( 'admin.php' )
41 );
42 $url = esc_url( $url );
43
44 // Start output bufferring to catch the filesystem form if credentials are needed.
45 ob_start();
46 $creds = request_filesystem_credentials( $url, $method, false, false, null );
47 if ( false === $creds ) {
48 $form = ob_get_clean();
49 echo wp_json_encode( array( 'form' => $form ) );
50 die;
51 }
52
53 // If we are not authenticated, make it happen now.
54 if ( ! WP_Filesystem( $creds ) ) {
55 ob_start();
56 request_filesystem_credentials( $url, $method, true, false, null );
57 $form = ob_get_clean();
58 echo wp_json_encode( array( 'form' => $form ) );
59 die;
60 }
61
62 // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
63 require_once (ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
64 require_once (plugin_dir_path( EMR_ROOT_FILE ) . 'classes/external/upgrader_skin.php');
65
66 // Create the plugin upgrader with our custom skin.
67 $skin = new EMR_Envira_Gallery_Skin();
68 $installer = new Plugin_Upgrader( $skin );
69 $installer->install( $download_url );
70
71 // Flush the cache and return the newly installed plugin basename.
72 wp_cache_flush();
73
74 if ( $installer->plugin_info() ) {
75 $plugin_basename = $installer->plugin_info();
76
77 ob_clean();
78
79
80 wp_send_json_success( array( 'plugin' => $plugin_basename ) );
81
82 die();
83 }
84 }
85
86 // Send back a response.
87 wp_send_json(array('result'=> false));
88 die;
89
90 }
91
92 add_action( 'wp_ajax_emr_plugin_activate', 'emr_activate' );
93
94 /**
95 * Activates an Envira addon.
96 *
97 * @since 1.0.0
98 */
99 function emr_activate() {
100
101 // Run a security check first.
102 check_admin_referer( 'emr-plugin-activate', 'nonce' );
103
104 $plugin = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : null;
105
106 switch($plugin)
107 {
108 case "envira":
109 $plugin = 'envira-gallery-lite/envira-gallery-lite.php';
110 break;
111 case 'spio':
112 $plugin = 'shortpixel-image-optimiser/wp-shortpixel.php';
113 break;
114 case 'spai':
115 $plugin = 'shortpixel-adaptive-images/short-pixel-ai.php';
116 break;
117 }
118
119 // Activate the addon.
120 if ( ! is_null($plugin) ) {
121 $activate = activate_plugin( $plugin );
122 if ( is_wp_error( $activate ) ) {
123 echo json_encode( array( 'error' => $activate->get_error_message() ) );
124 die;
125 }
126 }
127
128 echo json_encode( true );
129 die;
130
131 }
1 <?php
2 namespace EnableMediaReplace\Externals;
3
4
5 // Note! This class doubles as integration for both Visual Composer *and* WP Bakery. They both need URLENCODE.
6 class WpBakery
7 {
8 private static $instance;
9
10 protected $queryKey = 'wpbakery';
11
12 public static function getInstance()
13 {
14 if (is_null(self::$instance))
15 self::$instance = new WpBakery();
16
17 return self::$instance;
18 }
19
20 public function __construct()
21 {
22 if ($this->bakery_is_active()) // elementor is active
23 {
24 add_filter('emr/replacer/custom_replace_query', array($this, 'addURLEncoded'), 10, 4); // custom query for elementor \ // problem
25 }
26 }
27
28 public function addUrlEncoded($items, $base_url, $search_urls, $replace_urls)
29 {
30 $base_url = $this->addEncode($base_url);
31 $el_search_urls = array_map(array($this, 'addEncode'), $search_urls);
32 $el_replace_urls = array_map(array($this, 'addEncode'), $replace_urls);
33 $items[$this->queryKey] = array('base_url' => $base_url, 'search_urls' => $el_search_urls, 'replace_urls' => $el_replace_urls);
34 return $items;
35 }
36
37 public function addEncode($value)
38 {
39 return urlencode($value);
40 }
41
42 protected function bakery_is_active()
43 {
44 $bool = false;
45
46 // did_action -> wpbakery , VCV_version -> detect Visual Composer
47 if (did_action('vc_plugins_loaded') || defined('VCV_VERSION'))
48 $bool = true;
49
50 return apply_filters('emr/externals/urlencode_is_active', $bool); // manual override
51 }
52 }
1 <?php
2 namespace EnableMediaReplace;
3 use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
4 use EnableMediaReplace\Notices\NoticeController as Notices;
5
6 use EnableMediaReplace\Externals\Elementor as Elementor;
7 use EnableMediaReplace\Externals\WpBakery as WpBakery;
8
9 class Externals
10 {
11 protected $replaceType = null;
12 protected $replaceSearchType = null;
13
14 protected $messages = array();
15
16 public function __construct()
17 {
18 // These hooks prevent loading of options when plugin conflicts arise.
19 add_filter('emr_display_replace_type_options', array($this, 'get_replace_type'));
20 add_filter('emr_enable_replace_and_search', array($this, 'get_replacesearch_type'));
21 add_action('emr_after_replace_type_options', array($this, 'get_messages'));
22
23 $this->check();
24
25 // integrations
26 $this->loadElementor();
27 $this->loadBakery(); // in case of urlencoded issues, this class should be used probably.
28 }
29
30 protected function check() // check if any of the options should be disabled due to conflicts
31 {
32 /*if (class_exists('FLBuilder'))
33 {
34 $this->replaceSearchType = false;
35 $this->messages[] = __('Replace and Search feature is not compatible with Beaver Builder.', 'enable-media-replace');
36 } */
37 }
38
39 public function get_replace_type($bool)
40 {
41 if ($this->replaceType === null)
42 return $bool;
43
44 return $this->replaceType;
45 }
46
47 public function get_replacesearch_type($bool)
48 {
49 if ($this->replaceSearchType === null)
50 return $bool;
51
52 return $this->replaceSearchType;
53 }
54
55 public function get_messages()
56 {
57 foreach($this->messages as $message)
58 {
59 echo '<span class="nofeature-notice"><p>'. $message . '</p></span>';
60 }
61 }
62
63 public function loadElementor()
64 {
65 Elementor::getInstance();
66 }
67
68 public function loadBakery()
69 {
70 WpBakery::getInstance();
71 }
72
73 } // class
1 <?php
2 namespace EnableMediaReplace;
3
4 use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
5 use EnableMediaReplace\Notices\NoticeController as Notices;
6
7 class emrFile
8 {
9
10 protected $file; // the full file w/ path.
11 protected $extension;
12 protected $fileName;
13 protected $filePath; // with trailing slash! not the image name.
14 protected $fileURL;
15 protected $fileMime;
16 protected $permissions = 0;
17
18 protected $exists = false;
19
20 public function __construct($file)
21 {
22 clearstatcache($file);
23 // file can not exist i.e. crashed files replacement and the lot.
24 if ( file_exists($file))
25 {
26 $this->exists = true;
27 }
28
29 $this->file = $file;
30 $fileparts = pathinfo($file);
31
32 $this->fileName = isset($fileparts['basename']) ? $fileparts['basename'] : '';
33 $this->filePath = isset($fileparts['dirname']) ? trailingslashit($fileparts['dirname']) : '';
34 $this->extension = isset($fileparts['extension']) ? $fileparts['extension'] : '';
35 if ($this->exists) // doesn't have to be.
36 $this->permissions = fileperms($file) & 0777;
37
38 $filedata = wp_check_filetype_and_ext($this->file, $this->fileName);
39 // This will *not* be checked, is not meant for permission of validation!
40 // Note: this function will work on non-existing file, but not on existing files containing wrong mime in file.
41 $this->fileMime = (isset($filedata['type']) && strlen($filedata['type']) > 0) ? $filedata['type'] : false;
42
43 if ($this->fileMime == false && strlen($this->file) > 0 && function_exists('mime_content_type') && $this->exists)
44 {
45 // If it's not a registered mimetype
46 $this->fileMime = mime_content_type($this->file);
47 }
48
49 }
50
51 public function checkAndCreateFolder()
52 {
53 $path = $this->getFilePath();
54 if (! is_dir($path) && ! file_exists($path))
55 {
56 return wp_mkdir_p($path);
57 }
58 }
59
60 public function getFullFilePath()
61 {
62 return $this->file;
63 }
64
65 public function getPermissions()
66 {
67 return $this->permissions;
68 }
69
70 public function setPermissions($permissions)
71 {
72 @chmod($this->file, $permissions);
73 }
74
75 public function getFileSize()
76 {
77 return filesize($this->file);
78 }
79
80 public function getFilePath()
81 {
82 return $this->filePath;
83 }
84
85 public function getFileName()
86 {
87 return $this->fileName;
88 }
89
90 public function getFileExtension()
91 {
92 return $this->extension;
93 }
94
95 public function getFileMime()
96 {
97 return $this->fileMime;
98 }
99
100 public function exists()
101 {
102 return $this->exists;
103 }
104 }
1 <?php
2 namespace EnableMediaReplace;
3
4 // Legacy functions.
5
6 /**
7 * Maybe remove query string from URL.
8 *
9 * @param string $url
10 *
11 * @return string
12 */
13
14 function emr_maybe_remove_query_string( $url ) {
15 $parts = explode( '?', $url );
16
17 return reset( $parts );
18 }
19
20 /**
21 * Remove scheme from URL.
22 *
23 * @param string $url
24 *
25 * @return string
26 */
27 function emr_remove_scheme( $url ) {
28 return preg_replace( '/^(?:http|https):/', '', $url );
29 }
30
31 /**
32 * Remove size from filename (image[-100x100].jpeg).
33 *
34 * @param string $url
35 * @param bool $remove_extension
36 *
37 * @return string
38 */
39 function emr_remove_size_from_filename( $url, $remove_extension = false ) {
40 $url = preg_replace( '/^(\S+)-[0-9]{1,4}x[0-9]{1,4}(\.[a-zA-Z0-9\.]{2,})?/', '$1$2', $url );
41
42 if ( $remove_extension ) {
43 $ext = pathinfo( $url, PATHINFO_EXTENSION );
44 $url = str_replace( ".$ext", '', $url );
45 }
46
47 return $url;
48 }
49
50 /**
51 * Strip an image URL down to bare minimum for matching.
52 *
53 * @param string $url
54 *
55 * @return string
56 */
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 }
64
65
66 function emr_remove_domain_from_filename($url) {
67 // Holding place for possible future function
68 $url = str_replace(emr_remove_scheme(get_bloginfo('url')), '', $url);
69 return $url;
70 }
71
72 /**
73 * Build an array of search or replace URLs for given attachment GUID and its metadata.
74 *
75 * @param string $guid
76 * @param array $metadata
77 *
78 * @return array
79 */
80 function emr_get_file_urls( $guid, $metadata ) {
81 $urls = array();
82
83 $guid = emr_remove_scheme( $guid );
84 $guid= emr_remove_domain_from_filename($guid);
85
86 $urls['guid'] = $guid;
87
88 if ( empty( $metadata ) ) {
89 return $urls;
90 }
91
92 $base_url = dirname( $guid );
93
94 if ( ! empty( $metadata['file'] ) ) {
95 $urls['file'] = trailingslashit( $base_url ) . wp_basename( $metadata['file'] );
96 }
97
98 if ( ! empty( $metadata['sizes'] ) ) {
99 foreach ( $metadata['sizes'] as $key => $value ) {
100 $urls[ $key ] = trailingslashit( $base_url ) . wp_basename( $value['file'] );
101 }
102 }
103
104 return $urls;
105 }
106
107 /**
108 * Ensure new search URLs cover known sizes for old attachment.
109 * Falls back to full URL if size not covered (srcset or width/height attributes should compensate).
110 *
111 * @param array $old
112 * @param array $new
113 *
114 * @return array
115 */
116 function emr_normalize_file_urls( $old, $new ) {
117 $result = array();
118
119 if ( empty( $new['guid'] ) ) {
120 return $result;
121 }
122
123 $guid = $new['guid'];
124
125 foreach ( $old as $key => $value ) {
126 $result[ $key ] = empty( $new[ $key ] ) ? $guid : $new[ $key ];
127 }
128
129 return $result;
130 }
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 use EnableMediaReplace\Externals\Elementor as Elementor; // like Skeletor.
8
9 class Replacer
10 {
11 protected $post_id;
12
13 // everything source is the attachment being replaced
14 protected $sourceFile; // File Object
15 protected $source_post; // wpPost;
16 protected $source_is_image;
17 protected $source_metadata;
18 protected $source_url;
19
20 // everything target is what will be. This is set when the image is replace, the result. Used for replacing.
21 protected $targetFile;
22 protected $targetName;
23 protected $target_metadata;
24 protected $target_url;
25
26 protected $target_location = false; // option for replacing to another target location
27
28 protected $replaceMode = 1; // replace if nothing is set
29 protected $timeMode = 1;
30 protected $datetime = null;
31
32 protected $ThumbnailUpdater; // class
33
34 const MODE_REPLACE = 1;
35 const MODE_SEARCHREPLACE = 2;
36
37 const TIME_UPDATEALL = 1; // replace the date
38 const TIME_UPDATEMODIFIED = 2; // keep the date, update only modified
39 const TIME_CUSTOM = 3; // custom time entry
40
41 public function __construct($post_id)
42 {
43 $this->post_id = $post_id;
44
45 if (function_exists('wp_get_original_image_path')) // WP 5.3+
46 {
47 $source_file = wp_get_original_image_path($post_id);
48 if ($source_file === false) // if it's not an image, returns false, use the old way.
49 $source_file = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )));
50 }
51 else
52 $source_file = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )));
53
54 /* It happens that the SourceFile returns relative / incomplete when something messes up get_upload_dir with an error something.
55 This case shoudl be detected here and create a non-relative path anyhow..
56 */
57 if (! file_exists($source_file) && $source_file && 0 !== strpos( $source_file, '/' ) && ! preg_match( '|^.:\\\|', $source_file ) )
58 {
59 $file = get_post_meta( $post_id, '_wp_attached_file', true );
60 $uploads = wp_get_upload_dir();
61 $source_file = $uploads['basedir'] . "/$source_file";
62 }
63
64 Log::addDebug('SourceFile ' . $source_file);
65 $this->sourceFile = new File($source_file);
66
67 $this->source_post = get_post($post_id);
68 $this->source_is_image = wp_attachment_is('image', $this->source_post);
69 $this->source_metadata = wp_get_attachment_metadata( $post_id );
70
71 if (function_exists('wp_get_original_image_url')) // WP 5.3+
72 {
73 $source_url = wp_get_original_image_url($post_id);
74 if ($source_url === false) // not an image, or borked, try the old way
75 $source_url = wp_get_attachment_url($post_id);
76
77 $this->source_url = $source_url;
78 }
79 else
80 $this->source_url = wp_get_attachment_url($post_id);
81 // $this->ThumbnailUpdater = new \ThumbnailUpdater($post_id);
82 //$this->ThumbnailUpdater->setOldMetadata($this->source_metadata);
83 }
84
85 public function setMode($mode)
86 {
87 $this->replaceMode = $mode;
88 }
89
90 public function setTimeMode($mode, $datetime = 0)
91 {
92 if ($datetime == 0)
93 $datetime = current_time('mysql');
94
95 $this->datetime = $datetime;
96 $this->timeMode = $mode;
97 }
98
99 /** Replace the sourceFile with a target
100 * @param $file String Full Path to the Replacement File. This will usually be an uploaded file in /tmp/
101 * @param $fileName String The fileName of the uploaded file. This will be used if sourcefile is not to be overwritten.
102 * @throws RunTimeException Can throw exception if something went wrong with the files.
103 */
104 public function replaceWith($file, $fileName)
105 {
106 global $wpdb;
107 $this->targetName = $fileName;
108
109 $targetFile = $this->getTargetFile();
110
111 if (is_null($targetFile))
112 {
113 return null;
114 // $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");
115 // throw new \RuntimeException($ex);
116 }
117
118 $targetFileObj = new File($targetFile);
119 $result = $targetFileObj->checkAndCreateFolder();
120 if ($result === false)
121 Log::addError('Directory creation for targetFile failed');
122
123
124 $this->removeCurrent(); // tries to remove the current files.
125
126 /* @todo See if wp_handle_sideload / wp_handle_upload can be more securely used for this */
127 $result_moved = move_uploaded_file($file,$targetFile);
128
129 if (false === $result_moved)
130 {
131 $ex = sprintf( esc_html__('The uploaded file could not be moved to %1$s. This is most likely an issue with permissions, or upload failed.', "enable-media-replace"), $targetFile );
132 throw new \RuntimeException($ex);
133 }
134
135 // init targetFile.
136 $this->targetFile = new File($targetFile);
137
138 if ($this->sourceFile->getPermissions() > 0)
139 chmod( $targetFile, $this->sourceFile->getPermissions() ); // restore permissions
140 else {
141 Log::addWarn('Setting permissions failed');
142 }
143
144 // update the file attached. This is required for wp_get_attachment_url to work.
145 $updated = update_attached_file($this->post_id, $this->targetFile->getFullFilePath() );
146 if (! $updated)
147 Log::addError('Update Attached File reports as not updated or same value');
148
149 $this->target_url = $this->getTargetURL(); //wp_get_attachment_url($this->post_id);
150
151 // Run the filter, so other plugins can hook if needed.
152 $filtered = apply_filters( 'wp_handle_upload', array(
153 'file' => $this->targetFile->getFullFilePath(),
154 'url' => $this->target_url,
155 'type' => $this->targetFile->getFileMime(),
156 ), 'sideload');
157
158 // check if file changed during filter. Set changed to attached file meta properly.
159 if (isset($filtered['file']) && $filtered['file'] != $this->targetFile->getFullFilePath() )
160 {
161 update_attached_file($this->post_id, $filtered['file'] );
162 $this->targetFile = new File($filtered['file']); // handle as a new file
163 Log::addInfo('WP_Handle_upload filter returned different file', $filtered);
164 }
165
166 // Check and update post mimetype, otherwise badly coded plugins cry.
167 $post_mime = get_post_mime_type($this->post_id);
168 $target_mime = $this->targetFile->getFileMime();
169
170 // update DB post mime type, if somebody decided to mess it up, and the target one is not empty.
171 if ($target_mime !== $post_mime && strlen($target_mime) > 0)
172 {
173
174 \wp_update_post(array('post_mime_type' => $this->targetFile->getFileMime(), 'ID' => $this->post_id));
175 }
176
177 $metadata = wp_generate_attachment_metadata( $this->post_id, $this->targetFile->getFullFilePath() );
178 wp_update_attachment_metadata( $this->post_id, $metadata );
179 $this->target_metadata = $metadata;
180
181 /** If author is different from replacer, note this */
182 $author_id = get_post_meta($this->post_id, '_emr_replace_author', true);
183
184 if ( intval($this->source_post->post_author) !== get_current_user_id())
185 {
186 update_post_meta($this->post_id, '_emr_replace_author', get_current_user_id());
187 }
188 elseif ($author_id)
189 {
190 delete_post_meta($this->post_id, '_emr_replace_author');
191 }
192
193 if ($this->replaceMode == self::MODE_SEARCHREPLACE)
194 {
195 // Write new image title.
196 $title = $this->getNewTitle();
197 $excerpt = $this->getNewExcerpt();
198 $update_ar = array('ID' => $this->post_id);
199 $update_ar['post_title'] = $title;
200 $update_ar['post_name'] = sanitize_title($title);
201 if ($excerpt !== false)
202 {
203 $update_ar['post_excerpt'] = $excerpt;
204 }
205 $update_ar['guid'] = $this->target_url; //wp_get_attachment_url($this->post_id);
206 // $update_ar['post_mime_type'] = $this->targetFile->getFileMime();
207
208 $post_id = \wp_update_post($update_ar, true);
209
210 // update post doesn't update GUID on updates.
211 $wpdb->update( $wpdb->posts, array( 'guid' => $this->target_url), array('ID' => $this->post_id) );
212 //enable-media-replace-upload-done
213
214 // @todo Replace this one with proper Notices:addError;
215 if (is_wp_error($post_id))
216 {
217 $errors = $post_id->get_error_messages();
218 foreach ($errors as $error) {
219 echo $error;
220 }
221 }
222
223 } // SEARCH REPLACE MODE
224
225 $args = array(
226 'thumbnails_only' => ($this->replaceMode == self::MODE_SEARCHREPLACE) ? false : true,
227 );
228
229 // Search Replace will also update thumbnails.
230 $this->doSearchReplace($args);
231
232 /*if(wp_attachment_is_image($this->post_id))
233 {
234 $this->ThumbnailUpdater->setNewMetadata($this->target_metadata);
235 $result = $this->ThumbnailUpdater->updateThumbnails();
236 if (false === $result)
237 Log::addWarn('Thumbnail Updater returned false');
238 }*/
239
240
241 // if all set and done, update the date.
242 // This must be done after wp_update_posts
243 $this->updateDate(); // updates the date.
244
245 // Give the caching a kick. Off pending specifics.
246 $cache_args = array(
247 'flush_mode' => 'post',
248 'post_id' => $this->post_id,
249 );
250
251 $cache = new emrCache();
252 $cache->flushCache($cache_args);
253
254 do_action("enable-media-replace-upload-done", $this->target_url, $this->source_url, $this->post_id);
255
256 return true;
257 }
258
259 protected function getNewTitle()
260 {
261 // get basename without extension
262 $title = basename($this->targetFile->getFileName(), '.' . $this->targetFile->getFileExtension());
263 $meta = $this->target_metadata;
264
265 if (isset($meta['image_meta']))
266 {
267 if (isset($meta['image_meta']['title']))
268 {
269 if (strlen($meta['image_meta']['title']) > 0)
270 {
271 $title = $meta['image_meta']['title'];
272 }
273 }
274 }
275
276 // Thanks Jonas Lundman (http://wordpress.org/support/topic/add-filter-hook-suggestion-to)
277 $title = apply_filters( 'enable_media_replace_title', $title );
278
279 return $title;
280 }
281
282 protected function getNewExcerpt()
283 {
284 $meta = $this->target_metadata;
285 $excerpt = false;
286
287 if (isset($meta['image_meta']))
288 {
289 if (isset($meta['image_meta']['caption']))
290 {
291 if (strlen($meta['image_meta']['caption']) > 0)
292 {
293 $excerpt = $meta['image_meta']['caption'];
294 }
295 }
296 }
297
298 return $excerpt;
299 }
300
301 /** Gets the source file after processing. Returns a file */
302 public function getSourceFile()
303 {
304 return $this->sourceFile;
305 }
306
307 public function setNewTargetLocation($new_rel_location)
308 {
309 $uploadDir = wp_upload_dir();
310 $newPath = trailingslashit($uploadDir['basedir']) . $new_rel_location;
311
312 if (! is_dir($newPath))
313 {
314 Notices::addError(__('Specificed new directory does not exist. Path must be a relative path from the upload directory and exist', 'enable-media-replace'));
315 return false;
316 }
317 $this->target_location = trailingslashit($newPath);
318 return true;
319 }
320
321 /** Returns a full target path to place to new file. Including the file name! **/
322 protected function getTargetFile()
323 {
324 $targetPath = null;
325 if ($this->replaceMode == self::MODE_REPLACE)
326 {
327 $targetFile = $this->sourceFile->getFullFilePath(); // overwrite source
328 }
329 elseif ($this->replaceMode == self::MODE_SEARCHREPLACE)
330 {
331 $path = $this->sourceFile->getFilePath();
332 if ($this->target_location) // Replace to another path.
333 {
334 $otherTarget = new File($this->target_location . $this->targetName);
335 if ($otherTarget->exists())
336 {
337 Notices::addError(__('In specificied directory there is already a file with the same name. Can\'t replace.', 'enable-media-replace'));
338 return null;
339 }
340 $path = $this->target_location; // if all went well.
341 }
342 //if ($this->sourceFile->getFileName() == $this->targetName)
343 $targetpath = $path . $this->targetName;
344
345 // If the source and target path AND filename are identical, user has wrong mode, just overwrite the sourceFile.
346 if ($targetpath == $this->sourceFile->getFullFilePath())
347 {
348 $unique = $this->sourceFile->getFileName();
349 $this->replaceMode == self::MODE_REPLACE;
350 }
351 else
352 {
353 $unique = wp_unique_filename($path, $this->targetName);
354 }
355 $new_filename = apply_filters( 'emr_unique_filename', $unique, $path, $this->post_id );
356 $targetFile = trailingslashit($path) . $new_filename;
357 }
358 if (is_dir($targetFile)) // this indicates an error with the source.
359 {
360 Log::addWarn('TargetFile is directory ' . $targetFile );
361 $upload_dir = wp_upload_dir();
362 if (isset($upload_dir['path']))
363 {
364 $targetFile = trailingslashit($upload_dir['path']) . wp_unique_filename($targetFile, $this->targetName);
365 }
366 else {
367 $err = __('EMR could not establish a proper destination for replacement', 'enable-media-replace');
368 Notices::addError($err);
369 Log::addError($err);
370 // throw new \RuntimeException($err);
371 // exit($err); // fallback
372 return null;
373 }
374 }
375 return $targetFile;
376 }
377
378 /** Since WP functions also can't be trusted here in certain cases, create the URL by ourselves */
379 protected function getTargetURL()
380 {
381 //$uploads['baseurl']
382 $url = wp_get_attachment_url($this->post_id);
383 $url_basename = basename($url);
384
385 // Seems all worked as normal.
386 if (strpos($url, '://') >= 0 && $this->targetFile->getFileName() == $url_basename)
387 return $url;
388
389 // Relative path for some reason
390 if (strpos($url, '://') === false)
391 {
392 $uploads = wp_get_upload_dir();
393 $url = str_replace($uploads['basedir'], $uploads['baseurl'], $this->targetFile->getFullFilePath());
394 }
395 // This can happen when WordPress is not taking from attached file, but wrong /old GUID. Try to replace it to the new one.
396 elseif ($this->targetFile->getFileName() != $url_basename)
397 {
398 $url = str_replace($url_basename, $this->targetFile->getFileName(), $url);
399 }
400
401 return $url;
402 //$this->targetFile
403
404 }
405
406 /** Tries to remove all of the old image, without touching the metadata in database
407 * This might fail on certain files, but this is not an indication of success ( remove might fail, but overwrite can still work)
408 */
409 protected function removeCurrent()
410 {
411 $meta = \wp_get_attachment_metadata( $this->post_id );
412 $backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true );
413
414 // this must be -scaled if that exists, since wp_delete_attachment_files checks for original_files but doesn't recheck if scaled is included since that the one 'that exists' in WP . $this->source_file replaces original image, not the -scaled one.
415 $file = $this->sourceFile->getFullFilePath();
416 $result = \wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $file );
417
418 // If Attached file is not the same path as file, this indicates a -scaled images is in play.
419 $attached_file = get_attached_file($this->post_id);
420 if ($file !== $attached_file && file_exists($attached_file))
421 {
422 @unlink($attached_file);
423 }
424
425
426 }
427
428 /** Handle new dates for the replacement */
429 protected function updateDate()
430 {
431 global $wpdb;
432 $post_date = $this->datetime;
433 $post_date_gmt = get_gmt_from_date($post_date);
434
435 $update_ar = array('ID' => $this->post_id);
436 if ($this->timeMode == static::TIME_UPDATEALL || $this->timeMode == static::TIME_CUSTOM)
437 {
438 $update_ar['post_date'] = $post_date;
439 $update_ar['post_date_gmt'] = $post_date_gmt;
440 }
441 else {
442 //$update_ar['post_date'] = 'post_date';
443 // $update_ar['post_date_gmt'] = 'post_date_gmt';
444 }
445 $update_ar['post_modified'] = $post_date;
446 $update_ar['post_modified_gmt'] = $post_date_gmt;
447
448 $updated = $wpdb->update( $wpdb->posts, $update_ar , array('ID' => $this->post_id) );
449
450 wp_cache_delete($this->post_id, 'posts');
451
452 }
453
454
455 protected function doSearchReplace($args = array())
456 {
457 $defaults = array(
458 'thumbnails_only' => false,
459 );
460
461 $args = wp_parse_args($args, $defaults);
462
463 // Search-and-replace filename in post database
464 // @todo Check this with scaled images.
465 $base_url = parse_url($this->source_url, PHP_URL_PATH);// emr_get_match_url( $this->source_url);
466 $base_url = str_replace('.' . pathinfo($base_url, PATHINFO_EXTENSION), '', $base_url);
467
468
469 /** Fail-safe if base_url is a whole directory, don't go search/replace */
470 if (is_dir($base_url))
471 {
472 Log::addError('Search Replace tried to replace to directory - ' . $base_url);
473 Notices::addError(__('Fail Safe :: Source Location seems to be a directory.', 'enable-media-replace'));
474 return;
475 }
476
477 if (strlen(trim($base_url)) == 0)
478 {
479 Log::addError('Current Base URL emtpy - ' . $base_url);
480 Notices::addError(__('Fail Safe :: Source Location returned empty string. Not replacing content','enable-media-replace'));
481 return;
482 }
483
484 // get relurls of both source and target.
485 $urls = $this->getRelativeURLS();
486
487
488 if ($args['thumbnails_only'])
489 {
490 foreach($urls as $side => $data)
491 {
492 if (isset($data['base']))
493 {
494 unset($urls[$side]['base']);
495 }
496 if (isset($data['file']))
497 {
498 unset($urls[$side]['file']);
499 }
500 }
501 }
502
503 $search_urls = $urls['source'];
504 $replace_urls = $urls['target'];
505
506 /* If the replacement is much larger than the source, there can be more thumbnails. This leads to disbalance in the search/replace arrays.
507 Remove those from the equation. If the size doesn't exist in the source, it shouldn't be in use either */
508 foreach($replace_urls as $size => $url)
509 {
510 if (! isset($search_urls[$size]))
511 {
512 Log::addDebug('Dropping size ' . $size . ' - not found in source urls');
513 unset($replace_urls[$size]);
514 }
515 }
516
517 Log::addDebug('Source', $this->source_metadata);
518 Log::addDebug('Target', $this->target_metadata);
519 /* If on the other hand, some sizes are available in source, but not in target, try to replace them with something closeby. */
520 foreach($search_urls as $size => $url)
521 {
522 if (! isset($replace_urls[$size]))
523 {
524 $closest = $this->findNearestSize($size);
525 if ($closest)
526 {
527 $sourceUrl = $search_urls[$size];
528 $baseurl = trailingslashit(str_replace(wp_basename($sourceUrl), '', $sourceUrl));
529 Log::addDebug('Nearest size of source ' . $size . ' for target is ' . $closest);
530 $replace_urls[$size] = $baseurl . $closest;
531 }
532 else
533 {
534 Log::addDebug('Unset size ' . $size . ' - no closest found in source');
535 }
536 }
537 }
538
539 /* If source and target are the same, remove them from replace. This happens when replacing a file with same name, and +/- same dimensions generated.
540
541 After previous loops, for every search there should be a replace size.
542 */
543 foreach($search_urls as $size => $url)
544 {
545 $replace_url = isset($replace_urls[$size]) ? $replace_urls[$size] : false;
546 if ($url == $replace_url) // if source and target as the same, no need for replacing.
547 {
548 unset($search_urls[$size]);
549 unset($replace_urls[$size]);
550 }
551 }
552
553 // 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.
554 if (count($search_urls) !== count($replace_urls))
555 {
556 Log::addError('Unbalanced Replace Arrays, aborting', array($search_urls, $replace_urls, count($search_urls), count($replace_urls) ));
557 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'));
558 return;
559 }
560
561 Log::addDebug('Doing meta search and replace -', array($search_urls, $replace_urls) );
562 Log::addDebug('Searching with BaseuRL ' . $base_url);
563
564 do_action('emr/replace_urls', $search_urls, $replace_urls);
565 $updated = 0;
566
567 $updated += $this->doReplaceQuery($base_url, $search_urls, $replace_urls);
568
569 $replaceRuns = apply_filters('emr/replacer/custom_replace_query', array(), $base_url, $search_urls, $replace_urls);
570 Log::addDebug("REPLACE RUNS", $replaceRuns);
571 foreach($replaceRuns as $component => $run)
572 {
573 Log::addDebug('Running additional replace for : '. $component, $run);
574 $updated += $this->doReplaceQuery($run['base_url'], $run['search_urls'], $run['replace_urls']);
575 }
576 //do_action('')
577
578 Log::addDebug("Updated Records : " . $updated);
579 return $updated;
580 } // doSearchReplace
581
582
583 private function doReplaceQuery($base_url, $search_urls, $replace_urls)
584 {
585 global $wpdb;
586 /* Search and replace in WP_POSTS */
587 // Removed $wpdb->remove_placeholder_escape from here, not compatible with WP 4.8
588 $posts_sql = $wpdb->prepare(
589 "SELECT ID, post_content FROM $wpdb->posts WHERE post_status = 'publish' AND post_content LIKE %s",
590 '%' . $base_url . '%');
591
592 $rs = $wpdb->get_results( $posts_sql, ARRAY_A );
593 $number_of_updates = 0;
594
595 if ( ! empty( $rs ) ) {
596 foreach ( $rs AS $rows ) {
597 $number_of_updates = $number_of_updates + 1;
598 // replace old URLs with new URLs.
599
600 $post_content = $rows["post_content"];
601 $post_id = $rows['ID'];
602 $replaced_content = $this->replaceContent($post_content, $search_urls, $replace_urls);
603
604 if ($replaced_content !== $post_content)
605 {
606 //Log::addDebug('POST CONTENT TO SAVE', $replaced_content);
607
608 // $result = wp_update_post($post_ar);
609 $sql = 'UPDATE ' . $wpdb->posts . ' SET post_content = %s WHERE ID = %d';
610 $sql = $wpdb->prepare($sql, $replaced_content, $post_id);
611
612 //Log::addTemp("POSt update query " . $sql);
613 $result = $wpdb->query($sql);
614
615 if ($result === false)
616 {
617 Notice::addError('Something went wrong while replacing' . $result->get_error_message() );
618 Log::addError('WP-Error during post update', $result);
619 }
620 }
621
622 }
623 }
624
625 $number_of_updates += $this->handleMetaData($base_url, $search_urls, $replace_urls);
626 return $number_of_updates;
627 }
628
629 private function handleMetaData($url, $search_urls, $replace_urls)
630 {
631 global $wpdb;
632
633 $meta_options = apply_filters('emr/metadata_tables', array('post', 'comment', 'term', 'user'));
634 $number_of_updates = 0;
635
636 foreach($meta_options as $type)
637 {
638 switch($type)
639 {
640 case "post": // special case.
641 $sql = 'SELECT meta_id as id, meta_key, meta_value FROM ' . $wpdb->postmeta . '
642 WHERE post_id in (SELECT ID from '. $wpdb->posts . ' where post_status = "publish") AND meta_value like %s';
643 $type = 'post';
644
645 $update_sql = ' UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d';
646 break;
647 default:
648 $table = $wpdb->{$type . 'meta'}; // termmeta, commentmeta etc
649
650 $meta_id = 'meta_id';
651 if ($type == 'user')
652 $meta_id = 'umeta_id';
653
654 $sql = 'SELECT ' . $meta_id . ' as id, meta_value FROM ' . $table . '
655 WHERE meta_value like %s';
656
657 $update_sql = " UPDATE $table set meta_value = %s WHERE $meta_id = %d ";
658 break;
659 }
660
661 $sql = $wpdb->prepare($sql, '%' . $url . '%');
662
663 // This is a desparate solution. Can't find anyway for wpdb->prepare not the add extra slashes to the query, which messes up the query.
664 // $postmeta_sql = str_replace('[JSON_URL]', $json_url, $postmeta_sql);
665 $rsmeta = $wpdb->get_results($sql, ARRAY_A);
666
667 if (! empty($rsmeta))
668 {
669 foreach ($rsmeta as $row)
670 {
671 $number_of_updates++;
672 $content = $row['meta_value'];
673
674
675 $id = $row['id'];
676
677 $content = $this->replaceContent($content, $search_urls, $replace_urls); //str_replace($search_urls, $replace_urls, $content);
678
679 $prepared_sql = $wpdb->prepare($update_sql, $content, $id);
680
681 Log::addDebug('Update Meta SQl' . $prepared_sql);
682 $result = $wpdb->query($prepared_sql);
683
684 }
685 }
686 } // foreach
687
688 return $number_of_updates;
689 } // function
690
691
692
693 /**
694 * Replaces Content across several levels of possible data
695 * @param $content String The Content to replace
696 * @param $search String Search string
697 * @param $replace String Replacement String
698 * @param $in_deep Boolean. This is use to prevent serialization of sublevels. Only pass back serialized from top.
699 */
700 private function replaceContent($content, $search, $replace, $in_deep = false)
701 {
702 //$is_serial = false;
703 $content = maybe_unserialize($content);
704 $isJson = $this->isJSON($content);
705
706 if ($isJson)
707 {
708 Log::addDebug('Found JSON Content');
709 $content = json_decode($content);
710 Log::addDebug('J/Son Content', $content);
711
712 }
713
714 if (is_string($content)) // let's check the normal one first.
715 {
716 $content = apply_filters('emr/replace/content', $content, $search, $replace);
717
718 $content = str_replace($search, $replace, $content);
719 }
720 elseif (is_wp_error($content)) // seen this.
721 {
722 //return $content; // do nothing.
723 }
724 elseif (is_array($content) ) // array metadata and such.
725 {
726 foreach($content as $index => $value)
727 {
728 $content[$index] = $this->replaceContent($value, $search, $replace, true); //str_replace($value, $search, $replace);
729 if (is_string($index)) // If the key is the URL (sigh)
730 {
731 $index_replaced = $this->replaceContent($index, $search,$replace, true);
732 if ($index_replaced !== $index)
733 $content = $this->change_key($content, array($index => $index_replaced));
734 }
735 }
736 }
737 elseif(is_object($content)) // metadata objects, they exist.
738 {
739 foreach($content as $key => $value)
740 {
741 $content->{$key} = $this->replaceContent($value, $search, $replace, true); //str_replace($value, $search, $replace);
742 }
743 }
744
745 if ($isJson && $in_deep === false) // convert back to JSON, if this was JSON. Different than serialize which does WP automatically.
746 {
747 Log::addDebug('Value was found to be JSON, encoding');
748 // wp-slash -> WP does stripslashes_deep which destroys JSON
749 $content = json_encode($content, JSON_UNESCAPED_SLASHES);
750 Log::addDebug('Content returning', array($content));
751 }
752 elseif($in_deep === false && (is_array($content) || is_object($content)))
753 $content = maybe_serialize($content);
754
755 return $content;
756 }
757
758 private function change_key($arr, $set) {
759 if (is_array($arr) && is_array($set)) {
760 $newArr = array();
761 foreach ($arr as $k => $v) {
762 $key = array_key_exists( $k, $set) ? $set[$k] : $k;
763 $newArr[$key] = is_array($v) ? $this->change_key($v, $set) : $v;
764 }
765 return $newArr;
766 }
767 return $arr;
768 }
769
770 private function getFilesFromMetadata($meta)
771 {
772 $fileArray = array();
773 if (isset($meta['file']))
774 $fileArray['file'] = $meta['file'];
775
776 if (isset($meta['sizes']))
777 {
778 foreach($meta['sizes'] as $name => $data)
779 {
780 if (isset($data['file']))
781 {
782 $fileArray[$name] = $data['file'];
783 }
784 }
785 }
786 return $fileArray;
787 }
788
789 /* Check if given content is JSON format. */
790 private function isJSON($content)
791 {
792 if (is_array($content) || is_object($content))
793 return false; // can never be.
794
795 $json = json_decode($content);
796 return $json && $json != $content;
797 }
798
799 // Get REL Urls of both source and target.
800 private function getRelativeURLS()
801 {
802 $dataArray = array(
803 'source' => array('url' => $this->source_url, 'metadata' => $this->getFilesFromMetadata($this->source_metadata) ),
804 'target' => array('url' => $this->target_url, 'metadata' => $this->getFilesFromMetadata($this->target_metadata) ),
805 );
806
807 // Log::addDebug('Source Metadata', $this->source_metadata);
808 // Log::addDebug('Target Metadata', $this->target_metadata);
809
810 $result = array();
811
812 foreach($dataArray as $index => $item)
813 {
814 $result[$index] = array();
815 $metadata = $item['metadata'];
816
817 $baseurl = parse_url($item['url'], PHP_URL_PATH);
818 $result[$index]['base'] = $baseurl; // this is the relpath of the mainfile.
819 $baseurl = trailingslashit(str_replace( wp_basename($item['url']), '', $baseurl)); // get the relpath of main file.
820
821 foreach($metadata as $name => $filename)
822 {
823 $result[$index][$name] = $baseurl . wp_basename($filename); // filename can have a path like 19/08 etc.
824 }
825
826 }
827 // Log::addDebug('Relative URLS', $result);
828 return $result;
829 }
830
831
832 /** FindNearestsize
833 * 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.
834 */
835 private function findNearestSize($sizeName)
836 {
837 Log::addDebug('Find Nearest: '. $sizeName);
838
839 if (! isset($this->source_metadata['sizes'][$sizeName]) || ! isset($this->target_metadata['width'])) // This can happen with non-image files like PDF.
840 {
841 // Check if metadata-less item is a svg file. Just the main file to replace all thumbnails since SVG's don't need thumbnails.
842 if (strpos($this->target_url, '.svg') !== false)
843 {
844 $svg_file = wp_basename($this->target_url);
845 return $svg_file; // this is the relpath of the mainfile.
846 }
847
848
849 return false;
850 }
851 $old_width = $this->source_metadata['sizes'][$sizeName]['width']; // the width from size not in new image
852 $new_width = $this->target_metadata['width']; // default check - the width of the main image
853
854 $diff = abs($old_width - $new_width);
855 // $closest_file = str_replace($this->relPath, '', $this->newMeta['file']);
856 $closest_file = wp_basename($this->target_metadata['file']); // mainfile as default
857
858 foreach($this->target_metadata['sizes'] as $sizeName => $data)
859 {
860 $thisdiff = abs($old_width - $data['width']);
861
862 if ( $thisdiff < $diff )
863 {
864 $closest_file = $data['file'];
865 if(is_array($closest_file)) { $closest_file = $closest_file[0];} // HelpScout case 709692915
866 if(!empty($closest_file)) {
867 $diff = $thisdiff;
868 $found_metasize = true;
869 }
870 }
871 }
872
873
874 if(empty($closest_file)) return false;
875
876 return $closest_file;
877
878
879 }
880
881 } // class
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 public function getFormUrl($attach_id)
25 {
26 $url = admin_url('upload.php');
27 $url = add_query_arg(array(
28 'page' => 'enable-media-replace/enable-media-replace.php',
29 'noheader' => true,
30 'action' => 'media_replace_upload',
31 'attachment_id' => $attach_id,
32 ));
33
34 if (isset($_REQUEST['SHORTPIXEL_DEBUG']))
35 {
36 $spdebug = $_REQUEST['SHORTPIXEL_DEBUG'];
37 if (is_numeric($spdebug))
38 $spdebug = intval($spdebug);
39 else {
40 $spdebug = sanitize_text_field($spdebug);
41 }
42
43 $url = add_query_arg('SHORTPIXEL_DEBUG', $spdebug, $url);
44 }
45
46 return $url;
47
48 }
49
50 public function getSuccesRedirect($post_id)
51 {
52 $url = admin_url('post.php');
53 $url = add_query_arg(array('action' => 'edit', 'post' => $post_id, 'emr_replaced' => '1'), $url);
54
55 if (isset($_REQUEST['SHORTPIXEL_DEBUG']))
56 {
57 $spdebug = $_REQUEST['SHORTPIXEL_DEBUG'];
58 if (is_numeric($spdebug))
59 $spdebug = intval($spdebug);
60 else {
61 $spdebug = sanitize_text_field($spdebug);
62 }
63
64 $url = add_query_arg('SHORTPIXEL_DEBUG', $spdebug, $url);
65 }
66
67 $url = apply_filters('emr_returnurl', $url);
68 Log::addDebug('Success URL- ' . $url);
69
70 return $url;
71
72 }
73
74 public function getFailedRedirect($attach_id)
75 {
76 $url = admin_url('upload.php');
77 $url = add_query_arg(array(
78 'page' => 'enable-media-replace/enable-media-replace.php',
79 'action' => 'media_replace',
80 'attachment_id' => $attach_id,
81 '_wpnonce' => wp_create_nonce('media_replace'),
82 ), $url
83 );
84
85 $url = apply_filters('emr_returnurl_failed', $url);
86 Log::addDebug('Failed URL- ' . $url);
87 return $url;
88 }
89
90
91
92 public function setPreviewSizes()
93 {
94 list($this->preview_size, $this->preview_width, $this->preview_height) = $this->findImageSizeByMax($this->preview_max_width);
95 }
96
97 public function setSourceSizes($attach_id)
98 {
99 $data = $this->getImageSizes($attach_id, 'full'); // wp_get_attachment_image_src($attach_id, 'full');
100 // $file = get_attached_file($attach_id);
101
102 if (is_array($data))
103 {
104
105 $this->full_width = $data[1];
106 $this->full_height = $data[2];
107 }
108
109 }
110
111 // Returns Preview Image HTML Output.
112 public function getPreviewImage($attach_id,$file)
113 {
114 $data = false;
115
116 if ($attach_id > 0)
117 {
118 $data = $this->getImageSizes($attach_id, $this->preview_size); //wp_get_attachment_image_src($attach_id, $this->preview_size);
119 /*$file = get_attached_file($attach_id);
120
121 // If the file is relative, prepend upload dir.
122 if (! file_exists($file) && $file && 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) )
123 {
124 $file = get_post_meta( $attach_id, '_wp_attached_file', true );
125 $uploads = wp_get_upload_dir();
126 $file = $uploads['basedir'] . "/$file";
127 }
128 */
129 Log::addDebug('Attached File ' . $file->getFullFilePath(), $data);
130 }
131
132 $mime_type = get_post_mime_type($attach_id);
133
134 if (! is_array($data) || ! $file->exists() )
135 {
136 // if attachid higher than zero ( exists ) but not the image, fail, that's an error state.
137 $icon = ($attach_id < 0) ? '' : 'dashicons-no';
138 $is_document = false;
139
140 $args = array(
141 'width' => $this->preview_width,
142 'height' => $this->preview_height,
143 'is_image' => false,
144 'is_document' => $is_document,
145 'icon' => $icon,
146 'mime_type' => null,
147 );
148
149
150
151 // failed, it might be this server doens't support PDF thumbnails. Fallback to File preview.
152 if ($mime_type == 'application/pdf')
153 {
154 return $this->getPreviewFile($attach_id, $file);
155 }
156
157 return $this->getPlaceHolder($args);
158 }
159
160
161 $url = $data[0];
162 $width = $data[1];
163 $height = $data[2];
164
165 // SVG's without any helpers return around 0 for width / height. Fix preview.
166
167 // preview width, if source if found, should be set to source.
168 $this->preview_width = $width;
169 $this->preview_height = $height;
170
171
172 if ($width > $this->preview_max_width)
173 $width = $this->preview_max_width;
174 if ($height > $this->preview_max_height)
175 $height = $this->preview_max_height;
176
177 $image = "<img src='$url' width='$width' height='$height' class='image' style='max-width:100%; max-height: 100%;' />";
178
179 $args = array(
180 'width' => $width,
181 'height' => $height,
182 'image' => $image,
183 'mime_type' => $mime_type,
184 'file_size' => $file->getFileSize(),
185 );
186
187 $output = $this->getPlaceHolder($args);
188 return $output;
189 }
190
191 protected function getImageSizes($attach_id, $size = 'thumbnail')
192 {
193 $data = wp_get_attachment_image_src($attach_id, $size);
194 $width = isset($data[1]) ? $data[1] : 0;
195 //$mime_type = get_post_mime_type($attach_id);
196 $file = get_attached_file($attach_id);
197 $mime_type = wp_get_image_mime($file);
198
199 if (strpos($mime_type, 'svg') !== false && $width <= 5)
200 {
201 $file = get_attached_file($attach_id);
202 $data = $this->fixSVGSize($data, $file);
203 }
204
205 return $data;
206 }
207
208 protected function fixSVGSize($data, $file)
209 {
210 if (! function_exists('simplexml_load_file'))
211 return $data;
212
213 $xml = simplexml_load_file($file);
214 //Log::addDebug('XML LOAD FILE', $xml);
215 if ($xml)
216 { // stolen from SVG Upload plugin
217 $attr = $xml->attributes();
218 $viewbox = explode(' ', $attr->viewBox);
219 $data[1] = isset($attr->width) && preg_match('/\d+/', $attr->width, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[2] : null);
220 $data[2] = isset($attr->height) && preg_match('/\d+/', $attr->height, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[3] : null);
221 }
222
223 return $data;
224 }
225
226 public function getPreviewError($attach_id)
227 {
228 $args = array(
229 'width' => $this->preview_width,
230 'height' => $this->preview_height,
231 'icon' => 'dashicons-no',
232 'is_image' => false,
233 );
234 $output = $this->getPlaceHolder($args);
235 return $output;
236 }
237
238 public function getPreviewFile($attach_id, $file)
239 {
240 if ($attach_id > 0)
241 {
242 //$filepath = get_attached_file($attach_id);
243 $filename = $file->getFileName();
244 }
245 else {
246 $filename = false;
247 }
248
249 $mime_type = $file->getFileMime();
250
251 $args = array(
252 'width' => 300,
253 'height' => 300,
254 'is_image' => false,
255 'is_document' => true,
256 'layer' => $filename,
257 'mime_type' => $mime_type,
258 'file_size' => $file->getFileSize(),
259 );
260 $output = $this->getPlaceHolder($args);
261 return $output;
262 }
263
264 public function findImageSizeByMax($maxwidth)
265 {
266 $image_sizes = $this->get_image_sizes();
267
268 $match_width = 0;
269 $match_height = 0;
270 $match = '';
271
272 foreach($image_sizes as $sizeName => $sizeItem)
273 {
274
275 $width = $sizeItem['width'];
276 if ($width > $match_width && $width <= $maxwidth)
277 {
278 $match = $sizeName;
279 $match_width = $width;
280 $match_height = $sizeItem['height'];
281 }
282 }
283 return array($match, $match_width, $match_height);
284 }
285
286 public function getPlaceHolder($args)
287 {
288 $defaults = array(
289 'width' => 150,
290 'height' => 150,
291 'image' => '',
292 'icon' => 'dashicons-media-document',
293 'layer' => $this->full_width . ' x ' . $this->full_height,
294 'is_image' => true,
295 'is_document' => false,
296 'mime_type' => false,
297 'file_size' => false,
298 );
299
300 $args = wp_parse_args($args, $defaults);
301
302 $w = $args['width'];
303 $h = $args['height'];
304
305 if ($w < 150) // minimum
306 $w = 150;
307 if ($h < 150)
308 $h = 150;
309
310 $icon = $args['icon'];
311
312 if ($args['is_image'])
313 {
314 $placeholder_class = 'is_image';
315 }
316 else {
317 $placeholder_class = 'not_image';
318 }
319
320 if ($args['is_document'])
321 {
322 $placeholder_class .= ' is_document';
323 }
324
325 $filetype = '';
326 if ($args['mime_type'])
327 {
328 $filetype = 'data-filetype="' . $args['mime_type'] . '"';
329 }
330
331 $filesize = ($args['file_size']) ? $args['file_size'] : '';
332
333
334 $output = "<div class='image_placeholder $placeholder_class' $filetype style='width:" . $w . "px; height:". $h ."px'> ";
335 $output .= $args['image'];
336 $output .= "<div class='dashicons $icon'>&nbsp;</div>";
337 $output .= "<span class='textlayer'>" . $args['layer'] . "</span>";
338 $output .= "<div class='image_size'>" . $this->convertFileSize($filesize). "</div>";
339 $output .= "</div>";
340
341
342
343 return $output;
344 }
345
346 private function convertFileSize($filesize)
347 {
348 return size_format($filesize);
349 }
350
351 /**
352 * Get size information for all currently-registered image sizes.
353 * Directly stolen from - https://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes
354 * @global $_wp_additional_image_sizes
355 * @uses get_intermediate_image_sizes()
356 * @return array $sizes Data for all currently-registered image sizes.
357 */
358 private function get_image_sizes() {
359 global $_wp_additional_image_sizes;
360
361 $sizes = array();
362
363 foreach ( get_intermediate_image_sizes() as $_size ) {
364 if ( in_array( $_size, array('thumbnail', 'medium', 'medium_large', 'large') ) ) {
365 $sizes[ $_size ]['width'] = get_option( "{$_size}_size_w" );
366 $sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" );
367 } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
368 $sizes[ $_size ] = array(
369 'width' => $_wp_additional_image_sizes[ $_size ]['width'],
370 'height' => $_wp_additional_image_sizes[ $_size ]['height'],
371 );
372 }
373 }
374
375 return $sizes;
376 }
377
378 /** For Location Dir replacement. Get the Subdir that is in use now. */
379 public function getRelPathNow()
380 {
381 $uploadDir = wp_upload_dir();
382 if (isset($uploadDir['subdir']))
383 return ltrim($uploadDir['subdir'], '/');
384 else
385 return false;
386 }
387
388 } // class
1 .ui-widget-content {
2 border: 1px solid #dddddd;
3 background: #ffffff;
4 color: #333333;
5 }
6
7 .ui-widget-overlay {
8 position: fixed;
9 top: 0;
10 left: 0;
11 width: 100%;
12 height: 100%;
13 }
14
15 .ui-datepicker {
16 width: 17em;
17 padding: 0.2em 0.2em 0;
18 display: none;
19 }
20
21 .ui-datepicker .ui-datepicker-header {
22 position: relative;
23 padding: 0.2em 0;
24 }
25
26 .ui-datepicker .ui-datepicker-prev,
27 .ui-datepicker .ui-datepicker-next {
28 position: absolute;
29 top: 2px;
30 width: 1.8em;
31 height: 1.8em;
32 }
33
34 .ui-datepicker .ui-datepicker-prev-hover,
35 .ui-datepicker .ui-datepicker-next-hover {
36 top: 1px;
37 }
38
39 .ui-datepicker .ui-datepicker-prev {
40 left: 2px;
41 }
42
43 .ui-datepicker .ui-datepicker-next {
44 right: 2px;
45 }
46
47 .ui-datepicker .ui-datepicker-prev-hover {
48 left: 1px;
49 }
50
51 .ui-datepicker .ui-datepicker-next-hover {
52 right: 1px;
53 }
54
55 .ui-datepicker .ui-datepicker-prev span,
56 .ui-datepicker .ui-datepicker-next span {
57 display: block;
58 position: absolute;
59 left: 50%;
60 margin-left: -8px;
61 top: 50%;
62 margin-top: -8px;
63 }
64
65 .ui-datepicker .ui-datepicker-title {
66 margin: 0 2.3em;
67 line-height: 1.8em;
68 text-align: center;
69 }
70
71 .ui-datepicker .ui-datepicker-title select {
72 font-size: 1em;
73 margin: 1px 0;
74 }
75
76 .ui-datepicker select.ui-datepicker-month,
77 .ui-datepicker select.ui-datepicker-year {
78 width: 45%;
79 }
80
81 .ui-datepicker table {
82 width: 100%;
83 font-size: 0.9em;
84 border-collapse: collapse;
85 margin: 0 0 0.4em;
86 }
87
88 .ui-datepicker th {
89 padding: 0.7em 0.3em;
90 text-align: center;
91 font-weight: bold;
92 border: 0;
93 }
94
95 .ui-datepicker td {
96 border: 0;
97 padding: 1px;
98 }
99
100 .ui-datepicker td span,
101 .ui-datepicker td a {
102 display: block;
103 padding: 0.2em;
104 text-align: center;
105 text-decoration: none;
106 }
107
108 .ui-datepicker .ui-datepicker-buttonpane {
109 background-image: none;
110 margin: 0.7em 0 0 0;
111 padding: 0 0.2em;
112 border-left: 0;
113 border-right: 0;
114 border-bottom: 0;
115 }
116
117 .ui-datepicker .ui-datepicker-buttonpane button {
118 float: right;
119 margin: 0.5em 0.2em 0.4em;
120 cursor: pointer;
121 padding: 0.2em 0.6em 0.3em 0.6em;
122 width: auto;
123 overflow: visible;
124 }
125
126 .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
127 float: left;
128 }
129
130 /* with multiple calendars */
131 .ui-datepicker.ui-datepicker-multi {
132 width: auto;
133 }
134
135 .ui-datepicker-multi .ui-datepicker-group {
136 float: left;
137 }
138
139 .ui-datepicker-multi .ui-datepicker-group table {
140 width: 95%;
141 margin: 0 auto 0.4em;
142 }
143
144 .ui-datepicker-multi-2 .ui-datepicker-group {
145 width: 50%;
146 }
147
148 .ui-datepicker-multi-3 .ui-datepicker-group {
149 width: 33.3%;
150 }
151
152 .ui-datepicker-multi-4 .ui-datepicker-group {
153 width: 25%;
154 }
155
156 .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
157 .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
158 border-left-width: 0;
159 }
160
161 .ui-datepicker-multi .ui-datepicker-buttonpane {
162 clear: left;
163 }
164
165 .ui-datepicker-row-break {
166 clear: both;
167 width: 100%;
168 font-size: 0;
169 }
170
171 /* RTL support */
172 .ui-datepicker-rtl {
173 direction: rtl;
174 }
175
176 .ui-datepicker-rtl .ui-datepicker-prev {
177 right: 2px;
178 left: auto;
179 }
180
181 .ui-datepicker-rtl .ui-datepicker-next {
182 left: 2px;
183 right: auto;
184 }
185
186 .ui-datepicker-rtl .ui-datepicker-prev:hover {
187 right: 1px;
188 left: auto;
189 }
190
191 .ui-datepicker-rtl .ui-datepicker-next:hover {
192 left: 1px;
193 right: auto;
194 }
195
196 .ui-datepicker-rtl .ui-datepicker-buttonpane {
197 clear: right;
198 }
199
200 .ui-datepicker-rtl .ui-datepicker-buttonpane button {
201 float: left;
202 }
203
204 .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
205 .ui-datepicker-rtl .ui-datepicker-group {
206 float: right;
207 }
208
209 .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
210 .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
211 border-right-width: 0;
212 border-left-width: 1px;
213 }
214
215 /* Icons */
216 .ui-datepicker .ui-icon {
217 display: block;
218 text-indent: -99999px;
219 overflow: hidden;
220 background-repeat: no-repeat;
221 left: 0.5em;
222 top: 0.3em;
223 }
224
225 .ui-icon {
226 width: 16px;
227 height: 16px;
228 }
229
230 .ui-icon,
231 .ui-widget-content .ui-icon {
232 background-image: url("../img/ui-icons_444444_256x240.png");
233 }
234
235 .ui-widget-header .ui-icon {
236 background-image: url("../img/ui-icons_444444_256x240.png");
237 }
238
239 .ui-state-hover .ui-icon,
240 .ui-state-focus .ui-icon,
241 .ui-button:hover .ui-icon,
242 .ui-button:focus .ui-icon {
243 background-image: url("../img/ui-icons_555555_256x240.png");
244 }
245
246 .ui-state-active .ui-icon,
247 .ui-button:active .ui-icon {
248 background-image: url("../img/ui-icons_ffffff_256x240.png");
249 }
250
251 .ui-state-highlight .ui-icon,
252 .ui-button .ui-state-highlight.ui-icon {
253 background-image: url("../img/ui-icons_777620_256x240.png");
254 }
255
256 /* positioning */
257 .ui-icon-blank {
258 background-position: 16px 16px;
259 }
260
261 .ui-icon-caret-1-n {
262 background-position: 0 0;
263 }
264
265 .ui-icon-caret-1-ne {
266 background-position: -16px 0;
267 }
268
269 .ui-icon-caret-1-e {
270 background-position: -32px 0;
271 }
272
273 .ui-icon-caret-1-se {
274 background-position: -48px 0;
275 }
276
277 .ui-icon-caret-1-s {
278 background-position: -65px 0;
279 }
280
281 .ui-icon-caret-1-sw {
282 background-position: -80px 0;
283 }
284
285 .ui-icon-caret-1-w {
286 background-position: -96px 0;
287 }
288
289 .ui-icon-caret-1-nw {
290 background-position: -112px 0;
291 }
292
293 .ui-icon-caret-2-n-s {
294 background-position: -128px 0;
295 }
296
297 .ui-icon-caret-2-e-w {
298 background-position: -144px 0;
299 }
300
301 .ui-icon-triangle-1-n {
302 background-position: 0 -16px;
303 }
304
305 .ui-icon-triangle-1-ne {
306 background-position: -16px -16px;
307 }
308
309 .ui-icon-triangle-1-e {
310 background-position: -32px -16px;
311 }
312
313 .ui-icon-triangle-1-se {
314 background-position: -48px -16px;
315 }
316
317 .ui-icon-triangle-1-s {
318 background-position: -65px -16px;
319 }
320
321 .ui-icon-triangle-1-sw {
322 background-position: -80px -16px;
323 }
324
325 .ui-icon-triangle-1-w {
326 background-position: -96px -16px;
327 }
328
329 .ui-icon-triangle-1-nw {
330 background-position: -112px -16px;
331 }
332
333 .ui-icon-triangle-2-n-s {
334 background-position: -128px -16px;
335 }
336
337 .ui-icon-triangle-2-e-w {
338 background-position: -144px -16px;
339 }
340
341 .ui-icon-arrow-1-n {
342 background-position: 0 -32px;
343 }
344
345 .ui-icon-arrow-1-ne {
346 background-position: -16px -32px;
347 }
348
349 .ui-icon-arrow-1-e {
350 background-position: -32px -32px;
351 }
352
353 .ui-icon-arrow-1-se {
354 background-position: -48px -32px;
355 }
356
357 .ui-icon-arrow-1-s {
358 background-position: -65px -32px;
359 }
360
361 .ui-icon-arrow-1-sw {
362 background-position: -80px -32px;
363 }
364
365 .ui-icon-arrow-1-w {
366 background-position: -96px -32px;
367 }
368
369 .ui-icon-arrow-1-nw {
370 background-position: -112px -32px;
371 }
372
373 .ui-icon-arrow-2-n-s {
374 background-position: -128px -32px;
375 }
376
377 .ui-icon-arrow-2-ne-sw {
378 background-position: -144px -32px;
379 }
380
381 .ui-icon-arrow-2-e-w {
382 background-position: -160px -32px;
383 }
384
385 .ui-icon-arrow-2-se-nw {
386 background-position: -176px -32px;
387 }
388
389 .ui-icon-arrowstop-1-n {
390 background-position: -192px -32px;
391 }
392
393 .ui-icon-arrowstop-1-e {
394 background-position: -208px -32px;
395 }
396
397 .ui-icon-arrowstop-1-s {
398 background-position: -224px -32px;
399 }
400
401 .ui-icon-arrowstop-1-w {
402 background-position: -240px -32px;
403 }
404
405 .ui-icon-arrowthick-1-n {
406 background-position: 1px -48px;
407 }
408
409 .ui-icon-arrowthick-1-ne {
410 background-position: -16px -48px;
411 }
412
413 .ui-icon-arrowthick-1-e {
414 background-position: -32px -48px;
415 }
416
417 .ui-icon-arrowthick-1-se {
418 background-position: -48px -48px;
419 }
420
421 .ui-icon-arrowthick-1-s {
422 background-position: -64px -48px;
423 }
424
425 .ui-icon-arrowthick-1-sw {
426 background-position: -80px -48px;
427 }
428
429 .ui-icon-arrowthick-1-w {
430 background-position: -96px -48px;
431 }
432
433 .ui-icon-arrowthick-1-nw {
434 background-position: -112px -48px;
435 }
436
437 .ui-icon-arrowthick-2-n-s {
438 background-position: -128px -48px;
439 }
440
441 .ui-icon-arrowthick-2-ne-sw {
442 background-position: -144px -48px;
443 }
444
445 .ui-icon-arrowthick-2-e-w {
446 background-position: -160px -48px;
447 }
448
449 .ui-icon-arrowthick-2-se-nw {
450 background-position: -176px -48px;
451 }
452
453 .ui-icon-arrowthickstop-1-n {
454 background-position: -192px -48px;
455 }
456
457 .ui-icon-arrowthickstop-1-e {
458 background-position: -208px -48px;
459 }
460
461 .ui-icon-arrowthickstop-1-s {
462 background-position: -224px -48px;
463 }
464
465 .ui-icon-arrowthickstop-1-w {
466 background-position: -240px -48px;
467 }
468
469 .ui-icon-arrowreturnthick-1-w {
470 background-position: 0 -64px;
471 }
472
473 .ui-icon-arrowreturnthick-1-n {
474 background-position: -16px -64px;
475 }
476
477 .ui-icon-arrowreturnthick-1-e {
478 background-position: -32px -64px;
479 }
480
481 .ui-icon-arrowreturnthick-1-s {
482 background-position: -48px -64px;
483 }
484
485 .ui-icon-arrowreturn-1-w {
486 background-position: -64px -64px;
487 }
488
489 .ui-icon-arrowreturn-1-n {
490 background-position: -80px -64px;
491 }
492
493 .ui-icon-arrowreturn-1-e {
494 background-position: -96px -64px;
495 }
496
497 .ui-icon-arrowreturn-1-s {
498 background-position: -112px -64px;
499 }
500
501 .ui-icon-arrowrefresh-1-w {
502 background-position: -128px -64px;
503 }
504
505 .ui-icon-arrowrefresh-1-n {
506 background-position: -144px -64px;
507 }
508
509 .ui-icon-arrowrefresh-1-e {
510 background-position: -160px -64px;
511 }
512
513 .ui-icon-arrowrefresh-1-s {
514 background-position: -176px -64px;
515 }
516
517 .ui-icon-arrow-4 {
518 background-position: 0 -80px;
519 }
520
521 .ui-icon-arrow-4-diag {
522 background-position: -16px -80px;
523 }
524
525 .ui-icon-extlink {
526 background-position: -32px -80px;
527 }
528
529 .ui-icon-newwin {
530 background-position: -48px -80px;
531 }
532
533 .ui-icon-refresh {
534 background-position: -64px -80px;
535 }
536
537 .ui-icon-shuffle {
538 background-position: -80px -80px;
539 }
540
541 .ui-icon-transfer-e-w {
542 background-position: -96px -80px;
543 }
544
545 .ui-icon-transferthick-e-w {
546 background-position: -112px -80px;
547 }
548
549 .ui-icon-folder-collapsed {
550 background-position: 0 -96px;
551 }
552
553 .ui-icon-folder-open {
554 background-position: -16px -96px;
555 }
556
557 .ui-icon-document {
558 background-position: -32px -96px;
559 }
560
561 .ui-icon-document-b {
562 background-position: -48px -96px;
563 }
564
565 .ui-icon-note {
566 background-position: -64px -96px;
567 }
568
569 .ui-icon-mail-closed {
570 background-position: -80px -96px;
571 }
572
573 .ui-icon-mail-open {
574 background-position: -96px -96px;
575 }
576
577 .ui-icon-suitcase {
578 background-position: -112px -96px;
579 }
580
581 .ui-icon-comment {
582 background-position: -128px -96px;
583 }
584
585 .ui-icon-person {
586 background-position: -144px -96px;
587 }
588
589 .ui-icon-print {
590 background-position: -160px -96px;
591 }
592
593 .ui-icon-trash {
594 background-position: -176px -96px;
595 }
596
597 .ui-icon-locked {
598 background-position: -192px -96px;
599 }
600
601 .ui-icon-unlocked {
602 background-position: -208px -96px;
603 }
604
605 .ui-icon-bookmark {
606 background-position: -224px -96px;
607 }
608
609 .ui-icon-tag {
610 background-position: -240px -96px;
611 }
612
613 .ui-icon-home {
614 background-position: 0 -112px;
615 }
616
617 .ui-icon-flag {
618 background-position: -16px -112px;
619 }
620
621 .ui-icon-calendar {
622 background-position: -32px -112px;
623 }
624
625 .ui-icon-cart {
626 background-position: -48px -112px;
627 }
628
629 .ui-icon-pencil {
630 background-position: -64px -112px;
631 }
632
633 .ui-icon-clock {
634 background-position: -80px -112px;
635 }
636
637 .ui-icon-disk {
638 background-position: -96px -112px;
639 }
640
641 .ui-icon-calculator {
642 background-position: -112px -112px;
643 }
644
645 .ui-icon-zoomin {
646 background-position: -128px -112px;
647 }
648
649 .ui-icon-zoomout {
650 background-position: -144px -112px;
651 }
652
653 .ui-icon-search {
654 background-position: -160px -112px;
655 }
656
657 .ui-icon-wrench {
658 background-position: -176px -112px;
659 }
660
661 .ui-icon-gear {
662 background-position: -192px -112px;
663 }
664
665 .ui-icon-heart {
666 background-position: -208px -112px;
667 }
668
669 .ui-icon-star {
670 background-position: -224px -112px;
671 }
672
673 .ui-icon-link {
674 background-position: -240px -112px;
675 }
676
677 .ui-icon-cancel {
678 background-position: 0 -128px;
679 }
680
681 .ui-icon-plus {
682 background-position: -16px -128px;
683 }
684
685 .ui-icon-plusthick {
686 background-position: -32px -128px;
687 }
688
689 .ui-icon-minus {
690 background-position: -48px -128px;
691 }
692
693 .ui-icon-minusthick {
694 background-position: -64px -128px;
695 }
696
697 .ui-icon-close {
698 background-position: -80px -128px;
699 }
700
701 .ui-icon-closethick {
702 background-position: -96px -128px;
703 }
704
705 .ui-icon-key {
706 background-position: -112px -128px;
707 }
708
709 .ui-icon-lightbulb {
710 background-position: -128px -128px;
711 }
712
713 .ui-icon-scissors {
714 background-position: -144px -128px;
715 }
716
717 .ui-icon-clipboard {
718 background-position: -160px -128px;
719 }
720
721 .ui-icon-copy {
722 background-position: -176px -128px;
723 }
724
725 .ui-icon-contact {
726 background-position: -192px -128px;
727 }
728
729 .ui-icon-image {
730 background-position: -208px -128px;
731 }
732
733 .ui-icon-video {
734 background-position: -224px -128px;
735 }
736
737 .ui-icon-script {
738 background-position: -240px -128px;
739 }
740
741 .ui-icon-alert {
742 background-position: 0 -144px;
743 }
744
745 .ui-icon-info {
746 background-position: -16px -144px;
747 }
748
749 .ui-icon-notice {
750 background-position: -32px -144px;
751 }
752
753 .ui-icon-help {
754 background-position: -48px -144px;
755 }
756
757 .ui-icon-check {
758 background-position: -64px -144px;
759 }
760
761 .ui-icon-bullet {
762 background-position: -80px -144px;
763 }
764
765 .ui-icon-radio-on {
766 background-position: -96px -144px;
767 }
768
769 .ui-icon-radio-off {
770 background-position: -112px -144px;
771 }
772
773 .ui-icon-pin-w {
774 background-position: -128px -144px;
775 }
776
777 .ui-icon-pin-s {
778 background-position: -144px -144px;
779 }
780
781 .ui-icon-play {
782 background-position: 0 -160px;
783 }
784
785 .ui-icon-pause {
786 background-position: -16px -160px;
787 }
788
789 .ui-icon-seek-next {
790 background-position: -32px -160px;
791 }
792
793 .ui-icon-seek-prev {
794 background-position: -48px -160px;
795 }
796
797 .ui-icon-seek-end {
798 background-position: -64px -160px;
799 }
800
801 .ui-icon-seek-start {
802 background-position: -80px -160px;
803 }
804
805 /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
806 .ui-icon-seek-first {
807 background-position: -80px -160px;
808 }
809
810 .ui-icon-stop {
811 background-position: -96px -160px;
812 }
813
814 .ui-icon-eject {
815 background-position: -112px -160px;
816 }
817
818 .ui-icon-volume-off {
819 background-position: -128px -160px;
820 }
821
822 .ui-icon-volume-on {
823 background-position: -144px -160px;
824 }
825
826 .ui-icon-power {
827 background-position: 0 -176px;
828 }
829
830 .ui-icon-signal-diag {
831 background-position: -16px -176px;
832 }
833
834 .ui-icon-signal {
835 background-position: -32px -176px;
836 }
837
838 .ui-icon-battery-0 {
839 background-position: -48px -176px;
840 }
841
842 .ui-icon-battery-1 {
843 background-position: -64px -176px;
844 }
845
846 .ui-icon-battery-2 {
847 background-position: -80px -176px;
848 }
849
850 .ui-icon-battery-3 {
851 background-position: -96px -176px;
852 }
853
854 .ui-icon-circle-plus {
855 background-position: 0 -192px;
856 }
857
858 .ui-icon-circle-minus {
859 background-position: -16px -192px;
860 }
861
862 .ui-icon-circle-close {
863 background-position: -32px -192px;
864 }
865
866 .ui-icon-circle-triangle-e {
867 background-position: -48px -192px;
868 }
869
870 .ui-icon-circle-triangle-s {
871 background-position: -64px -192px;
872 }
873
874 .ui-icon-circle-triangle-w {
875 background-position: -80px -192px;
876 }
877
878 .ui-icon-circle-triangle-n {
879 background-position: -96px -192px;
880 }
881
882 .ui-icon-circle-arrow-e {
883 background-position: -112px -192px;
884 }
885
886 .ui-icon-circle-arrow-s {
887 background-position: -128px -192px;
888 }
889
890 .ui-icon-circle-arrow-w {
891 background-position: -144px -192px;
892 }
893
894 .ui-icon-circle-arrow-n {
895 background-position: -160px -192px;
896 }
897
898 .ui-icon-circle-zoomin {
899 background-position: -176px -192px;
900 }
901
902 .ui-icon-circle-zoomout {
903 background-position: -192px -192px;
904 }
905
906 .ui-icon-circle-check {
907 background-position: -208px -192px;
908 }
909
910 .ui-icon-circlesmall-plus {
911 background-position: 0 -208px;
912 }
913
914 .ui-icon-circlesmall-minus {
915 background-position: -16px -208px;
916 }
917
918 .ui-icon-circlesmall-close {
919 background-position: -32px -208px;
920 }
921
922 .ui-icon-squaresmall-plus {
923 background-position: -48px -208px;
924 }
925
926 .ui-icon-squaresmall-minus {
927 background-position: -64px -208px;
928 }
929
930 .ui-icon-squaresmall-close {
931 background-position: -80px -208px;
932 }
933
934 .ui-icon-grip-dotted-vertical {
935 background-position: 0 -224px;
936 }
937
938 .ui-icon-grip-dotted-horizontal {
939 background-position: -16px -224px;
940 }
941
942 .ui-icon-grip-solid-vertical {
943 background-position: -32px -224px;
944 }
945
946 .ui-icon-grip-solid-horizontal {
947 background-position: -48px -224px;
948 }
949
950 .ui-icon-gripsmall-diagonal-se {
951 background-position: -64px -224px;
952 }
953
954 .ui-icon-grip-diagonal-se {
955 background-position: -80px -224px;
956 }
957
958 /* Corner radius */
959 .ui-corner-all,
960 .ui-corner-top,
961 .ui-corner-left,
962 .ui-corner-tl {
963 border-top-left-radius: 3px;
964 }
965
966 .ui-corner-all,
967 .ui-corner-top,
968 .ui-corner-right,
969 .ui-corner-tr {
970 border-top-right-radius: 3px;
971 }
972
973 .ui-corner-all,
974 .ui-corner-bottom,
975 .ui-corner-left,
976 .ui-corner-bl {
977 border-bottom-left-radius: 3px;
978 }
979
980 .ui-corner-all,
981 .ui-corner-bottom,
982 .ui-corner-right,
983 .ui-corner-br {
984 border-bottom-right-radius: 3px;
985 }
986
987 .emr_upload_form form {
988 display: flex;
989 }
990 .emr_upload_form form .upsell-wrapper {
991 margin-left: 10px;
992 }
993 .emr_upload_form .wrapper {
994 padding: 18px;
995 border: 1px solid #ccc;
996 }
997 .emr_upload_form .wrapper .section-header {
998 font-size: 18px;
999 border-bottom: 1px solid #ccc;
1000 padding: 6px 0;
1001 margin: 0 0 15px 0;
1002 }
1003 .emr_upload_form .image_chooser.wrapper {
1004 min-height: 350px;
1005 }
1006 .emr_upload_form .image_chooser.wrapper .emr_drop_area {
1007 border: 4px dashed #b4b9be;
1008 max-width: 600px;
1009 padding: 28px 14px;
1010 text-align: center;
1011 position: relative;
1012 }
1013 .emr_upload_form .image_chooser.wrapper .emr_drop_area h1 {
1014 display: none;
1015 }
1016 .emr_upload_form .image_chooser.wrapper .emr_drop_area .drop-wrapper {
1017 margin: 0 auto;
1018 }
1019 .emr_upload_form .image_chooser.wrapper .emr_drop_area.drop_breakout {
1020 position: fixed;
1021 left: 0;
1022 right: 0;
1023 bottom: 0;
1024 top: 0;
1025 max-width: none;
1026 border-color: #83b4d8;
1027 border-width: 10px;
1028 z-index: 999999;
1029 background-color: rgba(68, 68, 68, 0.7);
1030 }
1031 .emr_upload_form .image_chooser.wrapper .emr_drop_area.drop_breakout h1 {
1032 color: #fff;
1033 position: absolute;
1034 font-size: 50px;
1035 line-height: 50px;
1036 margin-top: -25px;
1037 top: 50%;
1038 width: 100%;
1039 text-align: center;
1040 display: block;
1041 }
1042 .emr_upload_form .image_chooser.wrapper .emr_drop_area.drop_breakout .drop-wrapper {
1043 display: none;
1044 }
1045 .emr_upload_form .image_chooser.wrapper .image_previews {
1046 margin: 15px 0;
1047 }
1048 .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder {
1049 position: relative;
1050 display: inline-block;
1051 margin-right: 25px;
1052 margin-bottom: 10px;
1053 border: 1px solid #ddd;
1054 vertical-align: top;
1055 max-height: 500px;
1056 }
1057 .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .textlayer {
1058 font-size: 25px;
1059 line-height: 25px;
1060 opacity: 0.7;
1061 position: absolute;
1062 color: #ccc;
1063 left: 48%;
1064 top: 50%;
1065 transform: translate(-50%, -50%);
1066 border: 1px dashed #eee;
1067 background-color: #333;
1068 padding: 8px;
1069 }
1070 .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .dashicons {
1071 font-size: 60px;
1072 position: absolute;
1073 top: 50%;
1074 margin-top: -30px;
1075 left: 50%;
1076 margin-left: -30px;
1077 opacity: 0.5;
1078 }
1079 .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .image_size {
1080 text-align: center;
1081 position: absolute;
1082 bottom: -25px;
1083 width: 100%;
1084 }
1085 .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 {
1086 display: none;
1087 }
1088 .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image img {
1089 display: none;
1090 }
1091 .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image .textlayer {
1092 display: none;
1093 }
1094 .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image.is_document .textlayer {
1095 font-size: 18px;
1096 line-height: 20px;
1097 display: block;
1098 }
1099 .emr_upload_form .form-error, .emr_upload_form .form-warning {
1100 background: #fff;
1101 padding: 8px;
1102 border-left: 4px solid #ff0000;
1103 margin: 10px 0;
1104 display: none;
1105 }
1106 .emr_upload_form .form-error p, .emr_upload_form .form-warning p {
1107 margin: 0;
1108 font-size: 12px;
1109 font-weight: 700;
1110 }
1111 .emr_upload_form .form-warning {
1112 border-left: 4px solid #ffb900;
1113 }
1114 .emr_upload_form .option-flex-wrapper {
1115 display: flex;
1116 }
1117 .emr_upload_form .replace_type.wrapper {
1118 flex: 1;
1119 border: 1px solid #ccc;
1120 margin: 15px 0;
1121 }
1122 .emr_upload_form .replace_type.wrapper .option {
1123 position: relative;
1124 z-index: 1;
1125 }
1126 .emr_upload_form .replace_type.wrapper .option label {
1127 font-size: 1.2em;
1128 }
1129 .emr_upload_form .replace_type.wrapper .option .nofeature-notice {
1130 border: 1px solid #ccc;
1131 padding: 8px;
1132 margin: 0;
1133 position: absolute;
1134 left: 0;
1135 right: 0;
1136 top: 0;
1137 bottom: 0;
1138 opacity: 0.8;
1139 z-index: 9;
1140 background: #444;
1141 }
1142 .emr_upload_form .replace_type.wrapper .option .nofeature-notice p {
1143 text-align: center;
1144 color: #fff;
1145 margin: 15px 0;
1146 }
1147 .emr_upload_form .options.wrapper {
1148 flex: 1;
1149 border: 1px solid #ccc;
1150 padding: 15px;
1151 margin: 15px 0 15px 35px;
1152 }
1153 .emr_upload_form .options.wrapper .custom_date .emr_datepicker {
1154 width: 150px;
1155 }
1156 .emr_upload_form .options.wrapper .custom_date .emr_hour, .emr_upload_form .options.wrapper .custom_date .emr_minute {
1157 width: 45px;
1158 }
1159 .emr_upload_form .options.wrapper .replace_custom_date {
1160 margin-left: 5px;
1161 }
1162 .emr_upload_form .options.wrapper .replace_custom_date:hover {
1163 text-decoration: underline;
1164 cursor: pointer;
1165 }
1166 .emr_upload_form .options.wrapper ul li input {
1167 margin-right: 8px;
1168 }
1169 .emr_upload_form .options.wrapper .option label {
1170 vertical-align: top;
1171 }
1172 .emr_upload_form .options.wrapper .small {
1173 font-size: 10px;
1174 vertical-align: top;
1175 margin-left: 8px;
1176 }
1177 .emr_upload_form .options.wrapper .custom_date {
1178 margin: 8px 0 0 25px;
1179 visibility: hidden;
1180 opacity: 0;
1181 }
1182 .emr_upload_form .options.wrapper .custom_date span.field-title {
1183 display: inline-block;
1184 margin-bottom: 4px;
1185 color: #444;
1186 font-size: 12px;
1187 width: 100%;
1188 text-align: left;
1189 vertical-align: middle;
1190 line-height: 26px;
1191 }
1192 .emr_upload_form .options.wrapper .custom_date span.field-title::before {
1193 font-size: 20px;
1194 vertical-align: top;
1195 margin-right: 4px;
1196 }
1197 .emr_upload_form .options.wrapper .location_option {
1198 display: none;
1199 margin-top: 12px;
1200 }
1201 .emr_upload_form .options.wrapper .location_option label {
1202 vertical-align: baseline;
1203 margin-right: 8px;
1204 }
1205 .emr_upload_form .form_controls.wrapper {
1206 clear: both;
1207 margin: 8px 0 15px 0;
1208 border: 0;
1209 padding: 0;
1210 }
1211 .emr_upload_form .form_controls.wrapper .button {
1212 padding-left: 20px;
1213 padding-right: 20px;
1214 }
1215 .emr_upload_form .shortpixel.notice {
1216 padding: 12px;
1217 }
1218 .emr_upload_form .shortpixel-offer {
1219 background: #fff;
1220 width: 250px;
1221 min-height: 270px;
1222 border: 1px solid #ccc;
1223 padding: 10px;
1224 margin-bottom: 10px;
1225 float: right;
1226 clear: both;
1227 background-color: #dcfdff;
1228 }
1229 .emr_upload_form .shortpixel-offer h3 {
1230 color: #00d0e5;
1231 font-size: 18px;
1232 text-align: center;
1233 margin: 0;
1234 line-height: 1.3em;
1235 }
1236 .emr_upload_form .shortpixel-offer h4 {
1237 font-size: 16px;
1238 text-align: center;
1239 }
1240 .emr_upload_form .shortpixel-offer .red {
1241 color: #ff0000;
1242 }
1243 .emr_upload_form .shortpixel-offer .cyan {
1244 color: #00d0e5;
1245 }
1246 .emr_upload_form .shortpixel-offer .grey {
1247 color: grey;
1248 }
1249 .emr_upload_form .shortpixel-offer .ucase {
1250 text-transform: uppercase;
1251 }
1252 .emr_upload_form .shortpixel-offer a {
1253 text-decoration: none;
1254 }
1255 .emr_upload_form .shortpixel-offer .button-wrapper {
1256 text-align: center;
1257 margin-top: 35px;
1258 }
1259 .emr_upload_form .shortpixel-offer .button-wrapper a {
1260 background-color: #ff0000;
1261 color: #fff;
1262 display: inline-block;
1263 padding: 8px;
1264 text-decoration: none;
1265 font-weight: 700;
1266 font-size: 20px;
1267 text-transform: uppercase;
1268 }
1269 .emr_upload_form .shortpixel-offer .hidden {
1270 display: none !important;
1271 }
1272 .emr_upload_form .shortpixel-offer .img-wrapper {
1273 text-align: center;
1274 margin: 0 0 25px 0;
1275 }
1276 .emr_upload_form .shortpixel-offer .img-wrapper img {
1277 max-width: 140px;
1278 max-height: 140px;
1279 margin: 0;
1280 }
1281 .emr_upload_form .shortpixel-offer.envira-shortpixel-install {
1282 background: #fff;
1283 }
1284 @media (max-width: 1200px) {
1285 .emr_upload_form .image_previews {
1286 text-align: center;
1287 }
1288 .emr_upload_form .option-flex-wrapper {
1289 flex-direction: column;
1290 }
1291 .emr_upload_form .option-flex-wrapper .options.wrapper {
1292 margin-left: 0;
1293 }
1294 }
1295 @media (max-width: 960px) {
1296 .emr_upload_form .upsell-wrapper {
1297 display: none;
1298 }
1299 }
1300 @media (max-width: 450px) {
1301 .emr_upload_form .replace_custom_date_wrapper {
1302 display: block;
1303 margin-top: 15px;
1304 font-size: 16px;
1305 }
1306 .emr_upload_form .location_option label {
1307 margin: 25px 0;
1308 display: inline-block;
1309 }
1310 }
1311
1312 /*# sourceMappingURL=admin.css.map */
1 {"version":3,"sourceRoot":"","sources":["../scss/_datepicker.scss","../scss/admin.scss"],"names":[],"mappings":"AAEA;EACC;EACA;EACA;;;AAID;EACC;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;EACA;EACA;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;;;AAED;AAAA;EAEC;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;;;AAGD;AACA;EACC;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAGD;AACA;EACC;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;AAAA;EAEC;;;AAED;AAAA;EAEC;EACA;;;AAGD;AACA;EACC;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;;;AAED;AAAA;EAEC;;;AAED;EACC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;EAEC;;;AAED;AAAA;EAEC;;;AAGD;AACA;EAAiB;;;AACjB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAuB;;;AACvB;EAAuB;;;AACvB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAAwB;;;AACxB;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAsB;;;AACtB;EAAuB;;;AACvB;EAAyB;;;AACzB;EAAuB;;;AACvB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA0B;;;AAC1B;EAA2B;;;AAC3B;EAA4B;;;AAC5B;EAA8B;;;AAC9B;EAA4B;;;AAC5B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAA8B;;;AAC9B;EAAgC;;;AAChC;EAAgC;;;AAChC;EAAgC;;;AAChC;EAAgC;;;AAChC;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA2B;;;AAC3B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAA4B;;;AAC5B;EAAmB;;;AACnB;EAAwB;;;AACxB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAmB;;;AACnB;EAAmB;;;AACnB;EAAwB;;;AACxB;EAA6B;;;AAC7B;EAA4B;;;AAC5B;EAAuB;;;AACvB;EAAoB;;;AACpB;EAAsB;;;AACtB;EAAgB;;;AAChB;EAAuB;;;AACvB;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAe;;;AACf;EAAgB;;;AAChB;EAAgB;;;AAChB;EAAoB;;;AACpB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAsB;;;AACtB;EAAkB;;;AAClB;EAAmB;;;AACnB;EAAkB;;;AAClB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAe;;;AACf;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAqB;;;AACrB;EAAgB;;;AAChB;EAAmB;;;AACnB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAkB;;;AAClB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAkB;;;AAClB;EAAoB;;;AACpB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAiB;;;AACjB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAoB;;;AACpB;EAAsB;;;AACtB;AACA;EAAsB;;;AACtB;EAAgB;;;AAChB;EAAiB;;;AACjB;EAAsB;;;AACtB;EAAqB;;;AACrB;EAAiB;;;AACjB;EAAuB;;;AACvB;EAAkB;;;AAClB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAqB;;;AACrB;EAAuB;;;AACvB;EAAwB;;;AACxB;EAAwB;;;AACxB;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAA0B;;;AAC1B;EAAyB;;;AACzB;EAA0B;;;AAC1B;EAAwB;;;AACxB;EAA4B;;;AAC5B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAA4B;;;AAC5B;EAA6B;;;AAC7B;EAA6B;;;AAC7B;EAAgC;;;AAChC;EAAkC;;;AAClC;EAA+B;;;AAC/B;EAAiC;;;AACjC;EAAiC;;;AACjC;EAA4B;;;AAE5B;AACA;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AAED;AAAA;AAAA;AAAA;EAIC;;;AC/ZC;EAEE;;AACA;EAEE;;AAIJ;EAGE;EACA;;AAEA;EAEE;EAEA;EACA;EACA;;AAIJ;EAEE;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AACA;EAAK;;AACL;EAEE;;AAGF;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EAAgB;;AAGtB;EAEE;;AACA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEG;EACA;EACA;EACA;;AAID;EAAiC;;AAMjC;EAAM;;AACN;EAAa;;AAEX;EACE;EACA;EACA;;AASZ;EAEE;EACA;EACA;EAEA;EACA;;AACA;EACI;EACA;EACA;;AAIN;EAEE;;AAGF;EAEE;;AAGF;EAEE;EACA;EACA;;AACA;EAEE;EACA;;AAKA;EAEE;;AAEF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;;AAOR;EAEE;EACA;EACA;EACA;;AAGE;EACE;;AAEF;EAEE;;AAGN;EAEE;;AACA;EACC;EACA;;AAOG;EAEE;;AAMJ;EAAQ;;AAEV;EAEE;EACA;EACA;;AAEF;EAEE;EACA;EACA;;AACA;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;;AACA;EAEE;EACA;EACA;;AAIN;EAEE;EACA;;AACA;EAEE;EACA;;AAKN;EAEE;EACA;EACA;EACA;;AACA;EAEE;EACA;;AAIJ;EAEG;;AAEH;EAEE;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACF;;AACE;EACE;EACA;EACA;EACA;EACA;;AAEJ;EAEE;EACA;;AAEF;EAAO;;AACP;EAAQ;;AACR;EAAQ;;AACR;EAAS;;AACR;EACE;;AAED;EAEE;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACJ;;AAGF;EAAU;;AAER;EAEE;EACA;;AACA;EAAM;EAAkB;EAAmB;;AAS/C;EAEE;;AAIF;EAEI;IAEG;;EAEH;IACE;;EACA;IACE;;;AAGR;EAEE;IAAkB;;;AAErB;EAEE;IACE;IACA;IACA;;EAIA;IACE;IACD","file":"admin.css"}
...\ No newline at end of file ...\ No newline at end of file
1 .ui-widget-content {
2 border: 1px solid #dddddd;
3 background: #ffffff;
4 color: #333333; }
5
6 .ui-widget-overlay {
7 position: fixed;
8 top: 0;
9 right: 0;
10 width: 100%;
11 height: 100%; }
12
13 .ui-datepicker {
14 width: 17em;
15 padding: .2em .2em 0;
16 display: none; }
17
18 .ui-datepicker .ui-datepicker-header {
19 position: relative;
20 padding: .2em 0; }
21
22 .ui-datepicker .ui-datepicker-prev,
23 .ui-datepicker .ui-datepicker-next {
24 position: absolute;
25 top: 2px;
26 width: 1.8em;
27 height: 1.8em; }
28
29 .ui-datepicker .ui-datepicker-prev-hover,
30 .ui-datepicker .ui-datepicker-next-hover {
31 top: 1px; }
32
33 .ui-datepicker .ui-datepicker-prev {
34 right: 2px; }
35
36 .ui-datepicker .ui-datepicker-next {
37 left: 2px; }
38
39 .ui-datepicker .ui-datepicker-prev-hover {
40 right: 1px; }
41
42 .ui-datepicker .ui-datepicker-next-hover {
43 left: 1px; }
44
45 .ui-datepicker .ui-datepicker-prev span,
46 .ui-datepicker .ui-datepicker-next span {
47 display: block;
48 position: absolute;
49 right: 50%;
50 margin-right: -8px;
51 top: 50%;
52 margin-top: -8px; }
53
54 .ui-datepicker .ui-datepicker-title {
55 margin: 0 2.3em;
56 line-height: 1.8em;
57 text-align: center; }
58
59 .ui-datepicker .ui-datepicker-title select {
60 font-size: 1em;
61 margin: 1px 0; }
62
63 .ui-datepicker select.ui-datepicker-month,
64 .ui-datepicker select.ui-datepicker-year {
65 width: 45%; }
66
67 .ui-datepicker table {
68 width: 100%;
69 font-size: .9em;
70 border-collapse: collapse;
71 margin: 0 0 .4em; }
72
73 .ui-datepicker th {
74 padding: .7em .3em;
75 text-align: center;
76 font-weight: bold;
77 border: 0; }
78
79 .ui-datepicker td {
80 border: 0;
81 padding: 1px; }
82
83 .ui-datepicker td span,
84 .ui-datepicker td a {
85 display: block;
86 padding: .2em;
87 text-align: center;
88 text-decoration: none; }
89
90 .ui-datepicker .ui-datepicker-buttonpane {
91 background-image: none;
92 margin: .7em 0 0 0;
93 padding: 0 .2em;
94 border-right: 0;
95 border-left: 0;
96 border-bottom: 0; }
97
98 .ui-datepicker .ui-datepicker-buttonpane button {
99 float: left;
100 margin: .5em .2em .4em;
101 cursor: pointer;
102 padding: .2em .6em .3em .6em;
103 width: auto;
104 overflow: visible; }
105
106 .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
107 float: right; }
108
109 /* with multiple calendars */
110 .ui-datepicker.ui-datepicker-multi {
111 width: auto; }
112
113 .ui-datepicker-multi .ui-datepicker-group {
114 float: right; }
115
116 .ui-datepicker-multi .ui-datepicker-group table {
117 width: 95%;
118 margin: 0 auto .4em; }
119
120 .ui-datepicker-multi-2 .ui-datepicker-group {
121 width: 50%; }
122
123 .ui-datepicker-multi-3 .ui-datepicker-group {
124 width: 33.3%; }
125
126 .ui-datepicker-multi-4 .ui-datepicker-group {
127 width: 25%; }
128
129 .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
130 .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
131 border-right-width: 0; }
132
133 .ui-datepicker-multi .ui-datepicker-buttonpane {
134 clear: right; }
135
136 .ui-datepicker-row-break {
137 clear: both;
138 width: 100%;
139 font-size: 0; }
140
141 /* RTL support */
142 .ui-datepicker-rtl {
143 direction: ltr; }
144
145 .ui-datepicker-rtl .ui-datepicker-prev {
146 left: 2px;
147 right: auto; }
148
149 .ui-datepicker-rtl .ui-datepicker-next {
150 right: 2px;
151 left: auto; }
152
153 .ui-datepicker-rtl .ui-datepicker-prev:hover {
154 left: 1px;
155 right: auto; }
156
157 .ui-datepicker-rtl .ui-datepicker-next:hover {
158 right: 1px;
159 left: auto; }
160
161 .ui-datepicker-rtl .ui-datepicker-buttonpane {
162 clear: left; }
163
164 .ui-datepicker-rtl .ui-datepicker-buttonpane button {
165 float: right; }
166
167 .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
168 .ui-datepicker-rtl .ui-datepicker-group {
169 float: left; }
170
171 .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
172 .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
173 border-left-width: 0;
174 border-right-width: 1px; }
175
176 /* Icons */
177 .ui-datepicker .ui-icon {
178 display: block;
179 text-indent: -99999px;
180 overflow: hidden;
181 background-repeat: no-repeat;
182 right: .5em;
183 top: .3em; }
184
185 .ui-icon {
186 width: 16px;
187 height: 16px; }
188
189 .ui-icon,
190 .ui-widget-content .ui-icon {
191 background-image: url("../img/ui-icons_444444_256x240.png"); }
192
193 .ui-widget-header .ui-icon {
194 background-image: url("../img/ui-icons_444444_256x240.png"); }
195
196 .ui-state-hover .ui-icon,
197 .ui-state-focus .ui-icon,
198 .ui-button:hover .ui-icon,
199 .ui-button:focus .ui-icon {
200 background-image: url("../img/ui-icons_555555_256x240.png"); }
201
202 .ui-state-active .ui-icon,
203 .ui-button:active .ui-icon {
204 background-image: url("../img/ui-icons_ffffff_256x240.png"); }
205
206 .ui-state-highlight .ui-icon,
207 .ui-button .ui-state-highlight.ui-icon {
208 background-image: url("../img/ui-icons_777620_256x240.png"); }
209
210 /* positioning */
211 .ui-icon-blank {
212 background-position: 16px 16px; }
213
214 .ui-icon-caret-1-n {
215 background-position: 100% 0; }
216
217 .ui-icon-caret-1-ne {
218 background-position: -16px 0; }
219
220 .ui-icon-caret-1-e {
221 background-position: -32px 0; }
222
223 .ui-icon-caret-1-se {
224 background-position: -48px 0; }
225
226 .ui-icon-caret-1-s {
227 background-position: -65px 0; }
228
229 .ui-icon-caret-1-sw {
230 background-position: -80px 0; }
231
232 .ui-icon-caret-1-w {
233 background-position: -96px 0; }
234
235 .ui-icon-caret-1-nw {
236 background-position: -112px 0; }
237
238 .ui-icon-caret-2-n-s {
239 background-position: -128px 0; }
240
241 .ui-icon-caret-2-e-w {
242 background-position: -144px 0; }
243
244 .ui-icon-triangle-1-n {
245 background-position: 100% -16px; }
246
247 .ui-icon-triangle-1-ne {
248 background-position: -16px -16px; }
249
250 .ui-icon-triangle-1-e {
251 background-position: -32px -16px; }
252
253 .ui-icon-triangle-1-se {
254 background-position: -48px -16px; }
255
256 .ui-icon-triangle-1-s {
257 background-position: -65px -16px; }
258
259 .ui-icon-triangle-1-sw {
260 background-position: -80px -16px; }
261
262 .ui-icon-triangle-1-w {
263 background-position: -96px -16px; }
264
265 .ui-icon-triangle-1-nw {
266 background-position: -112px -16px; }
267
268 .ui-icon-triangle-2-n-s {
269 background-position: -128px -16px; }
270
271 .ui-icon-triangle-2-e-w {
272 background-position: -144px -16px; }
273
274 .ui-icon-arrow-1-n {
275 background-position: 100% -32px; }
276
277 .ui-icon-arrow-1-ne {
278 background-position: -16px -32px; }
279
280 .ui-icon-arrow-1-e {
281 background-position: -32px -32px; }
282
283 .ui-icon-arrow-1-se {
284 background-position: -48px -32px; }
285
286 .ui-icon-arrow-1-s {
287 background-position: -65px -32px; }
288
289 .ui-icon-arrow-1-sw {
290 background-position: -80px -32px; }
291
292 .ui-icon-arrow-1-w {
293 background-position: -96px -32px; }
294
295 .ui-icon-arrow-1-nw {
296 background-position: -112px -32px; }
297
298 .ui-icon-arrow-2-n-s {
299 background-position: -128px -32px; }
300
301 .ui-icon-arrow-2-ne-sw {
302 background-position: -144px -32px; }
303
304 .ui-icon-arrow-2-e-w {
305 background-position: -160px -32px; }
306
307 .ui-icon-arrow-2-se-nw {
308 background-position: -176px -32px; }
309
310 .ui-icon-arrowstop-1-n {
311 background-position: -192px -32px; }
312
313 .ui-icon-arrowstop-1-e {
314 background-position: -208px -32px; }
315
316 .ui-icon-arrowstop-1-s {
317 background-position: -224px -32px; }
318
319 .ui-icon-arrowstop-1-w {
320 background-position: -240px -32px; }
321
322 .ui-icon-arrowthick-1-n {
323 background-position: 1px -48px; }
324
325 .ui-icon-arrowthick-1-ne {
326 background-position: -16px -48px; }
327
328 .ui-icon-arrowthick-1-e {
329 background-position: -32px -48px; }
330
331 .ui-icon-arrowthick-1-se {
332 background-position: -48px -48px; }
333
334 .ui-icon-arrowthick-1-s {
335 background-position: -64px -48px; }
336
337 .ui-icon-arrowthick-1-sw {
338 background-position: -80px -48px; }
339
340 .ui-icon-arrowthick-1-w {
341 background-position: -96px -48px; }
342
343 .ui-icon-arrowthick-1-nw {
344 background-position: -112px -48px; }
345
346 .ui-icon-arrowthick-2-n-s {
347 background-position: -128px -48px; }
348
349 .ui-icon-arrowthick-2-ne-sw {
350 background-position: -144px -48px; }
351
352 .ui-icon-arrowthick-2-e-w {
353 background-position: -160px -48px; }
354
355 .ui-icon-arrowthick-2-se-nw {
356 background-position: -176px -48px; }
357
358 .ui-icon-arrowthickstop-1-n {
359 background-position: -192px -48px; }
360
361 .ui-icon-arrowthickstop-1-e {
362 background-position: -208px -48px; }
363
364 .ui-icon-arrowthickstop-1-s {
365 background-position: -224px -48px; }
366
367 .ui-icon-arrowthickstop-1-w {
368 background-position: -240px -48px; }
369
370 .ui-icon-arrowreturnthick-1-w {
371 background-position: 100% -64px; }
372
373 .ui-icon-arrowreturnthick-1-n {
374 background-position: -16px -64px; }
375
376 .ui-icon-arrowreturnthick-1-e {
377 background-position: -32px -64px; }
378
379 .ui-icon-arrowreturnthick-1-s {
380 background-position: -48px -64px; }
381
382 .ui-icon-arrowreturn-1-w {
383 background-position: -64px -64px; }
384
385 .ui-icon-arrowreturn-1-n {
386 background-position: -80px -64px; }
387
388 .ui-icon-arrowreturn-1-e {
389 background-position: -96px -64px; }
390
391 .ui-icon-arrowreturn-1-s {
392 background-position: -112px -64px; }
393
394 .ui-icon-arrowrefresh-1-w {
395 background-position: -128px -64px; }
396
397 .ui-icon-arrowrefresh-1-n {
398 background-position: -144px -64px; }
399
400 .ui-icon-arrowrefresh-1-e {
401 background-position: -160px -64px; }
402
403 .ui-icon-arrowrefresh-1-s {
404 background-position: -176px -64px; }
405
406 .ui-icon-arrow-4 {
407 background-position: 100% -80px; }
408
409 .ui-icon-arrow-4-diag {
410 background-position: -16px -80px; }
411
412 .ui-icon-extlink {
413 background-position: -32px -80px; }
414
415 .ui-icon-newwin {
416 background-position: -48px -80px; }
417
418 .ui-icon-refresh {
419 background-position: -64px -80px; }
420
421 .ui-icon-shuffle {
422 background-position: -80px -80px; }
423
424 .ui-icon-transfer-e-w {
425 background-position: -96px -80px; }
426
427 .ui-icon-transferthick-e-w {
428 background-position: -112px -80px; }
429
430 .ui-icon-folder-collapsed {
431 background-position: 100% -96px; }
432
433 .ui-icon-folder-open {
434 background-position: -16px -96px; }
435
436 .ui-icon-document {
437 background-position: -32px -96px; }
438
439 .ui-icon-document-b {
440 background-position: -48px -96px; }
441
442 .ui-icon-note {
443 background-position: -64px -96px; }
444
445 .ui-icon-mail-closed {
446 background-position: -80px -96px; }
447
448 .ui-icon-mail-open {
449 background-position: -96px -96px; }
450
451 .ui-icon-suitcase {
452 background-position: -112px -96px; }
453
454 .ui-icon-comment {
455 background-position: -128px -96px; }
456
457 .ui-icon-person {
458 background-position: -144px -96px; }
459
460 .ui-icon-print {
461 background-position: -160px -96px; }
462
463 .ui-icon-trash {
464 background-position: -176px -96px; }
465
466 .ui-icon-locked {
467 background-position: -192px -96px; }
468
469 .ui-icon-unlocked {
470 background-position: -208px -96px; }
471
472 .ui-icon-bookmark {
473 background-position: -224px -96px; }
474
475 .ui-icon-tag {
476 background-position: -240px -96px; }
477
478 .ui-icon-home {
479 background-position: 100% -112px; }
480
481 .ui-icon-flag {
482 background-position: -16px -112px; }
483
484 .ui-icon-calendar {
485 background-position: -32px -112px; }
486
487 .ui-icon-cart {
488 background-position: -48px -112px; }
489
490 .ui-icon-pencil {
491 background-position: -64px -112px; }
492
493 .ui-icon-clock {
494 background-position: -80px -112px; }
495
496 .ui-icon-disk {
497 background-position: -96px -112px; }
498
499 .ui-icon-calculator {
500 background-position: -112px -112px; }
501
502 .ui-icon-zoomin {
503 background-position: -128px -112px; }
504
505 .ui-icon-zoomout {
506 background-position: -144px -112px; }
507
508 .ui-icon-search {
509 background-position: -160px -112px; }
510
511 .ui-icon-wrench {
512 background-position: -176px -112px; }
513
514 .ui-icon-gear {
515 background-position: -192px -112px; }
516
517 .ui-icon-heart {
518 background-position: -208px -112px; }
519
520 .ui-icon-star {
521 background-position: -224px -112px; }
522
523 .ui-icon-link {
524 background-position: -240px -112px; }
525
526 .ui-icon-cancel {
527 background-position: 100% -128px; }
528
529 .ui-icon-plus {
530 background-position: -16px -128px; }
531
532 .ui-icon-plusthick {
533 background-position: -32px -128px; }
534
535 .ui-icon-minus {
536 background-position: -48px -128px; }
537
538 .ui-icon-minusthick {
539 background-position: -64px -128px; }
540
541 .ui-icon-close {
542 background-position: -80px -128px; }
543
544 .ui-icon-closethick {
545 background-position: -96px -128px; }
546
547 .ui-icon-key {
548 background-position: -112px -128px; }
549
550 .ui-icon-lightbulb {
551 background-position: -128px -128px; }
552
553 .ui-icon-scissors {
554 background-position: -144px -128px; }
555
556 .ui-icon-clipboard {
557 background-position: -160px -128px; }
558
559 .ui-icon-copy {
560 background-position: -176px -128px; }
561
562 .ui-icon-contact {
563 background-position: -192px -128px; }
564
565 .ui-icon-image {
566 background-position: -208px -128px; }
567
568 .ui-icon-video {
569 background-position: -224px -128px; }
570
571 .ui-icon-script {
572 background-position: -240px -128px; }
573
574 .ui-icon-alert {
575 background-position: 100% -144px; }
576
577 .ui-icon-info {
578 background-position: -16px -144px; }
579
580 .ui-icon-notice {
581 background-position: -32px -144px; }
582
583 .ui-icon-help {
584 background-position: -48px -144px; }
585
586 .ui-icon-check {
587 background-position: -64px -144px; }
588
589 .ui-icon-bullet {
590 background-position: -80px -144px; }
591
592 .ui-icon-radio-on {
593 background-position: -96px -144px; }
594
595 .ui-icon-radio-off {
596 background-position: -112px -144px; }
597
598 .ui-icon-pin-w {
599 background-position: -128px -144px; }
600
601 .ui-icon-pin-s {
602 background-position: -144px -144px; }
603
604 .ui-icon-play {
605 background-position: 100% -160px; }
606
607 .ui-icon-pause {
608 background-position: -16px -160px; }
609
610 .ui-icon-seek-next {
611 background-position: -32px -160px; }
612
613 .ui-icon-seek-prev {
614 background-position: -48px -160px; }
615
616 .ui-icon-seek-end {
617 background-position: -64px -160px; }
618
619 .ui-icon-seek-start {
620 background-position: -80px -160px; }
621
622 /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
623 .ui-icon-seek-first {
624 background-position: -80px -160px; }
625
626 .ui-icon-stop {
627 background-position: -96px -160px; }
628
629 .ui-icon-eject {
630 background-position: -112px -160px; }
631
632 .ui-icon-volume-off {
633 background-position: -128px -160px; }
634
635 .ui-icon-volume-on {
636 background-position: -144px -160px; }
637
638 .ui-icon-power {
639 background-position: 100% -176px; }
640
641 .ui-icon-signal-diag {
642 background-position: -16px -176px; }
643
644 .ui-icon-signal {
645 background-position: -32px -176px; }
646
647 .ui-icon-battery-0 {
648 background-position: -48px -176px; }
649
650 .ui-icon-battery-1 {
651 background-position: -64px -176px; }
652
653 .ui-icon-battery-2 {
654 background-position: -80px -176px; }
655
656 .ui-icon-battery-3 {
657 background-position: -96px -176px; }
658
659 .ui-icon-circle-plus {
660 background-position: 100% -192px; }
661
662 .ui-icon-circle-minus {
663 background-position: -16px -192px; }
664
665 .ui-icon-circle-close {
666 background-position: -32px -192px; }
667
668 .ui-icon-circle-triangle-e {
669 background-position: -48px -192px; }
670
671 .ui-icon-circle-triangle-s {
672 background-position: -64px -192px; }
673
674 .ui-icon-circle-triangle-w {
675 background-position: -80px -192px; }
676
677 .ui-icon-circle-triangle-n {
678 background-position: -96px -192px; }
679
680 .ui-icon-circle-arrow-e {
681 background-position: -112px -192px; }
682
683 .ui-icon-circle-arrow-s {
684 background-position: -128px -192px; }
685
686 .ui-icon-circle-arrow-w {
687 background-position: -144px -192px; }
688
689 .ui-icon-circle-arrow-n {
690 background-position: -160px -192px; }
691
692 .ui-icon-circle-zoomin {
693 background-position: -176px -192px; }
694
695 .ui-icon-circle-zoomout {
696 background-position: -192px -192px; }
697
698 .ui-icon-circle-check {
699 background-position: -208px -192px; }
700
701 .ui-icon-circlesmall-plus {
702 background-position: 100% -208px; }
703
704 .ui-icon-circlesmall-minus {
705 background-position: -16px -208px; }
706
707 .ui-icon-circlesmall-close {
708 background-position: -32px -208px; }
709
710 .ui-icon-squaresmall-plus {
711 background-position: -48px -208px; }
712
713 .ui-icon-squaresmall-minus {
714 background-position: -64px -208px; }
715
716 .ui-icon-squaresmall-close {
717 background-position: -80px -208px; }
718
719 .ui-icon-grip-dotted-vertical {
720 background-position: 100% -224px; }
721
722 .ui-icon-grip-dotted-horizontal {
723 background-position: -16px -224px; }
724
725 .ui-icon-grip-solid-vertical {
726 background-position: -32px -224px; }
727
728 .ui-icon-grip-solid-horizontal {
729 background-position: -48px -224px; }
730
731 .ui-icon-gripsmall-diagonal-se {
732 background-position: -64px -224px; }
733
734 .ui-icon-grip-diagonal-se {
735 background-position: -80px -224px; }
736
737 /* Corner radius */
738 .ui-corner-all,
739 .ui-corner-top,
740 .ui-corner-left,
741 .ui-corner-tl {
742 border-top-right-radius: 3px; }
743
744 .ui-corner-all,
745 .ui-corner-top,
746 .ui-corner-right,
747 .ui-corner-tr {
748 border-top-left-radius: 3px; }
749
750 .ui-corner-all,
751 .ui-corner-bottom,
752 .ui-corner-left,
753 .ui-corner-bl {
754 border-bottom-right-radius: 3px; }
755
756 .ui-corner-all,
757 .ui-corner-bottom,
758 .ui-corner-right,
759 .ui-corner-br {
760 border-bottom-left-radius: 3px; }
761
762 .emr_upload_form .wrapper {
763 margin: 15px 0;
764 padding: 18px;
765 border: 1px solid #ccc; }
766 .emr_upload_form .wrapper .section-header {
767 font-size: 18px;
768 border-bottom: 1px solid #ccc;
769 padding: 6px 0;
770 margin: 0 0 15px 0; }
771 .emr_upload_form .image_chooser.wrapper {
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 label {
782 font-size: 1.2em; }
783 .emr_upload_form .options.wrapper {
784 flex: 1;
785 border: 1px solid #ccc;
786 padding: 15px;
787 margin: 15px 35px 15px 0; }
788 .emr_upload_form .options.wrapper .custom_date .emr_datepicker {
789 width: 150px; }
790 .emr_upload_form .options.wrapper .custom_date .emr_hour, .emr_upload_form .options.wrapper .custom_date .emr_minute {
791 width: 45px; }
792 .emr_upload_form .options.wrapper ul li input {
793 margin-left: 8px; }
794 .emr_upload_form .options.wrapper .option label {
795 vertical-align: top; }
796 .emr_upload_form .options.wrapper .small {
797 font-size: 10px;
798 vertical-align: top;
799 margin-right: 8px; }
800 .emr_upload_form .options.wrapper .custom_date {
801 margin: 8px 25px 0 0;
802 visibility: hidden;
803 opacity: 0; }
804 .emr_upload_form .options.wrapper .custom_date span.field-title {
805 display: inline-block;
806 margin-bottom: 4px;
807 color: #444;
808 font-size: 12px;
809 width: 100%;
810 text-align: right;
811 vertical-align: middle;
812 line-height: 26px; }
813 .emr_upload_form .options.wrapper .custom_date span.field-title::before {
814 font-size: 20px;
815 vertical-align: top;
816 margin-left: 4px; }
817 .emr_upload_form .form_controls.wrapper {
818 clear: both;
819 margin: 8px 0 15px 0;
820 border: 0;
821 padding: 0; }
822 .emr_upload_form .form_controls.wrapper .button {
823 padding-right: 20px;
824 padding-left: 20px; }
825 .emr_upload_form .shortpixel-notice {
826 background: #fff;
827 width: 250px;
828 min-height: 270px;
829 border: 1px solid #ccc;
830 padding: 15px;
831 margin: 0 0 10px;
832 float: left; }
833 .emr_upload_form .shortpixel-notice h3 {
834 line-height: 1.3em; }
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 }
8 #emr-replace-box .previewwrapper img, #emr-showthumbs-box .previewwrapper img {
9 max-width: 100%;
10 }
11 #emr-replace-box .previewwrapper span.label, #emr-showthumbs-box .previewwrapper span.label {
12 font-size: 14px;
13 color: #fff;
14 position: absolute;
15 line-height: 16px;
16 margin-top: -8px;
17 top: 50%;
18 left: 0;
19 right: 0;
20 background: rgba(0, 0, 0, 0.5);
21 text-align: center;
22 padding: 4px 0;
23 }
24
25 /*# sourceMappingURL=edit_attachment.css.map */
1 {"version":3,"sourceRoot":"","sources":["../scss/edit_attachment.scss"],"names":[],"mappings":"AACA;AAGE;EAEE;EACA;EACA;EACA;;AAEA;EAAM;;AACN;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EAAS;EACT;EACA;EACA","file":"edit_attachment.css"}
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 /**
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.6.3
7 * Author: ShortPixel
8 * Author URI: https://shortpixel.com
9 * GitHub Plugin URI: https://github.com/short-pixel-optimizer/enable-media-replace
10 * Text Domain: enable-media-replace
11 * Domain Path: /languages
12 * Dual licensed under the MIT and GPL licenses:
13 * License URI: http://www.opensource.org/licenses/mit-license.php
14 * License URI: http://www.gnu.org/licenses/gpl.html
15 */
16
17 /**
18 * Main Plugin file
19 * Set action hooks and add shortcode
20 *
21 * @author ShortPixel <https://shortpixel.com>
22 * @copyright ShortPixel 2018-2020
23 * @package wordpress
24 * @subpackage enable-media-replace
25 *
26 */
27
28 namespace EnableMediaReplace;
29
30 define('EMR_VERSION', '3.6.3');
31
32 if ( ! defined( 'ABSPATH' ) ) {
33 exit; // Exit if accessed directly.
34 }
35
36 /* Not sure why we define this?
37 if(!defined("S3_UPLOADS_AUTOENABLE")) {
38 define('S3_UPLOADS_AUTOENABLE', true);
39 } */
40
41 if (! defined("EMR_ROOT_FILE")) {
42 define("EMR_ROOT_FILE", __FILE__);
43 }
44
45 if(!defined("SHORTPIXEL_AFFILIATE_CODE")) {
46 define("SHORTPIXEL_AFFILIATE_CODE", 'VKG6LYN28044');
47 }
48
49 /** Usage:
50 * Define in wp-config.php
51 * // User must have this capability to replace all
52 * define('EMR_CAPABILITY' ,'edit_upload_all' );
53 * // User must have first capability to replace all OR second capability to replace only own files
54 * define('EMR_CAPABILITY' ,array('edit_upload_all', 'edit_upload_user') );
55 *
56 *
57 **/
58 if (! defined('EMR_CAPABILITY'))
59 define('EMR_CAPABILITY', false);
60
61 /* if (! defined('EMR_CAPABILITY_USERONLY'))
62 define('EMR_CAPABILITY_USERONLY', false); */
63
64 $plugin_path = plugin_dir_path(EMR_ROOT_FILE);
65
66 require_once($plugin_path . 'build/shortpixel/autoload.php');
67 require_once($plugin_path . 'classes/compat.php');
68 require_once($plugin_path . 'classes/functions.php');
69 require_once($plugin_path . 'classes/replacer.php');
70 require_once($plugin_path . 'classes/uihelper.php');
71 require_once($plugin_path . 'classes/file.php');
72 require_once($plugin_path . 'classes/cache.php');
73 require_once($plugin_path . 'classes/emr-plugin.php');
74 require_once($plugin_path . 'classes/externals.php');
75 require_once($plugin_path . 'classes/external/elementor.php');
76 require_once($plugin_path . 'classes/external/wpbakery.php');
77 require_once($plugin_path . 'classes/external/upsell_installer.php');
78 require_once($plugin_path . 'thumbnail_updater.php');
79
80 $emr_plugin = EnableMediaReplacePlugin::get();
81
82 register_uninstall_hook(__FILE__, '\EnableMediaReplace\emr_uninstall');
83
84 function emr_uninstall()
85 {
86 delete_option('enable_media_replace');
87 delete_option('emr_news');
88 }
1 <?php // Silence is golden
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4 <svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12 width="51.877094mm"
13 height="53.161201mm"
14 viewBox="0 0 51.877094 53.161201"
15 version="1.1"
16 id="svg985"
17 inkscape:version="0.92.3 (2405546, 2018-03-11)"
18 sodipodi:docname="SHORTPIXEL Robot Regular.svg">
19 <defs
20 id="defs979" />
21 <sodipodi:namedview
22 id="base"
23 pagecolor="#ffffff"
24 bordercolor="#666666"
25 borderopacity="1.0"
26 inkscape:pageopacity="0.0"
27 inkscape:pageshadow="2"
28 inkscape:zoom="0.35"
29 inkscape:cx="-407.38638"
30 inkscape:cy="99.20227"
31 inkscape:document-units="mm"
32 inkscape:current-layer="layer1"
33 showgrid="false"
34 fit-margin-top="0"
35 fit-margin-left="0"
36 fit-margin-right="0"
37 fit-margin-bottom="0"
38 inkscape:window-width="1853"
39 inkscape:window-height="1025"
40 inkscape:window-x="67"
41 inkscape:window-y="27"
42 inkscape:window-maximized="1" />
43 <metadata
44 id="metadata982">
45 <rdf:RDF>
46 <cc:Work
47 rdf:about="">
48 <dc:format>image/svg+xml</dc:format>
49 <dc:type
50 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
51 <dc:title></dc:title>
52 </cc:Work>
53 </rdf:RDF>
54 </metadata>
55 <g
56 inkscape:label="Layer 1"
57 inkscape:groupmode="layer"
58 id="layer1"
59 transform="translate(-79.061456,-121.9194)">
60 <g
61 id="g6698"
62 transform="matrix(0.72173333,0,0,0.72173333,220.51847,157.29398)">
63 <g
64 transform="matrix(0.35277777,0,0,-0.35277777,-171.70416,8.601389)"
65 id="g1336">
66 <path
67 inkscape:connector-curvature="0"
68 id="path1338"
69 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
70 d="m 0,0 c 0,0 -4.484,-4.226 -4.484,-14.851 0,-10.625 16.769,-30.625 56.384,-30.625 39.616,0 53.116,13.875 53.116,25.25 0,11.375 -2.792,12.708 -2.792,12.708 z" />
71 </g>
72 <g
73 transform="matrix(0.35277777,0,0,-0.35277777,-170.27428,8.482539)"
74 id="g1340">
75 <path
76 inkscape:connector-curvature="0"
77 id="path1342"
78 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
79 d="m 0,0 -4.086,-0.337 c 0,0 -1.243,-11.309 -1.243,-14.687 0,-7.673 15.443,-27.664 52.565,-27.664 31.872,0 50.935,9.953 50.935,22.099 0,3.253 0,13.985 0,13.985 l -7.591,3.897 z" />
80 </g>
81 <g
82 transform="matrix(0.35277777,0,0,-0.35277777,-170.80208,5.020899)"
83 id="g1344">
84 <path
85 inkscape:connector-curvature="0"
86 id="path1346"
87 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
88 d="m 0,0 c 0,0 -2.59,-1.499 -2.59,-12.169 0,-7.581 15.257,-27.331 51.933,-27.331 31.49,0 50.324,9.833 50.324,21.833 0,14.5 -7.5,17.667 -7.5,17.667 z" />
89 </g>
90 <g
91 transform="matrix(0.35277777,0,0,-0.35277777,-177.76203,-43.276561)"
92 id="g1348">
93 <path
94 inkscape:connector-curvature="0"
95 id="path1350"
96 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
97 d="m 0,0 -28.562,-27.74 v -95.166 l 29.624,-11.75 z" />
98 </g>
99 <g
100 transform="matrix(0.35277777,0,0,-0.35277777,-157.45526,7.534449)"
101 id="g1352">
102 <path
103 inkscape:connector-curvature="0"
104 id="path1354"
105 style="fill:#d7292a;fill-opacity:1;fill-rule:nonzero;stroke:none"
106 d="m 0,0 0.574,7.125 h -38.407 c 0,0 -2.591,-1.499 -2.591,-12.169 0,-2.132 1.207,-5.227 3.758,-8.575 z" />
107 </g>
108 <g
109 transform="matrix(0.35277777,0,0,-0.35277777,-148.37123,8.601389)"
110 id="g1356">
111 <path
112 inkscape:connector-curvature="0"
113 id="path1358"
114 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none"
115 d="m 0,0 c 0,-3.266 -6.375,-5.913 -14.24,-5.913 -7.865,0 -14.24,2.647 -14.24,5.913 0,3.267 6.375,5.913 14.24,5.913 C -6.375,5.913 0,3.267 0,0" />
116 </g>
117 <path
118 inkscape:connector-curvature="0"
119 id="path1360"
120 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
121 d="m -148.37123,5.791719 h -10.04711 v 2.80988 h 10.04711 z" />
122 <g
123 transform="matrix(0.35277777,0,0,-0.35277777,-148.37123,5.791579)"
124 id="g1362">
125 <path
126 inkscape:connector-curvature="0"
127 id="path1364"
128 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none"
129 d="m 0,0 c 0,-3.267 -6.375,-5.913 -14.24,-5.913 -7.865,0 -14.24,2.646 -14.24,5.913 0,3.266 6.375,5.913 14.24,5.913 C -6.375,5.913 0,3.266 0,0" />
130 </g>
131 <path
132 inkscape:connector-curvature="0"
133 id="path1366"
134 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
135 d="m -148.37123,3.903659 h -10.04711 v 1.73461 h 10.04711 z" />
136 <g
137 transform="matrix(0.35277777,0,0,-0.35277777,-150.92887,-44.367981)"
138 id="g1368">
139 <path
140 inkscape:connector-curvature="0"
141 id="path1370"
142 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
143 d="m 0,0 h -68 c -6.6,0 -12,-5.4 -12,-12 v -116 c 0,-6.6 5.4,-12 12,-12 H 0 Z" />
144 </g>
145 <g
146 transform="matrix(0.35277777,0,0,-0.35277777,-128.35109,-44.367981)"
147 id="g1372">
148 <path
149 inkscape:connector-curvature="0"
150 id="path1374"
151 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
152 d="M 0,0 H -64 V -140 H 0 c 6.6,0 12,5.4 12,12 V -12 C 12,-5.4 6.6,0 0,0" />
153 </g>
154 <g
155 transform="matrix(0.35277777,0,0,-0.35277777,-146.69554,-48.380831)"
156 id="g1376">
157 <path
158 inkscape:connector-curvature="0"
159 id="path1378"
160 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
161 d="m 0,0 v -5.5 l 32.648,-4.046 0.227,8.171 z" />
162 </g>
163 <g
164 transform="matrix(0.35277777,0,0,-0.35277777,-153.48651,-47.807571)"
165 id="g1380">
166 <path
167 inkscape:connector-curvature="0"
168 id="path1382"
169 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
170 d="M 0,0 -41.083,3.418 -41.5,-6.666 -0.375,-6.5 Z" />
171 </g>
172 <g
173 transform="matrix(0.35277777,0,0,-0.35277777,-181.97331,-17.909651)"
174 id="g1384">
175 <path
176 inkscape:connector-curvature="0"
177 id="path1386"
178 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
179 d="m 0,0 c 0,-15.33 -7.219,-27.758 -16.125,-27.758 -8.906,0 -16.125,12.428 -16.125,27.758 0,15.33 7.219,27.758 16.125,27.758 C -7.219,27.758 0,15.33 0,0" />
180 </g>
181 <g
182 transform="matrix(0.35277777,0,0,-0.35277777,-187.5466,-26.596801)"
183 id="g1388">
184 <path
185 inkscape:connector-curvature="0"
186 id="path1390"
187 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
188 d="m 0,0 c -0.108,0 -5.711,0.023 -5.82,0.023 -6.93,0 -12.548,-11.037 -12.548,-24.636 0,-13.6 5.618,-24.631 12.548,-24.631 0.109,0 5.712,-0.012 5.82,-0.012 6.931,0 12.548,11.027 12.548,24.628 C 12.548,-11.027 6.931,0 0,0" />
189 </g>
190 <g
191 transform="matrix(0.35277777,0,0,-0.35277777,-185.23651,-17.909651)"
192 id="g1392">
193 <path
194 inkscape:connector-curvature="0"
195 id="path1394"
196 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
197 d="m 0,0 c 0,-13.6 -5.578,-24.625 -12.458,-24.625 -6.881,0 -12.459,11.025 -12.459,24.625 0,13.6 5.578,24.625 12.459,24.625 C -5.578,24.625 0,13.6 0,0" />
198 </g>
199 <g
200 transform="matrix(0.35277777,0,0,-0.35277777,-189.55803,-18.130141)"
201 id="g1396">
202 <path
203 inkscape:connector-curvature="0"
204 id="path1398"
205 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
206 d="m 0,0 c 0,-3.383 -1.679,-6.125 -3.75,-6.125 -2.071,0 -3.75,2.742 -3.75,6.125 0,3.383 1.679,6.125 3.75,6.125 C -1.679,6.125 0,3.383 0,0" />
207 </g>
208 <g
209 transform="matrix(0.35277777,0,0,-0.35277777,-191.45422,-20.290901)"
210 id="g1400">
211 <path
212 inkscape:connector-curvature="0"
213 id="path1402"
214 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
215 d="m 0,0 h -10.875 c -1.104,0 -2,-2.742 -2,-6.125 0,-3.383 0.896,-6.125 2,-6.125 H 0 c 1.104,0 2,2.742 2,6.125 C 2,-2.742 1.104,0 0,0" />
216 </g>
217 <g
218 transform="matrix(0.35277777,0,0,-0.35277777,-139.99276,-31.551531)"
219 id="g1404">
220 <path
221 inkscape:connector-curvature="0"
222 id="path1406"
223 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
224 d="m 0,0 c -1.042,0.008 -4.266,0.84 -4.349,0.832 -12.234,-1.086 -20.401,-9.461 -20.401,-20.127 0,-10.666 8.908,-19.326 19.896,-19.326 0.084,0 3.812,-0.002 4.854,-0.002 z" />
225 </g>
226 <g
227 transform="matrix(0.35277777,0,0,-0.35277777,-133.23124,-24.943161)"
228 id="g1408">
229 <path
230 inkscape:connector-curvature="0"
231 id="path1410"
232 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
233 d="m 0,0 c 0,-10.988 -8.908,-19.896 -19.896,-19.896 -10.989,0 -19.897,8.908 -19.897,19.896 0,10.988 8.908,19.896 19.897,19.896 C -8.908,19.896 0,10.988 0,0" />
234 </g>
235 <g
236 transform="matrix(0.35277777,0,0,-0.35277777,-135.0387,-25.075451)"
237 id="g1412">
238 <path
239 inkscape:connector-curvature="0"
240 id="path1414"
241 style="fill:#b4d9e8;fill-opacity:1;fill-rule:nonzero;stroke:none"
242 d="m 0,0 c 0,-7.951 -6.446,-14.398 -14.398,-14.398 -7.952,0 -14.398,6.447 -14.398,14.398 0,7.951 6.446,14.398 14.398,14.398 C -6.446,14.398 0,7.951 0,0" />
243 </g>
244 <g
245 transform="matrix(0.35277777,0,0,-0.35277777,-137.49128,-25.031351)"
246 id="g1416">
247 <path
248 inkscape:connector-curvature="0"
249 id="path1418"
250 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
251 d="m 0,0 c 0,-4.182 -3.39,-7.57 -7.571,-7.57 -4.181,0 -7.571,3.388 -7.571,7.57 0,4.182 3.39,7.57 7.571,7.57 C -3.39,7.57 0,4.182 0,0" />
252 </g>
253 <g
254 transform="matrix(0.35277777,0,0,-0.35277777,-159.39554,-31.551531)"
255 id="g1420">
256 <path
257 inkscape:connector-curvature="0"
258 id="path1422"
259 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
260 d="m 0,0 c -1.042,0.008 -4.266,0.84 -4.349,0.832 -12.234,-1.086 -20.401,-9.461 -20.401,-20.127 0,-10.666 8.908,-19.326 19.896,-19.326 0.084,0 3.812,-0.002 4.854,-0.002 z" />
261 </g>
262 <g
263 transform="matrix(0.35277777,0,0,-0.35277777,-152.63402,-24.943161)"
264 id="g1424">
265 <path
266 inkscape:connector-curvature="0"
267 id="path1426"
268 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
269 d="m 0,0 c 0,-10.988 -8.908,-19.896 -19.896,-19.896 -10.989,0 -19.897,8.908 -19.897,19.896 0,10.988 8.908,19.896 19.897,19.896 C -8.908,19.896 0,10.988 0,0" />
270 </g>
271 <g
272 transform="matrix(0.35277777,0,0,-0.35277777,-154.44148,-25.075451)"
273 id="g1428">
274 <path
275 inkscape:connector-curvature="0"
276 id="path1430"
277 style="fill:#b4d9e8;fill-opacity:1;fill-rule:nonzero;stroke:none"
278 d="m 0,0 c 0,-7.951 -6.446,-14.398 -14.398,-14.398 -7.952,0 -14.398,6.447 -14.398,14.398 0,7.951 6.446,14.398 14.398,14.398 C -6.446,14.398 0,7.951 0,0" />
279 </g>
280 <g
281 transform="matrix(0.35277777,0,0,-0.35277777,-156.89406,-25.031351)"
282 id="g1432">
283 <path
284 inkscape:connector-curvature="0"
285 id="path1434"
286 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
287 d="m 0,0 c 0,-4.182 -3.39,-7.57 -7.571,-7.57 -4.181,0 -7.571,3.388 -7.571,7.57 0,4.182 3.39,7.57 7.571,7.57 C -3.39,7.57 0,4.182 0,0" />
288 </g>
289 <g
290 transform="matrix(0.35277777,0,0,-0.35277777,-156.80498,-7.286001)"
291 id="g1436">
292 <path
293 inkscape:connector-curvature="0"
294 id="path1438"
295 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
296 d="m 0,0 c 0.07,-4.725 -3.702,-8.61 -8.426,-8.68 -4.724,-0.07 -8.609,3.702 -8.679,8.427 -0.07,4.723 3.702,8.608 8.426,8.678 C -3.956,8.495 -0.07,4.724 0,0" />
297 </g>
298 <g
299 transform="matrix(0.35277777,0,0,-0.35277777,-138.27367,-7.560241)"
300 id="g1440">
301 <path
302 inkscape:connector-curvature="0"
303 id="path1442"
304 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
305 d="m 0,0 c 0.07,-4.724 -3.702,-8.61 -8.426,-8.68 -4.724,-0.07 -8.609,3.702 -8.679,8.427 -0.07,4.724 3.702,8.609 8.425,8.679 C -3.956,8.495 -0.07,4.724 0,0" />
306 </g>
307 <g
308 transform="matrix(0.35277777,0,0,-0.35277777,-139.38005,-5.182771)"
309 id="g1444">
310 <path
311 inkscape:connector-curvature="0"
312 id="path1446"
313 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
314 d="m 0,0 c 0,0 -11.162,-12.342 -32.756,-12.661 -18.804,-0.278 -31.421,12.65 -31.421,12.65 l 12.321,11.853 c 0,0 9.5,-8.029 19.708,-7.822 13.944,0.28 20.337,8.343 20.337,8.343 z" />
315 </g>
316 <g
317 transform="matrix(0.35277777,0,0,-0.35277777,-156.51906,-8.281291)"
318 id="g1448">
319 <path
320 inkscape:connector-curvature="0"
321 id="path1450"
322 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
323 d="m 0,0 c 0,-4.788 -3.881,-8.67 -8.668,-8.67 -4.788,0 -8.669,3.882 -8.669,8.67 0,4.787 3.881,8.668 8.669,8.668 C -3.881,8.668 0,4.787 0,0" />
324 </g>
325 <g
326 transform="matrix(0.35277777,0,0,-0.35277777,-137.73674,-8.281291)"
327 id="g1452">
328 <path
329 inkscape:connector-curvature="0"
330 id="path1454"
331 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
332 d="m 0,0 c 0,-4.788 -3.881,-8.67 -8.668,-8.67 -4.789,0 -8.669,3.882 -8.669,8.67 0,4.787 3.88,8.668 8.669,8.668 C -3.881,8.668 0,4.787 0,0" />
333 </g>
334 <g
335 transform="matrix(0.35277777,0,0,-0.35277777,-138.89343,-5.888321)"
336 id="g1456">
337 <path
338 inkscape:connector-curvature="0"
339 id="path1458"
340 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
341 d="m 0,0 c 0,0 -11.496,-12.338 -33.383,-12.338 -19.058,0 -31.65,13.291 -31.65,13.291 l 12.663,11.824 c 0,0 9.507,-8.277 19.853,-8.222 14.135,0.076 20.734,8.15 20.734,8.15 z" />
342 </g>
343 <path
344 inkscape:connector-curvature="0"
345 id="path1460"
346 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
347 d="m -149.10854,-3.483861 h -1.47496 v -1.88701 h 1.47496 z" />
348 <g
349 transform="matrix(0.35277777,0,0,-0.35277777,-151.67284,-3.580141)"
350 id="g1462">
351 <path
352 inkscape:connector-curvature="0"
353 id="path1464"
354 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
355 d="M 0,0 -4.076,0.926 -2.893,6.143 1.185,5.217 Z" />
356 </g>
357 <g
358 transform="matrix(0.35277777,0,0,-0.35277777,-154.05857,-4.178521)"
359 id="g1466">
360 <path
361 inkscape:connector-curvature="0"
362 id="path1468"
363 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
364 d="m 0,0 -3.894,1.521 1.946,4.982 3.894,-1.52 z" />
365 </g>
366 <g
367 transform="matrix(0.35277777,0,0,-0.35277777,-156.28908,-5.076651)"
368 id="g1470">
369 <path
370 inkscape:connector-curvature="0"
371 id="path1472"
372 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
373 d="M 0,0 -3.727,1.894 -1.304,6.662 2.423,4.769 Z" />
374 </g>
375 <g
376 transform="matrix(0.35277777,0,0,-0.35277777,-158.47725,-6.252141)"
377 id="g1474">
378 <path
379 inkscape:connector-curvature="0"
380 id="path1476"
381 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
382 d="M 0,0 -3.383,2.456 -0.241,6.783 3.142,4.327 Z" />
383 </g>
384 <path
385 inkscape:connector-curvature="0"
386 id="path1478"
387 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
388 d="m -150.5835,-3.483861 h 1.47496 v -1.88701 h -1.47496 z" />
389 <g
390 transform="matrix(0.35277777,0,0,-0.35277777,-148.01898,-3.580141)"
391 id="g1480">
392 <path
393 inkscape:connector-curvature="0"
394 id="path1482"
395 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
396 d="M 0,0 4.076,0.926 2.893,6.143 -1.185,5.217 Z" />
397 </g>
398 <g
399 transform="matrix(0.35277777,0,0,-0.35277777,-145.63325,-4.178521)"
400 id="g1484">
401 <path
402 inkscape:connector-curvature="0"
403 id="path1486"
404 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
405 d="M 0,0 3.894,1.521 1.948,6.503 -1.946,4.983 Z" />
406 </g>
407 <g
408 transform="matrix(0.35277777,0,0,-0.35277777,-143.40271,-5.076651)"
409 id="g1488">
410 <path
411 inkscape:connector-curvature="0"
412 id="path1490"
413 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
414 d="M 0,0 3.727,1.894 1.304,6.662 -2.423,4.769 Z" />
415 </g>
416 <g
417 transform="matrix(0.35277777,0,0,-0.35277777,-141.21457,-6.252141)"
418 id="g1492">
419 <path
420 inkscape:connector-curvature="0"
421 id="path1494"
422 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
423 d="M 0,0 3.383,2.456 0.241,6.783 -3.142,4.327 Z" />
424 </g>
425 <g
426 transform="matrix(0.35277777,0,0,-0.35277777,-132.42508,-42.839041)"
427 id="g1496">
428 <path
429 inkscape:connector-curvature="0"
430 id="path1498"
431 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
432 d="m 0,0 v -3.166 c 0,0 6.917,0.75 11.333,-3.666 4.416,-4.417 4,-10.668 4,-10.668 h 3 c 0,0 1.334,9.668 -3.833,14.168 C 9.333,1.168 0,0 0,0" />
433 </g>
434 </g>
435 </g>
436 </svg>
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4 <svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12 width="52.027439mm"
13 height="53.148357mm"
14 viewBox="0 0 52.027439 53.148357"
15 version="1.1"
16 id="svg4043"
17 inkscape:version="0.92.3 (2405546, 2018-03-11)"
18 sodipodi:docname="SHORTPIXEL Robot Winky.svg">
19 <defs
20 id="defs4037" />
21 <sodipodi:namedview
22 id="base"
23 pagecolor="#ffffff"
24 bordercolor="#666666"
25 borderopacity="1.0"
26 inkscape:pageopacity="0.0"
27 inkscape:pageshadow="2"
28 inkscape:zoom="0.35"
29 inkscape:cx="-1798.8233"
30 inkscape:cy="486.15214"
31 inkscape:document-units="mm"
32 inkscape:current-layer="layer1"
33 showgrid="false"
34 fit-margin-top="0"
35 fit-margin-left="0"
36 fit-margin-right="0"
37 fit-margin-bottom="0"
38 inkscape:window-width="1853"
39 inkscape:window-height="1025"
40 inkscape:window-x="67"
41 inkscape:window-y="27"
42 inkscape:window-maximized="1" />
43 <metadata
44 id="metadata4040">
45 <rdf:RDF>
46 <cc:Work
47 rdf:about="">
48 <dc:format>image/svg+xml</dc:format>
49 <dc:type
50 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
51 <dc:title></dc:title>
52 </cc:Work>
53 </rdf:RDF>
54 </metadata>
55 <g
56 inkscape:label="Layer 1"
57 inkscape:groupmode="layer"
58 id="layer1"
59 transform="translate(-447.21247,-224.31273)">
60 <g
61 id="g6944"
62 transform="matrix(-0.53078769,0,0,0.53078769,489.41328,252.13805)">
63 <g
64 transform="matrix(0.35277777,0,0,-0.35277777,46.460542,25.88487)"
65 id="g997">
66 <path
67 inkscape:connector-curvature="0"
68 id="path999"
69 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
70 d="m 0,0 c 0,0 6.101,-5.748 6.101,-20.201 0,-14.454 -22.813,-41.661 -76.704,-41.661 -53.889,0 -72.254,18.875 -72.254,34.348 0,15.475 3.796,17.287 3.796,17.287 z" />
71 </g>
72 <g
73 transform="matrix(0.35277777,0,0,-0.35277777,44.515462,25.72298)"
74 id="g1001">
75 <path
76 inkscape:connector-curvature="0"
77 id="path1003"
78 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
79 d="m 0,0 5.559,-0.459 c 0,0 1.689,-15.385 1.689,-19.979 0,-10.438 -21.007,-37.632 -71.505,-37.632 -43.358,0 -69.29,13.539 -69.29,30.062 v 19.024 l 10.327,5.301 z" />
80 </g>
81 <g
82 transform="matrix(0.35277777,0,0,-0.35277777,45.233402,21.01421)"
83 id="g1005">
84 <path
85 inkscape:connector-curvature="0"
86 id="path1007"
87 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
88 d="m 0,0 c 0,0 3.523,-2.039 3.523,-16.554 0,-10.312 -20.755,-37.179 -70.647,-37.179 -42.837,0 -68.458,13.377 -68.458,29.7 0,19.725 10.202,24.033 10.202,24.033 z" />
89 </g>
90 <g
91 transform="matrix(0.35277777,0,0,-0.35277777,54.701222,-44.619004)"
92 id="g1009">
93 <path
94 inkscape:connector-curvature="0"
95 id="path1011"
96 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
97 d="m 0,0 38.855,-37.736 v -129.459 l -40.3,-15.984 z" />
98 </g>
99 <g
100 transform="matrix(0.35277777,0,0,-0.35277777,27.077062,24.43347)"
101 id="g1013">
102 <path
103 inkscape:connector-curvature="0"
104 id="path1015"
105 style="fill:#d7292a;fill-opacity:1;fill-rule:nonzero;stroke:none"
106 d="m 0,0 -0.781,9.692 h 52.248 c 0,0 3.523,-2.039 3.523,-16.553 0,-2.9 -1.641,-7.112 -5.111,-11.665 z" />
107 </g>
108 <g
109 transform="matrix(0.35277777,0,0,-0.35277777,14.719852,25.9531)"
110 id="g1017">
111 <path
112 inkscape:connector-curvature="0"
113 id="path1019"
114 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none"
115 d="m 0,0 c 0,-4.442 8.672,-8.044 19.371,-8.044 10.699,0 19.372,3.602 19.372,8.044 0,4.444 -8.673,8.044 -19.372,8.044 C 8.672,8.044 0,4.444 0,0" />
116 </g>
117 <path
118 inkscape:connector-curvature="0"
119 id="path1021"
120 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
121 d="m 14.719822,22.13075 h 13.66767 v 3.82235 h -13.66767 z" />
122 <g
123 transform="matrix(0.35277777,0,0,-0.35277777,14.719852,22.13075)"
124 id="g1023">
125 <path
126 inkscape:connector-curvature="0"
127 id="path1025"
128 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none"
129 d="m 0,0 c 0,-4.443 8.672,-8.044 19.371,-8.044 10.699,0 19.372,3.601 19.372,8.044 0,4.442 -8.673,8.044 -19.372,8.044 C 8.672,8.044 0,4.442 0,0" />
130 </g>
131 <path
132 inkscape:connector-curvature="0"
133 id="path1027"
134 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
135 d="m 14.719822,19.56253 h 13.66767 v 2.56822 h -13.66767 z" />
136 <g
137 transform="matrix(0.35277777,0,0,-0.35277777,17.822852,-46.01357)"
138 id="g1029">
139 <path
140 inkscape:connector-curvature="0"
141 id="path1031"
142 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
143 d="M 0,0 H 93.569 C 102.547,0 109,-7.092 109,-16.069 v -157.8 C 109,-182.847 102.547,-190 93.569,-190 H 0 Z" />
144 </g>
145 <g
146 transform="matrix(0.35277777,0,0,-0.35277777,-12.514658,-46.01357)"
147 id="g1033">
148 <path
149 inkscape:connector-curvature="0"
150 id="path1035"
151 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
152 d="M 0,0 H 85.996 V -190 H 0 c -8.978,0 -17.004,7.153 -17.004,16.131 v 157.8 C -17.004,-7.092 -8.978,0 0,0" />
153 </g>
154 <g
155 transform="matrix(0.35277777,0,0,-0.35277777,12.178412,-51.562235)"
156 id="g1037">
157 <path
158 inkscape:connector-curvature="0"
159 id="path1039"
160 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
161 d="m 0,0 v -7.481 l -44.041,-5.504 -0.494,11.115 z" />
162 </g>
163 <g
164 transform="matrix(0.35277777,0,0,-0.35277777,21.678252,-50.782631)"
165 id="g1041">
166 <path
167 inkscape:connector-curvature="0"
168 id="path1043"
169 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
170 d="M 0,0 55.889,4.649 56.454,-9.068 0.51,-8.843 Z" />
171 </g>
172 <g
173 transform="matrix(0.35277777,0,0,-0.35277777,60.430082,-10.1112)"
174 id="g1045">
175 <path
176 inkscape:connector-curvature="0"
177 id="path1047"
178 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
179 d="m 0,0 c 0,-20.854 9.82,-37.761 21.936,-37.761 12.115,0 21.935,16.907 21.935,37.761 0,20.854 -9.82,37.76 -21.935,37.76 C 9.82,37.76 0,20.854 0,0" />
180 </g>
181 <g
182 transform="matrix(0.35277777,0,0,-0.35277777,68.012052,-21.92855)"
183 id="g1049">
184 <path
185 inkscape:connector-curvature="0"
186 id="path1051"
187 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
188 d="m 0,0 c 0.146,0 7.769,0.032 7.916,0.032 9.428,0 17.069,-15.014 17.069,-33.514 0,-18.5 -7.641,-33.506 -17.069,-33.506 -0.147,0 -7.77,-0.017 -7.916,-0.017 -9.43,0 -17.071,15.001 -17.071,33.503 C -17.071,-15.001 -9.43,0 0,0" />
189 </g>
190 <g
191 transform="matrix(0.35277777,0,0,-0.35277777,64.869082,-10.1112)"
192 id="g1053">
193 <path
194 inkscape:connector-curvature="0"
195 id="path1055"
196 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
197 d="m 0,0 c 0,-18.5 7.588,-33.499 16.947,-33.499 9.361,0 16.948,14.999 16.948,33.499 0,18.5 -7.587,33.498 -16.948,33.498 C 7.588,33.498 0,18.5 0,0" />
198 </g>
199 <g
200 transform="matrix(0.35277777,0,0,-0.35277777,70.747772,-10.41092)"
201 id="g1057">
202 <path
203 inkscape:connector-curvature="0"
204 id="path1059"
205 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
206 d="m 0,0 c 0,-4.602 2.285,-8.332 5.102,-8.332 2.816,0 5.101,3.73 5.101,8.332 0,4.603 -2.285,8.333 -5.101,8.333 C 2.285,8.333 0,4.603 0,0" />
207 </g>
208 <g
209 transform="matrix(0.35277777,0,0,-0.35277777,73.327462,-13.35062)"
210 id="g1061">
211 <path
212 inkscape:connector-curvature="0"
213 id="path1063"
214 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
215 d="m 0,0 h 14.793 c 1.503,0 2.721,-3.73 2.721,-8.333 0,-4.602 -1.218,-8.332 -2.721,-8.332 H 0 c -1.503,0 -2.721,3.73 -2.721,8.332 C -2.721,-3.73 -1.503,0 0,0" />
216 </g>
217 <g
218 transform="matrix(0.35277777,0,0,-0.35277777,29.464522,-28.6689)"
219 id="g1065">
220 <path
221 inkscape:connector-curvature="0"
222 id="path1067"
223 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
224 d="m 0,0 c 3,0.011 6.16,1.143 6.273,1.132 16.645,-1.478 27.931,-12.87 27.931,-27.38 0,-14.51 -12.386,-26.29 -27.334,-26.29 -0.114,0 -3.87,-0.003 -6.87,-0.003 z" />
225 </g>
226 <g
227 transform="matrix(0.35277777,0,0,-0.35277777,20.518992,-19.67927)"
228 id="g1069">
229 <path
230 inkscape:connector-curvature="0"
231 id="path1071"
232 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
233 d="m 0,0 c 0,-14.948 12.117,-27.066 27.065,-27.066 14.949,0 27.067,12.118 27.067,27.066 0,14.947 -12.118,27.065 -27.067,27.065 C 12.117,27.065 0,14.947 0,0" />
234 </g>
235 <g
236 transform="matrix(0.35277777,0,0,-0.35277777,22.977392,-19.85908)"
237 id="g1073">
238 <path
239 inkscape:connector-curvature="0"
240 id="path1075"
241 style="fill:#b4d9e8;fill-opacity:1;fill-rule:nonzero;stroke:none"
242 d="m 0,0 c 0,-10.816 8.77,-19.587 19.587,-19.587 10.816,0 19.585,8.771 19.585,19.587 0,10.816 -8.769,19.587 -19.585,19.587 C 8.77,19.587 0,10.816 0,0" />
243 </g>
244 <g
245 transform="matrix(0.35277777,0,0,-0.35277777,26.313652,-19.79915)"
246 id="g1077">
247 <path
248 inkscape:connector-curvature="0"
249 id="path1079"
250 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
251 d="m 0,0 c 0,-5.688 4.611,-10.299 10.3,-10.299 5.686,0 10.298,4.611 10.298,10.299 0,5.688 -4.612,10.298 -10.298,10.298 C 4.611,10.298 0,5.688 0,0" />
252 </g>
253 <g
254 transform="matrix(0.35277777,0,0,-0.35277777,26.192362,4.34062)"
255 id="g1081">
256 <path
257 inkscape:connector-curvature="0"
258 id="path1083"
259 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
260 d="M 0,0 C -0.095,-6.427 5.036,-11.713 11.462,-11.808 17.889,-11.903 23.174,-6.771 23.27,-0.344 23.365,6.08 18.232,11.366 11.807,11.461 5.381,11.557 0.096,6.426 0,0" />
261 </g>
262 <g
263 transform="matrix(0.35277777,0,0,-0.35277777,0.9835719,3.96753)"
264 id="g1085">
265 <path
266 inkscape:connector-curvature="0"
267 id="path1087"
268 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
269 d="M 0,0 C -0.096,-6.426 5.035,-11.713 11.462,-11.808 17.889,-11.903 23.174,-6.771 23.27,-0.345 23.365,6.081 18.233,11.367 11.808,11.462 5.38,11.556 0.096,6.426 0,0" />
270 </g>
271 <g
272 transform="matrix(0.35277777,0,0,-0.35277777,2.4887319,7.20179)"
273 id="g1089">
274 <path
275 inkscape:connector-curvature="0"
276 id="path1091"
277 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
278 d="m 0,0 c 0,0 15.184,-16.789 44.56,-17.224 25.579,-0.379 42.743,17.209 42.743,17.209 L 70.541,16.109 c 0,0 -12.923,-10.922 -26.808,-10.641 -18.97,0.382 -27.667,11.35 -27.667,11.35 z" />
279 </g>
280 <g
281 transform="matrix(0.35277777,0,0,-0.35277777,25.803432,2.9867)"
282 id="g1093">
283 <path
284 inkscape:connector-curvature="0"
285 id="path1095"
286 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
287 d="m 0,0 c 0,-6.514 5.279,-11.794 11.792,-11.794 6.514,0 11.793,5.28 11.793,11.794 0,6.512 -5.279,11.791 -11.793,11.791 C 5.279,11.791 0,6.512 0,0" />
288 </g>
289 <g
290 transform="matrix(0.35277777,0,0,-0.35277777,0.2535719,2.9867)"
291 id="g1097">
292 <path
293 inkscape:connector-curvature="0"
294 id="path1099"
295 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
296 d="m 0,0 c 0,-6.514 5.279,-11.794 11.791,-11.794 6.514,0 11.793,5.28 11.793,11.794 0,6.512 -5.279,11.791 -11.793,11.791 C 5.279,11.791 0,6.512 0,0" />
297 </g>
298 <g
299 transform="matrix(0.35277777,0,0,-0.35277777,1.8265719,6.24199)"
300 id="g1101">
301 <path
302 inkscape:connector-curvature="0"
303 id="path1103"
304 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
305 d="m 0,0 c 0,0 15.639,-16.784 45.412,-16.784 25.925,0 43.055,18.081 43.055,18.081 L 71.241,17.382 c 0,0 -12.932,-11.261 -27.007,-11.186 C 25.006,6.3 16.028,17.283 16.028,17.283 Z" />
306 </g>
307 <path
308 inkscape:connector-curvature="0"
309 id="path1105"
310 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
311 d="m 15.722772,9.51259 h 2.00624 V 6.94578 h -2.00624 z" />
312 <g
313 transform="matrix(0.35277777,0,0,-0.35277777,19.211212,9.38185)"
314 id="g1107">
315 <path
316 inkscape:connector-curvature="0"
317 id="path1109"
318 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
319 d="M 0,0 5.545,1.259 3.936,8.355 -1.612,7.097 Z" />
320 </g>
321 <g
322 transform="matrix(0.35277777,0,0,-0.35277777,22.456162,8.56778)"
323 id="g1111">
324 <path
325 inkscape:connector-curvature="0"
326 id="path1113"
327 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
328 d="M 0,0 5.298,2.069 2.65,8.846 -2.646,6.778 Z" />
329 </g>
330 <g
331 transform="matrix(0.35277777,0,0,-0.35277777,25.490622,7.34615)"
332 id="g1115">
333 <path
334 inkscape:connector-curvature="0"
335 id="path1117"
336 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
337 d="M 0,0 5.069,2.576 1.773,9.063 -3.296,6.487 Z" />
338 </g>
339 <g
340 transform="matrix(0.35277777,0,0,-0.35277777,28.467182,5.74694)"
341 id="g1119">
342 <path
343 inkscape:connector-curvature="0"
344 id="path1121"
345 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
346 d="M 0,0 4.602,3.341 0.328,9.227 -4.273,5.886 Z" />
347 </g>
348 <path
349 inkscape:connector-curvature="0"
350 id="path1123"
351 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
352 d="m 17.728662,9.51259 h -2.00625 V 6.94578 h 2.00625 z" />
353 <g
354 transform="matrix(0.35277777,0,0,-0.35277777,14.240642,9.38185)"
355 id="g1125">
356 <path
357 inkscape:connector-curvature="0"
358 id="path1127"
359 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
360 d="M 0,0 -5.545,1.259 -3.936,8.355 1.61,7.097 Z" />
361 </g>
362 <g
363 transform="matrix(0.35277777,0,0,-0.35277777,10.995012,8.56778)"
364 id="g1129">
365 <path
366 inkscape:connector-curvature="0"
367 id="path1131"
368 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
369 d="M 0,0 -5.297,2.069 -2.649,8.846 2.648,6.778 Z" />
370 </g>
371 <g
372 transform="matrix(0.35277777,0,0,-0.35277777,7.9609119,7.34615)"
373 id="g1133">
374 <path
375 inkscape:connector-curvature="0"
376 id="path1135"
377 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
378 d="M 0,0 -5.069,2.576 -1.775,9.063 3.296,6.487 Z" />
379 </g>
380 <g
381 transform="matrix(0.35277777,0,0,-0.35277777,4.9840019,5.74694)"
382 id="g1137">
383 <path
384 inkscape:connector-curvature="0"
385 id="path1139"
386 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
387 d="M 0,0 -4.602,3.341 -0.327,9.227 4.274,5.886 Z" />
388 </g>
389 <g
390 transform="matrix(0.35277777,0,0,-0.35277777,-6.9722081,-44.023691)"
391 id="g1141">
392 <path
393 inkscape:connector-curvature="0"
394 id="path1143"
395 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
396 d="m 0,0 v -4.307 c 0,0 -9.411,1.02 -15.418,-4.987 -6.008,-6.009 -5.441,-14.512 -5.441,-14.512 h -4.081 c 0,0 -1.816,13.152 5.214,19.273 C -12.697,1.589 0,0 0,0" />
397 </g>
398 <g
399 transform="matrix(0.35277777,0,0,-0.35277777,-10.267078,-18.98197)"
400 id="g1145">
401 <path
402 inkscape:connector-curvature="0"
403 id="path1147"
404 style="fill:#ee2824;fill-opacity:1;fill-rule:nonzero;stroke:none"
405 d="m 0,0 c 0,0 8.375,10.125 21.125,10.125 12.75,0 19.125,-12.875 19.125,-12.875 l 5.375,2 c 0,0 -5.25,19.5 -24.75,19.5 C 1.375,18.75 -6.25,2.125 -6.25,2.125 Z" />
406 </g>
407 <g
408 transform="matrix(0.35277777,0,0,-0.35277777,-11.991348,-20.57413)"
409 id="g1149">
410 <path
411 inkscape:connector-curvature="0"
412 id="path1151"
413 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
414 d="M 0,0 C 0.002,0.001 11.373,9.681 26.263,9.362 39.589,9.076 46.138,3.528 46.183,3.49 42.526,8.674 36.179,14.237 25.763,14.237 10.909,14.237 2.952,4.597 0,0" />
415 </g>
416 </g>
417 </g>
418 </svg>
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
4 <svg
5 xmlns:dc="http://purl.org/dc/elements/1.1/"
6 xmlns:cc="http://creativecommons.org/ns#"
7 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8 xmlns:svg="http://www.w3.org/2000/svg"
9 xmlns="http://www.w3.org/2000/svg"
10 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12 version="1.1"
13 id="svg3767"
14 xml:space="preserve"
15 width="128"
16 height="128"
17 viewBox="0 0 128 128"
18 sodipodi:docname="SPAI_logo.svg"
19 inkscape:version="0.92.3 (2405546, 2018-03-11)"
20 inkscape:export-filename="/home/eros/Desktop/SPAI_logo.svg.png"
21 inkscape:export-xdpi="96"
22 inkscape:export-ydpi="96"><metadata
23 id="metadata3773"><rdf:RDF><cc:Work
24 rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
25 rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
26 id="defs3771"><clipPath
27 clipPathUnits="userSpaceOnUse"
28 id="clipPath3797"><path
29 d="M 0,972 H 1400 V 0 H 0 Z"
30 id="path3795"
31 inkscape:connector-curvature="0" /></clipPath><clipPath
32 clipPathUnits="userSpaceOnUse"
33 id="clipPath3973"><path
34 d="M 0,972 H 1400 V 0 H 0 Z"
35 id="path3971"
36 inkscape:connector-curvature="0" /></clipPath><clipPath
37 clipPathUnits="userSpaceOnUse"
38 id="clipPath4159"><path
39 d="M 0,972 H 1400 V 0 H 0 Z"
40 id="path4157"
41 inkscape:connector-curvature="0" /></clipPath><clipPath
42 clipPathUnits="userSpaceOnUse"
43 id="clipPath4193"><path
44 d="M 0,972 H 1400 V 0 H 0 Z"
45 id="path4191"
46 inkscape:connector-curvature="0" /></clipPath><clipPath
47 clipPathUnits="userSpaceOnUse"
48 id="clipPath4618"><g
49 inkscape:label="Clip"
50 id="use4620"><g
51 transform="translate(551.1328,622.08282)"
52 id="g4790"><path
53 inkscape:connector-curvature="0"
54 id="path4788"
55 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
56 d="m 0,0 c 0,0 -4.484,-4.226 -4.484,-14.851 0,-10.625 16.769,-30.625 56.384,-30.625 39.616,0 53.116,13.875 53.116,25.25 0,11.375 -2.791,12.708 -2.791,12.708 z" /></g><g
57 transform="translate(555.1855,622.41972)"
58 id="g4794"><path
59 inkscape:connector-curvature="0"
60 id="path4792"
61 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
62 d="m 0,0 -4.086,-0.337 c 0,0 -1.242,-11.309 -1.242,-14.687 0,-7.673 15.443,-27.664 52.564,-27.664 31.873,0 50.936,9.953 50.936,22.099 v 13.985 l -7.592,3.897 z" /></g><g
63 transform="translate(553.6894,632.23222)"
64 id="g4798"><path
65 inkscape:connector-curvature="0"
66 id="path4796"
67 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
68 d="m 0,0 c 0,0 -2.59,-1.499 -2.59,-12.169 0,-7.581 15.258,-27.331 51.934,-27.331 31.49,0 50.324,9.833 50.324,21.833 0,14.5 -7.5,17.667 -7.5,17.667 z" /></g><g
69 transform="translate(533.9609,769.13842)"
70 id="g4802"><path
71 inkscape:connector-curvature="0"
72 id="path4800"
73 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
74 d="m 0,0 -28.562,-27.74 v -95.166 l 29.624,-11.75 z" /></g><g
75 transform="translate(591.5234,625.10722)"
76 id="g4806"><path
77 inkscape:connector-curvature="0"
78 id="path4804"
79 style="fill:#d7292a;fill-opacity:1;fill-rule:nonzero;stroke:none"
80 d="m 0,0 0.574,7.125 h -38.408 c 0,0 -2.59,-1.499 -2.59,-12.169 0,-2.132 1.207,-5.227 3.758,-8.575 z" /></g><g
81 transform="translate(617.2734,622.08282)"
82 id="g4810"><path
83 inkscape:connector-curvature="0"
84 id="path4808"
85 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none"
86 d="m 0,0 c 0,-3.266 -6.375,-5.913 -14.24,-5.913 -7.865,0 -14.24,2.647 -14.24,5.913 0,3.267 6.375,5.913 14.24,5.913 C -6.375,5.913 0,3.267 0,0" /></g><path
87 inkscape:connector-curvature="0"
88 id="path4812"
89 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none"
90 d="m 617.2729,630.04723 h -28.48 v -7.96501 h 28.48 z" /><g
91 transform="translate(617.2734,630.04762)"
92 id="g4816"><path
93 inkscape:connector-curvature="0"
94 id="path4814"
95 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none"
96 d="m 0,0 c 0,-3.267 -6.375,-5.913 -14.24,-5.913 -7.865,0 -14.24,2.646 -14.24,5.913 0,3.266 6.375,5.913 14.24,5.913 C -6.375,5.913 0,3.266 0,0" /></g><path
97 inkscape:connector-curvature="0"
98 id="path4818"
99 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none"
100 d="m 617.2729,635.39922 h -28.48 v -4.917 h 28.48 z" /><g
101 transform="translate(609.7109,772.23222)"
102 id="g4822"><path
103 inkscape:connector-curvature="0"
104 id="path4820"
105 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
106 d="M 0,0 H -67.688 C -74.287,0 -80,-5.4 -80,-12 v -116 c 0,-6.6 5.713,-12 12.312,-12 H 0 Z" /></g><g
107 transform="translate(674.0234,772.23222)"
108 id="g4826"><path
109 inkscape:connector-curvature="0"
110 id="path4824"
111 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
112 d="M 0,0 H -64.313 V -140 H 0 c 6.6,0 11.688,5.4 11.688,12 V -12 C 11.688,-5.4 6.6,0 0,0" /></g><g
113 transform="translate(621.7109,783.60722)"
114 id="g4830"><path
115 inkscape:connector-curvature="0"
116 id="path4828"
117 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
118 d="m 0,0 v -5.5 l 32.805,-4.046 0.148,8.171 z" /></g><g
119 transform="translate(602.7734,781.98222)"
120 id="g4834"><path
121 inkscape:connector-curvature="0"
122 id="path4832"
123 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
124 d="M 0,0 -41.084,3.418 -41.5,-6.666 -0.375,-6.5 Z" /></g><g
125 transform="translate(522.0234,697.23222)"
126 id="g4838"><path
127 inkscape:connector-curvature="0"
128 id="path4836"
129 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
130 d="m 0,0 c 0,-15.33 -7.219,-27.758 -16.125,-27.758 -8.906,0 -16.125,12.428 -16.125,27.758 0,15.33 7.219,27.758 16.125,27.758 C -7.219,27.758 0,15.33 0,0" /></g><g
131 transform="translate(506.2246,721.85722)"
132 id="g4842"><path
133 inkscape:connector-curvature="0"
134 id="path4840"
135 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
136 d="m 0,0 c -0.107,0 -5.711,0.023 -5.818,0.023 -6.932,0 -12.549,-11.037 -12.549,-24.636 0,-13.6 5.617,-24.631 12.549,-24.631 0.107,0 5.711,-0.012 5.818,-0.012 6.932,0 12.549,11.027 12.549,24.628 C 12.549,-11.027 6.932,0 0,0" /></g><g
137 transform="translate(512.7734,697.23222)"
138 id="g4846"><path
139 inkscape:connector-curvature="0"
140 id="path4844"
141 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
142 d="m 0,0 c 0,-13.6 -5.578,-24.625 -12.457,-24.625 -6.881,0 -12.459,11.025 -12.459,24.625 0,13.6 5.578,24.625 12.459,24.625 C -5.578,24.625 0,13.6 0,0" /></g><g
143 transform="translate(500.5234,697.85722)"
144 id="g4850"><path
145 inkscape:connector-curvature="0"
146 id="path4848"
147 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
148 d="m 0,0 c 0,-3.383 -1.68,-6.125 -3.75,-6.125 -2.07,0 -3.75,2.742 -3.75,6.125 0,3.383 1.68,6.125 3.75,6.125 C -1.68,6.125 0,3.383 0,0" /></g><g
149 transform="translate(495.1484,703.98222)"
150 id="g4854"><path
151 inkscape:connector-curvature="0"
152 id="path4852"
153 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
154 d="m 0,0 h -10.875 c -1.104,0 -2,-2.742 -2,-6.125 0,-3.383 0.896,-6.125 2,-6.125 H 0 c 1.105,0 2,2.742 2,6.125 C 2,-2.742 1.105,0 0,0" /></g><g
155 transform="translate(640.7109,735.90212)"
156 id="g4858"><path
157 inkscape:connector-curvature="0"
158 id="path4856"
159 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
160 d="m 0,0 c -1,0.008 -4.109,0.84 -4.193,0.832 -12.235,-1.086 -20.323,-9.461 -20.323,-20.127 0,-10.666 8.791,-19.326 19.78,-19.326 0.084,0 3.736,-0.002 4.736,-0.002 z" /></g><g
161 transform="translate(660.1894,717.16972)"
162 id="g4862"><path
163 inkscape:connector-curvature="0"
164 id="path4860"
165 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
166 d="m 0,0 c 0,-10.988 -8.908,-19.896 -19.896,-19.896 -10.989,0 -19.897,8.908 -19.897,19.896 0,10.988 8.908,19.896 19.897,19.896 C -8.908,19.896 0,10.988 0,0" /></g><g
167 transform="translate(655.0664,717.54472)"
168 id="g4866"><path
169 inkscape:connector-curvature="0"
170 id="path4864"
171 style="fill:#b4d9e8;fill-opacity:1;fill-rule:nonzero;stroke:none"
172 d="m 0,0 c 0,-7.951 -6.445,-14.398 -14.398,-14.398 -7.952,0 -14.397,6.447 -14.397,14.398 0,7.951 6.445,14.398 14.397,14.398 C -6.445,14.398 0,7.951 0,0" /></g><g
173 transform="translate(648.1152,717.41972)"
174 id="g4870"><path
175 inkscape:connector-curvature="0"
176 id="path4868"
177 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
178 d="m 0,0 c 0,-4.182 -3.391,-7.57 -7.572,-7.57 -4.18,0 -7.571,3.388 -7.571,7.57 0,4.182 3.391,7.57 7.571,7.57 C -3.391,7.57 0,4.182 0,0" /></g><g
179 transform="translate(585.7109,735.90212)"
180 id="g4874"><path
181 inkscape:connector-curvature="0"
182 id="path4872"
183 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
184 d="m 0,0 c -1,0.008 -4.109,0.84 -4.193,0.832 -12.235,-1.086 -20.323,-9.461 -20.323,-20.127 0,-10.666 8.791,-19.326 19.78,-19.326 0.084,0 3.736,-0.002 4.736,-0.002 z" /></g><g
185 transform="translate(605.1894,717.16972)"
186 id="g4878"><path
187 inkscape:connector-curvature="0"
188 id="path4876"
189 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
190 d="m 0,0 c 0,-10.988 -8.908,-19.896 -19.896,-19.896 -10.989,0 -19.897,8.908 -19.897,19.896 0,10.988 8.908,19.896 19.897,19.896 C -8.908,19.896 0,10.988 0,0" /></g><g
191 transform="translate(600.0664,717.54472)"
192 id="g4882"><path
193 inkscape:connector-curvature="0"
194 id="path4880"
195 style="fill:#b4d9e8;fill-opacity:1;fill-rule:nonzero;stroke:none"
196 d="m 0,0 c 0,-7.951 -6.445,-14.398 -14.398,-14.398 -7.952,0 -14.397,6.447 -14.397,14.398 0,7.951 6.445,14.398 14.397,14.398 C -6.445,14.398 0,7.951 0,0" /></g><g
197 transform="translate(593.1152,717.41972)"
198 id="g4886"><path
199 inkscape:connector-curvature="0"
200 id="path4884"
201 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
202 d="m 0,0 c 0,-4.182 -3.391,-7.57 -7.572,-7.57 -4.18,0 -7.571,3.388 -7.571,7.57 0,4.182 3.391,7.57 7.571,7.57 C -3.391,7.57 0,4.182 0,0" /></g><g
203 transform="translate(593.3671,667.11793)"
204 id="g4890"><path
205 inkscape:connector-curvature="0"
206 id="path4888"
207 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
208 d="m 0,0 c 0.07,-4.725 -3.701,-8.61 -8.426,-8.68 -4.724,-0.07 -8.609,3.702 -8.679,8.427 -0.071,4.723 3.703,8.608 8.425,8.678 C -3.955,8.495 -0.07,4.724 0,0" /></g><g
209 transform="translate(645.8964,667.89532)"
210 id="g4894"><path
211 inkscape:connector-curvature="0"
212 id="path4892"
213 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
214 d="m 0,0 c 0.07,-4.724 -3.701,-8.61 -8.426,-8.68 -4.724,-0.07 -8.609,3.702 -8.679,8.427 -0.071,4.724 3.703,8.609 8.425,8.679 C -3.955,8.495 -0.07,4.724 0,0" /></g><g
215 transform="translate(642.7597,661.15602)"
216 id="g4898"><path
217 inkscape:connector-curvature="0"
218 id="path4896"
219 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
220 d="m 0,0 c 0,0 -11.16,-12.342 -32.756,-12.661 -18.803,-0.278 -31.42,12.65 -31.42,12.65 l 12.321,11.853 c 0,0 9.5,-8.029 19.707,-7.822 13.945,0.28 20.337,8.343 20.337,8.343 z" /></g><g
221 transform="translate(594.1777,669.93922)"
222 id="g4902"><path
223 inkscape:connector-curvature="0"
224 id="path4900"
225 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
226 d="m 0,0 c 0,-4.788 -3.881,-8.67 -8.668,-8.67 -4.789,0 -8.67,3.882 -8.67,8.67 0,4.787 3.881,8.668 8.67,8.668 C -3.881,8.668 0,4.787 0,0" /></g><g
227 transform="translate(647.4179,669.93922)"
228 id="g4906"><path
229 inkscape:connector-curvature="0"
230 id="path4904"
231 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
232 d="m 0,0 c 0,-4.788 -3.881,-8.67 -8.668,-8.67 -4.787,0 -8.668,3.882 -8.668,8.67 0,4.787 3.881,8.668 8.668,8.668 C -3.881,8.668 0,4.787 0,0" /></g><g
233 transform="translate(644.1406,663.15602)"
234 id="g4910"><path
235 inkscape:connector-curvature="0"
236 id="path4908"
237 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
238 d="m 0,0 c 0,0 -11.496,-12.338 -33.383,-12.338 -19.058,0 -31.65,13.291 -31.65,13.291 l 12.662,11.824 c 0,0 9.508,-8.277 19.853,-8.222 14.135,0.076 20.735,8.15 20.735,8.15 z" /></g><path
239 inkscape:connector-curvature="0"
240 id="path4912"
241 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
242 d="m 615.1839,656.34022 h -4.18 v 5.349 h 4.18 z" /><g
243 transform="translate(607.914,656.61312)"
244 id="g4916"><path
245 inkscape:connector-curvature="0"
246 id="path4914"
247 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
248 d="M 0,0 -4.076,0.926 -2.893,6.143 1.186,5.217 Z" /></g><g
249 transform="translate(601.1523,658.30932)"
250 id="g4920"><path
251 inkscape:connector-curvature="0"
252 id="path4918"
253 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
254 d="m 0,0 -3.895,1.521 1.948,4.982 3.892,-1.52 z" /></g><g
255 transform="translate(594.83,660.85523)"
256 id="g4924"><path
257 inkscape:connector-curvature="0"
258 id="path4922"
259 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
260 d="M 0,0 -3.727,1.894 -1.305,6.662 2.422,4.769 Z" /></g><g
261 transform="translate(588.6269,664.18732)"
262 id="g4928"><path
263 inkscape:connector-curvature="0"
264 id="path4926"
265 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
266 d="M 0,0 -3.383,2.456 -0.24,6.783 3.143,4.327 Z" /></g><path
267 inkscape:connector-curvature="0"
268 id="path4930"
269 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
270 d="m 611.0039,656.34022 h 4.18 v 5.349 h -4.18 z" /><g
271 transform="translate(618.2714,656.61312)"
272 id="g4934"><path
273 inkscape:connector-curvature="0"
274 id="path4932"
275 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
276 d="M 0,0 4.076,0.926 2.895,6.143 -1.184,5.217 Z" /></g><g
277 transform="translate(625.0351,658.30932)"
278 id="g4938"><path
279 inkscape:connector-curvature="0"
280 id="path4936"
281 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
282 d="M 0,0 3.895,1.521 1.947,6.503 -1.947,4.983 Z" /></g><g
283 transform="translate(631.3574,660.85523)"
284 id="g4942"><path
285 inkscape:connector-curvature="0"
286 id="path4940"
287 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
288 d="M 0,0 3.727,1.894 1.305,6.662 -2.422,4.769 Z" /></g><g
289 transform="translate(637.5605,664.18732)"
290 id="g4946"><path
291 inkscape:connector-curvature="0"
292 id="path4944"
293 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
294 d="M 0,0 3.383,2.456 0.24,6.783 -3.143,4.327 Z" /></g><g
295 transform="translate(662.4746,767.89823)"
296 id="g4950"><path
297 inkscape:connector-curvature="0"
298 id="path4948"
299 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
300 d="m 0,0 v -3.166 c 0,0 6.918,0.75 11.334,-3.666 4.416,-4.417 4,-10.668 4,-10.668 h 3 c 0,0 1.334,9.668 -3.834,14.168 C 9.334,1.168 0,0 0,0" /></g></g></clipPath><marker
301 style="overflow:visible"
302 id="Scissors"
303 orient="auto"
304 refY="0"
305 refX="0"><path
306 style="marker-start:none"
307 id="schere"
308 d="M 9.0898857,-3.6061018 C 8.1198849,-4.7769976 6.3697607,-4.7358294 5.0623558,-4.2327734 l -8.2124046,3.0779029 c -2.3882933,-1.3067135 -4.7482873,-0.9325372 -4.7482873,-1.5687873 0,-0.4973164 0.4566662,-0.3883222 0.3883068,-1.6831941 -0.065635,-1.2432767 -1.3635771,-2.1630796 -2.5903987,-2.0816435 -1.227271,-0.00735 -2.499439,0.9331613 -2.510341,2.2300611 -0.09143,1.3063864 1.007209,2.5196896 2.306764,2.6052316 1.5223406,0.2266616 4.218258,-0.6955566 5.482945,1.57086006 -0.9422847,1.73825774 -2.6140244,1.74307674 -4.1255107,1.65607034 -1.2548743,-0.072235 -2.7620933,0.2873979 -3.3606483,1.5208605 -0.578367,1.1820862 -0.0112,2.8646022 1.316749,3.226412 1.3401912,0.4918277 3.1806689,-0.129711 3.4993722,-1.6707242 0.2456585,-1.187823 -0.5953659,-1.7459574 -0.2725074,-2.1771537 0.2436135,-0.32536 1.7907806,-0.1368452 4.5471053,-1.3748244 L 5.6763468,4.2330688 C 6.8000164,4.5467672 8.1730685,4.5362646 9.1684433,3.4313614 l -9.22008423,-3.48508362 z m -18.3078016,-1.900504 c 1.294559,0.7227998 1.1888392,2.6835702 -0.1564272,3.0632889 -1.2165179,0.423661 -2.7710269,-0.7589694 -2.3831779,-2.0774648 0.227148,-1.0818519 1.653387,-1.480632 2.5396051,-0.9858241 z m 0.056264,8.0173649 c 1.3508301,0.4988648 1.1214429,2.7844356 -0.2522207,3.091609 -0.9110594,0.3163391 -2.2135494,-0.1387976 -2.3056964,-1.2121394 -0.177609,-1.305055 1.356085,-2.4841482 2.5579171,-1.8794696 z"
309 inkscape:connector-curvature="0" /></marker></defs><sodipodi:namedview
310 pagecolor="#ffffff"
311 bordercolor="#666666"
312 borderopacity="1"
313 objecttolerance="10"
314 gridtolerance="10"
315 guidetolerance="10"
316 inkscape:pageopacity="0"
317 inkscape:pageshadow="2"
318 inkscape:window-width="1853"
319 inkscape:window-height="1025"
320 id="namedview3769"
321 showgrid="false"
322 inkscape:zoom="3.6042856"
323 inkscape:cx="75.458418"
324 inkscape:cy="48.883031"
325 inkscape:window-x="67"
326 inkscape:window-y="27"
327 inkscape:window-maximized="1"
328 inkscape:current-layer="g3775" /><g
329 id="g3775"
330 inkscape:groupmode="layer"
331 inkscape:label="SP_landing_page_BF"
332 transform="matrix(1.3333333,0,0,-1.3333333,0,128)"><g
333 transform="matrix(0.3749127,0,0,0.3749127,-57.012955,-199.31617)"
334 id="g7806-3"><g
335 id="g3799-7-67"
336 transform="translate(220.92934,624.37578)"><path
337 d="m 0,0 c 0,0 -4.484,-4.226 -4.484,-14.851 0,-10.625 16.769,-30.625 56.384,-30.625 39.616,0 53.116,13.875 53.116,25.25 0,11.375 -2.791,12.708 -2.791,12.708 z"
338 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
339 id="path3801-6-5"
340 inkscape:connector-curvature="0" /></g><g
341 id="g3803-1-3"
342 transform="translate(224.98204,624.71268)"><path
343 d="m 0,0 -4.086,-0.337 c 0,0 -1.242,-11.309 -1.242,-14.687 0,-7.673 15.443,-27.664 52.564,-27.664 31.873,0 50.936,9.953 50.936,22.099 v 13.985 l -7.592,3.897 z"
344 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
345 id="path3805-3-5"
346 inkscape:connector-curvature="0" /></g><g
347 id="g3807-2-6"
348 transform="translate(223.48594,634.52518)"><path
349 d="m 0,0 c 0,0 -2.59,-1.499 -2.59,-12.169 0,-7.581 15.258,-27.331 51.934,-27.331 31.49,0 50.324,9.833 50.324,21.833 0,14.5 -7.5,17.667 -7.5,17.667 z"
350 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
351 id="path3809-1-29"
352 inkscape:connector-curvature="0" /></g><g
353 id="g3815-59-1"
354 transform="translate(261.31996,627.40018)"><path
355 d="m 0,0 0.574,7.125 h -38.408 c 0,0 -2.59,-1.499 -2.59,-12.169 0,-2.132 1.207,-5.227 3.758,-8.575 z"
356 style="fill:#d7292a;fill-opacity:1;fill-rule:nonzero;stroke:none"
357 id="path3817-9-2"
358 inkscape:connector-curvature="0" /></g><g
359 id="g3811-0-6"
360 transform="translate(203.75745,771.43138)"><path
361 d="m 0,0 -28.562,-27.74 v -95.166 l 29.624,-11.75 z"
362 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
363 id="path3813-7-0"
364 inkscape:connector-curvature="0" /></g><g
365 id="g3819-5-6"
366 transform="translate(287.06995,624.37578)"><path
367 d="m 0,0 c 0,-3.266 -6.375,-5.913 -14.24,-5.913 -7.865,0 -14.24,2.647 -14.24,5.913 0,3.267 6.375,5.913 14.24,5.913 C -6.375,5.913 0,3.267 0,0"
368 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none"
369 id="path3821-8-2"
370 inkscape:connector-curvature="0" /></g><path
371 d="m 287.06945,632.34019 h -28.48 v -7.96501 h 28.48 z"
372 style="fill:#ebeadb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994"
373 id="path3823-0-1"
374 inkscape:connector-curvature="0" /><g
375 id="g3825-4-8"
376 transform="translate(287.06995,632.34058)"><path
377 d="m 0,0 c 0,-3.267 -6.375,-5.913 -14.24,-5.913 -7.865,0 -14.24,2.646 -14.24,5.913 0,3.266 6.375,5.913 14.24,5.913 C -6.375,5.913 0,3.266 0,0"
378 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none"
379 id="path3827-8-7"
380 inkscape:connector-curvature="0" /></g><path
381 d="m 287.06945,637.69218 h -28.48 v -4.917 h 28.48 z"
382 style="fill:#cbcdc5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994"
383 id="path3829-0-9"
384 inkscape:connector-curvature="0" /><g
385 id="g3831-4-2"
386 transform="translate(279.50746,774.52517)"><path
387 d="M 0,0 H -67.688 C -74.287,0 -80,-5.4 -80,-12 v -116 c 0,-6.6 5.713,-12 12.312,-12 H 0 Z"
388 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
389 id="path3833-2-0"
390 inkscape:connector-curvature="0" /></g><g
391 id="g3835-9-23"
392 transform="translate(343.81995,774.52517)"><path
393 d="M 0,0 H -64.313 V -140 H 0 c 6.6,0 11.688,5.4 11.688,12 V -12 C 11.688,-5.4 6.6,0 0,0"
394 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
395 id="path3837-61-7"
396 inkscape:connector-curvature="0" /></g><g
397 id="g3839-0-5"
398 transform="translate(291.50746,785.90018)"><path
399 d="m 0,0 v -5.5 l 32.805,-4.046 0.148,8.171 z"
400 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
401 id="path3841-4-9"
402 inkscape:connector-curvature="0" /></g><g
403 id="g3843-2-2"
404 transform="translate(272.56996,784.27517)"><path
405 d="M 0,0 -41.084,3.418 -41.5,-6.666 -0.375,-6.5 Z"
406 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
407 id="path3845-2-2"
408 inkscape:connector-curvature="0" /></g><g
409 id="g3847-2-89"
410 transform="translate(191.81995,699.52518)"><path
411 d="m 0,0 c 0,-15.33 -7.219,-27.758 -16.125,-27.758 -8.906,0 -16.125,12.428 -16.125,27.758 0,15.33 7.219,27.758 16.125,27.758 C -7.219,27.758 0,15.33 0,0"
412 style="fill:#1fbfca;fill-opacity:1;fill-rule:nonzero;stroke:none"
413 id="path3849-0-7"
414 inkscape:connector-curvature="0" /></g><g
415 id="g3851-55-3"
416 transform="translate(176.02115,724.15018)"><path
417 d="m 0,0 c -0.107,0 -5.711,0.023 -5.818,0.023 -6.932,0 -12.549,-11.037 -12.549,-24.636 0,-13.6 5.617,-24.631 12.549,-24.631 0.107,0 5.711,-0.012 5.818,-0.012 6.932,0 12.549,11.027 12.549,24.628 C 12.549,-11.027 6.932,0 0,0"
418 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
419 id="path3853-2-6"
420 inkscape:connector-curvature="0" /></g><g
421 id="g3855-9-1"
422 transform="translate(182.56995,699.52518)"><path
423 d="m 0,0 c 0,-13.6 -5.578,-24.625 -12.457,-24.625 -6.881,0 -12.459,11.025 -12.459,24.625 0,13.6 5.578,24.625 12.459,24.625 C -5.578,24.625 0,13.6 0,0"
424 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
425 id="path3857-0-29"
426 inkscape:connector-curvature="0" /></g><g
427 id="g3859-2-3"
428 transform="translate(170.31995,700.15018)"><path
429 d="m 0,0 c 0,-3.383 -1.68,-6.125 -3.75,-6.125 -2.07,0 -3.75,2.742 -3.75,6.125 0,3.383 1.68,6.125 3.75,6.125 C -1.68,6.125 0,3.383 0,0"
430 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
431 id="path3861-8-1"
432 inkscape:connector-curvature="0" /></g><g
433 id="g3863-3-9"
434 transform="translate(164.94495,706.27518)"><path
435 d="m 0,0 h -10.875 c -1.104,0 -2,-2.742 -2,-6.125 0,-3.383 0.896,-6.125 2,-6.125 H 0 c 1.105,0 2,2.742 2,6.125 C 2,-2.742 1.105,0 0,0"
436 style="fill:#92d5e3;fill-opacity:1;fill-rule:nonzero;stroke:none"
437 id="path3865-8-4"
438 inkscape:connector-curvature="0" /></g><g
439 id="g3867-0-7"
440 transform="translate(310.50745,738.19508)"><path
441 d="m 0,0 c -1,0.008 -4.109,0.84 -4.193,0.832 -12.235,-1.086 -20.323,-9.461 -20.323,-20.127 0,-10.666 8.791,-19.326 19.78,-19.326 0.084,0 3.736,-0.002 4.736,-0.002 z"
442 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
443 id="path3869-4-8"
444 inkscape:connector-curvature="0" /></g><g
445 id="g3871-0-4"
446 transform="translate(329.98595,719.46268)"><path
447 d="m 0,0 c 0,-10.988 -8.908,-19.896 -19.896,-19.896 -10.989,0 -19.897,8.908 -19.897,19.896 0,10.988 8.908,19.896 19.897,19.896 C -8.908,19.896 0,10.988 0,0"
448 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
449 id="path3873-9-5"
450 inkscape:connector-curvature="0" /></g><g
451 id="g3875-1-0"
452 transform="translate(324.86295,719.83768)"><path
453 d="m 0,0 c 0,-7.951 -6.445,-14.398 -14.398,-14.398 -7.952,0 -14.397,6.447 -14.397,14.398 0,7.951 6.445,14.398 14.397,14.398 C -6.445,14.398 0,7.951 0,0"
454 style="fill:#b4d9e8;fill-opacity:1;fill-rule:nonzero;stroke:none"
455 id="path3877-9-3"
456 inkscape:connector-curvature="0" /></g><g
457 id="g3879-6-6"
458 transform="translate(317.91175,719.71268)"><path
459 d="m 0,0 c 0,-4.182 -3.391,-7.57 -7.572,-7.57 -4.18,0 -7.571,3.388 -7.571,7.57 0,4.182 3.391,7.57 7.571,7.57 C -3.391,7.57 0,4.182 0,0"
460 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
461 id="path3881-2-1"
462 inkscape:connector-curvature="0" /></g><g
463 id="g3883-5-0"
464 transform="translate(255.50746,738.19508)"><path
465 d="m 0,0 c -1,0.008 -4.109,0.84 -4.193,0.832 -12.235,-1.086 -20.323,-9.461 -20.323,-20.127 0,-10.666 8.791,-19.326 19.78,-19.326 0.084,0 3.736,-0.002 4.736,-0.002 z"
466 style="fill:#c22828;fill-opacity:1;fill-rule:nonzero;stroke:none"
467 id="path3885-4-6"
468 inkscape:connector-curvature="0" /></g><g
469 id="g3887-4-3"
470 transform="translate(274.98595,719.46268)"><path
471 d="m 0,0 c 0,-10.988 -8.908,-19.896 -19.896,-19.896 -10.989,0 -19.897,8.908 -19.897,19.896 0,10.988 8.908,19.896 19.897,19.896 C -8.908,19.896 0,10.988 0,0"
472 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
473 id="path3889-9-2"
474 inkscape:connector-curvature="0" /></g><g
475 id="g3891-9-0"
476 transform="translate(269.86295,719.83768)"><path
477 d="m 0,0 c 0,-7.951 -6.445,-14.398 -14.398,-14.398 -7.952,0 -14.397,6.447 -14.397,14.398 0,7.951 6.445,14.398 14.397,14.398 C -6.445,14.398 0,7.951 0,0"
478 style="fill:#b4d9e8;fill-opacity:1;fill-rule:nonzero;stroke:none"
479 id="path3893-3-6"
480 inkscape:connector-curvature="0" /></g><g
481 id="g3895-6-15"
482 transform="translate(262.91176,719.71268)"><path
483 d="m 0,0 c 0,-4.182 -3.391,-7.57 -7.572,-7.57 -4.18,0 -7.571,3.388 -7.571,7.57 0,4.182 3.391,7.57 7.571,7.57 C -3.391,7.57 0,4.182 0,0"
484 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
485 id="path3897-0-5"
486 inkscape:connector-curvature="0" /></g><g
487 id="g3899-5-4"
488 transform="translate(263.16365,669.41089)"><path
489 d="m 0,0 c 0.07,-4.725 -3.701,-8.61 -8.426,-8.68 -4.724,-0.07 -8.609,3.702 -8.679,8.427 -0.071,4.723 3.703,8.608 8.425,8.678 C -3.955,8.495 -0.07,4.724 0,0"
490 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
491 id="path3901-0-7"
492 inkscape:connector-curvature="0" /></g><g
493 id="g3903-2-6"
494 transform="translate(315.69295,670.18828)"><path
495 d="m 0,0 c 0.07,-4.724 -3.701,-8.61 -8.426,-8.68 -4.724,-0.07 -8.609,3.702 -8.679,8.427 -0.071,4.724 3.703,8.609 8.425,8.679 C -3.955,8.495 -0.07,4.724 0,0"
496 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
497 id="path3905-9-5"
498 inkscape:connector-curvature="0" /></g><g
499 id="g3907-4-6"
500 transform="translate(312.55625,663.44898)"><path
501 d="m 0,0 c 0,0 -11.16,-12.342 -32.756,-12.661 -18.803,-0.278 -31.42,12.65 -31.42,12.65 l 12.321,11.853 c 0,0 9.5,-8.029 19.707,-7.822 13.945,0.28 20.337,8.343 20.337,8.343 z"
502 style="fill:#116c7e;fill-opacity:1;fill-rule:nonzero;stroke:none"
503 id="path3909-3-9"
504 inkscape:connector-curvature="0" /></g><g
505 id="g3911-5-3"
506 transform="translate(263.97425,672.23218)"><path
507 d="m 0,0 c 0,-4.788 -3.881,-8.67 -8.668,-8.67 -4.789,0 -8.67,3.882 -8.67,8.67 0,4.787 3.881,8.668 8.67,8.668 C -3.881,8.668 0,4.787 0,0"
508 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
509 id="path3913-1-7"
510 inkscape:connector-curvature="0" /></g><g
511 id="g3915-7-45"
512 transform="translate(317.21446,672.23218)"><path
513 d="m 0,0 c 0,-4.788 -3.881,-8.67 -8.668,-8.67 -4.787,0 -8.668,3.882 -8.668,8.67 0,4.787 3.881,8.668 8.668,8.668 C -3.881,8.668 0,4.787 0,0"
514 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
515 id="path3917-4-2"
516 inkscape:connector-curvature="0" /></g><g
517 id="g3919-3-5"
518 transform="translate(313.93715,665.44898)"><path
519 d="m 0,0 c 0,0 -11.496,-12.338 -33.383,-12.338 -19.058,0 -31.65,13.291 -31.65,13.291 l 12.662,11.824 c 0,0 9.508,-8.277 19.853,-8.222 14.135,0.076 20.735,8.15 20.735,8.15 z"
520 style="fill:#ed2d26;fill-opacity:1;fill-rule:nonzero;stroke:none"
521 id="path3921-1-4"
522 inkscape:connector-curvature="0" /></g><path
523 d="m 284.98045,658.63318 h -4.18 v 5.349 h 4.18 z"
524 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994"
525 id="path3923-4-7"
526 inkscape:connector-curvature="0" /><g
527 id="g3925-6-4"
528 transform="translate(277.71055,658.90608)"><path
529 d="M 0,0 -4.076,0.926 -2.893,6.143 1.186,5.217 Z"
530 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
531 id="path3927-9-4"
532 inkscape:connector-curvature="0" /></g><g
533 id="g3929-4-3"
534 transform="translate(270.94885,660.60228)"><path
535 d="m 0,0 -3.895,1.521 1.948,4.982 3.892,-1.52 z"
536 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
537 id="path3931-2-0"
538 inkscape:connector-curvature="0" /></g><g
539 id="g3933-2-7"
540 transform="translate(264.62656,663.14819)"><path
541 d="M 0,0 -3.727,1.894 -1.305,6.662 2.422,4.769 Z"
542 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
543 id="path3935-6-8"
544 inkscape:connector-curvature="0" /></g><g
545 id="g3937-4-6"
546 transform="translate(258.42346,666.48028)"><path
547 d="M 0,0 -3.383,2.456 -0.24,6.783 3.143,4.327 Z"
548 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
549 id="path3939-1-8"
550 inkscape:connector-curvature="0" /></g><path
551 d="m 280.80045,658.63318 h 4.18 v 5.349 h -4.18 z"
552 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994"
553 id="path3941-2-8"
554 inkscape:connector-curvature="0" /><g
555 id="g3943-8-4"
556 transform="translate(288.06796,658.90608)"><path
557 d="M 0,0 4.076,0.926 2.895,6.143 -1.184,5.217 Z"
558 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
559 id="path3945-8-3"
560 inkscape:connector-curvature="0" /></g><g
561 id="g3947-92-1"
562 transform="translate(294.83165,660.60228)"><path
563 d="M 0,0 3.895,1.521 1.947,6.503 -1.947,4.983 Z"
564 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
565 id="path3949-8-4"
566 inkscape:connector-curvature="0" /></g><g
567 id="g3951-8-9"
568 transform="translate(301.15396,663.14819)"><path
569 d="M 0,0 3.727,1.894 1.305,6.662 -2.422,4.769 Z"
570 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
571 id="path3953-8-2"
572 inkscape:connector-curvature="0" /></g><g
573 id="g3955-6-0"
574 transform="translate(307.35706,666.48028)"><path
575 d="M 0,0 3.383,2.456 0.24,6.783 -3.143,4.327 Z"
576 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
577 id="path3957-8-6"
578 inkscape:connector-curvature="0" /></g><g
579 id="g3959-3-8"
580 transform="translate(332.27115,770.19119)"><path
581 d="m 0,0 v -3.166 c 0,0 6.918,0.75 11.334,-3.666 4.416,-4.417 4,-10.668 4,-10.668 h 3 c 0,0 1.334,9.668 -3.834,14.168 C 9.334,1.168 0,0 0,0"
582 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
583 id="path3961-8-9"
584 inkscape:connector-curvature="0" /></g></g><g
585 transform="matrix(0.19045745,0,0,-0.19045745,-58.039109,104.03018)"
586 id="layer1-3"><g
587 transform="matrix(4.4799,0,0,2.9866,-22.373,-404.56)"
588 id="g3953"
589 style="stroke:#000000"><rect
590 x="79.462997"
591 y="291.39001"
592 width="88.001999"
593 height="26.205999"
594 id="rect2953"
595 style="fill:#ffcc00;stroke-width:1.5" /><g
596 transform="matrix(1,0,0,0.76435,0.78697,68.514)"
597 id="g3915-9"><rect
598 x="81.922997"
599 y="291.14001"
600 width="1.8688999"
601 height="19.539"
602 id="rect3725"
603 style="stroke-width:0.26172" /><rect
604 x="92.504997"
605 y="291.10001"
606 width="1.9425"
607 height="9.7123003"
608 id="rect3727"
609 style="stroke-width:0.18811999" /><rect
610 x="87.195999"
611 y="291.10001"
612 width="1.9425"
613 height="9.7123003"
614 id="rect3729"
615 style="stroke-width:0.18811999" /><rect
616 x="97.814003"
617 y="291.10001"
618 width="1.9425"
619 height="9.7123003"
620 id="rect3731"
621 style="stroke-width:0.18811999" /><rect
622 x="103.12"
623 y="291.10001"
624 width="1.9425"
625 height="9.7123003"
626 id="rect3733"
627 style="stroke-width:0.18811999" /><rect
628 x="108.47"
629 y="291.14001"
630 width="1.8688999"
631 height="19.539"
632 id="rect3765"
633 style="stroke-width:0.26172" /><rect
634 x="119.05"
635 y="291.10001"
636 width="1.9425"
637 height="9.7123003"
638 id="rect3767"
639 style="stroke-width:0.18811999" /><rect
640 x="113.74"
641 y="291.10001"
642 width="1.9425"
643 height="9.7123003"
644 id="rect3769"
645 style="stroke-width:0.18811999" /><rect
646 x="124.36"
647 y="291.10001"
648 width="1.9425"
649 height="9.7123003"
650 id="rect3771"
651 style="stroke-width:0.18811999" /><rect
652 x="129.67"
653 y="291.10001"
654 width="1.9425"
655 height="9.7123003"
656 id="rect3773"
657 style="stroke-width:0.18811999" /><rect
658 x="135.00999"
659 y="291.14001"
660 width="1.8688999"
661 height="19.539"
662 id="rect3779"
663 style="stroke-width:0.26172" /><rect
664 x="145.60001"
665 y="291.10001"
666 width="1.9425"
667 height="9.7123003"
668 id="rect3781"
669 style="stroke-width:0.18811999" /><rect
670 x="140.28999"
671 y="291.10001"
672 width="1.9425"
673 height="9.7123003"
674 id="rect3783"
675 style="stroke-width:0.18811999" /><rect
676 x="150.91"
677 y="291.10001"
678 width="1.9425"
679 height="9.7123003"
680 id="rect3785"
681 style="stroke-width:0.18811999" /><rect
682 x="156.21001"
683 y="291.10001"
684 width="1.9425"
685 height="9.7123003"
686 id="rect3787"
687 style="stroke-width:0.18811999" /><rect
688 x="161.56"
689 y="291.14001"
690 width="1.8688999"
691 height="19.539"
692 id="rect3907"
693 style="stroke-width:0.26172" /></g></g></g><g
694 transform="matrix(0,0.19045745,0.19045745,0,-8.0301814,-48.206035)"
695 id="layer1-3-4"><g
696 transform="matrix(4.4799,0,0,2.9866,-22.373,-404.56)"
697 id="g3953-8"
698 style="stroke:#000000"><rect
699 x="79.462997"
700 y="291.39001"
701 width="88.001999"
702 height="26.205999"
703 id="rect2953-1"
704 style="fill:#ffcc00;stroke-width:1.5" /><g
705 transform="matrix(1,0,0,0.76435,0.78697,68.514)"
706 id="g3915-9-2"><rect
707 x="81.922997"
708 y="291.14001"
709 width="1.8688999"
710 height="19.539"
711 id="rect3725-9"
712 style="stroke-width:0.26172" /><rect
713 x="92.504997"
714 y="291.10001"
715 width="1.9425"
716 height="9.7123003"
717 id="rect3727-3"
718 style="stroke-width:0.18811999" /><rect
719 x="87.195999"
720 y="291.10001"
721 width="1.9425"
722 height="9.7123003"
723 id="rect3729-9"
724 style="stroke-width:0.18811999" /><rect
725 x="97.814003"
726 y="291.10001"
727 width="1.9425"
728 height="9.7123003"
729 id="rect3731-0"
730 style="stroke-width:0.18811999" /><rect
731 x="103.12"
732 y="291.10001"
733 width="1.9425"
734 height="9.7123003"
735 id="rect3733-8"
736 style="stroke-width:0.18811999" /><rect
737 x="108.47"
738 y="291.14001"
739 width="1.8688999"
740 height="19.539"
741 id="rect3765-8"
742 style="stroke-width:0.26172" /><rect
743 x="119.05"
744 y="291.10001"
745 width="1.9425"
746 height="9.7123003"
747 id="rect3767-5"
748 style="stroke-width:0.18811999" /><rect
749 x="113.74"
750 y="291.10001"
751 width="1.9425"
752 height="9.7123003"
753 id="rect3769-0"
754 style="stroke-width:0.18811999" /><rect
755 x="124.36"
756 y="291.10001"
757 width="1.9425"
758 height="9.7123003"
759 id="rect3771-9"
760 style="stroke-width:0.18811999" /><rect
761 x="129.67"
762 y="291.10001"
763 width="1.9425"
764 height="9.7123003"
765 id="rect3773-6"
766 style="stroke-width:0.18811999" /><rect
767 x="135.00999"
768 y="291.14001"
769 width="1.8688999"
770 height="19.539"
771 id="rect3779-3"
772 style="stroke-width:0.26172" /><rect
773 x="145.60001"
774 y="291.10001"
775 width="1.9425"
776 height="9.7123003"
777 id="rect3781-8"
778 style="stroke-width:0.18811999" /><rect
779 x="140.28999"
780 y="291.10001"
781 width="1.9425"
782 height="9.7123003"
783 id="rect3783-5"
784 style="stroke-width:0.18811999" /><rect
785 x="150.91"
786 y="291.10001"
787 width="1.9425"
788 height="9.7123003"
789 id="rect3785-6"
790 style="stroke-width:0.18811999" /><rect
791 x="156.21001"
792 y="291.10001"
793 width="1.9425"
794 height="9.7123003"
795 id="rect3787-1"
796 style="stroke-width:0.18811999" /><rect
797 x="161.56"
798 y="291.14001"
799 width="1.8688999"
800 height="19.539"
801 id="rect3907-1"
802 style="stroke-width:0.26172" /></g></g></g></g></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <?php // Silence is golden
...\ No newline at end of file ...\ No newline at end of file
1
2 // interface for emr.
3 var emrIf = function ($)
4 {
5 var source_type;
6 var source_is_image;
7 var target_type;
8 var target_is_image;
9
10 var is_debug = false;
11
12 var is_dragging = false;
13
14 this.init = function()
15 {
16
17 if ( emr_options.is_debug)
18 {
19 this.is_debug = true;
20 this.debug('EMR Debug is active');
21 }
22
23 $('input[name="timestamp_replace"]').on('change', $.proxy(this.checkCustomDate, this));
24 $('input[name="replace_type"]').on('change', $.proxy(this.showReplaceOptions, this));
25 $('input[name="userfile"]').on('change', $.proxy(this.handleImage, this));
26 $('.replace_custom_date').on('click', $.proxy(this.updateCustomDate, this));
27
28 // DragDrop
29 $('.wrap.emr_upload_form').on('dragover', $.proxy(this.dragOverArea, this));
30 $('.wrap.emr_upload_form').on('dragleave', $.proxy(this.dragOutArea, this));
31 $('.emr_drop_area').on('drop', $.proxy(this.fileDrop, this));
32
33 this.checkCustomDate();
34 this.loadDatePicker();
35
36 var source = $('.image_placeholder').first();
37 if (typeof( $(source).data('filetype') ) !== 'undefined')
38 {
39 source_type = $(source).data('filetype').trim();
40 this.debug('detected type - ' + source_type);
41 }
42 else
43 source_type = ''; // error state
44
45 if (source.hasClass('is_image'))
46 {
47 source_is_image = true;
48 }
49
50 this.updateTextLayer(source, false);
51 this.showReplaceOptions();
52
53 }
54 this.loadDatePicker = function()
55 {
56 $('#emr_datepicker').datepicker({
57 dateFormat: emr_options.dateFormat,
58 onClose: function() {
59 var date = $(this).datepicker( 'getDate' );
60 if (date) {
61 var formattedDate = (date.getFullYear()) + "-" +
62 (date.getMonth()+1) + "-" +
63 date.getDate();
64 $('input[name="custom_date_formatted"]').val(formattedDate);
65 //$('input[name="custom_date"]').val($.datepicker.parseDate( emr_options.dateFormat, date));
66 }
67 },
68 });
69 },
70 this.checkCustomDate = function()
71 {
72 if ($('input[name="timestamp_replace"]:checked').val() == 3)
73 this.showCustomDate();
74 else
75 this.hideCustomDate();
76 },
77 this.showCustomDate = function()
78 {
79 $('.custom_date').css('visibility', 'visible').fadeTo(100, 1);
80 },
81 this.hideCustomDate = function()
82 {
83 $('.custom_date').fadeTo(100,0,
84 function ()
85 {
86 $('.custom_date').css('visibility', 'hidden');
87 });
88 }
89 this.handleImage = function(e)
90 {
91 this.toggleErrors(false);
92 var target = e.target;
93 var file = target.files[0];
94
95 if (! target.files || target.files.length <= 0) // FileAPI appears to be not present, handle files on backend.
96 {
97 if ($('input[name="userfile"]').val().length > 0)
98 this.checkSubmit();
99 console.log('FileAPI not detected');
100 return false;
101 }
102
103 var status = this.checkUpload(file);
104 this.debug('check upload status ' + status);
105 this.debug('file size:' + file.size);
106
107 if (status)
108 {
109 this.updatePreview(file);
110 }
111 else {
112 this.updatePreview(null);
113 }
114 this.checkSubmit();
115 },
116 this.updatePreview = function(file)
117 {
118 var preview = $('.image_placeholder').last();
119
120 $(preview).find('img').remove();
121 $(preview).removeClass('is_image not_image is_document');
122 var is_empty = false;
123
124 if (file !== null) /// file is null when empty, or error
125 {
126 target_is_image = (file.type.indexOf('image') >= 0) ? true : false;
127 target_type = file.type.trim();
128 }
129 else
130 {
131 is_empty = true;
132 }
133 // If image, load thumbnail and get dimensions.
134 if (file && target_is_image)
135 {
136 var img = new Image();
137 img.src = window.URL.createObjectURL(file);
138 self = this;
139
140 img.setAttribute('style', 'max-width:100%; max-height: 100%;');
141 img.addEventListener("load", function () {
142 // with formats like svg it can be rough.
143 var width = img.naturalWidth;
144 var height = img.naturalHeight;
145 if (width == 0)
146 width = img.width;
147 if (height == 0)
148 height = img.height;
149 // $(preview).find('.textlayer').text(img.naturalWidth + ' x ' + img.naturalHeight );
150 self.updateTextLayer(preview, width + ' x ' + height);
151 self.updateFileSize(preview, file);
152 });
153
154 $(preview).prepend(img);
155 $(preview).addClass('is_image');
156 }
157 else if(file === null)
158 {
159 $(preview).addClass('not_image');
160 $(preview).find('.dashicons').removeClass().addClass('dashicons dashicons-no');
161 //$(preview).find('.textlayer').text('');
162 this.updateTextLayer(preview, '');
163 this.updateFileSize(preview, null);
164 this.debug('File is null');
165 }
166 else { // not an image
167 $(preview).addClass('not_image is_document');
168 $(preview).find('.dashicons').removeClass().addClass('dashicons dashicons-media-document');
169 //$(preview).find('.textlayer').text(file.name);
170 this.updateTextLayer(preview, file.name);
171 this.updateFileSize(preview, file);
172 this.debug('Not image, media document');
173 }
174
175 if (! is_empty && target_type != source_type)
176 {
177 this.debug(target_type + ' not ' + source_type);
178 var falsePositive = this.checkFalsePositiveType(source_type, target_type);
179 if (! falsePositive)
180 this.warningFileType(source_type, target_type);
181 }
182
183 if (! is_empty && emr_options.allowed_mime.indexOf(target_type) == -1)
184 {
185 this.debug(target_type + ' not ' + ' in allowed types ');
186 var falsePositive = this.checkFalsePositiveType(source_type, target_type);
187
188 if (! falsePositive)
189 this.warningMimeType();
190 }
191 // this.debug(emr_options.allowed_mime);
192
193 }
194 this.checkFalsePositiveType = function(source_type, target_type)
195 {
196 // windows (sigh) reports application/zip as application/x-zip-compressed. Or something else, why not.
197 if (source_type.indexOf('zip') >= 0 && target_type.indexOf('zip') >= 0)
198 {
199 this.debug('Finding ' + source_type + ' ' + target_type + ' close enough, false positive');
200 return true;
201 }
202 return false;
203 }
204 // replace the text, check if text is there ( or hide ), and fix the layout.
205 this.updateTextLayer = function (preview, newtext)
206 {
207 textlayer = $(preview).find('.textlayer');
208 textlayer.css('opacity', '0');
209 if (newtext !== false)
210 textlayer.text(newtext);
211
212 if (textlayer.text() !== '')
213 {
214 textlayer.css('opacity', '0.7');
215 // textlayer.css('margin-left', '-' + (textlayer.width() / 2 ) + 'px');
216 }
217
218 },
219 this.updateFileSize = function(preview, file)
220 {
221 if (file === null)
222 {
223 $(preview).find('.image_size').text('');
224 return;
225 }
226 var bytes = file.size;
227 if (bytes == 0) { return "0.00 B"; }
228 var e = Math.floor(Math.log(bytes) / Math.log(1024));
229 var size = (bytes/Math.pow(1024, e)).toFixed(2)+' '+' KMGTP'.charAt(e)+'B';
230
231 $(preview).find('.image_size').text(size);
232 }
233 this.updateCustomDate = function(e)
234 {
235 var $target = $(e.target);
236 var min = $target.data('min');
237 var hour = $target.data('hour');
238 var date = $target.data('date');
239 var format = $target.data('format');
240
241 $('input[name="custom_date"]').val(date);
242 $('input[name="custom_hour"]').val(hour);
243 $('input[name="custom_minute"]').val(min);
244 $('input[name="custom_date_formatted"]').val(format);
245 }
246 this.checkSubmit = function()
247 {
248 var check = ($('input[name="userfile"]').val().length > 0) ? true : false;
249
250 if (check)
251 {
252 $('input[type="submit"]').prop('disabled', false);
253 }
254 else {
255 $('input[type="submit"]').prop('disabled', true);
256 }
257 },
258 this.toggleErrors = function(toggle)
259 {
260 $('.form-error').fadeOut();
261 $('.form-warning').fadeOut();
262 },
263 this.checkUpload = function(fileItem)
264 {
265 var maxsize = emr_options.maxfilesize;
266
267 if ($('input[name="userfile"]').val().length <= 0)
268 {
269 console.info('[EMR] - Upload file value not set in form. Pick a file');
270 $('input[name="userfile"]').val('');
271 return false;
272 }
273
274 if (fileItem.size > maxsize)
275 {
276 console.info('[EMR] - File too big for uploading - exceeds upload limits');
277 this.errorFileSize(fileItem);
278 $('input[name="userfile"]').val('');
279 return false;
280 }
281 return true;
282 },
283 this.errorFileSize = function(fileItem)
284 {
285 $('.form-error.filesize').find('.fn').text(fileItem.name);
286 $('.form-error.filesize').fadeIn();
287 }
288 this.warningFileType = function(source_type, target_type)
289 {
290 $('.form-warning.filetype').find('.source_type').text(source_type);
291 $('.form-warning.filetype').find('.target_type').text(target_type);
292 $('.form-warning.filetype').fadeIn();
293 }
294 this.warningMimeType = function(fileItem)
295 {
296 $('.form-warning.mimetype').fadeIn();
297 }
298 this.debug = function(message)
299 {
300 console.debug(message);
301 }
302 this.showReplaceOptions = function(e)
303 {
304 $('section.options .location_option').hide();
305 var replace_option = $('input[name="replace_type"]:checked').val();
306 if (replace_option == 'replace_and_search')
307 {
308 $('section.options .location_option').show();
309 }
310
311 }
312 this.dragOverArea = function(e)
313 {
314 e.preventDefault();
315 e.stopPropagation();
316
317 if ( this.is_dragging)
318 return;
319
320 //this.debug('dragover');
321 //$('.emr_drop_area').css('border-color', '#83b4d8');
322 $('.emr_drop_area').addClass('drop_breakout');
323 this.is_dragging = true;
324 }
325 this.dragOutArea = function(e)
326 {
327 e.preventDefault();
328 e.stopPropagation();
329 // this.debug('dragout');
330 //$('.emr_drop_area').css('border-color', '#b4b9be');
331 $('.emr_drop_area').removeClass('drop_breakout');
332 this.is_dragging = false;
333 }
334 this.fileDrop = function (e)
335 {
336 var ev = e.originalEvent;
337 this.dragOutArea(e);
338 ev.preventDefault();
339 e.preventDefault();
340
341 if (ev.dataTransfer.items) {
342 // Use DataTransferItemList interface to access the file(s)
343 document.getElementById('userfile').files = ev.dataTransfer.files;
344 $('input[name="userfile"]').trigger('change');
345 }
346 }
347 } // emrIf
348
349 jQuery(document).ready(function($)
350 {
351 window.enableMediaReplace = new emrIf($);
352 window.enableMediaReplace.init();
353 });
354
355
356 function emrDelayedInit() {
357 console.log('Checking delayed init ');
358 if(typeof window.enableMediaReplace == "undefined") {
359 console.log(emrIf);
360 window.enableMediaReplace = new emrIf(jQuery);
361 window.enableMediaReplace.init();
362 }
363 else if (typeof window.enableMediaReplace !== 'undefined')
364 {
365 // All fine.
366 }
367 else { // Nothing yet, try again.
368 setTimeout(emrdelayedInit, 3000);
369 }
370 }
371 setTimeout(emrDelayedInit, 3000);
1 jQuery(document).ready(function($)
2 {
3 $('.emr-installer').on('click', function(e){
4 e.preventDefault();
5 // var $this = $(this);
6 var button = $(this);
7 var plugin = button.data('plugin');
8 var nonce = $('#upsell-nonce').val();
9
10 button.text(emr_upsell.installing);
11
12 var enr_eg_opts = {
13 url: emr_upsell.ajax,
14 type: 'post',
15 async: true,
16 cache: false,
17 dataType: 'json',
18 data: {
19 action: 'emr_plugin_install',
20 nonce: nonce,
21 plugin: plugin //'https://downloads.wordpress.org/plugin/envira-gallery-lite.zip',
22 },
23 success: function(response) {
24 $(button).addClass('hidden');
25
26 $('.emr-activate[data-plugin="' + plugin + '"]').removeClass('hidden');
27
28 },
29 error: function(xhr, textStatus, e) {
30 },
31 };
32
33 $.ajax(enr_eg_opts);
34 });
35
36 $('.emr-activate').on('click', function(e){
37 e.preventDefault();
38
39 var button = $(this);
40 var plugin = button.data('plugin');
41 var nonce = $('#upsell-nonce-activate').val();
42
43 var enr_eg_opts = {
44 url: emr_upsell.ajax,
45 type: 'post',
46 async: true,
47 cache: false,
48 dataType: 'json',
49 data: {
50 action: 'emr_plugin_activate',
51 nonce: nonce,
52 plugin: plugin,
53 },
54 success: function(response) {
55 $(button).addClass('hidden')
56 $('.emr-activate-done[data-plugin="' + plugin + '"]').removeClass('hidden');
57
58 },
59 error: function(xhr, textStatus, e) {
60 },
61 };
62 $.ajax(enr_eg_opts);
63 });
64
65 });
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2010-09-13 14:57+0100\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: Michael Bering Petersen <michaelbering@gmail.com>\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Poedit-SearchPath-0: .\n"
15
16 #: enable-media-replace.php:40
17 #: enable-media-replace.php:68
18 msgid "Replace media"
19 msgstr "Udskift media"
20
21 #: enable-media-replace.php:68
22 msgid "Upload a new file"
23 msgstr "Upload en ny fil"
24
25 #: enable-media-replace.php:68
26 msgid "To replace the current file, click the link and upload a replacement."
27 msgstr "Hvis du ønsker at udskifte den aktuelle fil - klik på linket og upload den nye fil."
28
29 #: popup.php:14
30 #: upload.php:21
31 msgid "You do not have permission to upload files."
32 msgstr "Du har ikke tilladelse til at uploade filer."
33
34 #: popup.php:30
35 msgid "Replace Media Upload"
36 msgstr "Replace Media Upload"
37
38 #: popup.php:41
39 msgid "NOTE: You are about to replace the media file"
40 msgstr "OBS: Du er nu ved at overskrive filen,"
41
42 #: popup.php:41
43 msgid "There is no undo. Think about it!"
44 msgstr "Der er ingen mulighed for at fortryde, så tænkt dig godt om inden du accepterer."
45
46 #: popup.php:43
47 msgid "Choose a file to upload from your computer"
48 msgstr "Vælg den fil du ønsker at uploade fra din computer."
49
50 #: popup.php:47
51 msgid "Select media replacement type:"
52 msgstr "Vælg media type:"
53
54 #: popup.php:49
55 msgid "Just replace the file"
56 msgstr "Udskift filen"
57
58 #: popup.php:50
59 msgid "Note: This option requires you to upload a file of the same type ("
60 msgstr "OBS: Denne mulighed kræver at du uploader en fil af samme type ("
61
62 #: popup.php:50
63 msgid ") as the one you are replacing. The name of the attachment will stay the same ("
64 msgstr ") som den du overskriver. Navnet på filen vil forblive det samme ("
65
66 #: popup.php:50
67 msgid ") no matter what the file you upload is called."
68 msgstr ") uanset hvad den fil du uploader hedder."
69
70 #: popup.php:52
71 msgid "Replace the file, use new file name and update all links"
72 msgstr "Overskriv filen, brug det nye fil navn og opdater alle links-"
73
74 #: popup.php:53
75 msgid "Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file ("
76 msgstr "OBS: Hvis du vælger denne mulighed - vil filnavnet og filtypen som du er ved at uploade overskrive den gamle fil. Alle links der peger på den nuværende fil ("
77
78 #: popup.php:53
79 msgid ") will be updated to point to the new file name."
80 msgstr ") vil blive opdateret så de peger på den nye fil."
81
82 #: popup.php:55
83 msgid "Upload"
84 msgstr "Upload"
85
86 #: popup.php:55
87 msgid "Cancel"
88 msgstr "Fortryd"
89
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2010-09-13 14:57+0100\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: Martin Lettner <m.lettner@gmail.com>\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Poedit-SearchPath-0: .\n"
15
16 #: enable-media-replace.php:40
17 #: enable-media-replace.php:68
18 msgid "Replace media"
19 msgstr "Datei ersetzen"
20
21 #: enable-media-replace.php:68
22 msgid "Upload a new file"
23 msgstr "Eine neue Datei hochladen"
24
25 #: enable-media-replace.php:68
26 msgid "To replace the current file, click the link and upload a replacement."
27 msgstr "Eine neue Datei hochladen, die die aktuelle ersetzen soll."
28
29 #: popup.php:14
30 #: upload.php:21
31 msgid "You do not have permission to upload files."
32 msgstr "Sie haben nicht die benötigten Rechte um Dateien hochzuladen."
33
34 #: popup.php:30
35 msgid "Replace Media Upload"
36 msgstr "Medien-Datei ersetzen"
37
38 #: popup.php:41
39 msgid "NOTE: You are about to replace the media file"
40 msgstr "HINWEIS: Sie sind dabei, eine Datei in der Mediathek zu ersetzen"
41
42 #: popup.php:41
43 msgid "There is no undo. Think about it!"
44 msgstr "Diese Aktion kann nicht rückgängig gemacht werden!"
45
46 #: popup.php:43
47 msgid "Choose a file to upload from your computer"
48 msgstr "Datei vom Computer auswählen:"
49
50 #: popup.php:47
51 msgid "Select media replacement type:"
52 msgstr "Wählen Sie die gewünschte Aktion:"
53
54 #: popup.php:49
55 msgid "Just replace the file"
56 msgstr "Datei einfach ersetzen"
57
58 #: popup.php:50
59 msgid "Note: This option requires you to upload a file of the same type ("
60 msgstr "Hinweis: Die Datei muss vom selben Dateityp sein ("
61
62 #: popup.php:50
63 msgid ") as the one you are replacing. The name of the attachment will stay the same ("
64 msgstr ") wie die Datei, die Sie ersetzen. Der Name der der Datei bleibt erhalten ("
65
66 #: popup.php:50
67 msgid ") no matter what the file you upload is called."
68 msgstr "), ganz egal wie die neue Datei heißt."
69
70 #: popup.php:52
71 msgid "Replace the file, use new file name and update all links"
72 msgstr "Datei ersetzen, aber neuen Dateinamen verwenden und alle Links automatisch aktualisieren"
73
74 #: popup.php:53
75 msgid "Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file ("
76 msgstr "Hinweis: Der Name der neuen Datei wird die alte ersetzen. Alle Verweise auf die aktuelle Datei ("
77
78 #: popup.php:53
79 msgid ") will be updated to point to the new file name."
80 msgstr ") werden auf die neue aktualisiert."
81
82 #: popup.php:55
83 msgid "Upload"
84 msgstr "Hochladen"
85
86 #: popup.php:55
87 msgid "Cancel"
88 msgstr "Abbrechen"
89
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: Enable Media Replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2011-03-24 10:57+0100\n"
6 "PO-Revision-Date: 2011-03-24 11:41+0100\n"
7 "Last-Translator: François Collette <francois.collette@gmail.com>\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: _e;__\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Poedit-SearchPath-0: .\n"
15
16 #: enable-media-replace.php:39
17 #: enable-media-replace.php:67
18 msgid "Replace media"
19 msgstr "Remplacer le média"
20
21 #: enable-media-replace.php:67
22 msgid "Upload a new file"
23 msgstr "Choisir le nouveau fichier"
24
25 #: enable-media-replace.php:67
26 msgid "To replace the current file, click the link and upload a replacement."
27 msgstr "Pour remplacer le fichier actuel, cliquez ci-dessus et choisissez le nouveau fichier."
28
29 #: popup.php:14
30 #: upload.php:3
31 msgid "You do not have permission to upload files."
32 msgstr "Vous n'avez pas la permission d'envoyer des fichiers."
33
34 #: popup.php:30
35 msgid "Replace Media Upload"
36 msgstr "Remplacement de média"
37
38 #: popup.php:46
39 msgid "NOTE: You are about to replace the media file"
40 msgstr "ATTENTION : vous vous apprêtez à remplacer le fichier"
41
42 #: popup.php:46
43 msgid "There is no undo. Think about it!"
44 msgstr "Cette opération est irréversible. Soyez sûr(e) de vous !"
45
46 #: popup.php:48
47 msgid "Choose a file to upload from your computer"
48 msgstr "Envoyez un fichier depuis votre ordinateur :"
49
50 #: popup.php:52
51 msgid "Select media replacement type:"
52 msgstr "Choisissez la méthode de remplacement :"
53
54 #: popup.php:54
55 msgid "Just replace the file"
56 msgstr "Remplacer le fichier seulement"
57
58 #: popup.php:55
59 msgid "Note: This option requires you to upload a file of the same type ("
60 msgstr "Avec cette option, vous devez choisir un fichier du même type ("
61
62 #: popup.php:55
63 msgid ") as the one you are replacing. The name of the attachment will stay the same ("
64 msgstr ") que le précédent. Le nom du fichier actuel ("
65
66 #: popup.php:55
67 msgid ") no matter what the file you upload is called."
68 msgstr ") sera conservé, quel que soit le nom de votre nouveau fichier."
69
70 #: popup.php:57
71 msgid "Replace the file, use new file name and update all links"
72 msgstr "Remplacer le fichier, utiliser le nouveau nom de fichier et mettre à jour tous les liens"
73
74 #: popup.php:58
75 msgid "Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file ("
76 msgstr "Avec cette option, le nom et le type de votre nouveau fichier vont remplacer ceux du fichier actuel. Tous les liens vers celui-ci ("
77
78 #: popup.php:58
79 msgid ") will be updated to point to the new file name."
80 msgstr ") seront mis à jour selon le nouveau nom du fichier."
81
82 #: popup.php:60
83 msgid "Upload"
84 msgstr "Envoyer"
85
86 #: popup.php:60
87 msgid "Cancel"
88 msgstr "Annuler"
89
90 #: upload.php:35
91 msgid "File type does not meet security guidelines. Try another."
92 msgstr "Ce type de fichier est incompatible avec les règles de sécurité. Essayez-en un autre."
93
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: Enable Media Replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2011-03-24 10:57+0100\n"
6 "PO-Revision-Date: 2012-11-27 12:03+0100\n"
7 "Last-Translator: Marco <marco@blackstudio.it>\n"
8 "Language-Team: Black Studio <info@blackstudio.it>\n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: _e;__\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Poedit-Language: Italian\n"
15 "X-Poedit-Country: ITALY\n"
16 "X-Poedit-SearchPath-0: .\n"
17
18 #: enable-media-replace.php:39
19 #: enable-media-replace.php:67
20 msgid "Replace media"
21 msgstr "Sostituisci file"
22
23 #: enable-media-replace.php:67
24 msgid "Upload a new file"
25 msgstr "Carica un nuovo file"
26
27 #: enable-media-replace.php:67
28 msgid "To replace the current file, click the link and upload a replacement."
29 msgstr "Per sostituire il file corrente, clicca il link e carica un file sostitutivo."
30
31 #: popup.php:14
32 #: upload.php:3
33 msgid "You do not have permission to upload files."
34 msgstr "Non hai sufficienti permessi per caricare file."
35
36 #: popup.php:30
37 msgid "Replace Media Upload"
38 msgstr "Caricamento file sostitutivo"
39
40 #: popup.php:46
41 msgid "NOTE: You are about to replace the media file"
42 msgstr "NOTA: Stai per sostituire il file"
43
44 #: popup.php:46
45 msgid "There is no undo. Think about it!"
46 msgstr "Questa operazione non è reversibile. Fai attenzione!"
47
48 #: popup.php:48
49 msgid "Choose a file to upload from your computer"
50 msgstr "Seleziona un file da caricare dal tuo computer"
51
52 #: popup.php:52
53 msgid "Select media replacement type:"
54 msgstr "Seleziona il tipo di sostituzione:"
55
56 #: popup.php:54
57 msgid "Just replace the file"
58 msgstr "Sostituire semplicemente il file"
59
60 #: popup.php:55
61 msgid "Note: This option requires you to upload a file of the same type ("
62 msgstr "Nota: Questa opzione richiede il caricamento di un file dello stesso tipo ("
63
64 #: popup.php:55
65 msgid ") as the one you are replacing. The name of the attachment will stay the same ("
66 msgstr ") di quello sostituito. Il nome dell'allegato rimarrà invariato ("
67
68 #: popup.php:55
69 msgid ") no matter what the file you upload is called."
70 msgstr ") indipendentemente dal nome del file caricato."
71
72 #: popup.php:57
73 msgid "Replace the file, use new file name and update all links"
74 msgstr "Sostituire il file, usare il nome del nuovo file ed aggiornare tutti i collegamenti"
75
76 #: popup.php:58
77 msgid "Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file ("
78 msgstr "Nota: Se selezioni questa opzione, il nome ed il tipo di file che stai per caricare sostituiranno quelli del file precedente. Tutti i collegamenti che puntavano al file precedente ("
79
80 #: popup.php:58
81 msgid ") will be updated to point to the new file name."
82 msgstr ") saranno aggiornati per puntare al nuovo file."
83
84 #: popup.php:60
85 msgid "Upload"
86 msgstr "Carica"
87
88 #: popup.php:60
89 msgid "Cancel"
90 msgstr "Annulla"
91
92 #: upload.php:35
93 msgid "File type does not meet security guidelines. Try another."
94 msgstr "Il tipo di file non rispetta le restrizioni di sicurezza. Riprova con un altro tipo."
95
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2015-01-19 09:00+0900\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: chacomv\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Generator: Poedit 1.5.7\n"
15 "X-Poedit-SearchPath-0: .\n"
16
17 #: enable-media-replace.php:40 enable-media-replace.php:79
18 #: enable-media-replace.php:120
19 msgid "Replace media"
20 msgstr "メディアを置換"
21
22 #: enable-media-replace.php:79
23 msgid "Upload a new file"
24 msgstr "新しいファイルをアップロード"
25
26 #: enable-media-replace.php:79
27 msgid "To replace the current file, click the link and upload a replacement."
28 msgstr ""
29 "現在のファイルを置換するには、このリンクをクリックしてアップロードします。"
30
31 #: enable-media-replace.php:168
32 msgid "Revised"
33 msgstr "変更されました"
34
35 #: popup.php:14 upload.php:3
36 msgid "You do not have permission to upload files."
37 msgstr "ファイルをアップロードする権限がありません。"
38
39 #: popup.php:30
40 msgid "Replace Media Upload"
41 msgstr "新しいメディアファイルをアップロード"
42
43 #: popup.php:46
44 msgid "NOTE: You are about to replace the media file"
45 msgstr "※ このメディアを置き換えようとしています。"
46
47 #: popup.php:46
48 msgid "There is no undo. Think about it!"
49 msgstr "元に戻せませんのでご注意ください。"
50
51 #: popup.php:48
52 msgid "Choose a file to upload from your computer"
53 msgstr "コンピューターからアップロードするファイルを選択"
54
55 #: popup.php:52
56 msgid "Select media replacement type:"
57 msgstr "メディアを置換する方式を選択:"
58
59 #: popup.php:54
60 msgid "Just replace the file"
61 msgstr "ファイルの置換のみ"
62
63 #: popup.php:55
64 msgid "Note: This option requires you to upload a file of the same type ("
65 msgstr ""
66 "※ このオプションは、元のファイルと同じファイル形式でアップロードする必要があ"
67 "ります。("
68
69 #: popup.php:55
70 msgid ""
71 ") as the one you are replacing. The name of the attachment will stay the "
72 "same ("
73 msgstr ") ファイル名は同じになります。("
74
75 #: popup.php:55
76 msgid ") no matter what the file you upload is called."
77 msgstr ")"
78
79 #: popup.php:57
80 msgid "Replace the file, use new file name and update all links"
81 msgstr "ファイルを置換して新しいファイル名で全てのリンクを更新する"
82
83 #: popup.php:58
84 msgid ""
85 "Note: If you check this option, the name and type of the file you are about "
86 "to upload will replace the old file. All links pointing to the current file ("
87 msgstr ""
88 "※ このオプションをチェックすると、アップロードしたファイルの名称と形式に置換"
89 "されます。現在のファイル名("
90
91 #: popup.php:58
92 msgid ") will be updated to point to the new file name."
93 msgstr ")へのリンクが全て新しいファイル名に更新されます。"
94
95 #: popup.php:60
96 msgid "Upload"
97 msgstr "アップロード"
98
99 #: popup.php:60
100 msgid "Cancel"
101 msgstr "キャンセル"
102
103 #: upload.php:33
104 msgid "File type does not meet security guidelines. Try another."
105 msgstr ""
106 "ファイル形式がセキュリティ的に許可されません。他の形式をお試しください。"
107
108 #: popup.php:63
109 msgid ""
110 "Please note that if you upload a new image, only embeds/links of the "
111 "original size image will be replaced in your posts."
112 msgstr ""
113 "新しいファイルをアップロードすると、元のサイズの画像へのリンクや埋め込みのみ"
114 "が置換されますのでご注意ください。"
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2010-09-10 20:53+0100\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: WarmStal D!sign | Ben ter Stal <mail@warmstal.nl>\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Poedit-SearchPath-0: .\n"
15
16 #: enable-media-replace.php:26
17 #: enable-media-replace.php:45
18 msgid "Replace media"
19 msgstr "Vervangen media"
20
21 #: enable-media-replace.php:45
22 msgid "Upload a new file"
23 msgstr "Uploaden nieuw bestand"
24
25 #: enable-media-replace.php:45
26 msgid "To replace the current file, click the link and upload a replacement."
27 msgstr "Klik om het bestaande bestand te vervangen door een nieuw te uploaden bestand."
28
29 #: popup.php:7
30 #: upload.php:10
31 msgid "You do not have permission to upload files."
32 msgstr "U heeft geen rechten om bestanden te uplaoden"
33
34 #: popup.php:23
35 msgid "Replace Media Upload"
36 msgstr "Replace Media Upload"
37
38 #: popup.php:34
39 msgid "NOTE: You are about to replace the media file"
40 msgstr "Opmerking: U staat op het punt het media bestand"
41
42 #: popup.php:34
43 msgid "There is no undo. Think about it!"
44 msgstr "Deze bewerking kan niet ongedaan worden gemaakt!"
45
46 #: popup.php:36
47 msgid "Choose a file to upload from your computer"
48 msgstr "Selecteer een bestand op de PC om te uploaden"
49
50 #: popup.php:40
51 msgid "Select media replacement type:"
52 msgstr "Selecteer de wijze van vervanging"
53
54 #: popup.php:42
55 msgid "Just replace the file"
56 msgstr "Vervang alleen het bestand"
57
58 #: popup.php:43
59 msgid "Note: This option requires you to upload a file of the same type ("
60 msgstr "Opmerking: voor deze optie moet u een bestand van hetzelfde type uploaden ("
61
62 #: popup.php:43
63 msgid ") as the one you are replacing. The name of the attachment will stay the same ("
64 msgstr ") De naam in de media bibliotheek blijft hetzelfde ("
65
66 #: popup.php:43
67 msgid ") no matter what the file you upload is called."
68 msgstr ") onafhankelijk van de naam van het nieuwe bestand."
69
70 #: popup.php:45
71 msgid "Replace the file, use new file name and update all links"
72 msgstr "Vervang het bestand, gebruik de nieuwe naam en werk alle links bij."
73
74 #: popup.php:46
75 msgid "Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file ("
76 msgstr "Opmerking: bij deze keuze wordt het bestand volledig vervangen. Alle links naar het huidige bestand ("
77
78 #: popup.php:46
79 msgid ") will be updated to point to the new file name."
80 msgstr ") worden bijgewerkt naar het nieuwe bestand."
81
82 #: popup.php:48
83 msgid "Upload"
84 msgstr "Uploaden"
85
86 #: popup.php:48
87 msgid "Cancel"
88 msgstr "Annuleren"
89
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2010-09-13 14:57+0100\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: Roger <rogerhnn@hotmail.com>\n"
8 "Language-Team: Roger Nobrega <rogerhnn@hotmail.com>\n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Generator: Poedit 1.5.4\n"
15 "Language: Português - Brasil\n"
16 "X-Poedit-SourceCharset: UTF-8\n"
17 "X-Poedit-SearchPath-0: .\n"
18
19 #: enable-media-replace.php:40 enable-media-replace.php:68
20 msgid "Replace media"
21 msgstr "Substituir mídia"
22
23 #: enable-media-replace.php:68
24 msgid "Upload a new file"
25 msgstr "Enviar novo arquivo"
26
27 #: enable-media-replace.php:68
28 msgid "To replace the current file, click the link and upload a replacement."
29 msgstr ""
30 "Para subtituir o arquivo atual, clique no link e carregue um substituto"
31
32 #: popup.php:14 upload.php:21
33 msgid "You do not have permission to upload files."
34 msgstr "Você não tem permissões para enviar arquivos."
35
36 #: popup.php:30
37 msgid "Replace Media Upload"
38 msgstr "Enviar Mídia Substituta"
39
40 #: popup.php:41
41 msgid "NOTE: You are about to replace the media file"
42 msgstr "NOTA: Você irá substituir o arquivo de mídia"
43
44 #: popup.php:41
45 msgid "There is no undo. Think about it!"
46 msgstr "Não é possível cancelar esta ação."
47
48 #: popup.php:43
49 msgid "Choose a file to upload from your computer"
50 msgstr "Escolha um arquivo para enviar do seu computador"
51
52 #: popup.php:47
53 msgid "Select media replacement type:"
54 msgstr "Selecione o tipo de substituição"
55
56 #: popup.php:49
57 msgid "Just replace the file"
58 msgstr "Apenas substituir arquivo"
59
60 #: popup.php:50
61 msgid "Note: This option requires you to upload a file of the same type ("
62 msgstr "Nota: Esta opção requer o carregamento de um arquivo do mesmo tipo ("
63
64 #: popup.php:50
65 msgid ""
66 ") as the one you are replacing. The name of the attachment will stay the "
67 "same ("
68 msgstr ""
69 ") do que está sendo substituído. O nome do arquivo permanecerá o mesmo("
70
71 #: popup.php:50
72 msgid ") no matter what the file you upload is called."
73 msgstr "), independente do nome do arquivo enviado."
74
75 #: popup.php:52
76 msgid "Replace the file, use new file name and update all links"
77 msgstr ""
78 "Substituir o arquivo, usar o novo nome de arquivo, e atualizar todos os links"
79
80 #: popup.php:53
81 msgid ""
82 "Note: If you check this option, the name and type of the file you are about "
83 "to upload will replace the old file. All links pointing to the current file ("
84 msgstr ""
85 "Nota: Se selecionar esta opção, o nome e tipo do arquivo que você enviar irá "
86 "substituir os do arquivo antigo. Todos os links do arquivo atual ("
87
88 #: popup.php:53
89 msgid ") will be updated to point to the new file name."
90 msgstr ") serão atualizados para o novo arquivo."
91
92 #: popup.php:55
93 msgid "Upload"
94 msgstr "Enviar"
95
96 #: popup.php:55
97 msgid "Cancel"
98 msgstr "Cancelar"
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2017-02-10 08:48+0000\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: Pedro Mendonça <ped.gaspar@gmail.com>\n"
8 "Language-Team: Pedro Mendonça <ped.gaspar@gmail.com>\n"
9 "Language: pt_PT\n"
10 "MIME-Version: 1.0\n"
11 "Content-Type: text/plain; charset=UTF-8\n"
12 "Content-Transfer-Encoding: 8bit\n"
13 "X-Poedit-KeywordsList: __;_e\n"
14 "X-Poedit-Basepath: ..\n"
15 "X-Generator: Poedit 1.8.11\n"
16 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17 "X-Poedit-SourceCharset: UTF-8\n"
18 "X-Poedit-WPHeader: enable-media-replace.php\n"
19 "X-Poedit-SearchPath-0: .\n"
20
21 #: enable-media-replace.php:38 enable-media-replace.php:64
22 #: enable-media-replace.php:105
23 msgid "Replace media"
24 msgstr "Substituir multimédia"
25
26 #: enable-media-replace.php:64
27 msgid "Upload a new file"
28 msgstr "Carregar novo ficheiro"
29
30 #: enable-media-replace.php:64
31 msgid "To replace the current file, click the link and upload a replacement."
32 msgstr ""
33 "Para subtituir o ficheiro actual, clique na ligação e carregue um substituto."
34
35 #: enable-media-replace.php:156
36 msgid "Revised"
37 msgstr "Revisto"
38
39 #: popup.php:14 upload.php:3
40 msgid "You do not have permission to upload files."
41 msgstr "Não tem permissão para carregar ficheiros."
42
43 #: popup.php:29
44 msgid "Replace Media Upload"
45 msgstr "Carregar multimédia de substituição"
46
47 #: popup.php:45
48 #, php-format
49 msgid ""
50 "NOTE: You are about to replace the media file \"%s\". There is no undo. "
51 "Think about it!"
52 msgstr ""
53 "NOTA: Está prestes a substituir o ficheiro multimédia \"%s\". Não será "
54 "possível voltar a trás!"
55
56 #: popup.php:47
57 msgid "Choose a file to upload from your computer"
58 msgstr "Escolher um ficheiro para carregar a partir do computador"
59
60 #: popup.php:54
61 msgid "Select media replacement type:"
62 msgstr "Seleccione o tipo de substituição de multimédia:"
63
64 #: popup.php:56
65 msgid "Just replace the file"
66 msgstr "Apenas substituir o ficheiro"
67
68 #: popup.php:57
69 #, php-format
70 msgid ""
71 "Note: This option requires you to upload a file of the same type (%s) as the "
72 "one you are replacing. The name of the attachment will stay the same (%s) no "
73 "matter what the file you upload is called."
74 msgstr ""
75 "Nota: Esta opção requer o carregamento de um ficheiro do mesmo tipo (%s) "
76 "daquele a substituir. O nome do ficheiro permanecerá o mesmo (%s), "
77 "independentemente do nome do ficheiro carregado."
78
79 #: popup.php:60
80 msgid "Replace the file, use new file name and update all links"
81 msgstr ""
82 "Substituir o ficheiro, usar o novo nome de ficheiro e actualizar todas as "
83 "ligações"
84
85 #: popup.php:61
86 #, php-format
87 msgid ""
88 "Note: If you check this option, the name and type of the file you are about "
89 "to upload will replace the old file. All links pointing to the current file "
90 "(%s) will be updated to point to the new file name."
91 msgstr ""
92 "Nota: Se seleccionar esta opção, o nome e tipo do ficheiro que está prestes "
93 "a carregar irá substituir os do ficheiro antigo. Todas as ligações que "
94 "referenciam o ficheiro actual (%s) serão actualizadas de modo a referenciar "
95 "o novo nome de ficheiro."
96
97 #: popup.php:62
98 msgid ""
99 "Please note that if you upload a new image, only embeds/links of the "
100 "original size image will be replaced in your posts."
101 msgstr ""
102 "Por favor tenha em atenção que se carregar uma nova imagem, apenas as "
103 "imagens incorporadas e ligações com o tamanho original serão substituídas "
104 "nos seus artigos."
105
106 #: popup.php:67
107 msgid "Upload"
108 msgstr "Carregar"
109
110 #: popup.php:67
111 msgid "Cancel"
112 msgstr "Cancelar"
113
114 #: upload.php:26
115 #, php-format
116 msgid ""
117 "The file %1$s can not be deleted by the web server, most likely because the "
118 "permissions on the file are wrong."
119 msgstr ""
120 "O ficheiro %1$s não pode ser apagado pelo servidor web, provavelmente porque "
121 "as permissões do ficheiro estão incorrectas."
122
123 #: upload.php:84
124 msgid "File type does not meet security guidelines. Try another."
125 msgstr ""
126 "O tipo de ficheiro não está de acordo com os padrões de segurança. Tente "
127 "outro."
128
129 #. Plugin Name of the plugin/theme
130 msgid "Enable Media Replace"
131 msgstr "Enable Media Replace"
132
133 #. Plugin URI of the plugin/theme
134 msgid "http://www.mansjonasson.se/enable-media-replace"
135 msgstr "http://www.mansjonasson.se/enable-media-replace"
136
137 #. Description of the plugin/theme
138 msgid ""
139 "Enable replacing media files by uploading a new file in the \"Edit Media\" "
140 "section of the WordPress Media Library."
141 msgstr ""
142 "Permite substituir ficheiros multimédia através de carregar um novo ficheiro "
143 "na secção \"Editar multimédia\" da biblioteca multimédia do WordPress."
144
145 #. Author of the plugin/theme
146 msgid "Måns Jonasson"
147 msgstr "Måns Jonasson"
148
149 #. Author URI of the plugin/theme
150 msgid "http://www.mansjonasson.se"
151 msgstr "http://www.mansjonasson.se"
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2010-09-13 14:57+0100\n"
6 "PO-Revision-Date: 2013-01-18 14:58+0400\n"
7 "Last-Translator: Vladislav (me@dsigh.ru)\n"
8 "Language-Team: DigitalSigh\n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Poedit-Language: Russian\n"
15 "X-Poedit-Country: RUSSIAN FEDERATION\n"
16 "X-Poedit-SourceCharset: utf-8\n"
17 "X-Poedit-SearchPath-0: .\n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11) ? 0 : ((n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20)) ? 1 : 2)\n"
19
20 #: enable-media-replace.php:40
21 #: enable-media-replace.php:68
22 msgid "Replace media"
23 msgstr "Заменить"
24
25 #: enable-media-replace.php:68
26 msgid "Upload a new file"
27 msgstr "Загрузить новый файл"
28
29 #: enable-media-replace.php:68
30 msgid "To replace the current file, click the link and upload a replacement."
31 msgstr "Для того, чтобы заменить текущий файл, нажмите на ссылку и загрузите замену."
32
33 #: popup.php:14
34 #: upload.php:21
35 msgid "You do not have permission to upload files."
36 msgstr "У вас нет прав для загрузки файлов."
37
38 #: popup.php:30
39 msgid "Replace Media Upload"
40 msgstr "Загрузка файла для замены"
41
42 #: popup.php:41
43 msgid "NOTE: You are about to replace the media file"
44 msgstr "ПРИМЕЧАНИЕ: Вы собираетесь заменить медиафайл"
45
46 #: popup.php:41
47 msgid "There is no undo. Think about it!"
48 msgstr "Данную операцию нельзя отменить. Учтите это!"
49
50 #: popup.php:43
51 msgid "Choose a file to upload from your computer"
52 msgstr "Выберите файл для загрузки с вашего компьютера:"
53
54 #: popup.php:47
55 msgid "Select media replacement type:"
56 msgstr "Выберите тип замены:"
57
58 #: popup.php:49
59 msgid "Just replace the file"
60 msgstr "Только заменить файл"
61
62 #: popup.php:50
63 msgid "Note: This option requires you to upload a file of the same type ("
64 msgstr "Этот вариант требуется, если нужно загрузить файл того же типа ("
65
66 #: popup.php:50
67 msgid ") as the one you are replacing. The name of the attachment will stay the same ("
68 msgstr "), как оригинальный. Имя вложения останется тем же ("
69
70 #: popup.php:50
71 msgid ") no matter what the file you upload is called."
72 msgstr ") не зависимо от того, как называется загружаемый файл."
73
74 #: popup.php:52
75 msgid "Replace the file, use new file name and update all links"
76 msgstr "Заменить файл, использовать новое имя и обновить все ссылки"
77
78 #: popup.php:53
79 msgid "Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file ("
80 msgstr "Если выбрать этот вариант, то имя и тип файла, который вы собираетесь загрузить, заменят старые. Все ссылки, указывающие на текущий файл ("
81
82 #: popup.php:53
83 msgid ") will be updated to point to the new file name."
84 msgstr ") будут обновлены новыми."
85
86 #: popup.php:55
87 msgid "Upload"
88 msgstr "Загрузить"
89
90 #: popup.php:55
91 msgid "Cancel"
92 msgstr "Отмена"
93
94 #~ msgid "Replace media upload"
95 #~ msgstr "Загрузка файла для замены"
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2015-01-16 15:55+0100\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: Måns Jonasson <mans@thejonassons.com>\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Generator: Poedit 1.5.5\n"
15 "X-Poedit-SearchPath-0: ..\n"
16
17 #: ../enable-media-replace.php:40 ../enable-media-replace.php:79
18 #: ../enable-media-replace.php:120
19 msgid "Replace media"
20 msgstr "Ersätt media"
21
22 #: ../enable-media-replace.php:79
23 msgid "Upload a new file"
24 msgstr "Ladda upp en ny fil"
25
26 #: ../enable-media-replace.php:79
27 msgid "To replace the current file, click the link and upload a replacement."
28 msgstr ""
29 "För att ersätta den nuvarande filen, klicka på länken och ladda upp en ny "
30 "fil."
31
32 #: ../enable-media-replace.php:161
33 msgid "Revised"
34 msgstr "Uppdaterad"
35
36 #: ../popup.php:14 ../upload.php:3
37 msgid "You do not have permission to upload files."
38 msgstr "Du har inte tillåtelse att ladda upp filer."
39
40 #: ../popup.php:30
41 msgid "Replace Media Upload"
42 msgstr "Ladda upp ny fil"
43
44 #: ../popup.php:46
45 msgid "NOTE: You are about to replace the media file"
46 msgstr "OBS: Du är på väg att ersätta filen"
47
48 #: ../popup.php:46
49 msgid "There is no undo. Think about it!"
50 msgstr "Det finns inget sätt att ångra. Tänk efter först!"
51
52 #: ../popup.php:48
53 msgid "Choose a file to upload from your computer"
54 msgstr "Välj en fil att ladda upp från din dator"
55
56 #: ../popup.php:55
57 msgid "Select media replacement type:"
58 msgstr "Välj ersättningsform:"
59
60 #: ../popup.php:57
61 msgid "Just replace the file"
62 msgstr "Ersätt bara filen"
63
64 #: ../popup.php:58
65 msgid "Note: This option requires you to upload a file of the same type ("
66 msgstr "Detta val kräver att du laddar upp en fil av exakt samma typ ("
67
68 #: ../popup.php:58
69 msgid ""
70 ") as the one you are replacing. The name of the attachment will stay the "
71 "same ("
72 msgstr ") som den du ersätter. Namnet på filen kommer att behållas ("
73
74 #: ../popup.php:58
75 msgid ") no matter what the file you upload is called."
76 msgstr ") oavsett vad filen du laddar upp heter på din dator."
77
78 #: ../popup.php:61
79 msgid "Replace the file, use new file name and update all links"
80 msgstr "Ersätt filen, använd det nya filnamnet och uppdatera alla länkar"
81
82 #: ../popup.php:62
83 msgid ""
84 "Note: If you check this option, the name and type of the file you are about "
85 "to upload will replace the old file. All links pointing to the current file ("
86 msgstr ""
87 "Om du klickar i den här rutan kommer den även namnet och typen på den nya "
88 "filen du laddar upp helt att ersätta den gamla. Alla länkar som pekar på den "
89 "gamla filen ("
90
91 #: ../popup.php:62
92 msgid ") will be updated to point to the new file name."
93 msgstr ") kommer att uppdateras så att de pekar på det nya filnamnet."
94
95 #: ../popup.php:63
96 msgid ""
97 "Please note that if you upload a new image, only embeds/links of the "
98 "original size image will be replaced in your posts."
99 msgstr ""
100 "Notera att om du laddar upp en ny bild kommer endast inbäddningar/länkar "
101 "till originalstorleken att bytas ut i dina poster."
102
103 #: ../popup.php:68
104 msgid "Upload"
105 msgstr "Ladda upp"
106
107 #: ../popup.php:68
108 msgid "Cancel"
109 msgstr "Avbryt"
110
111 #: ../upload.php:26
112 #, php-format
113 msgid ""
114 "The file %1$s can not be deleted by the web server, most likely because the "
115 "permissions on the file are wrong."
116 msgstr ""
117 "Filen %1$s kan inte raderas av webbservern, troligen på grund av "
118 "filrättigheterna."
119
120 #: ../upload.php:84
121 msgid "File type does not meet security guidelines. Try another."
122 msgstr ""
123 "Den här filen är inte tillåten enligt WordPress säkerhetsinställningar. "
124
125 #~ msgid "Enable Media Replace"
126 #~ msgstr "Ladda upp ny fil"
127
128 #~ msgid ""
129 #~ "This plugin allows you to replace any uploaded media file by uploading a "
130 #~ "new one."
131 #~ msgstr ""
132 #~ "Detta plugin låter dig ersätta en fil i mediebiblioteket genom att ladda "
133 #~ "upp en ny."
134
135 #~ msgid "First, locate the uploaded file you want to replace, using the"
136 #~ msgstr "Hitta först den fil du vill ersätta genom att bläddra i "
137
138 #~ msgid "media library browser"
139 #~ msgstr "mediebiblioteket"
140
141 #~ msgid "Click the \"Edit\" link"
142 #~ msgstr "Tryck på \"Redigera\"-länken"
143
144 #~ msgid ""
145 #~ "Second, click the link \"Upload a new file\" and follow the instructions."
146 #~ msgstr "Tryck sen på länken \"Ladda upp ny fil\" och följ instruktionerna."
147
148 #~ msgid "Replace media upload"
149 #~ msgstr "Ladda upp ny fil"
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: Enable Media Replace v2.6\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: \n"
6 "PO-Revision-Date: 2012-09-18 07:29:17+0000\n"
7 "Last-Translator: Tunghsiao Liu <info@sparanoid.com>\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "Plural-Forms: nplurals=2; plural=n != 1;\n"
13 "X-Poedit-Language: Chinese\n"
14 "X-Poedit-Country: PEOPLE'S REPUBLIC OF CHINA\n"
15 "X-Poedit-SourceCharset: utf-8\n"
16 "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
17 "X-Poedit-Basepath: \n"
18 "X-Poedit-Bookmarks: \n"
19 "X-Poedit-SearchPath-0: .\n"
20 "X-Textdomain-Support: yes"
21
22 #: enable-media-replace.php:39
23 #: enable-media-replace.php:67
24 #@ enable-media-replace
25 msgid "Replace media"
26 msgstr "替换媒体"
27
28 #: enable-media-replace.php:67
29 #@ enable-media-replace
30 msgid "Upload a new file"
31 msgstr "上传新文件"
32
33 #: enable-media-replace.php:67
34 #@ enable-media-replace
35 msgid "To replace the current file, click the link and upload a replacement."
36 msgstr "想要替换当前文件,点击上述链接并上传新文件"
37
38 #: popup.php:14
39 #: upload.php:3
40 #@ enable-media-replace
41 #@ default
42 msgid "You do not have permission to upload files."
43 msgstr "您没有权限上传文件"
44
45 #: popup.php:30
46 #@ enable-media-replace
47 msgid "Replace Media Upload"
48 msgstr "替换媒体文件"
49
50 #: popup.php:46
51 #@ enable-media-replace
52 msgid "NOTE: You are about to replace the media file"
53 msgstr "注意:您将要替换媒体文件"
54
55 #: popup.php:46
56 #@ enable-media-replace
57 msgid "There is no undo. Think about it!"
58 msgstr "此操作无法撤销。"
59
60 #: popup.php:48
61 #@ enable-media-replace
62 msgid "Choose a file to upload from your computer"
63 msgstr "从计算机中选择文件上传"
64
65 #: popup.php:52
66 #@ enable-media-replace
67 msgid "Select media replacement type:"
68 msgstr "选择媒体替换类型"
69
70 #: popup.php:54
71 #@ enable-media-replace
72 msgid "Just replace the file"
73 msgstr "仅替换文件"
74
75 #: popup.php:55
76 #@ enable-media-replace
77 msgid "Note: This option requires you to upload a file of the same type ("
78 msgstr "说明:此选项要求您上传与之前文件相同的文件类型("
79
80 #: popup.php:55
81 #@ enable-media-replace
82 msgid ") as the one you are replacing. The name of the attachment will stay the same ("
83 msgstr "),替换后,无论您上传的文件名是什么,上传后的媒体文件名称与地址都会保持不变("
84
85 #: popup.php:55
86 #@ enable-media-replace
87 msgid ") no matter what the file you upload is called."
88 msgstr ")。"
89
90 #: popup.php:57
91 #@ enable-media-replace
92 msgid "Replace the file, use new file name and update all links"
93 msgstr "替换文件,使用新文件名并更新所有链接"
94
95 #: popup.php:58
96 #@ enable-media-replace
97 msgid "Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file ("
98 msgstr "说明:使用此选项,将会使用新文件的文件名及文件类型,所有包含文件名("
99
100 #: popup.php:58
101 #@ enable-media-replace
102 msgid ") will be updated to point to the new file name."
103 msgstr ")的链接也将会被替换成新文件名。"
104
105 #: popup.php:60
106 #@ enable-media-replace
107 msgid "Upload"
108 msgstr "上传"
109
110 #: popup.php:60
111 #@ enable-media-replace
112 msgid "Cancel"
113 msgstr "取消"
114
115 #: upload.php:33
116 #@ default
117 msgid "File type does not meet security guidelines. Try another."
118 msgstr "文件类型不符合安全规范,请尝试其他文件。"
119
1 msgid ""
2 msgstr ""
3 "Project-Id-Version: enable-media-replace\n"
4 "Report-Msgid-Bugs-To: \n"
5 "POT-Creation-Date: 2015-01-16 17:42-0000\n"
6 "PO-Revision-Date: \n"
7 "Last-Translator: Pedro Mendonça <ped.gaspar@gmail.com>\n"
8 "Language-Team: \n"
9 "MIME-Version: 1.0\n"
10 "Content-Type: text/plain; charset=UTF-8\n"
11 "Content-Transfer-Encoding: 8bit\n"
12 "X-Poedit-KeywordsList: __;_e\n"
13 "X-Poedit-Basepath: .\n"
14 "X-Generator: Poedit 1.7.1\n"
15 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
16 "X-Poedit-SourceCharset: UTF-8\n"
17 "Language: en\n"
18 "X-Poedit-SearchPath-0: .\n"
19 "X-Poedit-SearchPath-1: ..\n"
20
21 #: ../enable-media-replace.php:40 ../enable-media-replace.php:79
22 #: ../enable-media-replace.php:120
23 msgid "Replace media"
24 msgstr ""
25
26 #: ../enable-media-replace.php:79
27 msgid "Upload a new file"
28 msgstr ""
29
30 #: ../enable-media-replace.php:79
31 msgid "To replace the current file, click the link and upload a replacement."
32 msgstr ""
33
34 #: ../enable-media-replace.php:161
35 msgid "Revised"
36 msgstr ""
37
38 #: ../popup.php:14 ../upload.php:3
39 msgid "You do not have permission to upload files."
40 msgstr ""
41
42 #: ../popup.php:30
43 msgid "Replace Media Upload"
44 msgstr ""
45
46 #: ../popup.php:46
47 msgid "NOTE: You are about to replace the media file"
48 msgstr ""
49
50 #: ../popup.php:46
51 msgid "There is no undo. Think about it!"
52 msgstr ""
53
54 #: ../popup.php:48
55 msgid "Choose a file to upload from your computer"
56 msgstr ""
57
58 #: ../popup.php:55
59 msgid "Select media replacement type:"
60 msgstr ""
61
62 #: ../popup.php:57
63 msgid "Just replace the file"
64 msgstr ""
65
66 #: ../popup.php:58
67 msgid "Note: This option requires you to upload a file of the same type ("
68 msgstr ""
69
70 #: ../popup.php:58
71 msgid ""
72 ") as the one you are replacing. The name of the attachment will stay the "
73 "same ("
74 msgstr ""
75
76 #: ../popup.php:58
77 msgid ") no matter what the file you upload is called."
78 msgstr ""
79
80 #: ../popup.php:61
81 msgid "Replace the file, use new file name and update all links"
82 msgstr ""
83
84 #: ../popup.php:62
85 msgid ""
86 "Note: If you check this option, the name and type of the file you are about "
87 "to upload will replace the old file. All links pointing to the current file ("
88 msgstr ""
89
90 #: ../popup.php:62
91 msgid ") will be updated to point to the new file name."
92 msgstr ""
93
94 #: ../popup.php:63
95 msgid ""
96 "Please note that if you upload a new image, only embeds/links of the "
97 "original size image will be replaced in your posts."
98 msgstr ""
99
100 #: ../popup.php:68
101 msgid "Upload"
102 msgstr ""
103
104 #: ../popup.php:68
105 msgid "Cancel"
106 msgstr ""
107
108 #: ../upload.php:26
109 #, php-format
110 msgid ""
111 "The file %1$s can not be deleted by the web server, most likely because the "
112 "permissions on the file are wrong."
113 msgstr ""
114
115 #: ../upload.php:84
116 msgid "File type does not meet security guidelines. Try another."
117 msgstr ""
1 <?php // Silence is golden
...\ No newline at end of file ...\ No newline at end of file
1 === Enable Media Replace ===
2 Contributors: ShortPixel
3 Donate link: https://www.paypal.me/resizeImage
4 Tags: replace, attachment, media, files, replace image, replace jpg, change media, replace media, image, file
5 Requires at least: 4.9.7
6 Tested up to: 5.8
7 Requires PHP: 5.6
8 Stable tag: 3.6.3
9
10 Easily replace any attached image/file by simply uploading a new file in the Media Library edit view - a real time saver!
11
12 == Description ==
13
14 **A free, lightweight and easy to use plugin that allows you to seamlessly replace an image or file in your Media Library by uploading a new file in its place. No more deleting, renaming and re-uploading files!
15 Supported by the friendly team that created <a href="https://wordpress.org/plugins/shortpixel-image-optimiser/" target="_blank">ShortPixel</a> :)**
16
17 #### A real timesaver
18
19 Don't you find it tedious and complicated to have to first delete a file and then upload one with the exact same name every time you want to update an image or any uploaded file inside the WordPress media library?
20
21 Well, no longer!
22
23 Now you'll be able to replace any uploaded file from the media "edit" view, where it should be. Media replacement can be done in one of two ways:
24
25 #### It's simple to replace a file
26
27 1. Just replace the file. This option requires you to upload a file of the same type as the one you are replacing. The name of the attachment will stay the same no matter what the file you upload is called.
28 1. Replace the file, use new file name and update all links. If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file will be updated to point to the new file name. Additional options for the folder where to place the new file, or the date of the new file are also available on the replace screen.
29
30 This plugin is very powerful and a must-have for any larger sites built with WordPress. It now also comes with a preview of the replaced image!
31
32 #### Display file modification time
33
34 There is a shortcode available which picks up the file modification date and displays it in a post or a page. The code is:
35 `[file_modified id=XX format=XXXX]` where the "id" is required and the "format" is optional and defaults to your current WordPress settings for date and time format.
36
37 So `[file_modified id=870]` would display the last time the file with ID 870 was updated on your site. To get the ID for a file, check the URL when editing a file in the media library (see screenshot #4)
38
39 If you want more control over the format used to display the time, you can use the format option, so `[file_modified id=870 format=Y-m-d]` would display the file modification date but not the time. The format string uses [standard PHP date() formatting tags](http://php.net/manual/en/function.date.php).
40
41
42 #### Compatible and recommended Plugins =
43
44 * [ShortPixel Image Optimization](https://wordpress.org/plugins/shortpixel-image-optimiser/) - Enable Media Replace is fully compatible with this plugin. Once enabled, ShortPixel will automatically optimize the images you replace using Enable Media Replace.
45 * [Resize Image After Upload plugin](https://wordpress.org/plugins/resize-image-after-upload/) - automatically resize images upon upload to save traffic & disk space. Good for SEO and compatible with EMR.
46 * [Regenerate Thumbnails Advanced](https://wordpress.org/plugins/regenerate-thumbnails-advanced/) - Fast, free and simple to use plugin to regenerate the thumbnails for your site after changing a theme (for example). Supported & maintained by [ShortPixel](https://ShortPixel.com)
47
48 == Changelog ==
49
50 = 3.6.3 =
51
52 Release date: November 25th, 2021
53 * Fix: the shortcode `file-modified` works again for non-privileged visitors as well;
54 * Compat: if other plugins don't properly use WP Hooks, don't return errors;
55 * Tweak: updated banners list from the EMR screen.
56
57 = 3.6.2 =
58
59 Release date: November 8th, 2021
60 * Fix: there was an issue in file.php with checking mime-type, resulting in weird mime-type values in certain cases (thanks @dougaxe1 for the PR);
61 * Fix: if target mime type returns empty, don't store that;
62 * Tweak: removed old notification about SPIO.
63
64 = 3.6.1 =
65
66 Release date: October 27th, 2021
67 * Fix: there was a broken image in one of the plugin notices;
68 * Fix: added a check for the function `mime_content_type`, which doesn't seem to always be available on various hosts;
69 * Fix: the plugin checks if the current user has rights to install/activate plugins and only then displays the 1-click installers and also a filter is available now;
70
71 = 3.6.0 =
72
73 Release date: October 11th, 2021
74 * New: Constant EMR_CAPABILITY can define extra user roles to allow and deny replacements;
75 * New: Replacing an usual image with an SVG file will just replace all thumbnails by the main file;
76 * New: Also replaces caption when set in Exif data (when replacing with updating all links);
77 * Tweak: Added Now and Original options to Custom Date for usability;
78 * Tweak: changes/updates to the banners from the EMR screen;
79 * Fix: EMR now respects edit_other_posts permissions using default permissions;
80 * Fix: EMR with ALLOW_UNFILTERED_UPLOADS enabled (and allowed role) will not limit non-allowed uploads;
81 * Fix: some missing and wrong text-domains are now corrected (thanks @alexclassroom);
82 * Fix: a missing dot in the plugin description was preventing the transaltions to properly work;
83 * Fix: the plugin can now be uninstalled/deleted on PHP 8.
84
85 = 3.5.0 =
86
87 Release date: October 29th 2020
88 * New: EMR now replaces across all meta tables;
89 * New: the plugin remembers last used settings;
90 * New: integration with the LiteSpeed cache plugin and webserver;
91 * Tweak: manual Logging will no longer work if user is not logged as administrator;
92 * Tweak: added `post_id` to `enable-media-replace-upload-done` action args, props to @Jan Stiegler;
93 * Fix: fully works now with Elementor;
94 * Fix: the issue for WP-Bakery and URL-Encoded links is now fixed;
95 * Fix: the plugin should now work with images added through Visual Composer;
96 * Fix: EMR now uses queries instead of WordPress functions, correctly handling slashes and JSON formats;
97 * Fix: `-scaled` images generated by WordPress are now removed when replacing an image;
98
99 = 3.4.2 =
100
101 Release date: August 17th 2020
102 * New - Also display files size in the replacement windows;
103 * Fix - Replacing image with pdf file would cause noticesi;
104 * Fix - Compensation for faulty WordPress installation that return empty error string on wp_upload_dir and falsely return relative paths and urls on WP core functions;
105 * Fix - When choosing 'replace file and update names' and then uploading a file with identical name as source, it would postfix the duplicate name. This is no longer the case;
106 * Fix - Wording clarification for the situation when the filename is changed, which will lead to broken links from external sites;
107 * Fix - Added hard paths to require_once satements in order to prevent WP-CLI errrors;
108 * Fix - If source image doesn't exist or in error state, replacement would be prevented by Javascript issue.
109
110 = 3.4.1 =
111
112 Release date: June 18th 2020
113 * Fix - PHP Error when settings permissions failed.
114
115 = 3.4.0 =
116
117 Release date: June 9th 2020
118 * New - In edit media screen EMR notes user who replaced file if this was not uploader;
119 * New - Added Drag and Drop area for files;
120 * New - When replacing with new file name, now also possible to update upload path;
121 * Fix - Various minor CSS tweaks and fixes;
122 * Update of Underlying libraries
123
124 = 3.3.12 =
125
126 Release date: 27th April 2020
127 * Fixed - When trying to upload over-limit file would show too many error messages;
128 * Language – 2 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted.
129
130 = 3.3.11 =
131
132 Release date: 10th March 2020
133 * Fix the crashing of certain frontend builders when the plugin is active.
134
135 = 3.3.10 =
136
137 Release date: 23rd February 2020
138 * Fix issue with JSON encoding which was interfering with Advanced Custom Fields and other plugins
139
140 = 3.3.9 =
141
142 Release date: 23rd February 2020
143 * Fix issue with JSON encoded strings
144 * Language – 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted
145
146 Release date: 19th February 2020
147 * Fix issue with search/replacing non-image attachments and query
148 * Language – 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted
149
150 = 3.3.8 =
151
152 Release date: 18th February 2020
153 * Fixes for WP 5.3+ -scaled images system. Will now replace those as well.
154 * Updating and replacing images and thumbnails should now work for serialized (and such) metadata.
155 - For Beaver Builder
156 * Add extra warning if mimetype is not allowed by WordPress for upload
157 * Put Javascript version in wp_register_script
158 * Hidden double 'replace media'
159 * Replace Image label to Replace Media
160 * Removed constant S3_UPLOADS_AUTOENABLE
161 * Improved detection of SVG image sizes
162 * Fixed - Logger doesn't call wp_upload_dir when not debugging
163 * Extra - Javascript tries to resume after external errors.
164 * Language – 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted
165
166 = 3.3.7 =
167
168 Release date: 13th November 2019
169 * call the hook enable-media-replace-upload-done on both modes
170 * fix JSON compatibility for hostings that don't have JSON module activated
171 * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
172
173 = 3.3.6 =
174
175 Release date: 5th September 2019
176 * fix JSON compatibility for hostings that don't have JSON module activated
177
178 = 3.3.5 =
179
180 Release date: 25th July 2019
181 * fix Replace button on the MediaLibrary image details popup
182
183 = 3.3.4 =
184
185 Release date: 23rd July 2019
186 * compatibility fixes for WP version 4.8 and below
187 * cache killer
188
189 = 3.3.3 =
190
191 Release date: 19th July 2019
192 * Fix error "using $this when not in object context" on some PHP versions
193
194 = 3.3.2 =
195
196 Release date: 17th July 2019
197 * Check if medium size !> 400px, display that one, otherwise smallest.
198 * Fixed: Links not updated when using Advanced Custom Fields
199 * Fixed: Fails silently when file is too big for upload
200 * When source file does not exist, show placeholder instead of failed image load
201 * Fixed: Fatal error when replacing images
202 * Fixed: Not the right time zone on replace
203 * Fixed Beaver Builder incompatibility by not allowing replace with rename.
204 * Fixed: Cannot replace non default Wordpress file types, even those allowed to upload [ Media Library Assistant compat ]
205 * Fixed: error when trying to remove a file that doesn't exist - because the files are actually on another server
206
207 = 3.3.1 =
208
209 Release date: 18th June 2019
210 * Fix error class not found on WPEngine
211
212 = 3.3.0 =
213 * When replacing an image and changing the name, Search / Replace is now also done on the meta_value of postmeta.
214 * Replace PDF thumbnails too
215 * Copy title from EXIF
216 * RTL View incorporated into the CSS
217 * ‘wp_handle_upload’ filter should be treated as such (and not as action)
218 * Use wp_attached_file instead of the GUID
219 * Fix: replace missing file
220 * Fix: aphostrophe breaking the upload
221 * Fix: broken "before" image
222 * Fix: update properly the date
223 * Fix: errors for non-image items in Media Library
224 * Fix: empty admin menu item created
225 * Refactored all the code
226
227 = 3.2.9 =
228 * properly replace thumbnails names in the content when the replaced image has a different aspect ratio, thus the new thumbnails have a different height in the name.
229
230 = 3.2.8 =
231 * fix for failures in link updating when replacing file because of addslashes - use prepared query instead
232 * replace basename with wp_basename because basename doesn't work well with UTF8
233
234 = 3.2.7 =
235 * Add minimum required php version to run the plugin.
236 * Security: Prevent direct access to php files.
237 * Security: Prevent direct access to directories.
238 * Security: Escape translation strings using `esc_attr__()` and `esc_html__()` functions.
239 * Fix RTL issues.
240
241 = 3.2.6 =
242 * no more 404 error if no image was selected when trying to replace it
243 * added preview so you can check the image being replaced and also the image that's being replaced with
244 * .dat files can be replaced (functionality accidentally removed in the previous version)
245 * added compatibility with S3 upload plugin
246 * when an image is replaced the date is also updated
247
248 = 3.2.5 =
249 * remove the leftover setcookie and the plugins recommendations.
250
251 = 3.2.4 =
252 * Fix PDF thumbnails not replaced when replacing a PDF
253 * Fix not replacing text files with .dat extension
254
255 = 3.2.3 =
256 * disable ShortPixel recommendation on secondary sites of a multisite install when it was network activated.
257
258 = 3.2.2 =
259 * Fixed compatibility with ShortPixel and Resize Image After Upload
260 * Added ShortPixel links and images, fixed the problem of ShortPixel recommendation not dismissing.
261
262 = 3.2.1 =
263 * Bugfix, typo made metadata changes (thanks GitHub user icecandy!)
264 * Removed Shortpixel links and images
265
266 = 3.2 =
267 * Tested with WP 4.9.4
268 * Added Shortpixel link in replace media screen
269
270 = 3.1.1 =
271 * Fixed bug introduced in an earlier version, preventing the updating of URLs on pages/posts if the link did not contain the domain name
272
273 = 3.1 =
274 * Got rid of some pesky old code, and added some better filtering options, thanks to GitHub users speerface, aaemnnosttv, and ururk
275 * Brand new, shiny code to replace other image sizes in embedded media, thanks to GitHub user ianmjones!
276 * Tested with WP 4.8
277
278 = 3.0.6 =
279 * Tested with WP 4.7.2
280 * New PT translations (thanks Pedro Mendonca! https://github.com/mansj/enable-media-replace/commit/b6e63b9a8a3ae46b3a6664bd5bbf19b2beaf9d3f)
281
282 = 3.0.5 =
283 * Tested with WP 4.6.1
284
285 = 3.0.4 =
286 * Fixed typo in .pt translations (https://github.com/mansj/enable-media-replace/pull/18)
287 * Fixed better error handling in modification date functions (https://github.com/mansj/enable-media-replace/pull/16)
288 * Tested with WP 4.4.1
289
290 = 3.0.3 =
291 * Scrapped old method of detecting media screen, button to replace media will now show up in more places, yay!
292 * Made sure the call to get_attached_file() no longer skips filters, in response to several users wishes.
293 * Suppressed error messages on chmod()
294 * Added Japanese translation (Thank you, chacomv!)
295
296 = 3.0.2 =
297 * Cleaned up language files
298 * Added Portuguese translation (Thanks pedro-mendonca!)
299 * Tested with WP 4.1
300 * Added missing Swedish translation strings
301
302 = 3.0.1 =
303 * Tiny fix to re-insert the EMR link in the media list view.
304
305 = 3.0 =
306 * Updated for WordPress 4.0
307 * Now inheriting permissions of the replaced files, [Thank you Fiwad](https://github.com/fiwad)
308
309 = 2.9.7RC1 =
310 * Moved localization files into their own directory. [Thank you Michael](https://github.com/michael-cannon)
311 * Moved screenshots into their own directory. [Thank you Michael](https://github.com/michael-cannon)
312
313 = 2.9.6 =
314 * Added fix by Grant K Norwood to address a possible security problem in SQL statements. Thanks Grant!
315 * Created GitHub repo for this plugin, please feel free to contribute at github.com/mansj/enable-media-replace
316
317 = 2.9.5 =
318 * Bug fix for the short code displaying the modification date of a file
319 * Updated all database queries in preparation for WP 3.9
320
321 = 2.9.4 =
322 * Bug fix for timezone changes in WordPress
323 * Minor UI change to inform the user about what actually happens when replacing an image and using a new file name
324
325 = 2.9.3 =
326 * Added call to update_attached_file() which should purge changed files for various CDN and cache plugs. Thanks Dylan Barlett for the suggestion! (http://wordpress.org/support/topic/compatibility-with-w3-total-cache)
327 * Suppressed possible error in new hook added in 2.9.2
328
329 = 2.9.2 =
330 * Small bug fix
331 * Added hook for developers to enable purging possible CDN when updating files - thanks rubious for the suggestion!
332
333 = 2.9.1 =
334 * Added Brazilian Portuguese translation, thanks Roger Nobrega!
335 * Added filter hook for file name creation, thanks to Jonas Lundman for the code!
336 * Added modification date to the edit attachment screen, thanks to Jonas Lundman for the code!
337 * Enhanced the deletion method for old file/image thumbnails to never give unnecessary error messages and more accurately delete orphaned thumbs
338
339 = 2.9 =
340 * Added Portuguese translation, thanks Bruno Miguel Bras Silva!
341 * New edit link from media library
342 * After uploading, the plugin now takes you back to edit screen instead of library
343
344 = 2.8.2 =
345 * Made another change to the discovery of media context which will hopefully fix a bug in certain cases. Thanks to "Joolee" at the WordPress.org forums!
346 * Added a new, supposedly better Russian translation from "Vlad".
347
348 = 2.8.1 =
349 * Fixed a small bug which could create error messages on some systems when deleting old image files.
350
351 = 2.8 =
352 * New and safer method for deleting thumbnails when a new image file is uploaded.
353 * New translations for simplified Chinese (thanks Tunghsiao Liu) and Italian (grazie Marco Chiesi)
354 * Added method for detecting upload screen to ensure backward compatibility with versions pre 3.5
355
356 = 2.7 =
357 * A couple of changes made to ensure compatibility with WordPress 3.5. Thanks to Elizabeth Powell for the fixes!
358
359 = 2.6 =
360 * New and improved validation of uploaded files, now using WP's own functions for checking file type and extension. Thanks again to my old friend Ulf "Årsta" Härnhammar for keeping us all on our toes! :) This should also hopefully fix the problems people have been having with their installations claiming that perfectly good PDF files are not allowed file types.
361
362 = 2.5.2 =
363 * The "more reliable way" of determining MIME types turned out to be less reliable. Go figure. There seems to be no perfect way of performing a reliable check for MIME-types on an uploaded file that is also truly portable. I have now made checks for the availability of mime_content_type() before using it, using the old method as a fall-back. It is far from beautiful, so if anybody has a better way of doing it, please contact me!
364
365 = 2.5.1 =
366 * Bug fix - there is now a more reliable way of determining file type on your upload so you can upload PDF files without seeing that pesky "File type does not meet security guidelines" message.
367 * New translation to Danish - thanks to Michael Bering Petersen!
368
369 = 2.5 =
370 * Tested with WordPress 3.2.1
371 * New translation to German - thanks to Martin Lettner!
372 * New translation to French - thanks to François Collette!
373
374 = 2.4.1 =
375 * Bug fix for WordPress 3.1 RC. Now properly tested and should be working with 3.1 whenever it finally comes out. :)
376
377 = 2.4 =
378 * Bug fixes, security fixes. Thanks to my old pal Ulf "&Aring;rsta" H&auml;rnhammar for pointing them out!
379 * New method for uploading avoids going around WP, for greater security.
380
381 = 2.3 =
382 * Lots of code trimmed and enhanced, thanks to Ben ter Stal! Now working properly with Windows systems, better security, optimized loading, and much more.
383 * Added Dutch translation by Ben ter Stal.
384
385 = 2.2 =
386 * Bug fix, fixed typo in popup.php, thanks to Bill Dennen and others for pointing this out!
387
388 = 2.1 =
389 * New shortcode - display file modification date on your site (see description for more info)
390 * A couple of bug fixes for final release of 3.0 - Thanks to Jim Isaacs for pointing them out!
391
392 = 2.0.1 =
393 * Added support for SSL admin
394
395 = 2.0 =
396 * Replaced popup with inline navigation when replacing media
397 * Added instructions in admin link under Media
398
399 = 1.4.1 =
400 * Tested with WordPress 3.0 beta 2
401
402 = 1.4 =
403 * Removed short tags for better compatibility.
404
405 = 1.3 =
406 * Added support for wp_config setting "FORCE_SSL_ADMIN"
407
408 = 1.2 =
409 * Added Russian translation, thanks to Fat Cower.
410
411 = 1.1 =
412 * Minor bugfix, now working with IE8 too!
413
414 = 1.0 =
415 * First stable version of plugin.
416
417 == Installation ==
418
419 Quick and easy installation:
420
421 1. Upload the folder `enable-media-replace` to your plugin directory
422 1. Activate the plugin through the 'Plugins' menu in WordPress
423 1. Done!
424
425 == Frequently Asked Questions ==
426
427 = What does this plugin actually do? =
428
429 This plugin makes it easy to update/replace files that have been uploaded to the WordPress Media Library.
430
431 = How does it work? =
432
433 A new option will be available in the Edit Media view, called "Replace Media". This is where you can upload a new file to replace the old one.
434
435 = I replaced a file, but it didn't change! =
436
437 There are two main reasons this would happen.
438
439 First, make sure you are not viewing a cached version of the file, especially if you replaced an image. Press "Refresh" in your browser to make sure.
440
441 Second, if the file really looks unchanged, make sure WordPress has write permissions to the files in your uploads folder. If you have ever moved your WP installation (maybe when you moved it to a new server), the permissions on your uploaded files are commonly reset so that WordPress no longer has permissions to change the files. If you don't know how to do this, contact your web server operator.
442
443 == Screenshots ==
444
445 1. The new link in the media library.
446 2. The replace media-button as seen in the "Edit media" view.
447 3. The upload options.
448 4. Get the file ID in the edit file URL
449
450 == Wishlist / Coming attractions ==
451
452 Do you have suggestions? Feel free to contact ShortPixel <a href="https://shortpixel.com/contact" target="_blank">here</a>
453
454
455 == Contribute ==
456
457 Want to help us improve the plugin feel free to submit PRs via GitHub <a href="https://github.com/short-pixel-optimizer/enable-media-replace" target="_blank">here</a>.
1 // Straight from jquery UI css
2
3 .ui-widget-content {
4 border: 1px solid #dddddd;
5 background: #ffffff;
6 color: #333333;
7 }
8
9
10 .ui-widget-overlay {
11 position: fixed;
12 top: 0;
13 left: 0;
14 width: 100%;
15 height: 100%;
16 }
17 .ui-datepicker {
18 width: 17em;
19 padding: .2em .2em 0;
20 display: none;
21 }
22 .ui-datepicker .ui-datepicker-header {
23 position: relative;
24 padding: .2em 0;
25 }
26 .ui-datepicker .ui-datepicker-prev,
27 .ui-datepicker .ui-datepicker-next {
28 position: absolute;
29 top: 2px;
30 width: 1.8em;
31 height: 1.8em;
32 }
33 .ui-datepicker .ui-datepicker-prev-hover,
34 .ui-datepicker .ui-datepicker-next-hover {
35 top: 1px;
36 }
37 .ui-datepicker .ui-datepicker-prev {
38 left: 2px;
39 }
40 .ui-datepicker .ui-datepicker-next {
41 right: 2px;
42 }
43 .ui-datepicker .ui-datepicker-prev-hover {
44 left: 1px;
45 }
46 .ui-datepicker .ui-datepicker-next-hover {
47 right: 1px;
48 }
49 .ui-datepicker .ui-datepicker-prev span,
50 .ui-datepicker .ui-datepicker-next span {
51 display: block;
52 position: absolute;
53 left: 50%;
54 margin-left: -8px;
55 top: 50%;
56 margin-top: -8px;
57 }
58 .ui-datepicker .ui-datepicker-title {
59 margin: 0 2.3em;
60 line-height: 1.8em;
61 text-align: center;
62 }
63 .ui-datepicker .ui-datepicker-title select {
64 font-size: 1em;
65 margin: 1px 0;
66 }
67 .ui-datepicker select.ui-datepicker-month,
68 .ui-datepicker select.ui-datepicker-year {
69 width: 45%;
70 }
71 .ui-datepicker table {
72 width: 100%;
73 font-size: .9em;
74 border-collapse: collapse;
75 margin: 0 0 .4em;
76 }
77 .ui-datepicker th {
78 padding: .7em .3em;
79 text-align: center;
80 font-weight: bold;
81 border: 0;
82 }
83 .ui-datepicker td {
84 border: 0;
85 padding: 1px;
86 }
87 .ui-datepicker td span,
88 .ui-datepicker td a {
89 display: block;
90 padding: .2em;
91 text-align: center;
92 text-decoration: none;
93 }
94 .ui-datepicker .ui-datepicker-buttonpane {
95 background-image: none;
96 margin: .7em 0 0 0;
97 padding: 0 .2em;
98 border-left: 0;
99 border-right: 0;
100 border-bottom: 0;
101 }
102 .ui-datepicker .ui-datepicker-buttonpane button {
103 float: right;
104 margin: .5em .2em .4em;
105 cursor: pointer;
106 padding: .2em .6em .3em .6em;
107 width: auto;
108 overflow: visible;
109 }
110 .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
111 float: left;
112 }
113
114 /* with multiple calendars */
115 .ui-datepicker.ui-datepicker-multi {
116 width: auto;
117 }
118 .ui-datepicker-multi .ui-datepicker-group {
119 float: left;
120 }
121 .ui-datepicker-multi .ui-datepicker-group table {
122 width: 95%;
123 margin: 0 auto .4em;
124 }
125 .ui-datepicker-multi-2 .ui-datepicker-group {
126 width: 50%;
127 }
128 .ui-datepicker-multi-3 .ui-datepicker-group {
129 width: 33.3%;
130 }
131 .ui-datepicker-multi-4 .ui-datepicker-group {
132 width: 25%;
133 }
134 .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
135 .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
136 border-left-width: 0;
137 }
138 .ui-datepicker-multi .ui-datepicker-buttonpane {
139 clear: left;
140 }
141 .ui-datepicker-row-break {
142 clear: both;
143 width: 100%;
144 font-size: 0;
145 }
146
147 /* RTL support */
148 .ui-datepicker-rtl {
149 direction: rtl;
150 }
151 .ui-datepicker-rtl .ui-datepicker-prev {
152 right: 2px;
153 left: auto;
154 }
155 .ui-datepicker-rtl .ui-datepicker-next {
156 left: 2px;
157 right: auto;
158 }
159 .ui-datepicker-rtl .ui-datepicker-prev:hover {
160 right: 1px;
161 left: auto;
162 }
163 .ui-datepicker-rtl .ui-datepicker-next:hover {
164 left: 1px;
165 right: auto;
166 }
167 .ui-datepicker-rtl .ui-datepicker-buttonpane {
168 clear: right;
169 }
170 .ui-datepicker-rtl .ui-datepicker-buttonpane button {
171 float: left;
172 }
173 .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
174 .ui-datepicker-rtl .ui-datepicker-group {
175 float: right;
176 }
177 .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
178 .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
179 border-right-width: 0;
180 border-left-width: 1px;
181 }
182
183 /* Icons */
184 .ui-datepicker .ui-icon {
185 display: block;
186 text-indent: -99999px;
187 overflow: hidden;
188 background-repeat: no-repeat;
189 left: .5em;
190 top: .3em;
191 }
192
193 .ui-icon {
194 width: 16px;
195 height: 16px;
196 }
197 .ui-icon,
198 .ui-widget-content .ui-icon {
199 background-image: url("../img/ui-icons_444444_256x240.png");
200 }
201 .ui-widget-header .ui-icon {
202 background-image: url("../img/ui-icons_444444_256x240.png");
203 }
204 .ui-state-hover .ui-icon,
205 .ui-state-focus .ui-icon,
206 .ui-button:hover .ui-icon,
207 .ui-button:focus .ui-icon {
208 background-image: url("../img/ui-icons_555555_256x240.png");
209 }
210 .ui-state-active .ui-icon,
211 .ui-button:active .ui-icon {
212 background-image: url("../img/ui-icons_ffffff_256x240.png");
213 }
214 .ui-state-highlight .ui-icon,
215 .ui-button .ui-state-highlight.ui-icon {
216 background-image: url("../img/ui-icons_777620_256x240.png");
217 }
218
219 /* positioning */
220 .ui-icon-blank { background-position: 16px 16px; }
221 .ui-icon-caret-1-n { background-position: 0 0; }
222 .ui-icon-caret-1-ne { background-position: -16px 0; }
223 .ui-icon-caret-1-e { background-position: -32px 0; }
224 .ui-icon-caret-1-se { background-position: -48px 0; }
225 .ui-icon-caret-1-s { background-position: -65px 0; }
226 .ui-icon-caret-1-sw { background-position: -80px 0; }
227 .ui-icon-caret-1-w { background-position: -96px 0; }
228 .ui-icon-caret-1-nw { background-position: -112px 0; }
229 .ui-icon-caret-2-n-s { background-position: -128px 0; }
230 .ui-icon-caret-2-e-w { background-position: -144px 0; }
231 .ui-icon-triangle-1-n { background-position: 0 -16px; }
232 .ui-icon-triangle-1-ne { background-position: -16px -16px; }
233 .ui-icon-triangle-1-e { background-position: -32px -16px; }
234 .ui-icon-triangle-1-se { background-position: -48px -16px; }
235 .ui-icon-triangle-1-s { background-position: -65px -16px; }
236 .ui-icon-triangle-1-sw { background-position: -80px -16px; }
237 .ui-icon-triangle-1-w { background-position: -96px -16px; }
238 .ui-icon-triangle-1-nw { background-position: -112px -16px; }
239 .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
240 .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
241 .ui-icon-arrow-1-n { background-position: 0 -32px; }
242 .ui-icon-arrow-1-ne { background-position: -16px -32px; }
243 .ui-icon-arrow-1-e { background-position: -32px -32px; }
244 .ui-icon-arrow-1-se { background-position: -48px -32px; }
245 .ui-icon-arrow-1-s { background-position: -65px -32px; }
246 .ui-icon-arrow-1-sw { background-position: -80px -32px; }
247 .ui-icon-arrow-1-w { background-position: -96px -32px; }
248 .ui-icon-arrow-1-nw { background-position: -112px -32px; }
249 .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
250 .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
251 .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
252 .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
253 .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
254 .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
255 .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
256 .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
257 .ui-icon-arrowthick-1-n { background-position: 1px -48px; }
258 .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
259 .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
260 .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
261 .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
262 .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
263 .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
264 .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
265 .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
266 .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
267 .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
268 .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
269 .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
270 .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
271 .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
272 .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
273 .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
274 .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
275 .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
276 .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
277 .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
278 .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
279 .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
280 .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
281 .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
282 .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
283 .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
284 .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
285 .ui-icon-arrow-4 { background-position: 0 -80px; }
286 .ui-icon-arrow-4-diag { background-position: -16px -80px; }
287 .ui-icon-extlink { background-position: -32px -80px; }
288 .ui-icon-newwin { background-position: -48px -80px; }
289 .ui-icon-refresh { background-position: -64px -80px; }
290 .ui-icon-shuffle { background-position: -80px -80px; }
291 .ui-icon-transfer-e-w { background-position: -96px -80px; }
292 .ui-icon-transferthick-e-w { background-position: -112px -80px; }
293 .ui-icon-folder-collapsed { background-position: 0 -96px; }
294 .ui-icon-folder-open { background-position: -16px -96px; }
295 .ui-icon-document { background-position: -32px -96px; }
296 .ui-icon-document-b { background-position: -48px -96px; }
297 .ui-icon-note { background-position: -64px -96px; }
298 .ui-icon-mail-closed { background-position: -80px -96px; }
299 .ui-icon-mail-open { background-position: -96px -96px; }
300 .ui-icon-suitcase { background-position: -112px -96px; }
301 .ui-icon-comment { background-position: -128px -96px; }
302 .ui-icon-person { background-position: -144px -96px; }
303 .ui-icon-print { background-position: -160px -96px; }
304 .ui-icon-trash { background-position: -176px -96px; }
305 .ui-icon-locked { background-position: -192px -96px; }
306 .ui-icon-unlocked { background-position: -208px -96px; }
307 .ui-icon-bookmark { background-position: -224px -96px; }
308 .ui-icon-tag { background-position: -240px -96px; }
309 .ui-icon-home { background-position: 0 -112px; }
310 .ui-icon-flag { background-position: -16px -112px; }
311 .ui-icon-calendar { background-position: -32px -112px; }
312 .ui-icon-cart { background-position: -48px -112px; }
313 .ui-icon-pencil { background-position: -64px -112px; }
314 .ui-icon-clock { background-position: -80px -112px; }
315 .ui-icon-disk { background-position: -96px -112px; }
316 .ui-icon-calculator { background-position: -112px -112px; }
317 .ui-icon-zoomin { background-position: -128px -112px; }
318 .ui-icon-zoomout { background-position: -144px -112px; }
319 .ui-icon-search { background-position: -160px -112px; }
320 .ui-icon-wrench { background-position: -176px -112px; }
321 .ui-icon-gear { background-position: -192px -112px; }
322 .ui-icon-heart { background-position: -208px -112px; }
323 .ui-icon-star { background-position: -224px -112px; }
324 .ui-icon-link { background-position: -240px -112px; }
325 .ui-icon-cancel { background-position: 0 -128px; }
326 .ui-icon-plus { background-position: -16px -128px; }
327 .ui-icon-plusthick { background-position: -32px -128px; }
328 .ui-icon-minus { background-position: -48px -128px; }
329 .ui-icon-minusthick { background-position: -64px -128px; }
330 .ui-icon-close { background-position: -80px -128px; }
331 .ui-icon-closethick { background-position: -96px -128px; }
332 .ui-icon-key { background-position: -112px -128px; }
333 .ui-icon-lightbulb { background-position: -128px -128px; }
334 .ui-icon-scissors { background-position: -144px -128px; }
335 .ui-icon-clipboard { background-position: -160px -128px; }
336 .ui-icon-copy { background-position: -176px -128px; }
337 .ui-icon-contact { background-position: -192px -128px; }
338 .ui-icon-image { background-position: -208px -128px; }
339 .ui-icon-video { background-position: -224px -128px; }
340 .ui-icon-script { background-position: -240px -128px; }
341 .ui-icon-alert { background-position: 0 -144px; }
342 .ui-icon-info { background-position: -16px -144px; }
343 .ui-icon-notice { background-position: -32px -144px; }
344 .ui-icon-help { background-position: -48px -144px; }
345 .ui-icon-check { background-position: -64px -144px; }
346 .ui-icon-bullet { background-position: -80px -144px; }
347 .ui-icon-radio-on { background-position: -96px -144px; }
348 .ui-icon-radio-off { background-position: -112px -144px; }
349 .ui-icon-pin-w { background-position: -128px -144px; }
350 .ui-icon-pin-s { background-position: -144px -144px; }
351 .ui-icon-play { background-position: 0 -160px; }
352 .ui-icon-pause { background-position: -16px -160px; }
353 .ui-icon-seek-next { background-position: -32px -160px; }
354 .ui-icon-seek-prev { background-position: -48px -160px; }
355 .ui-icon-seek-end { background-position: -64px -160px; }
356 .ui-icon-seek-start { background-position: -80px -160px; }
357 /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
358 .ui-icon-seek-first { background-position: -80px -160px; }
359 .ui-icon-stop { background-position: -96px -160px; }
360 .ui-icon-eject { background-position: -112px -160px; }
361 .ui-icon-volume-off { background-position: -128px -160px; }
362 .ui-icon-volume-on { background-position: -144px -160px; }
363 .ui-icon-power { background-position: 0 -176px; }
364 .ui-icon-signal-diag { background-position: -16px -176px; }
365 .ui-icon-signal { background-position: -32px -176px; }
366 .ui-icon-battery-0 { background-position: -48px -176px; }
367 .ui-icon-battery-1 { background-position: -64px -176px; }
368 .ui-icon-battery-2 { background-position: -80px -176px; }
369 .ui-icon-battery-3 { background-position: -96px -176px; }
370 .ui-icon-circle-plus { background-position: 0 -192px; }
371 .ui-icon-circle-minus { background-position: -16px -192px; }
372 .ui-icon-circle-close { background-position: -32px -192px; }
373 .ui-icon-circle-triangle-e { background-position: -48px -192px; }
374 .ui-icon-circle-triangle-s { background-position: -64px -192px; }
375 .ui-icon-circle-triangle-w { background-position: -80px -192px; }
376 .ui-icon-circle-triangle-n { background-position: -96px -192px; }
377 .ui-icon-circle-arrow-e { background-position: -112px -192px; }
378 .ui-icon-circle-arrow-s { background-position: -128px -192px; }
379 .ui-icon-circle-arrow-w { background-position: -144px -192px; }
380 .ui-icon-circle-arrow-n { background-position: -160px -192px; }
381 .ui-icon-circle-zoomin { background-position: -176px -192px; }
382 .ui-icon-circle-zoomout { background-position: -192px -192px; }
383 .ui-icon-circle-check { background-position: -208px -192px; }
384 .ui-icon-circlesmall-plus { background-position: 0 -208px; }
385 .ui-icon-circlesmall-minus { background-position: -16px -208px; }
386 .ui-icon-circlesmall-close { background-position: -32px -208px; }
387 .ui-icon-squaresmall-plus { background-position: -48px -208px; }
388 .ui-icon-squaresmall-minus { background-position: -64px -208px; }
389 .ui-icon-squaresmall-close { background-position: -80px -208px; }
390 .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
391 .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
392 .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
393 .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
394 .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
395 .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
396
397 /* Corner radius */
398 .ui-corner-all,
399 .ui-corner-top,
400 .ui-corner-left,
401 .ui-corner-tl {
402 border-top-left-radius: 3px;
403 }
404 .ui-corner-all,
405 .ui-corner-top,
406 .ui-corner-right,
407 .ui-corner-tr {
408 border-top-right-radius: 3px;
409 }
410 .ui-corner-all,
411 .ui-corner-bottom,
412 .ui-corner-left,
413 .ui-corner-bl {
414 border-bottom-left-radius: 3px;
415 }
416 .ui-corner-all,
417 .ui-corner-bottom,
418 .ui-corner-right,
419 .ui-corner-br {
420 border-bottom-right-radius: 3px;
421 }
1 @import 'datepicker';
2
3 .emr_upload_form
4 {
5 form
6 {
7 display: flex; //editor and upsell
8 .upsell-wrapper
9 {
10 margin-left: 10px;
11 }
12 }
13
14 .wrapper
15 {
16 // margin: 15px 0;
17 padding: 18px;
18 border: 1px solid #ccc;
19
20 .section-header
21 {
22 font-size: 18px;
23 //text-align: center;
24 border-bottom: 1px solid #ccc;
25 padding: 6px 0;
26 margin: 0 0 15px 0;
27 }
28 }
29
30 .image_chooser.wrapper
31 {
32 min-height: 350px;
33
34 .emr_drop_area
35 {
36 border: 4px dashed #b4b9be;
37 max-width: 600px;
38 padding: 28px 14px;
39 text-align: center;
40 position: relative;
41 h1 { display: none; }
42 .drop-wrapper
43 {
44 margin: 0 auto;
45
46 }
47 &.drop_breakout
48 {
49 position: fixed;
50 left: 0;
51 right:0;
52 bottom: 0;
53 top: 0;
54 max-width: none;
55 border-color: #83b4d8;
56 border-width: 10px;
57 z-index: 999999;
58 background-color: rgba(#444, 0.7);
59 h1 {
60 color: #fff;
61 position: absolute;
62 font-size: 50px;
63 line-height: 50px;
64 margin-top: -25px;
65 top: 50%;
66 width: 100%;
67 text-align: center;
68 display: block;
69 }
70 .drop-wrapper { display: none; }
71 }
72 }
73 .image_previews
74 {
75 margin: 15px 0;
76 .image_placeholder
77 {
78 position: relative;
79 display: inline-block;
80 margin-right: 25px;
81 margin-bottom: 10px;
82 border: 1px solid #ddd;
83 vertical-align: top;
84 max-height: 500px;
85 .textlayer
86 {
87 font-size: 25px;
88 line-height: 25px;
89 opacity: 0.7;
90 position: absolute;
91 color: #ccc;
92 left: 48%;
93 top: 50%;
94 transform: translate(-50%, -50%);
95 border: 1px dashed #eee;
96 background-color: #333;
97 padding: 8px;
98 //max-width: 100%;
99 }
100 .dashicons
101 {
102 font-size: 60px;
103 position: absolute;
104 top: 50%;
105 margin-top: -30px;
106 left: 50%;
107 margin-left: -30px;
108 opacity: 0.5;
109
110 }
111 .image_size
112 {
113 text-align: center;
114 position: absolute;
115 bottom: -25px;
116 width: 100%;
117 }
118 &.is_image
119 {
120 .dashicons::before, .dashicons { display: none }
121
122
123 }
124 &.not_image
125 {
126 img { display: none; }
127 .textlayer { display: none; }
128 &.is_document{
129 .textlayer {
130 font-size: 18px;
131 line-height: 20px;
132 display: block;
133
134 }
135 }
136 } // not_image
137 } // image_placeholder
138 } // image_previews
139 } // wrapper
140
141 .form-error, .form-warning
142 {
143 background: #fff;
144 padding: 8px;
145 border-left: 4px solid #ff0000;
146 // display: inline-block;
147 margin: 10px 0;
148 display: none;
149 p {
150 margin: 0;
151 font-size: 12px;
152 font-weight: 700;
153 }
154
155 }
156 .form-warning
157 {
158 border-left: 4px solid #ffb900;
159 }
160
161 .option-flex-wrapper
162 {
163 display: flex;
164 }
165
166 .replace_type.wrapper
167 {
168 flex: 1;
169 border: 1px solid #ccc;
170 margin: 15px 0;
171 .option
172 {
173 position: relative;
174 z-index: 1;
175 &.disabled
176 {
177 // color: #eee;
178 }
179 label
180 {
181 font-size: 1.2em;
182 }
183 .nofeature-notice
184 {
185 border: 1px solid #ccc;
186 padding: 8px;
187 margin: 0;
188 position: absolute;
189 left: 0;
190 right: 0;
191 top: 0;
192 bottom: 0;
193 opacity: 0.8;
194 z-index: 9;
195 background: #444;
196 p {
197 text-align: center;
198 color: #fff;
199 margin: 15px 0;
200 }
201 }
202 }
203
204 }
205
206 .options.wrapper
207 {
208 flex: 1;
209 border: 1px solid #ccc;
210 padding: 15px;
211 margin: 15px 0 15px 35px;
212 .custom_date
213 {
214 .emr_datepicker {
215 width: 150px;
216 }
217 .emr_hour, .emr_minute
218 {
219 width: 45px;
220 }
221 }
222 .replace_custom_date
223 {
224 margin-left: 5px;
225 &:hover {
226 text-decoration: underline;
227 cursor: pointer
228 }
229 }
230 ul
231 {
232 li
233 {
234 input
235 {
236 margin-right: 8px;
237 }
238 }
239 }
240 .option
241 {
242 label { vertical-align: top; }
243 }
244 .small
245 {
246 font-size: 10px;
247 vertical-align: top;
248 margin-left: 8px;
249 }
250 .custom_date
251 {
252 margin: 8px 0 0 25px;
253 visibility: hidden;
254 opacity: 0;
255 span.field-title {
256 display: inline-block;
257 margin-bottom: 4px;
258 color: #444;
259 //margin-left: 8px;
260 font-size: 12px;
261 width: 100%;
262 text-align: left;
263 vertical-align: middle;
264 line-height: 26px;
265 &::before
266 {
267 font-size: 20px;
268 vertical-align: top;
269 margin-right: 4px;
270 }
271 }
272 } // custom_date
273 .location_option
274 {
275 display: none;
276 margin-top: 12px;
277 label
278 {
279 vertical-align: baseline;
280 margin-right: 8px;
281 }
282 }
283 }
284
285 .form_controls.wrapper
286 {
287 clear: both;
288 margin: 8px 0 15px 0;
289 border: 0;
290 padding: 0;
291 .button
292 {
293 padding-left: 20px;
294 padding-right: 20px;
295 }
296 }
297
298 .shortpixel.notice
299 {
300 padding: 12px;
301 }
302 .shortpixel-offer
303 {
304 background: #fff;
305 width: 250px;
306 min-height: 270px;
307 border: 1px solid #ccc;
308 padding: 10px;
309 //margin: 0 0 10px 25px;
310 margin-bottom: 10px;
311 float: right;
312 clear: both;
313 background-color: #dcfdff;
314 h3 {
315 color: #00d0e5;
316 font-size: 18px;
317 text-align: center;
318 margin: 0;
319 line-height: 1.3em;
320 }
321 h4 {
322 // margin: 0;
323 font-size: 16px;
324 text-align: center;
325 }
326 .red { color: #ff0000; }
327 .cyan { color: #00d0e5; }
328 .grey { color: grey; }
329 .ucase { text-transform: uppercase; }
330 a {
331 text-decoration: none
332 }
333 .button-wrapper
334 {
335 text-align: center;
336 margin-top: 35px;
337 a {
338 background-color: #ff0000;
339 color: #fff;
340 display: inline-block;
341 padding: 8px;
342 text-decoration: none;
343 font-weight: 700;
344 font-size: 20px;
345 text-transform: uppercase;
346 }
347 }
348 .hidden { display: none !important; }
349
350 .img-wrapper
351 {
352 text-align: center;
353 margin: 0 0 25px 0;
354 img { max-width: 140px; max-height: 140px; margin: 0; }
355 }
356
357 &.spio // shortpixel
358 {
359 }
360 &.site-speed // Site speed
361 {
362 }
363 &.envira-shortpixel-install // envira
364 {
365 background: #fff;
366 }
367 }
368
369 @media( max-width: 1200px)
370 {
371 .image_previews
372 {
373 text-align: center;
374 }
375 .option-flex-wrapper {
376 flex-direction: column;
377 .options.wrapper
378 { margin-left: 0;}
379 }
380 }
381 @media (max-width: 960px)
382 {
383 .upsell-wrapper { display: none; }
384 }
385 @media (max-width: 450px )
386 {
387 .replace_custom_date_wrapper {
388 display: block;
389 margin-top: 15px;
390 font-size: 16px;
391
392 }
393 .location_option {
394 label {
395 margin: 25px 0;
396 display: inline-block;
397 }
398
399 }
400 }
401 } // emr_upload_form
1
2 /* Styling for the edit attachment screen */
3 #emr-replace-box, #emr-showthumbs-box
4 {
5 .previewwrapper
6 {
7 display: inline-block;
8 position: relative;
9 clear: both;
10 margin: 3px 0;
11
12 img { max-width: 100%; }
13 span.label
14 {
15 font-size: 14px;
16 color: #fff;
17 position: absolute;
18 line-height: 16px;
19 margin-top: -8px;
20 top: 50%;
21 left: 0; right: 0;
22 background: rgba(0,0,0,0.5);
23 text-align: center;
24 padding: 4px 0;
25
26
27 }
28
29 }
30
31 }
1 <?php
2 if ( ! defined( 'ABSPATH' ) )
3 exit; // Exit if accessed directly.
4
5 use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
6 use EnableMediaReplace\Notices\NoticeController as Notices;
7
8 /* Simple class for updating thumbnails.
9 */
10 class ThumbnailUpdater
11 {
12 protected $attach_id;
13 protected $oldMeta = array();
14 protected $newMeta = array();
15
16 protected $convertArray = array();
17 protected $relPath;
18
19 protected $post_table;
20
21 public function __construct($id)
22 {
23 $this->attach_id = intval($id);
24
25 global $wpdb;
26 $table_name = $wpdb->prefix . "posts";
27 // $postmeta_table_name = $wpdb->prefix . "postmeta";
28
29 $this->post_table = $table_name;
30 }
31
32 public function setOldMetadata($metadata)
33 {
34 if (isset($metadata['sizes']))
35 $this->oldMeta = $metadata;
36 }
37
38 public function setNewMetadata($metadata)
39 {
40 if (isset($metadata['sizes']))
41 $this->newMeta = $metadata;
42
43
44 // extract month prefix to prevent overwriting wrong images.
45 $file = $metadata['file'];
46 $pos = strrpos($metadata['file'], '/');
47 $month_path = substr($file, 0, $pos);
48 $this->relPath = trailingslashit($month_path);
49 }
50
51
52 public function updateThumbnails()
53 {
54 if (count($this->oldMeta) == 0 || count($this->newMeta) == 0)
55 return false;
56
57 $convertArray = array();
58 foreach($this->oldMeta['sizes'] as $sizeName => $data)
59 {
60 if (isset($this->newMeta['sizes'][$sizeName]))
61 {
62
63 //in some rare cases 'file' is missing
64 $oldFile = isset($data['file']) ? $data['file'] : null;
65 if(is_array($oldFile)) { $oldFile = $oldFile[0];} // HelpScout case 709692915
66 if(empty($oldFile)) {
67 return false; //make sure we don't replace in this case as we will break the URLs for all the images in the folder.
68 }
69 $newFile = $this->newMeta['sizes'][$sizeName]['file'];
70
71 // if images are not same size.
72 if ($oldFile != $newFile)
73 {
74 $this->convertArray[] = array('imageFrom' => $this->relPath . $oldFile, 'imageTo' => $this->relPath . $newFile );
75 }
76
77 }
78 else {
79 $this->findNearestSize($data, $sizeName);
80 }
81
82 }
83 $this->updateDatabase();
84
85 }
86
87 protected function updateDatabase()
88 {
89 global $wpdb;
90 $sql = "UPDATE " . $this->post_table . " set post_content = REPLACE(post_content, %s, %s)";
91
92 Log::addDebug('Thumbnail Updater - Converting Thumbnails for sizes', $this->convertArray);
93 foreach($this->convertArray as $convert_item)
94 {
95 $from = $convert_item['imageFrom'];
96 $to = $convert_item['imageTo'];
97
98 $replace_sql = $wpdb->prepare($sql, $from, $to );
99 $wpdb->query($replace_sql);
100 }
101 }
102
103 /** FindNearestsize
104 * 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.
105 */
106 protected function findNearestSize($oldData, $sizeName)
107 {
108 $old_width = $oldData['width']; // the width from size not in new image
109 $new_width = $this->newMeta['width']; // default check - new width on image
110
111 $diff = abs($old_width - $new_width);
112 $closest_file = str_replace($this->relPath, '', $this->newMeta['file']);
113
114 foreach($this->newMeta['sizes'] as $sizeName => $data)
115 {
116 $thisdiff = abs($old_width - $data['width']);
117
118 if ( $thisdiff < $diff )
119 {
120 $closest_file = $data['file'];
121 if(is_array($closest_file)) { $closest_file = $closest_file[0];} // HelpScout case 709692915
122 if(!empty($closest_file)) {
123 $diff = $thisdiff;
124 $found_metasize = true;
125 }
126 }
127 }
128
129 if(empty($closest_file)) return;
130 $oldFile = $oldData['file'];
131 if(is_array($oldFile)) { $oldFile = $oldFile[0];} // HelpScout case 709692915
132 if(empty($oldFile)) {
133 return; //make sure we don't replace in this case as we will break the URLs for all the images in the folder.
134 }
135 $this->convertArray[] = array('imageFrom' => $this->relPath . $oldFile, 'imageTo' => $this->relPath . $closest_file);
136
137 }
138
139
140 }
1 <div class='notice' id='emr-news' style="padding-top: 7px">
2 <div style="float:<?php echo (is_rtl()) ? 'left' : 'right' ?>;"><a href="javascript:emrDismissNews()" class="button" style="margin-top:10px;"><?php _e('Dismiss', 'enable-media-replace');?></a></div>
3 <a href="https://shortpixel.com/wp/af/VKG6LYN28044" target="_blank" style="float: <?php echo (is_rtl()) ? 'right' : 'left' ?>;margin-<?php echo (is_rtl()) ? 'left' : 'right' ?>: 10px;">
4 <img width="30" height="30" src="<?php echo $this->plugin_url . 'img/sp-logo-regular.svg' ?>" class="emr-sp"/>
5 </a>
6 <h3 style="margin:10px;"><?php echo esc_html__('Enable Media Replace is now compatible with ShortPixel!','enable-media-replace');?></h3>
7 <p style="margin-bottom:0px;">
8 <?php _e( '<a href="https://shortpixel.com/wp/af/VKG6LYN28044" target="_blank">ShortPixel</a> is an image optimization plugin and if you have it activated, upon replacing an image in Enable Media Replace, the image will be also automatically optimized.', 'enable-media-replace' ); ?>
9 </p>
10 <p style="text-align: <?php echo (is_rtl()) ? 'left' : 'right' ?>;margin-top: 0;">
11 <a href="https://shortpixel.com/wp/af/VKG6LYN28044" target="_blank">&gt;&gt; <?php _e( 'More info', 'enable-media-replace' ); ?></a>
12 </p>
13 </div>
14 <script>
15 function emrDismissNews() {
16 jQuery("#emr-news").hide();
17 var data = { action : 'emr_dismiss_notices'};
18 jQuery.get('<?php echo admin_url('admin-ajax.php'); ?>', data, function(response) {
19 data = JSON.parse(response);
20 if(data["Status"] == 0) {
21 console.log("dismissed");
22 }
23 });
24 }
25 </script>
1 <?php
2 namespace EnableMediaReplace;
3
4 //use \EnableMediaReplace\UIHelper;
5 use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
6 use EnableMediaReplace\Notices\NoticeController as Notices;
7
8 /**
9 * Uploadscreen for selecting and uploading new media file
10 *
11 * @author Måns Jonasson <http://www.mansjonasson.se>
12 * @copyright Måns Jonasson 13 sep 2010
13 * @version $Revision: 2303 $ | $Date: 2010-09-13 11:12:35 +0200 (ma, 13 sep 2010) $
14 * @package wordpress
15 * @subpackage enable-media-replace
16 *
17 */
18
19 if ( ! defined( 'ABSPATH' ) )
20 exit; // Exit if accessed directly.
21
22 if (!current_user_can('upload_files'))
23 wp_die( esc_html__('You do not have permission to upload files.', 'enable-media-replace') );
24
25 global $wpdb;
26
27 $emr = EnableMediaReplacePlugin::get();
28
29 $table_name = $wpdb->prefix . "posts";
30 $attachment_id = intval($_GET['attachment_id']);
31 $attachment = get_post($attachment_id);
32
33 if (! $emr->checkImagePermission($attachment->post_author, $attachment_id))
34 {
35 wp_die( esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace') );
36 }
37
38 $replacer = new Replacer($attachment_id);
39
40 $file = $replacer->getSourceFile();
41 $filepath = $file->getFullFilePath();
42 $filename = $file->getFileName();
43 $filetype = $file->getFileExtension();
44 $source_mime = get_post_mime_type($attachment_id);
45
46 $uiHelper = new UIHelper();
47 $uiHelper->setPreviewSizes();
48 $uiHelper->setSourceSizes($attachment_id);
49
50
51
52 $defaults = array(
53 'replace_type' => 'replace',
54 'timestamp_replace' => \EnableMediaReplace\Replacer::TIME_UPDATEMODIFIED,
55 'custom_date' => date("Y-m-d H:i:s"),
56 'new_location' => false,
57 'new_location_dir' => false,
58 );
59 $settings = get_option('enable_media_replace', $defaults);
60
61 ?>
62
63 <div class="wrap emr_upload_form">
64 <h1><?php echo esc_html__("Replace Media Upload", "enable-media-replace"); ?></h1>
65
66 <?php
67
68 $url = $uiHelper->getFormUrl($attachment_id);
69 $formurl = wp_nonce_url( $url, "media_replace_upload" );
70 if (FORCE_SSL_ADMIN) {
71 $formurl = str_replace("http:", "https:", $formurl);
72 }
73 ?>
74
75 <form enctype="multipart/form-data" method="POST" action="<?php echo $formurl; ?>">
76
77 <div class='editor-wrapper'>
78 <section class='image_chooser wrapper'>
79 <div class='section-header'> <?php _e('Choose Replacement Media', 'enable-media-replace'); ?></div>
80
81 <div id="message" class=""><strong><?php printf( esc_html__('NOTE: You are about to replace the media file "%s". There is no undo. Think about it!', "enable-media-replace"), $filename ); ?></strong></div>
82
83 <input type="hidden" name="ID" value="<?php echo $attachment_id ?>" />
84
85 <p><?php echo esc_html__("Choose a file to upload from your computer", "enable-media-replace"); ?></p>
86 <p><?php printf(__('Maximum file size: <strong>%s</strong>','enable-media-replace'), size_format(wp_max_upload_size() ) ) ?></p>
87 <div class='form-error filesize'><p><?php printf(__('%s f %s exceeds the maximum upload size for this site.', 'enable-media-replace'), '<span class="fn">', '</span>'); ?></p>
88 </div>
89
90 <div class='form-warning filetype'><p><?php printf(__('Replacement file is not the same filetype. This might cause unexpected issues ( %s )', 'enable-media-replace'), '<span class="source_type"></span> - <span class="target_type"></span>'); ?>
91
92 </p></div>
93
94 <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>
95
96 <div class='emr_drop_area'>
97 <div class='drop-wrapper'>
98
99 <p><input type="file" name="userfile" id="userfile" /></p>
100 <h1><?php _e('Drop File Here', 'enable-media-replace'); ?></h1>
101 </div>
102
103 </div>
104 <div class='image_previews'>
105 <?php if (wp_attachment_is('image', $attachment_id) || $source_mime == 'application/pdf')
106 {
107 echo $uiHelper->getPreviewImage($attachment_id, $file);
108 echo $uiHelper->getPreviewImage(-1, $file);
109 }
110 else {
111
112 if (strlen($filepath) == 0) // check if image in error state.
113 {
114 echo $uiHelper->getPreviewError(-1);
115 echo $uiHelper->getPreviewImage(-1, $file);
116 }
117 else {
118 echo $uiHelper->getPreviewFile($attachment_id, $file);
119 echo $uiHelper->getPreviewFile(-1, $file);
120 }
121
122 }
123 ?>
124 </div>
125
126 </section>
127
128 <div class='option-flex-wrapper'>
129 <section class='replace_type wrapper'>
130 <div class='section-header'> <?php _e('Replacement Options', 'enable-media-replace'); ?></div>
131
132 <?php
133 // these are also used in externals, for checks.
134 do_action( 'emr_before_replace_type_options' ); ?>
135
136
137 <?php $enabled_search = apply_filters( 'emr_display_replace_type_options', true );
138 $search_disabled = (! $enabled_search) ? 'disabled' : '';
139 ?>
140 <div class='option replace <?php echo $search_disabled ?>'>
141 <label for="replace_type_1" ><input <?php checked('replace', $settings['replace_type']) ?> id="replace_type_1" type="radio" name="replace_type" value="replace" <?php echo $search_disabled ?> > <?php echo esc_html__("Just replace the file", "enable-media-replace"); ?>
142 </label>
143
144 <p class="howto">
145 <?php printf( esc_html__("Note: This option requires you to upload a file of the same type (%s) as the one you are replacing. The name of the attachment will stay the same (%s) no matter what the file you upload is called.", "enable-media-replace"), $filetype, $filename ); ?>
146 </p>
147
148 <p class='form-warning filetype'><?php _e('If you replace the file with a different filetype, this file might become unreadable and / or cause unexpected issues', 'enable-media-replace'); ?>
149 </p>
150
151 <?php do_action('emr_after_search_type_options'); ?>
152 </div>
153
154 <?php $enabled_replacesearch = apply_filters( 'emr_enable_replace_and_search', true );
155 $searchreplace_disabled = (! $enabled_replacesearch) ? 'disabled' : '';
156 ?>
157
158 <div class="option searchreplace <?php echo $searchreplace_disabled ?>">
159 <label for="replace_type_2"><input id="replace_type_2" <?php checked('replace_and_search', $settings['replace_type']) ?> type="radio" name="replace_type" value="replace_and_search" <?php echo $searchreplace_disabled ?> > <?php echo __("Replace the file, use new file name and update all links", "enable-media-replace"); ?>
160 </label>
161
162 <p class="howto"><?php printf( esc_html__("Note: If you check this option, the name and type of the file you are about to upload will replace the old file. All links pointing to the current file (%s) will be updated to point to the new file name. (If any other websites link to the file directly, those links will no longer work. Be careful.)", "enable-media-replace"), $filename ); ?></p>
163
164 <!-- <p class="howto"><?php echo esc_html__("Please note that if you upload a new image, only embeds/links of the original size image will be replaced in your posts.", "enable-media-replace"); ?></p> -->
165
166 <?php do_action('emr_after_replace_type_options'); ?>
167 </div>
168
169 </section>
170 <section class='options wrapper'>
171 <div class='section-header'> <?php _e('Date Options', 'enable-media-replace'); ?></div>
172 <div class='option timestamp'>
173 <?php
174 $attachment_current_date = date_i18n('d/M/Y H:i', strtotime($attachment->post_date) );
175 $attachment_now_date = date_i18n('d/M/Y H:i', time() );
176 $time = current_time('mysql');
177 $date = $nowDate = new \dateTime($time); // default to now.
178 // var_dump(strtotime($attachment->post_date));
179 // exit();
180 $attachmentDate = new \dateTime($attachment->post_date);
181
182 if ($settings['timestamp_replace'] == \EnableMediaReplace\Replacer::TIME_CUSTOM)
183 {
184 $date = new \dateTime($settings['custom_date']);
185 }
186 ?>
187 <p><?php _e('When replacing the media, do you want to:', 'enable-media-replace'); ?></p>
188 <ul>
189 <li><label><input type='radio' <?php checked('1', $settings['timestamp_replace']) ?> name='timestamp_replace' value='1' /><?php printf(__('Replace the date with current date %s(%s)%s', 'enable-media-replace'), "<span class='small'>", $attachment_now_date, "</span>") ; ?></label></li>
190 <li><label><input type='radio' <?php checked('2', $settings['timestamp_replace']) ?> name='timestamp_replace' value='2' /><?php printf(__('Keep the date %s(%s)%s', 'enable-media-replace'), "<span class='small'>", $attachment_current_date, "</span>"); ?></label></li>
191 <li><label><input type='radio' <?php checked('3', $settings['timestamp_replace']) ?> name='timestamp_replace' value='3' /><?php _e('Set a Custom Date', 'enable-media-replace'); ?></label></li>
192 </ul>
193 <div class='custom_date'>
194
195 <span class='field-title dashicons dashicons-calendar'><?php _e('Custom Date', 'enable-media-replace'); ?></span>
196 <input type='text' name="custom_date" value="<?php echo $date->format(get_option('date_format')); ?>" id='emr_datepicker'
197 class='emr_datepicker' />
198
199 @ <input type='text' name="custom_hour" class='emr_hour' value="<?php echo $date->format('H') ?>" /> &nbsp;
200 <input type="text" name="custom_minute" class='emr_minute' value="<?php echo $date->format('i'); ?>" />
201 <input type="hidden" name="custom_date_formatted" value="<?php echo $date->format('Y-m-d'); ?>" />
202
203 <span class="replace_custom_date_wrapper">
204 <?php
205 printf('<a class="replace_custom_date" data-date="%s" data-hour="%s" data-min="%s" data-format="%s">%s</a>', $nowDate->format(get_option('date_format')), $nowDate->format('H'), $nowDate->format('i'), $nowDate->format('Y-m-d'), __('Now', 'enable-media-replace'));
206 echo " ";
207 printf('<a class="replace_custom_date" data-date="%s" data-hour="%s" data-min="%s" data-format="%s">%s</a>', $attachmentDate->format(get_option('date_format')), $attachmentDate->format('H'), $attachmentDate->format('i'), $attachmentDate->format('Y-m-d'), __('Original', 'enable-media-replace'));
208 ?>
209 </span>
210 </div>
211 <?php if ($subdir = $uiHelper->getRelPathNow()):
212
213 if ($settings['new_location'] !== false)
214 $subdir = $settings['new_location_dir'];
215 ?>
216 <div class='location_option'>
217 <label><input type="checkbox" name="new_location" value="1" <?php checked($settings['new_location'], 1); ?> /> <?php _e('Put new Upload in Updated Folder: ', 'enable-media-replace'); ?></label>
218 <input type="text" name="location_dir" value="<?php echo $subdir ?>" />
219 </div>
220 <?php endif; ?>
221 </div>
222
223 </section>
224 </div>
225 <section class='form_controls wrapper'>
226 <input id="submit" type="submit" class="button button-primary" disabled="disabled" value="<?php echo esc_attr__("Upload", "enable-media-replace"); ?>" />
227 <a href="#" class="button" onclick="history.back();"><?php echo esc_html__("Cancel", "enable-media-replace"); ?></a>
228 </section>
229 </div>
230
231 <?php include_once('upsell.php'); ?>
232
233
234
235 </form>
236 </div>
1 <?php
2 namespace EnableMediaReplace;
3
4 if ( ! defined( 'ABSPATH' ) )
5 exit; // Exit if accessed directly.
6
7 use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
8 use EnableMediaReplace\Notices\NoticeController as Notices;
9
10 if (!current_user_can('upload_files'))
11 wp_die( esc_html__('You do not have permission to upload files.', 'enable-media-replace') );
12
13 /*require_once('classes/replacer.php');
14 require_once('classes/file.php'); */
15
16 use \EnableMediaReplace\Replacer as Replacer;
17
18 // Define DB table names
19 global $wpdb;
20 $table_name = $wpdb->prefix . "posts";
21 $postmeta_table_name = $wpdb->prefix . "postmeta";
22
23 // Starts processing.
24 $uihelper = new UIHelper();
25 $emr = EnableMediaReplacePlugin::get();
26
27 // Get old guid and filetype from DB
28 $post_id = isset($_POST['ID']) ? intval($_POST['ID']) : null; // sanitize, post_id.
29 if (is_null($post_id))
30 {
31 wp_die( esc_html__('Error in request. Please try again', 'enable-media-replace') );
32 }
33 $attachment = get_post($post_id);
34
35 if (! $emr->checkImagePermission($attachment->post_author, $attachment->ID))
36 wp_die( esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace') );
37
38 $replacer = new Replacer($post_id);
39
40 // Massage a bunch of vars
41 $ID = intval($_POST["ID"]); // legacy
42 $replace_type = isset($_POST["replace_type"]) ? sanitize_text_field($_POST["replace_type"]) : false;
43 $timestamp_replace = intval($_POST['timestamp_replace']);
44
45 $redirect_error = $uihelper->getFailedRedirect($post_id);
46 $redirect_success = $uihelper->getSuccesRedirect($post_id);
47
48 $do_new_location = isset($_POST['new_location']) ? sanitize_text_field($_POST['new_location']) : false;
49 $new_location_dir = isset($_POST['location_dir']) ? sanitize_text_field($_POST['location_dir']) : null;
50
51 $settings = array(); // save settings and show last loaded.
52 $settings['replace_type'] = $replace_type;
53 $settings['timestamp_replace'] = $timestamp_replace;
54 $settings['new_location'] = $do_new_location;
55 $settings['new_location_dir'] = $new_location_dir;
56
57 switch($timestamp_replace)
58 {
59 case \EnableMediaReplace\Replacer::TIME_UPDATEALL:
60 case \EnableMediaReplace\Replacer::TIME_UPDATEMODIFIED:
61 $datetime = current_time('mysql');
62 break;
63 case \EnableMediaReplace\Replacer::TIME_CUSTOM:
64 $custom_date = $_POST['custom_date_formatted'];
65 $custom_hour = str_pad($_POST['custom_hour'],2,0, STR_PAD_LEFT);
66 $custom_minute = str_pad($_POST['custom_minute'], 2, 0, STR_PAD_LEFT);
67
68 // create a mysql time representation from what we have.
69 Log::addDebug($_POST);
70 Log::addDebug('Custom Date - ' . $custom_date . ' ' . $custom_hour . ':' . $custom_minute );
71 $custom_date = \DateTime::createFromFormat('Y-m-d G:i', $custom_date . ' ' . $custom_hour . ':' . $custom_minute );
72 if ($custom_date === false)
73 {
74
75 wp_safe_redirect($redirect_error);
76 $errors = \DateTime::getLastErrors();
77 $error = '';
78 if (isset($errors['errors']))
79 {
80 $error = implode(',', $errors['errors']);
81 }
82 Notices::addError(sprintf(__('Invalid Custom Date. Please custom date values (%s)', 'enable-media-replace'), $error));
83
84 exit();
85 }
86 $datetime = $custom_date->format("Y-m-d H:i:s");
87 $settings['custom_date'] = $datetime;
88 break;
89 }
90
91 update_option('enable_media_replace', $settings, false);
92
93 // We have two types: replace / replace_and_search
94 if ($replace_type == 'replace')
95 {
96 $replacer->setMode(\EnableMediaReplace\Replacer::MODE_REPLACE);
97 $mode = \EnableMediaReplace\Replacer::MODE_REPLACE;
98 }
99 elseif ( 'replace_and_search' == $replace_type && apply_filters( 'emr_enable_replace_and_search', true ) )
100 {
101 $replacer->setMode(\EnableMediaReplace\Replacer::MODE_SEARCHREPLACE);
102 $mode = \EnableMediaReplace\Replacer::MODE_SEARCHREPLACE;
103
104 if ($do_new_location && ! is_null($new_location_dir))
105 {
106 $result = $replacer->setNewTargetLocation($new_location_dir);
107 if (! $result)
108 {
109 wp_safe_redirect($redirect_error);
110 exit();
111 }
112 }
113 }
114
115 $replacer->setTimeMode($timestamp_replace, $datetime);
116
117 /** Check if file is uploaded properly **/
118 if (is_uploaded_file($_FILES["userfile"]["tmp_name"])) {
119
120 Log::addDebug($_FILES['userfile']);
121
122 // New method for validating that the uploaded file is allowed, using WP:s internal wp_check_filetype_and_ext() function.
123 $filedata = wp_check_filetype_and_ext($_FILES["userfile"]["tmp_name"], $_FILES["userfile"]["name"]);
124
125 Log::addDebug('Data after check', $filedata);
126 if (isset($_FILES['userfile']['error']) && $_FILES['userfile']['error'] > 0)
127 {
128 $e = new RunTimeException('File Uploaded Failed');
129 Notices::addError($e->getMessage());
130 wp_safe_redirect($redirect_error);
131 exit();
132 }
133
134
135 if ($filedata["ext"] == false && ! current_user_can( 'unfiltered_upload' )) {
136
137 Notices::addError(esc_html__("File type does not meet security guidelines. Try another.", 'enable-media-replace') );
138 wp_safe_redirect($redirect_error);
139 exit();
140 }
141
142 // Here we have the uploaded file
143 $new_filename = $_FILES["userfile"]["name"];
144 //$new_filesize = $_FILES["userfile"]["size"]; // Seems not to be in use.
145 $new_filetype = $filedata["type"];
146
147 // Gather all functions that both options do.
148 do_action('wp_handle_replace', array('post_id' => $post_id));
149
150
151 /* if ($mode = \EnableMediaReplace\Replacer::MODE_SEARCHREPLACE && $do_new_location && ! is_null($new_location_dir))
152 {
153 exit($new_filename);
154 $newdirfile = $replacer->newTargetLocation($new_location_dir);
155 }
156 */
157 try
158 {
159 $result = $replacer->replaceWith($_FILES["userfile"]["tmp_name"], $new_filename);
160 }
161 catch(\RunTimeException $e)
162 {
163 Log::addError($e->getMessage());
164 // exit($e->getMessage());
165 }
166
167 if (is_null($result))
168 {
169 wp_safe_redirect($redirect_error);
170 exit();
171 }
172 // $returnurl = admin_url("/post.php?post={$_POST["ID"]}&action=edit&message=1");
173
174 // Execute hook actions - thanks rubious for the suggestion!
175
176 } else {
177 //TODO Better error handling when no file is selected.
178 //For now just go back to media management
179 //$returnurl = admin_url("upload.php");
180 Log::addInfo('Failed. Redirecting - '. $redirect_error);
181 Notices::addError(__('File Upload seems to have failed. No files were returned by system','enable-media-replace'));
182 wp_safe_redirect($redirect_error);
183 exit();
184 }
185
186 Notices::addSuccess(__('File successfully replaced','enable-media-replace'));
187
188 // Allow developers to override $returnurl
189 //$returnurl = apply_filters('emr_returnurl', $returnurl);
190 wp_redirect($redirect_success);
191 exit();
192 ?>
1 <?php
2 namespace EnableMediaReplace;
3
4 //use \EnableMediaReplace\UIHelper;
5 use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log;
6 use EnableMediaReplace\Notices\NoticeController as Notices;
7
8 if (! apply_filters('emr/upsell', current_user_can('install_plugins')))
9 {
10 return;
11 }
12
13 #wp_nonce_field('enable-media-replace');
14 $plugins = get_plugins();
15
16 $spio_installed = isset($plugins['shortpixel-image-optimiser/wp-shortpixel.php']);
17 $spio_active = is_plugin_active('shortpixel-image-optimiser/wp-shortpixel.php');
18
19
20 $spai_installed = isset($plugins['shortpixel-adaptive-images/short-pixel-ai.php']);
21 $spai_active = is_plugin_active('shortpixel-adaptive-images/short-pixel-ai.php');
22
23 $envira_installed = isset($plugins['envira-gallery-lite/envira-gallery-lite.php']);
24 $envira_active = is_plugin_active('envira-gallery-lite/envira-gallery-lite.php');
25 $envira_pro_active = is_plugin_active('envira-gallery/envira-gallery.php');
26
27
28 ?>
29
30 <input type="hidden" id='upsell-nonce' value="<?php echo wp_create_nonce( 'emr-plugin-install' ); ?>" />
31 <input type="hidden" id='upsell-nonce-activate' value="<?php echo wp_create_nonce( 'emr-plugin-activate' ); ?>" />
32 <section class='upsell-wrapper'>
33
34 <!--- SHORTPIXEL -->
35 <?php if(! $spio_active): ?>
36
37 <div class='shortpixel-offer spio'>
38 <div class='img-wrapper'>
39 <img width="40" height="40" src="<?php echo $emr->getPluginURL('img/sp-logo-regular.svg') ?>" alt="ShortPixel">
40 </div>
41 <h4 class="grey">
42 <?php echo esc_html__("ShortPixel Image Optimizer", "enable-media-replace"); ?>
43 </h4>
44 <h3 class="red ucase"><?php _e('Is your website slow?', 'enable-media-replace'); ?></h3>
45 <br>
46 <h3 class="cyan ucase"><?php printf(__('Optimize all images %s automatically', 'enable-media-replace'), '<br>'); ?></h3>
47 <p class='button-wrapper '>
48 <?php
49 $install_class = (! $spio_installed) ? '' : 'hidden';
50 $activate_class = ($spio_installed && ! $spio_active) ? '' : 'hidden';
51 ?>
52 <a class="emr-installer <?php echo $install_class ?>" data-action="install" data-plugin="spio" href="javascript:void(0)">
53 <?php _e('INSTALL NOW', 'enable-media-replace') ?>
54 </a>
55
56 <a class='emr-activate <?php echo $activate_class ?>' data-action="activate" data-plugin="spio" href="javascript:void(0)">
57 <?php _e('ACTIVATE', 'enable-media-replace') ?>
58 </a>
59
60 <h4 class='emr-activate-done hidden' data-plugin='spio'><?php _e('Shortpixel activated!', 'enable-media-replace'); ?></h4>
61 </p>
62
63 </div>
64 <?php endif; ?>
65 <!--- // SHORTPIXEL -->
66
67 <!--- SHORTPIXEL AI -->
68 <?php if(! $spai_active): ?>
69
70 <div class='shortpixel-offer spai'>
71 <div class='img-wrapper'>
72 <img width="40" height="40" src="<?php echo $emr->getPluginURL('img/spai-logo.svg') ?>" alt="ShortPixel">
73 </div>
74 <h4 class="grey">
75 <?php echo esc_html__("ShortPixel Adaptive Images", "enable-media-replace"); ?>
76 </h4>
77
78
79 <h3 class="cyan ucase"><?php printf(__('Start Serving %s Optimized, %s Nextgen images %s From a global CDN', 'enable-media-replace'), '<br>', '<br>', '<br>'); ?></h3>
80 <h3 class="red ucase"><?php _e('In Minutes', 'enable-media-replace'); ?></h3>
81 <p class='button-wrapper '>
82 <?php
83 $install_class = (! $spai_installed) ? '' : 'hidden';
84 $activate_class = ($spai_installed && ! $spai_active) ? '' : 'hidden';
85 ?>
86 <a class="emr-installer <?php echo $install_class ?>" data-action="install" data-plugin="spai" href="javascript:void(0)">
87 <?php _e('INSTALL NOW', 'enable-media-replace') ?>
88 </a>
89
90 <a class='emr-activate <?php echo $activate_class ?>' data-action="activate" data-plugin="spai" href="javascript:void(0)">
91 <?php _e('ACTIVATE', 'enable-media-replace') ?>
92 </a>
93
94 <h4 class='emr-activate-done hidden' data-plugin='spai'><?php _e('Shortpixel Adaptive Images activated!', 'enable-media-replace'); ?></h4>
95 </p>
96
97 </div>
98 <?php endif; ?>
99 <!--- // SHORTPIXEL -->
100
101 <!--- WPSO -->
102 <div class='shortpixel-offer site-speed'>
103 <p class='img-wrapper'><img width="40" height="40" src="<?php echo $emr->getPluginURL('img/sp-logo-wink.svg'); ?>" alt='ShortPixel'></p>
104 <h3><?php printf(__('GET AN ASSESSMENT FOR %s YOUR WEBSITE %s AND %s %s FIND OUT HOW TO MAKE IT FASTER %s', 'enable-media-replace'),'<br>', '<br>','<br>', '<span class="red">','</span>'); ?></h3>
105
106 <p class='button-wrapper'><a href='https://wso.shortpixel.com/?utm_source=EMR' target="_blank"><?php _e('FIND OUT MORE', 'enable-media-replace') ?></a></p>
107 </div>
108 <!--- // WPSO -->
109
110 <!--- ENVIRA temprary deactivated
111 <?php if (! $envira_pro_active): ?>
112 <div class='envira-shortpixel-install shortpixel-offer'>
113
114 <p class='img-wrapper'><img src="<?php echo $emr->getPluginURL('img/envira-logo.png'); ?>" alt='Envira Gallery'></p>
115 <p><?php esc_html_e('Create beautiful, fast-loading photo & video galleries for your site in minutes.', 'enable-media-replace' ); ?></p>
116
117 <?php
118 $install_class = (! $envira_installed) ? '' : 'hidden';
119 $activate_class = ($envira_installed && ! $envira_active) ? '' : 'hidden';
120 ?>
121 <?php if (! $envira_active) { ?>
122 <p class='button-wrapper envira-emr-button-wrap'>
123
124 <a class="emr-installer button button-envira-emr emr-install-envira <?php echo $install_class ?>" data-action="install" data-plugin="envira" href='javascript:void(0)'><?php _e('Install now', 'enable-media-replace') ?></a>
125
126 <a class="emr-activate button button-envira-emr emr-activate-envira <?php echo $activate_class ?>" href='javascript:void(0)' data-action="activate" data-plugin="envira" ><?php _e('Activate', 'enable-media-replace') ?></a>
127
128 <h4 class='emr-activate-done hidden' data-plugin='envira'><?php _e('Envira Gallery activated!', 'enable-media-replace'); ?></h4>
129
130 </p>
131
132 <?php } else {
133 if ( is_plugin_active( 'envira-gallery-lite/envira-gallery-lite.php' ) ) {
134 ?>
135 <p class='button-wrapper envira-emr-button-wrap'><a class="button button-envira-emr" href='https://enviragallery.com/pricing' target="_blank"><?php _e('Get Pro', 'enable-media-replace') ?></a></p>
136
137 <?php } else { ?>
138
139 <?php }
140 } ?>
141 </div>
142 <style>
143 .envira-emr-button-wrap {
144 text-align: center;
145 }
146 .button-envira-emr {
147 background-color: #7cc048 !important;
148 border: none !important;
149 color: rgb(255,255,255) !important;
150 font-size: 21px !important;
151 }
152 .button-envira-emr:hover {
153 background-color: #95dc5e !important;
154 }
155 </style>
156 <?php endif; // envira ?>
157 -->
158
159 </section>
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 strong{font-family: Calibri;} 23 strong{font-family: Calibri;}
24 </style> 24 </style>
25 </head> 25 </head>
26 <body style="margin:0;padding:0;"> 26 <body style="margin:0;padding:0;max-width: 600px;">
27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;"> 27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
28 <tr> 28 <tr>
29 <td align="center" style="padding:0;"> 29 <td align="center" style="padding:0;">
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 strong{font-family: Calibri;} 23 strong{font-family: Calibri;}
24 </style> 24 </style>
25 </head> 25 </head>
26 <body style="margin:0;padding:0;"> 26 <body style="margin:0;padding:0;max-width: 600px;">
27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;"> 27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
28 <tr> 28 <tr>
29 <td align="center" style="padding:0;"> 29 <td align="center" style="padding:0;">
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 strong{font-family: Calibri;} 23 strong{font-family: Calibri;}
24 </style> 24 </style>
25 </head> 25 </head>
26 <body style="margin:0;padding:0;"> 26 <body style="margin:0;padding:0;max-width: 600px;">
27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;"> 27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
28 <tr> 28 <tr>
29 <td align="center" style="padding:0;"> 29 <td align="center" style="padding:0;">
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 strong{font-family: Calibri;} 23 strong{font-family: Calibri;}
24 </style> 24 </style>
25 </head> 25 </head>
26 <body style="margin:0;padding:0;"> 26 <body style="margin:0;padding:0;max-width: 600px;">
27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;"> 27 <table role="presentation" style="width:100%;border-collapse:collapse;border:0;border-spacing:0;background:#ffffff;">
28 <tr> 28 <tr>
29 <td align="center" style="padding:0;"> 29 <td align="center" style="padding:0;">
......