media replace
Signed-off-by: Jeff <jeff@gotenzing.com>
Showing
111 changed files
with
17346 additions
and
0 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 | <?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 | {"name":"EnableMediaReplace\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"EnableMediaReplace\\Notices":"notices\/src","EnableMediaReplace\\ShortPixelLogger":"log\/src","EnableMediaReplace\\FileSystem":"filesystem\/src","EnableMediaReplace\\Replacer":"replacer\/src"}}} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | { | ||
| 2 | "name": "shortpixel/filesystem", | ||
| 3 | "description": "ShortPixel FileSystem", | ||
| 4 | "version": 1.0, | ||
| 5 | "type": "library", | ||
| 6 | "license": "MIT", | ||
| 7 | "authors": [ | ||
| 8 | { | ||
| 9 | "name": "Bas", | ||
| 10 | "email": "bas@weblogmechanic.com" | ||
| 11 | } | ||
| 12 | ], | ||
| 13 | "minimum-stability": "dev", | ||
| 14 | "require": {}, | ||
| 15 | "autoload": { | ||
| 16 | "psr-4": { "ShortPixel\\FileSystem\\" : "src" } | ||
| 17 | } | ||
| 18 | } |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\FileSystem\Controller; | ||
| 3 | use EnableMediaReplace\ShortpixelLogger\ShortPixelLogger as Log; | ||
| 4 | |||
| 5 | use EnableMediaReplace\FileSystem\Model\File\DirectoryModel as DirectoryModel; | ||
| 6 | use EnableMediaReplace\FileSystem\Model\File\FileModel as FileModel; | ||
| 7 | |||
| 8 | |||
| 9 | /** Controller for FileSystem operations | ||
| 10 | * | ||
| 11 | * This controller is used for -compound- ( complex ) FS operations, using the provided models File en Directory. | ||
| 12 | * USE via \wpSPIO()->filesystem(); | ||
| 13 | */ | ||
| 14 | Class FileSystemController | ||
| 15 | { | ||
| 16 | |||
| 17 | public function __construct() | ||
| 18 | { | ||
| 19 | |||
| 20 | } | ||
| 21 | |||
| 22 | /** Get FileModel for a certain path. This can exist or not | ||
| 23 | * | ||
| 24 | * @param String Path Full Path to the file | ||
| 25 | * @return FileModel FileModel Object. If file does not exist, not all values are set. | ||
| 26 | */ | ||
| 27 | public function getFile($path) | ||
| 28 | { | ||
| 29 | return new FileModel($path); | ||
| 30 | } | ||
| 31 | |||
| 32 | |||
| 33 | |||
| 34 | /** Get DirectoryModel for a certain path. This can exist or not | ||
| 35 | * | ||
| 36 | * @param String $path Full Path to the Directory. | ||
| 37 | * @return DirectoryModel Object with status set on current directory. | ||
| 38 | */ | ||
| 39 | public function getDirectory($path) | ||
| 40 | { | ||
| 41 | return new DirectoryModel($path); | ||
| 42 | } | ||
| 43 | |||
| 44 | |||
| 45 | |||
| 46 | |||
| 47 | /** This function returns the WordPress Basedir for uploads ( without date and such ) | ||
| 48 | * Normally this would point to /wp-content/uploads. | ||
| 49 | * @returns DirectoryModel | ||
| 50 | */ | ||
| 51 | public function getWPUploadBase() | ||
| 52 | { | ||
| 53 | $upload_dir = wp_upload_dir(null, false); | ||
| 54 | |||
| 55 | return $this->getDirectory($upload_dir['basedir']); | ||
| 56 | } | ||
| 57 | |||
| 58 | /** This function returns the Absolute Path of the WordPress installation where the **CONTENT** directory is located. | ||
| 59 | * Normally this would be the same as ABSPATH, but there are installations out there with -cough- alternative approaches | ||
| 60 | * @returns DirectoryModel Either the ABSPATH or where the WP_CONTENT_DIR is located | ||
| 61 | */ | ||
| 62 | public function getWPAbsPath() | ||
| 63 | { | ||
| 64 | $wpContentAbs = str_replace( 'wp-content', '', WP_CONTENT_DIR); | ||
| 65 | if (ABSPATH == $wpContentAbs) | ||
| 66 | $abspath = ABSPATH; | ||
| 67 | else | ||
| 68 | $abspath = $wpContentAbs; | ||
| 69 | |||
| 70 | if (defined('UPLOADS')) // if this is set, lead. | ||
| 71 | $abspath = trailingslashit(ABSPATH) . UPLOADS; | ||
| 72 | |||
| 73 | $abspath = apply_filters('shortpixel/filesystem/abspath', $abspath ); | ||
| 74 | |||
| 75 | return $this->getDirectory($abspath); | ||
| 76 | } | ||
| 77 | |||
| 78 | public function getFullPathForWP(FileModel $file) | ||
| 79 | { | ||
| 80 | $fullpath = $file->getFullPath(); | ||
| 81 | $abspath = $this->getWPAbsPath(); | ||
| 82 | |||
| 83 | if (! strpos($abspath, $fullpath)) | ||
| 84 | { | ||
| 85 | |||
| 86 | } | ||
| 87 | |||
| 88 | } | ||
| 89 | |||
| 90 | |||
| 91 | /** Utility function that tries to convert a file-path to a webURL. | ||
| 92 | * | ||
| 93 | * If possible, rely on other better methods to find URL ( e.g. via WP functions ). | ||
| 94 | */ | ||
| 95 | public function pathToUrl(FileModel $file) | ||
| 96 | { | ||
| 97 | $filepath = $file->getFullPath(); | ||
| 98 | $directory = $file->getFileDir(); | ||
| 99 | |||
| 100 | $is_multi_site = (function_exists("is_multisite") && is_multisite()) ? true : false; | ||
| 101 | $is_main_site = is_main_site(); | ||
| 102 | |||
| 103 | //$is_multi_site = $this->env->is_multisite; | ||
| 104 | //$is_main_site = $this->env->is_mainsite; | ||
| 105 | |||
| 106 | // stolen from wp_get_attachment_url | ||
| 107 | if ( ( $uploads = wp_get_upload_dir() ) && (false === $uploads['error'] || strlen(trim($uploads['error'])) == 0 ) ) { | ||
| 108 | // Check that the upload base exists in the file location. | ||
| 109 | if ( 0 === strpos( $filepath, $uploads['basedir'] ) ) { // Simple as it should, filepath and basedir share. | ||
| 110 | // Replace file location with url location. | ||
| 111 | $url = str_replace( $uploads['basedir'], $uploads['baseurl'], $filepath ); | ||
| 112 | } | ||
| 113 | // Multisite backups are stored under uploads/ShortpixelBackups/etc , but basedir would include uploads/sites/2 etc, not matching above | ||
| 114 | // If this is case, test if removing the last two directories will result in a 'clean' uploads reference. | ||
| 115 | // This is used by getting preview path ( backup pathToUrl) in bulk and for comparer.. | ||
| 116 | elseif ($is_multi_site && ! $is_main_site && 0 === strpos($filepath, dirname(dirname($uploads['basedir']))) ) | ||
| 117 | { | ||
| 118 | |||
| 119 | $url = str_replace( dirname(dirname($uploads['basedir'])), dirname(dirname($uploads['baseurl'])), $filepath ); | ||
| 120 | $homeUrl = home_url(); | ||
| 121 | |||
| 122 | // The result didn't end in a full URL because URL might have less subdirs ( dirname dirname) . | ||
| 123 | // This happens when site has blogs.dir (sigh) on a subdomain . Try to substitue the ABSPATH root with the home_url | ||
| 124 | if (strpos($url, $homeUrl) === false) | ||
| 125 | { | ||
| 126 | $url = str_replace( trailingslashit(ABSPATH), trailingslashit($homeUrl), $filepath); | ||
| 127 | } | ||
| 128 | |||
| 129 | } elseif ( false !== strpos( $filepath, 'wp-content/uploads' ) ) { | ||
| 130 | // Get the directory name relative to the basedir (back compat for pre-2.7 uploads) | ||
| 131 | //$relativePath = $this->getFile(_wp_get_attachment_relative_path( $filepath ) ); | ||
| 132 | //$basename = wp_basename($relativePath->getFullPath()); | ||
| 133 | |||
| 134 | $url = trailingslashit( $uploads['baseurl'] . '/' . _wp_get_attachment_relative_path( $filepath ) ) . wp_basename( $filepath ); | ||
| 135 | } else { | ||
| 136 | // It's a newly-uploaded file, therefore $file is relative to the basedir. | ||
| 137 | $url = $uploads['baseurl'] . "/$filepath"; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | $wp_home_path = (string) $this->getWPAbsPath(); | ||
| 142 | // If the whole WP homepath is still in URL, assume the replace when wrong ( not replaced w/ URL) | ||
| 143 | // This happens when file is outside of wp_uploads_dir | ||
| 144 | if (strpos($url, $wp_home_path) !== false) | ||
| 145 | { | ||
| 146 | // This is SITE URL, for the same reason it should be home_url in FILEMODEL. The difference is when the site is running on a subdirectory | ||
| 147 | // (1) ** This is a fix for a real-life issue, do not change if this causes issues, another fix is needed then. | ||
| 148 | // (2) ** Also a real life fix when a path is /wwwroot/assets/sites/2/ etc, in get site url, the home URL is the site URL, without appending the sites stuff. Fails on original image. | ||
| 149 | if ($is_multi_site && ! $is_main_site) | ||
| 150 | { | ||
| 151 | $wp_home_path = trailingslashit($uploads['basedir']); | ||
| 152 | $home_url = trailingslashit($uploads['baseurl']); | ||
| 153 | } | ||
| 154 | else | ||
| 155 | $home_url = trailingslashit(get_site_url()); // (1) | ||
| 156 | $url = str_replace($wp_home_path, $home_url, $filepath); | ||
| 157 | } | ||
| 158 | |||
| 159 | // can happen if there are WP path errors. | ||
| 160 | if (is_null($url)) | ||
| 161 | return false; | ||
| 162 | |||
| 163 | $parsed = parse_url($url); // returns array, null, or false. | ||
| 164 | |||
| 165 | // Some hosts set the content dir to a relative path instead of a full URL. Api can't handle that, so add domain and such if this is the case. | ||
| 166 | if ( !isset($parsed['scheme']) ) {//no absolute URLs used -> we implement a hack | ||
| 167 | |||
| 168 | if (isset($parsed['host'])) // This is for URL's for // without http or https. hackhack. | ||
| 169 | { | ||
| 170 | $scheme = is_ssl() ? 'https:' : 'http:'; | ||
| 171 | return $scheme. $url; | ||
| 172 | } | ||
| 173 | else | ||
| 174 | { | ||
| 175 | // From Metafacade. Multiple solutions /hacks. | ||
| 176 | $home_url = trailingslashit((function_exists("is_multisite") && is_multisite()) ? trim(network_site_url("/")) : trim(home_url())); | ||
| 177 | return $home_url . ltrim($url,'/');//get the file URL | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | if (! is_null($parsed) && $parsed !== false) | ||
| 182 | return $url; | ||
| 183 | |||
| 184 | return false; | ||
| 185 | } | ||
| 186 | |||
| 187 | /** Utility function to check if a path is an URL | ||
| 188 | * Checks if this path looks like an URL. | ||
| 189 | * @param $path String Path to check | ||
| 190 | * @return Boolean If path seems domain. | ||
| 191 | */ | ||
| 192 | public function pathIsUrl($path) | ||
| 193 | { | ||
| 194 | $is_http = (substr($path, 0, 4) == 'http') ? true : false; | ||
| 195 | $is_https = (substr($path, 0, 5) == 'https') ? true : false; | ||
| 196 | $is_neutralscheme = (substr($path, 0, 2) == '//') ? true : false; // when URL is relative like //wp-content/etc | ||
| 197 | $has_urldots = (strpos($path, '://') !== false) ? true : false; // Like S3 offloads | ||
| 198 | |||
| 199 | if ($is_http || $is_https || $is_neutralscheme || $has_urldots) | ||
| 200 | return true; | ||
| 201 | else | ||
| 202 | return false; | ||
| 203 | } | ||
| 204 | |||
| 205 | /** Sort files / directories in a certain way. | ||
| 206 | * Future dev to include options via arg. | ||
| 207 | */ | ||
| 208 | public function sortFiles($array, $args = array() ) | ||
| 209 | { | ||
| 210 | if (count($array) == 0) | ||
| 211 | return $array; | ||
| 212 | |||
| 213 | // what are we sorting. | ||
| 214 | $class = get_class($array[0]); | ||
| 215 | $is_files = ($class == 'EnableMediaReplace\FileModel') ? true : false; // if not files, then dirs. | ||
| 216 | |||
| 217 | usort($array, function ($a, $b) use ($is_files) | ||
| 218 | { | ||
| 219 | if ($is_files) | ||
| 220 | return strcmp($a->getFileName(), $b->getFileName()); | ||
| 221 | else { | ||
| 222 | return strcmp($a->getName(), $b->getName()); | ||
| 223 | } | ||
| 224 | } | ||
| 225 | ); | ||
| 226 | |||
| 227 | return $array; | ||
| 228 | |||
| 229 | } | ||
| 230 | |||
| 231 | public function downloadFile($url, $destinationPath) | ||
| 232 | { | ||
| 233 | |||
| 234 | //$downloadTimeout = defined(SHORTPIXEL_MAX_EXECUTION_TIME) ? max(SHORTPIXEL_MAX_EXECUTION_TIME - 10, 15) :; | ||
| 235 | $max_exec = intval(ini_get('max_execution_time')); | ||
| 236 | if ($max_exec === 0) // max execution time of zero means infinite. Quantify. | ||
| 237 | $max_exec = 60; | ||
| 238 | elseif($max_exec < 0) // some hosts like to set negative figures on this. Ignore that. | ||
| 239 | $max_exec = 30; | ||
| 240 | |||
| 241 | $downloadTimeout = $max_exec; | ||
| 242 | |||
| 243 | |||
| 244 | $destinationFile = $this->getFile($destinationPath); | ||
| 245 | |||
| 246 | $args_for_get = array( | ||
| 247 | 'stream' => true, | ||
| 248 | 'filename' => $destinationPath, | ||
| 249 | ); | ||
| 250 | |||
| 251 | $response = wp_remote_get( $url, $args_for_get ); | ||
| 252 | |||
| 253 | if(is_wp_error( $response )) { | ||
| 254 | Log::addError('Download file failed', array($url, $response->get_error_messages(), $response->get_error_codes() )); | ||
| 255 | |||
| 256 | // Try to get it then via this way. | ||
| 257 | $response = download_url($url, $downloadTimeout); | ||
| 258 | if (!is_wp_error($response)) // response when alright is a tmp filepath. But given path can't be trusted since that can be reason for fail. | ||
| 259 | { | ||
| 260 | $tmpFile = $this->getFile($response); | ||
| 261 | $result = $tmpFile->move($destinationFile); | ||
| 262 | |||
| 263 | } // download_url .. | ||
| 264 | else { | ||
| 265 | Log::addError('Secondary download failed', array($url, $response->get_error_messages(), $response->get_error_codes() )); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | else { // success, at least the download. | ||
| 269 | $destinationFile = $this->getFile($response['filename']); | ||
| 270 | } | ||
| 271 | |||
| 272 | Log::addDebug('Remote Download attempt result', array($url, $destinationPath)); | ||
| 273 | if ($destinationFile->exists()) | ||
| 274 | return true; | ||
| 275 | else | ||
| 276 | return false; | ||
| 277 | } | ||
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | /** Get all files from a directory tree, starting at given dir. | ||
| 282 | * @param DirectoryModel $dir to recursive into | ||
| 283 | * @param Array $filters Collection of optional filters as accepted by FileFilter in directoryModel | ||
| 284 | * @return Array Array of FileModel Objects | ||
| 285 | **/ | ||
| 286 | public function getFilesRecursive(DirectoryModel $dir, $filters = array() ) | ||
| 287 | { | ||
| 288 | $fileArray = array(); | ||
| 289 | |||
| 290 | if (! $dir->exists()) | ||
| 291 | return $fileArray; | ||
| 292 | |||
| 293 | $files = $dir->getFiles($filters); | ||
| 294 | $fileArray = array_merge($fileArray, $files); | ||
| 295 | |||
| 296 | $subdirs = $dir->getSubDirectories(); | ||
| 297 | |||
| 298 | foreach($subdirs as $subdir) | ||
| 299 | { | ||
| 300 | $fileArray = array_merge($fileArray, $this->getFilesRecursive($subdir, $filters)); | ||
| 301 | } | ||
| 302 | |||
| 303 | return $fileArray; | ||
| 304 | } | ||
| 305 | |||
| 306 | // Url very sparingly. | ||
| 307 | public function url_exists($url) | ||
| 308 | { | ||
| 309 | if (! function_exists('curl_init')) | ||
| 310 | { | ||
| 311 | return null; | ||
| 312 | } | ||
| 313 | |||
| 314 | $ch = curl_init($url); | ||
| 315 | curl_setopt($ch, CURLOPT_NOBODY, true); | ||
| 316 | curl_exec($ch); | ||
| 317 | $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); | ||
| 318 | curl_close($ch); | ||
| 319 | |||
| 320 | if ($responseCode == 200) | ||
| 321 | { | ||
| 322 | return true; | ||
| 323 | } | ||
| 324 | else { | ||
| 325 | return false; | ||
| 326 | } | ||
| 327 | |||
| 328 | } | ||
| 329 | } |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\FileSystem\Model\File; | ||
| 3 | use EnableMediaReplace\ShortpixelLogger\ShortPixelLogger as Log; | ||
| 4 | |||
| 5 | /* Model for Directories | ||
| 6 | * | ||
| 7 | * For all low-level operations on directories | ||
| 8 | * Private model of FileSystemController. Please get your directories via there. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | class DirectoryModel | ||
| 13 | { | ||
| 14 | // Directory info | ||
| 15 | protected $path; | ||
| 16 | protected $name; | ||
| 17 | |||
| 18 | // Directory status | ||
| 19 | protected $exists = null; | ||
| 20 | protected $is_writable = null; | ||
| 21 | protected $is_readable = null; | ||
| 22 | protected $is_virtual = null; | ||
| 23 | |||
| 24 | protected $fields = array(); | ||
| 25 | |||
| 26 | protected $new_directory_permission = 0755; | ||
| 27 | |||
| 28 | /** Creates a directory model object. DirectoryModel directories don't need to exist on FileSystem | ||
| 29 | * | ||
| 30 | * When a filepath is given, it will remove the file part. | ||
| 31 | * @param $path String The Path | ||
| 32 | */ | ||
| 33 | public function __construct($path) | ||
| 34 | { | ||
| 35 | // $path = wp_normalize_path($path); | ||
| 36 | $fs = $this->getFS(); | ||
| 37 | |||
| 38 | if ($fs->pathIsUrl($path)) | ||
| 39 | { | ||
| 40 | $pathinfo = pathinfo($path); | ||
| 41 | if (isset($pathinfo['extension'])) // check if this is a file, remove the file information. | ||
| 42 | { | ||
| 43 | $path = $pathinfo['dirname']; | ||
| 44 | } | ||
| 45 | |||
| 46 | $this->is_virtual = true; | ||
| 47 | $this->is_readable = true; // assume | ||
| 48 | $this->exists = true; | ||
| 49 | } | ||
| 50 | |||
| 51 | if (! $this->is_virtual() && ! is_dir($path) ) // path is wrong, *or* simply doesn't exist. | ||
| 52 | { | ||
| 53 | /* Test for file input. | ||
| 54 | * If pathinfo is fed a fullpath, it rips of last entry without setting extension, don't further trust. | ||
| 55 | * If it's a file extension is set, then trust. | ||
| 56 | */ | ||
| 57 | $pathinfo = pathinfo($path); | ||
| 58 | |||
| 59 | if (isset($pathinfo['extension'])) | ||
| 60 | { | ||
| 61 | $path = $pathinfo['dirname']; | ||
| 62 | } | ||
| 63 | elseif (is_file($path)) | ||
| 64 | $path = dirname($path); | ||
| 65 | } | ||
| 66 | |||
| 67 | if (! $this->is_virtual() && ! is_dir($path)) | ||
| 68 | { | ||
| 69 | /* Check if realpath improves things. We support non-existing paths, which realpath fails on, so only apply on result. | ||
| 70 | Moved realpath to check after main pathinfo is set. Reason is that symlinked directories which don't include the WordPress upload dir will start to fail in file_model on processpath ( doesn't see it as a wp path, starts to try relative path). Not sure if realpath should be used anyhow in this model /BS | ||
| 71 | */ | ||
| 72 | $testpath = realpath($path); | ||
| 73 | if ($testpath) | ||
| 74 | $path = $testpath; | ||
| 75 | } | ||
| 76 | |||
| 77 | $this->path = trailingslashit($path); | ||
| 78 | |||
| 79 | // Basename doesn't work properly on non-latin ( cyrillic, greek etc ) directory names, returning the parent path instead. | ||
| 80 | $dir = new \SplFileInfo($path); | ||
| 81 | //basename($this->path); | ||
| 82 | $this->name = $dir->getFileName(); | ||
| 83 | |||
| 84 | // Off the keep resources / not sure if needed. | ||
| 85 | // if (file_exists($this->path)) | ||
| 86 | // { | ||
| 87 | // $this->exists(); | ||
| 88 | // $this->is_writable(); | ||
| 89 | // $this->is_readable(); | ||
| 90 | // } | ||
| 91 | } | ||
| 92 | |||
| 93 | private function getFS() | ||
| 94 | { | ||
| 95 | return new \EnableMediaReplace\FileSystem\Controller\FileSystemController(); | ||
| 96 | } | ||
| 97 | |||
| 98 | |||
| 99 | public function __toString() | ||
| 100 | { | ||
| 101 | return (string) $this->path; | ||
| 102 | } | ||
| 103 | |||
| 104 | /** Returns path *with* trailing slash | ||
| 105 | * | ||
| 106 | * @return String Path with trailing slash | ||
| 107 | */ | ||
| 108 | public function getPath() | ||
| 109 | { | ||
| 110 | return $this->path; | ||
| 111 | } | ||
| 112 | |||
| 113 | public function getModified() | ||
| 114 | { | ||
| 115 | return filemtime($this->path); | ||
| 116 | } | ||
| 117 | |||
| 118 | /** | ||
| 119 | * Get basename of the directory. Without path | ||
| 120 | */ | ||
| 121 | public function getName() | ||
| 122 | { | ||
| 123 | return $this->name; | ||
| 124 | } | ||
| 125 | |||
| 126 | public function exists() | ||
| 127 | { | ||
| 128 | if (is_null($this->exists)) | ||
| 129 | { | ||
| 130 | $this->exists = file_exists($this->path) && is_dir($this->path); | ||
| 131 | } | ||
| 132 | return $this->exists; | ||
| 133 | } | ||
| 134 | |||
| 135 | public function is_writable() | ||
| 136 | { | ||
| 137 | if (is_null($this->is_writable)) | ||
| 138 | { | ||
| 139 | $this->is_writable = is_writable($this->path); | ||
| 140 | } | ||
| 141 | return $this->is_writable; | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | public function is_readable() | ||
| 146 | { | ||
| 147 | if (is_null($this->is_readable)) | ||
| 148 | { | ||
| 149 | $this->is_readable = is_readable($this->path); | ||
| 150 | } | ||
| 151 | |||
| 152 | return $this->is_readable; | ||
| 153 | } | ||
| 154 | |||
| 155 | public function is_virtual() | ||
| 156 | { | ||
| 157 | return $this->is_virtual; | ||
| 158 | } | ||
| 159 | /** Try to obtain the path, minus the installation directory. | ||
| 160 | * @return Mixed False if this didn't work, Path as string without basedir if it did. With trailing slash, without starting slash. | ||
| 161 | */ | ||
| 162 | public function getRelativePath() | ||
| 163 | { | ||
| 164 | // not used anywhere in directory. | ||
| 165 | // $upload_dir = wp_upload_dir(null, false); | ||
| 166 | |||
| 167 | $install_dir = get_home_path(); | ||
| 168 | if($install_dir == '/') { | ||
| 169 | $install_dir = $this->getFS()->getWPAbsPath(); | ||
| 170 | } | ||
| 171 | |||
| 172 | $install_dir = trailingslashit($install_dir); | ||
| 173 | |||
| 174 | $path = $this->getPath(); | ||
| 175 | // try to build relativePath without first slash. | ||
| 176 | $relativePath = str_replace($install_dir, '', $path); | ||
| 177 | |||
| 178 | if (is_dir( $install_dir . $relativePath) === false) | ||
| 179 | { | ||
| 180 | $test_path = $this->reverseConstructPath($path, $install_dir); | ||
| 181 | if ($test_path !== false) | ||
| 182 | { | ||
| 183 | $relativePath = $test_path; | ||
| 184 | } | ||
| 185 | else { | ||
| 186 | if($test_path = $this->constructUsualDirectories($path)) | ||
| 187 | { | ||
| 188 | $relativePath = $test_path; | ||
| 189 | } | ||
| 190 | |||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | // If relativePath has less amount of characters, changes are this worked. | ||
| 195 | if (strlen($path) > strlen($relativePath)) | ||
| 196 | { | ||
| 197 | return ltrim(trailingslashit($relativePath), '/'); | ||
| 198 | } | ||
| 199 | return false; | ||
| 200 | } | ||
| 201 | |||
| 202 | |||
| 203 | private function reverseConstructPath($path, $install_path) | ||
| 204 | { | ||
| 205 | // Array value to reset index | ||
| 206 | $pathar = array_values(array_filter(explode('/', $path))); | ||
| 207 | $parts = array(); | ||
| 208 | |||
| 209 | if (is_array($pathar)) | ||
| 210 | { | ||
| 211 | // Reverse loop the structure until solid ground is found. | ||
| 212 | for ($i = (count($pathar)); $i > 0; $i--) | ||
| 213 | { | ||
| 214 | $parts[] = $pathar[$i - 1]; | ||
| 215 | $testpath = implode('/', array_reverse($parts)); | ||
| 216 | // if the whole thing exists | ||
| 217 | if (is_dir($install_path . $testpath) === true) | ||
| 218 | { | ||
| 219 | return $testpath; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | } | ||
| 223 | return false; | ||
| 224 | |||
| 225 | } | ||
| 226 | |||
| 227 | |||
| 228 | /* Last Resort function to just reduce path to various known WorPress paths. */ | ||
| 229 | private function constructUsualDirectories($path) | ||
| 230 | { | ||
| 231 | $pathar = array_values(array_filter(explode('/', $path))); // array value to reset index | ||
| 232 | $testpath = false; | ||
| 233 | if ( ($key = array_search('wp-content', $pathar)) !== false) | ||
| 234 | { | ||
| 235 | $testpath = implode('/', array_slice($pathar, $key)); | ||
| 236 | } | ||
| 237 | elseif ( ($key = array_search('uploads', $pathar)) !== false) | ||
| 238 | { | ||
| 239 | $testpath = implode('/', array_slice($pathar, $key)); | ||
| 240 | } | ||
| 241 | |||
| 242 | return $testpath; | ||
| 243 | } | ||
| 244 | |||
| 245 | /** Checks the directory into working order | ||
| 246 | * Tries to create directory if it doesn't exist | ||
| 247 | * Tries to fix file permission if writable is needed | ||
| 248 | * @param $check_writable Boolean Directory should be writable | ||
| 249 | */ | ||
| 250 | public function check($check_writable = false) | ||
| 251 | { | ||
| 252 | $permission = $this->getPermissionRecursive(); | ||
| 253 | |||
| 254 | if ($permission === false) // if something wrong, return to default. | ||
| 255 | { | ||
| 256 | $permission = $this->new_directory_permission; | ||
| 257 | } | ||
| 258 | |||
| 259 | if (! $this->exists()) | ||
| 260 | { | ||
| 261 | |||
| 262 | Log::addInfo('Directory does not exists. Try to create recursive ' . $this->path . ' with ' . $permission); | ||
| 263 | |||
| 264 | |||
| 265 | $result = @mkdir($this->path, $permission , true); | ||
| 266 | chmod ($this->path, $permission ); | ||
| 267 | |||
| 268 | if (! $result) | ||
| 269 | { | ||
| 270 | $error = error_get_last(); | ||
| 271 | Log::addWarn('MkDir failed: ' . $error['message'], array($error)); | ||
| 272 | } | ||
| 273 | // reset. | ||
| 274 | $this->exists = null; | ||
| 275 | $this->is_readable = null; | ||
| 276 | $this->is_writable = null; | ||
| 277 | |||
| 278 | } | ||
| 279 | if ($this->exists() && $check_writable && ! $this->is_writable()) | ||
| 280 | { | ||
| 281 | chmod($this->path, $this->permission); | ||
| 282 | if (! $this->is_writable()) // perhaps parent permission is no good. | ||
| 283 | { | ||
| 284 | chmod($this->path, $this->new_directory_permission); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | if (! $this->exists()) | ||
| 289 | { | ||
| 290 | Log::addInfo('Directory does not exist :' . $this->path); | ||
| 291 | return false; | ||
| 292 | } | ||
| 293 | if ($check_writable && !$this->is_writable()) | ||
| 294 | { | ||
| 295 | Log::addInfo('Directory not writable :' . $this->path); | ||
| 296 | return false; | ||
| 297 | } | ||
| 298 | return true; | ||
| 299 | } | ||
| 300 | |||
| 301 | public function getPermissionRecursive() | ||
| 302 | { | ||
| 303 | $parent = $this->getParent(); | ||
| 304 | if (! $parent->exists()) | ||
| 305 | { | ||
| 306 | return $parent->getPermissionRecursive(); | ||
| 307 | } | ||
| 308 | else | ||
| 309 | { | ||
| 310 | return $parent->getPermissions(); | ||
| 311 | } | ||
| 312 | |||
| 313 | } | ||
| 314 | |||
| 315 | /* Get files from directory | ||
| 316 | * @returns Array|boolean Returns false if something wrong w/ directory, otherwise a files array of FileModel Object. | ||
| 317 | */ | ||
| 318 | public function getFiles($args = array()) | ||
| 319 | { | ||
| 320 | |||
| 321 | $defaults = array( | ||
| 322 | 'date_newer' => null, | ||
| 323 | 'exclude_files' => null, | ||
| 324 | 'include_files' => null, | ||
| 325 | ); | ||
| 326 | $args = wp_parse_args($args, $defaults); | ||
| 327 | |||
| 328 | // if all filters are set to null, so point in checking those. | ||
| 329 | $has_filters = (count(array_filter($args)) > 0) ? true : false; | ||
| 330 | |||
| 331 | if ( ! $this->exists() || ! $this->is_readable() ) | ||
| 332 | return false; | ||
| 333 | |||
| 334 | $fileArray = array(); | ||
| 335 | |||
| 336 | if ($handle = opendir($this->path)) { | ||
| 337 | while (false !== ($entry = readdir($handle))) { | ||
| 338 | if ( ($entry != "." && $entry != "..") && ! is_dir($this->path . $entry) ) { | ||
| 339 | |||
| 340 | |||
| 341 | $fileObj = new FileModel($this->path . $entry); | ||
| 342 | if ($has_filters) | ||
| 343 | { | ||
| 344 | if ($this->fileFilter($fileObj,$args) === false) | ||
| 345 | { | ||
| 346 | $fileObj = null; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | |||
| 350 | if (! is_null($fileObj)) | ||
| 351 | $fileArray[] = $fileObj; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | closedir($handle); | ||
| 355 | } | ||
| 356 | |||
| 357 | /* | ||
| 358 | if ($has_filters) | ||
| 359 | { | ||
| 360 | $fileArray = array_filter($fileArray, function ($file) use ($args) { | ||
| 361 | return $this->fileFilter($file, $args); | ||
| 362 | } ); | ||
| 363 | } */ | ||
| 364 | return $fileArray; | ||
| 365 | } | ||
| 366 | |||
| 367 | // @return boolean true if it should be kept in array, false if not. | ||
| 368 | private function fileFilter(FileModel $file, $args) | ||
| 369 | { | ||
| 370 | $filter = true; | ||
| 371 | |||
| 372 | if (! is_null($args['include_files'])) | ||
| 373 | { | ||
| 374 | foreach($args['include_files'] as $inc) | ||
| 375 | { | ||
| 376 | // If any in included is true, filter is good for us. | ||
| 377 | $filter = false; | ||
| 378 | if (strpos( strtolower($file->getRawFullPath()), strtolower($inc) ) !== false) | ||
| 379 | { | ||
| 380 | $filter = true; | ||
| 381 | break; | ||
| 382 | } | ||
| 383 | } | ||
| 384 | } | ||
| 385 | if (! is_null($args['date_newer'])) | ||
| 386 | { | ||
| 387 | $modified = $file->getModified(); | ||
| 388 | if ($modified < $args['date_newer'] ) | ||
| 389 | $filter = false; | ||
| 390 | } | ||
| 391 | if (! is_null($args['exclude_files'])) | ||
| 392 | { | ||
| 393 | foreach($args['exclude_files'] as $ex) | ||
| 394 | { | ||
| 395 | if (strpos( strtolower($file->getRawFullPath()), strtolower($ex) ) !== false) | ||
| 396 | $filter = false; | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | return $filter; | ||
| 401 | } | ||
| 402 | |||
| 403 | /** Get subdirectories from directory | ||
| 404 | * * @returns Array|boolean Returns false if something wrong w/ directory, otherwise a files array of DirectoryModel Object. | ||
| 405 | */ | ||
| 406 | public function getSubDirectories() | ||
| 407 | { | ||
| 408 | |||
| 409 | if (! $this->exists() || ! $this->is_readable()) | ||
| 410 | { | ||
| 411 | return false; | ||
| 412 | } | ||
| 413 | |||
| 414 | $dirIt = new \DirectoryIterator($this->path); | ||
| 415 | $dirArray = array(); | ||
| 416 | foreach ($dirIt as $fileInfo) | ||
| 417 | { // IsDot must go first here, or there is possiblity to run into openbasedir restrictions. | ||
| 418 | if (! $fileInfo->isDot() && $fileInfo->isDir() && $fileInfo->isReadable()) | ||
| 419 | { | ||
| 420 | if ('EnableMediaReplace\Model\File\DirectoryOtherMediaModel' == get_called_class()) | ||
| 421 | { | ||
| 422 | $dir = new DirectoryOtherMediaModel($fileInfo->getRealPath()); | ||
| 423 | } | ||
| 424 | else | ||
| 425 | { | ||
| 426 | $dir = new DirectoryModel($fileInfo->getRealPath()); | ||
| 427 | } | ||
| 428 | |||
| 429 | if ($dir->exists()) | ||
| 430 | $dirArray[] = $dir; | ||
| 431 | } | ||
| 432 | |||
| 433 | } | ||
| 434 | return $dirArray; | ||
| 435 | } | ||
| 436 | |||
| 437 | /** Check if this dir is a subfolder | ||
| 438 | * @param DirectoryModel The directoryObject that is tested as the parent */ | ||
| 439 | public function isSubFolderOf(DirectoryModel $dir) | ||
| 440 | { | ||
| 441 | // the same path, is not a subdir of. | ||
| 442 | if ($this->getPath() === $dir->getPath()) | ||
| 443 | return false; | ||
| 444 | |||
| 445 | // the main path must be followed from the beginning to be a subfolder. | ||
| 446 | if (strpos($this->getPath(), $dir->getPath() ) === 0) | ||
| 447 | { | ||
| 448 | return true; | ||
| 449 | } | ||
| 450 | return false; | ||
| 451 | } | ||
| 452 | |||
| 453 | //** Note, use sparingly, recursive function | ||
| 454 | public function getFolderSize() | ||
| 455 | { | ||
| 456 | $size = 0; | ||
| 457 | $files = $this->getFiles(); | ||
| 458 | |||
| 459 | // GetFiles can return Boolean false on missing directory. | ||
| 460 | if (! is_array($files)) | ||
| 461 | { | ||
| 462 | return $size; | ||
| 463 | } | ||
| 464 | |||
| 465 | foreach($files as $fileObj) | ||
| 466 | { | ||
| 467 | $size += $fileObj->getFileSize(); | ||
| 468 | } | ||
| 469 | unset($files); //attempt at performance. | ||
| 470 | |||
| 471 | $subdirs = $this->getSubDirectories(); | ||
| 472 | |||
| 473 | foreach($subdirs as $subdir) | ||
| 474 | { | ||
| 475 | $size += $subdir->getFolderSize(); | ||
| 476 | } | ||
| 477 | |||
| 478 | return $size; | ||
| 479 | } | ||
| 480 | |||
| 481 | /** Get this paths parent */ | ||
| 482 | public function getParent() | ||
| 483 | { | ||
| 484 | $path = $this->getPath(); | ||
| 485 | $parentPath = dirname($path); | ||
| 486 | |||
| 487 | $parentDir = new DirectoryModel($parentPath); | ||
| 488 | |||
| 489 | return $parentDir; | ||
| 490 | } | ||
| 491 | |||
| 492 | public function getPermissions() | ||
| 493 | { | ||
| 494 | if (! $this->exists()) | ||
| 495 | { | ||
| 496 | Log::addWarning('Directory not existing (fileperms): '. $this->getPath() ); | ||
| 497 | return false; | ||
| 498 | } | ||
| 499 | $perms = fileperms($this->getPath()); | ||
| 500 | |||
| 501 | if ($perms !== false) | ||
| 502 | { | ||
| 503 | return $perms; | ||
| 504 | } | ||
| 505 | else | ||
| 506 | return false; | ||
| 507 | |||
| 508 | } | ||
| 509 | |||
| 510 | public function delete() | ||
| 511 | { | ||
| 512 | return rmdir($this->getPath()); | ||
| 513 | } | ||
| 514 | |||
| 515 | /** This will try to remove the whole structure. Use with care. | ||
| 516 | * This is mostly used to clear the backups. | ||
| 517 | */ | ||
| 518 | public function recursiveDelete() | ||
| 519 | { | ||
| 520 | if (! $this->exists() || ! $this->is_writable()) | ||
| 521 | return false; | ||
| 522 | |||
| 523 | // This is a security measure to prevent unintended wipes. | ||
| 524 | $wpdir = $this->getFS()->getWPUploadBase(); | ||
| 525 | if (! $this->isSubFolderOf($wpdir)) | ||
| 526 | return false; | ||
| 527 | |||
| 528 | $files = $this->getFiles(); | ||
| 529 | $subdirs = $this->getSubDirectories(); | ||
| 530 | |||
| 531 | foreach($files as $file) | ||
| 532 | $file->delete(); | ||
| 533 | |||
| 534 | foreach($subdirs as $subdir) | ||
| 535 | $subdir->recursiveDelete(); | ||
| 536 | |||
| 537 | $this->delete(); | ||
| 538 | |||
| 539 | } | ||
| 540 | |||
| 541 | } |
wp-content/plugins/enable-media-replace/build/shortpixel/filesystem/src/Model/File/FileModel.php
0 → 100644
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\FileSystem\Model\File; | ||
| 3 | use EnableMediaReplace\ShortpixelLogger\ShortPixelLogger as Log; | ||
| 4 | |||
| 5 | /* FileModel class. | ||
| 6 | * | ||
| 7 | * | ||
| 8 | * - Represents a -single- file. | ||
| 9 | * - Can handle any type | ||
| 10 | * - Usually controllers would use a collection of files | ||
| 11 | * - Meant for all low-level file operations and checks. | ||
| 12 | * - Every file can have a backup counterpart. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | class FileModel | ||
| 16 | { | ||
| 17 | |||
| 18 | // File info | ||
| 19 | protected $fullpath = null; | ||
| 20 | protected $rawfullpath = null; | ||
| 21 | protected $filename = null; // filename + extension | ||
| 22 | protected $filebase = null; // filename without extension | ||
| 23 | protected $directory = null; | ||
| 24 | protected $extension = null; | ||
| 25 | protected $mime = null; | ||
| 26 | protected $permissions = null; | ||
| 27 | |||
| 28 | // File Status | ||
| 29 | protected $exists = null; | ||
| 30 | protected $is_writable = null; | ||
| 31 | protected $is_readable = null; | ||
| 32 | protected $is_file = null; | ||
| 33 | protected $is_virtual = false; | ||
| 34 | |||
| 35 | protected $status; | ||
| 36 | |||
| 37 | protected $backupDirectory; | ||
| 38 | |||
| 39 | const FILE_OK = 1; | ||
| 40 | const FILE_UNKNOWN_ERROR = 2; | ||
| 41 | |||
| 42 | |||
| 43 | /** Creates a file model object. FileModel files don't need to exist on FileSystem */ | ||
| 44 | public function __construct($path) | ||
| 45 | { | ||
| 46 | |||
| 47 | $this->fullpath = trim($path); | ||
| 48 | $this->rawfullpath = $this->fullpath; // path without any doing. | ||
| 49 | $fs = $this->getFS(); | ||
| 50 | if ($fs->pathIsUrl($path)) // Asap check for URL's to prevent remote wrappers from running. | ||
| 51 | { | ||
| 52 | |||
| 53 | $this->UrlToPath($path); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | private function getFS() | ||
| 58 | { | ||
| 59 | return new \EnableMediaReplace\FileSystem\Controller\FileSystemController(); | ||
| 60 | } | ||
| 61 | |||
| 62 | /* Get a string representation of file, the fullpath | ||
| 63 | * Note - this might be risky, without processedpath, in cases. | ||
| 64 | * @return String Full path processed or unprocessed. | ||
| 65 | */ | ||
| 66 | public function __toString() | ||
| 67 | { | ||
| 68 | return (string) $this->fullpath; | ||
| 69 | } | ||
| 70 | |||
| 71 | protected function setFileInfo() | ||
| 72 | { | ||
| 73 | $processed_path = $this->processPath($this->fullpath); | ||
| 74 | if ($processed_path !== false) | ||
| 75 | $this->fullpath = $processed_path; // set processed path if that went alright | ||
| 76 | |||
| 77 | |||
| 78 | $info = $this->mb_pathinfo($this->fullpath); | ||
| 79 | // Todo, maybe replace this with splFileINfo. | ||
| 80 | if ($this->is_file()) // only set fileinfo when it's an actual file. | ||
| 81 | { | ||
| 82 | $this->filename = isset($info['basename']) ? $info['basename'] : null; // filename + extension | ||
| 83 | $this->filebase = isset($info['filename']) ? $info['filename'] : null; // only filename | ||
| 84 | $this->extension = isset($info['extension']) ? strtolower($info['extension']) : null; // only (last) extension | ||
| 85 | } | ||
| 86 | |||
| 87 | } | ||
| 88 | |||
| 89 | /** Call when file status changed, so writable / readable / exists are not reliable anymore */ | ||
| 90 | public function resetStatus() | ||
| 91 | { | ||
| 92 | $this->is_writable = null; | ||
| 93 | $this->is_readable = null; | ||
| 94 | $this->is_file = null; | ||
| 95 | $this->exists = null; | ||
| 96 | $this->is_virtual = null; | ||
| 97 | } | ||
| 98 | |||
| 99 | public function exists() | ||
| 100 | { | ||
| 101 | if (is_null($this->exists)) | ||
| 102 | { | ||
| 103 | $this->exists = (@file_exists($this->fullpath) && is_file($this->fullpath)); | ||
| 104 | } | ||
| 105 | |||
| 106 | $this->exists = apply_filters('shortpixel_image_exists', $this->exists, $this->fullpath, $this); //legacy | ||
| 107 | $this->exists = apply_filters('shortpixel/file/exists', $this->exists, $this->fullpath, $this); | ||
| 108 | return $this->exists; | ||
| 109 | } | ||
| 110 | |||
| 111 | public function is_writable() | ||
| 112 | { | ||
| 113 | if ($this->is_virtual()) | ||
| 114 | { | ||
| 115 | $this->is_writable = false; // can't write to remote files | ||
| 116 | } | ||
| 117 | elseif (is_null($this->is_writable)) | ||
| 118 | { | ||
| 119 | if ($this->exists()) | ||
| 120 | { | ||
| 121 | $this->is_writable = @is_writable($this->fullpath); | ||
| 122 | } | ||
| 123 | else // quite expensive check to see if file is writable. | ||
| 124 | { | ||
| 125 | $res = $this->create(); | ||
| 126 | $this->delete(); | ||
| 127 | $this->is_writable = $res; | ||
| 128 | } | ||
| 129 | |||
| 130 | } | ||
| 131 | |||
| 132 | return $this->is_writable; | ||
| 133 | } | ||
| 134 | |||
| 135 | public function is_readable() | ||
| 136 | { | ||
| 137 | if (is_null($this->is_readable)) | ||
| 138 | $this->is_readable = @is_readable($this->fullpath); | ||
| 139 | |||
| 140 | return $this->is_readable; | ||
| 141 | } | ||
| 142 | |||
| 143 | // A file is virtual when the file is remote with URL and no local alternative is present. | ||
| 144 | public function is_virtual() | ||
| 145 | { | ||
| 146 | if ( is_null($this->is_virtual)) | ||
| 147 | $this->is_virtual = false; // return bool | ||
| 148 | return $this->is_virtual; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Function checks if path is actually a file. This can be used to check possible confusion if a directory path is given to filemodel */ | ||
| 152 | public function is_file() | ||
| 153 | { | ||
| 154 | if ($this->is_virtual()) // don't look further when virtual | ||
| 155 | { | ||
| 156 | $this->is_file = true; | ||
| 157 | return $this->is_file; | ||
| 158 | } | ||
| 159 | elseif (is_null($this->is_file)) | ||
| 160 | { | ||
| 161 | if ($this->exists()) | ||
| 162 | { | ||
| 163 | if (basename($this->fullpath) == '..' || basename($this->fullpath) == '.') | ||
| 164 | $this->is_file = false; | ||
| 165 | else | ||
| 166 | $this->is_file = is_file($this->fullpath); | ||
| 167 | } | ||
| 168 | else // file can not exist, but still have a valid filepath format. In that case, if file should return true. | ||
| 169 | { | ||
| 170 | |||
| 171 | /* if file does not exist on disk, anything can become a file ( with/ without extension, etc). Meaning everything non-existing is a potential file ( or directory ) until created. */ | ||
| 172 | |||
| 173 | if (basename($this->fullpath) == '..' || basename($this->fullpath) == '.') // don't see this as file. | ||
| 174 | { | ||
| 175 | $this->is_file = false; | ||
| 176 | } | ||
| 177 | else if (! file_exists($this->fullpath) && ! is_dir($this->fullpath)) | ||
| 178 | { | ||
| 179 | $this->is_file = true; | ||
| 180 | } | ||
| 181 | else //if (! is_file($this->fullpath)) // can be a non-existing directory. / | ||
| 182 | { | ||
| 183 | $this->is_file = false; | ||
| 184 | } | ||
| 185 | |||
| 186 | } | ||
| 187 | } | ||
| 188 | return $this->is_file; | ||
| 189 | } | ||
| 190 | |||
| 191 | public function getModified() | ||
| 192 | { | ||
| 193 | return filemtime($this->fullpath); | ||
| 194 | } | ||
| 195 | |||
| 196 | public function hasBackup() | ||
| 197 | { | ||
| 198 | $directory = $this->getBackupDirectory(); | ||
| 199 | if (! $directory) | ||
| 200 | return false; | ||
| 201 | |||
| 202 | $backupFile = $directory . $this->getFileName(); | ||
| 203 | |||
| 204 | if (file_exists($backupFile) && ! is_dir($backupFile) ) | ||
| 205 | return true; | ||
| 206 | else { | ||
| 207 | return false; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | |||
| 212 | /** Returns the Directory Model this file resides in | ||
| 213 | * | ||
| 214 | * @return DirectoryModel Directorymodel Object | ||
| 215 | */ | ||
| 216 | public function getFileDir() | ||
| 217 | { | ||
| 218 | $fullpath = $this->getFullPath(); // triggers a file lookup if needed. | ||
| 219 | // create this only when needed. | ||
| 220 | if (is_null($this->directory) && strlen($fullpath) > 0) | ||
| 221 | { | ||
| 222 | // Feed to full path to DirectoryModel since it checks if input is file, or dir. Using dirname here would cause errors when fullpath is already just a dirpath ( faulty input ) | ||
| 223 | $this->directory = new DirectoryModel($fullpath); | ||
| 224 | } | ||
| 225 | |||
| 226 | return $this->directory; | ||
| 227 | } | ||
| 228 | |||
| 229 | public function getFileSize() | ||
| 230 | { | ||
| 231 | if ($this->exists() && false === $this->is_virtual() ) | ||
| 232 | { | ||
| 233 | return filesize($this->fullpath); | ||
| 234 | } | ||
| 235 | elseif (true === $this->is_virtual()) | ||
| 236 | { | ||
| 237 | return -1; | ||
| 238 | } | ||
| 239 | else | ||
| 240 | return 0; | ||
| 241 | } | ||
| 242 | |||
| 243 | // Creates an empty file | ||
| 244 | public function create() | ||
| 245 | { | ||
| 246 | if (! $this->exists() ) | ||
| 247 | { | ||
| 248 | $fileDir = $this->getFileDir(); | ||
| 249 | |||
| 250 | if (! is_null($fileDir) && $fileDir->exists()) | ||
| 251 | { | ||
| 252 | $res = @touch($this->fullpath); | ||
| 253 | $this->exists = $res; | ||
| 254 | return $res; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | else | ||
| 258 | Log::addWarn('Could not create/write file: ' . $this->fullpath); | ||
| 259 | |||
| 260 | return false; | ||
| 261 | } | ||
| 262 | |||
| 263 | public function append($message) | ||
| 264 | { | ||
| 265 | if (! $this->exists() ) | ||
| 266 | $this->create(); | ||
| 267 | |||
| 268 | if (! $this->is_writable() ) | ||
| 269 | { | ||
| 270 | Log::addWarn('File append failed on ' . $this->getFullPath() . ' - not writable'); | ||
| 271 | return false; | ||
| 272 | } | ||
| 273 | $handle = fopen($this->getFullPath(), 'a'); | ||
| 274 | fwrite($handle, $message); | ||
| 275 | fclose($handle); | ||
| 276 | |||
| 277 | return true; | ||
| 278 | } | ||
| 279 | |||
| 280 | |||
| 281 | /** Copy a file to somewhere | ||
| 282 | * | ||
| 283 | * @param $destination String Full Path to new file. | ||
| 284 | */ | ||
| 285 | public function copy(FileModel $destination) | ||
| 286 | { | ||
| 287 | $sourcePath = $this->getFullPath(); | ||
| 288 | $destinationPath = $destination->getFullPath(); | ||
| 289 | Log::addDebug("Copy from $sourcePath to $destinationPath "); | ||
| 290 | |||
| 291 | if (! strlen($sourcePath) > 0 || ! strlen($destinationPath) > 0) | ||
| 292 | { | ||
| 293 | Log::addWarn('Attempted Copy on Empty Path', array($sourcePath, $destinationPath)); | ||
| 294 | return false; | ||
| 295 | } | ||
| 296 | |||
| 297 | if (! $this->exists()) | ||
| 298 | { | ||
| 299 | Log::addWarn('Tried to copy non-existing file - ' . $sourcePath); | ||
| 300 | return false; | ||
| 301 | } | ||
| 302 | |||
| 303 | $is_new = ($destination->exists()) ? false : true; | ||
| 304 | $status = @copy($sourcePath, $destinationPath); | ||
| 305 | |||
| 306 | if (! $status) | ||
| 307 | { | ||
| 308 | Log::addWarn('Could not copy file ' . $sourcePath . ' to' . $destinationPath); | ||
| 309 | } | ||
| 310 | else | ||
| 311 | { | ||
| 312 | $destination->resetStatus(); | ||
| 313 | $destination->setFileInfo(); // refresh info. | ||
| 314 | } | ||
| 315 | // | ||
| 316 | do_action('shortpixel/filesystem/addfile', array($destinationPath, $destination, $this, $is_new)); | ||
| 317 | return $status; | ||
| 318 | } | ||
| 319 | |||
| 320 | /** Move a file to somewhere | ||
| 321 | * This uses copy and delete functions and will fail if any of those fail. | ||
| 322 | * @param $destination String Full Path to new file. | ||
| 323 | */ | ||
| 324 | public function move(FileModel $destination) | ||
| 325 | { | ||
| 326 | $result = false; | ||
| 327 | if ($this->copy($destination)) | ||
| 328 | { | ||
| 329 | $result = $this->delete(); | ||
| 330 | if ($result == false) | ||
| 331 | { | ||
| 332 | Log::addError('Move can\'t remove file ' . $this->getFullPath()); | ||
| 333 | } | ||
| 334 | |||
| 335 | $this->resetStatus(); | ||
| 336 | $destination->resetStatus(); | ||
| 337 | } | ||
| 338 | return $result; | ||
| 339 | } | ||
| 340 | |||
| 341 | /** Deletes current file | ||
| 342 | * This uses the WP function since it has a filter that might be useful | ||
| 343 | */ | ||
| 344 | public function delete() | ||
| 345 | { | ||
| 346 | if ($this->exists()) | ||
| 347 | { | ||
| 348 | \wp_delete_file($this->fullpath); // delete file hook via wp_delete_file | ||
| 349 | } | ||
| 350 | else | ||
| 351 | { | ||
| 352 | Log::addWarn('Trying to remove non-existing file: ' . $this->getFullPath()); | ||
| 353 | } | ||
| 354 | |||
| 355 | if (! file_exists($this->fullpath)) | ||
| 356 | { | ||
| 357 | $this->resetStatus(); | ||
| 358 | return true; | ||
| 359 | } | ||
| 360 | else { | ||
| 361 | $writable = ($this->is_writable()) ? 'true' : 'false'; | ||
| 362 | Log::addWarn('File seems not removed - ' . $this->getFullPath() . ' (writable:' . $writable . ')'); | ||
| 363 | return false; | ||
| 364 | } | ||
| 365 | |||
| 366 | } | ||
| 367 | |||
| 368 | public function getContents() | ||
| 369 | { | ||
| 370 | return file_get_contents($this->getFullPath()); | ||
| 371 | } | ||
| 372 | |||
| 373 | public function getFullPath() | ||
| 374 | { | ||
| 375 | // filename here since fullpath is set unchecked in constructor, but might be a different take | ||
| 376 | if (is_null($this->filename)) | ||
| 377 | { | ||
| 378 | $this->setFileInfo(); | ||
| 379 | } | ||
| 380 | |||
| 381 | return $this->fullpath; | ||
| 382 | } | ||
| 383 | |||
| 384 | // Testing this. Principle is that when the plugin is absolutely sure this is a file, not something remote, not something non-existing, get the fullpath without any check. | ||
| 385 | // This function should *only* be used when processing mega amounts of files while not doing optimization or any processing. | ||
| 386 | // So far, testing use for file Filter */ | ||
| 387 | public function getRawFullPath() | ||
| 388 | { | ||
| 389 | return $this->rawfullpath; | ||
| 390 | } | ||
| 391 | |||
| 392 | public function getFileName() | ||
| 393 | { | ||
| 394 | if (is_null($this->filename)) | ||
| 395 | $this->setFileInfo(); | ||
| 396 | |||
| 397 | return $this->filename; | ||
| 398 | } | ||
| 399 | |||
| 400 | public function getFileBase() | ||
| 401 | { | ||
| 402 | if (is_null($this->filebase)) | ||
| 403 | $this->setFileInfo(); | ||
| 404 | |||
| 405 | return $this->filebase; | ||
| 406 | } | ||
| 407 | |||
| 408 | |||
| 409 | public function getExtension() | ||
| 410 | { | ||
| 411 | if (is_null($this->extension)) | ||
| 412 | $this->setFileInfo(); | ||
| 413 | |||
| 414 | return $this->extension; | ||
| 415 | } | ||
| 416 | |||
| 417 | public function getMime() | ||
| 418 | { | ||
| 419 | if (is_null($this->mime)) | ||
| 420 | $this->setFileInfo(); | ||
| 421 | |||
| 422 | if ($this->exists() && ! $this->is_virtual() ) | ||
| 423 | { | ||
| 424 | $this->mime = wp_get_image_mime($this->fullpath); | ||
| 425 | if (false === $this->mime) | ||
| 426 | { | ||
| 427 | $image_data = wp_check_filetype_and_ext($this->getFullPath(), $this->getFileName()); | ||
| 428 | if (is_array($image_data) && isset($image_data['type']) && strlen($image_data['type']) > 0) | ||
| 429 | { | ||
| 430 | $this->mime = $image_data['type']; | ||
| 431 | } | ||
| 432 | |||
| 433 | } | ||
| 434 | } | ||
| 435 | else | ||
| 436 | $this->mime = false; | ||
| 437 | |||
| 438 | return $this->mime; | ||
| 439 | } | ||
| 440 | |||
| 441 | |||
| 442 | /* Internal function to check if path is a real path | ||
| 443 | * - Test for URL's based on http / https | ||
| 444 | * - Test if given path is absolute, from the filesystem root. | ||
| 445 | * @param $path String The file path | ||
| 446 | * @param String The Fixed filepath. | ||
| 447 | */ | ||
| 448 | protected function processPath($path) | ||
| 449 | { | ||
| 450 | $original_path = $path; | ||
| 451 | $fs = $this->getFS(); | ||
| 452 | |||
| 453 | if ($fs->pathIsUrl($path)) | ||
| 454 | { | ||
| 455 | $path = $this->UrlToPath($path); | ||
| 456 | } | ||
| 457 | |||
| 458 | if ($path === false) // don't process further | ||
| 459 | return false; | ||
| 460 | |||
| 461 | //$path = wp_normalize_path($path); | ||
| 462 | $abspath = $fs->getWPAbsPath(); | ||
| 463 | |||
| 464 | if ( is_file($path) && ! is_dir($path) ) // if path and file exist, all should be okish. | ||
| 465 | { | ||
| 466 | return $path; | ||
| 467 | } | ||
| 468 | // If attempted file does not exist, but the file is in a dir that exists, that is good enough. | ||
| 469 | elseif ( ! is_dir($path) && is_dir(dirname($path)) ) | ||
| 470 | { | ||
| 471 | return $path; | ||
| 472 | } | ||
| 473 | // If path is not in the abspath, it might be relative. | ||
| 474 | elseif (strpos($path, $abspath->getPath()) === false) | ||
| 475 | { | ||
| 476 | // if path does not contain basepath. | ||
| 477 | //$uploadDir = $fs->getWPUploadBase(); | ||
| 478 | //$abspath = $fs->getWPAbsPath(); | ||
| 479 | |||
| 480 | $path = $this->relativeToFullPath($path); | ||
| 481 | } | ||
| 482 | $path = apply_filters('shortpixel/filesystem/processFilePath', $path, $original_path); | ||
| 483 | /* This needs some check here on malformed path's, but can't be test for existing since that's not a requirement. | ||
| 484 | if (file_exists($path) === false) // failed to process path to something workable. | ||
| 485 | { | ||
| 486 | // Log::addInfo('Failed to process path', array($path)); | ||
| 487 | $path = false; | ||
| 488 | } */ | ||
| 489 | |||
| 490 | return $path; | ||
| 491 | } | ||
| 492 | |||
| 493 | |||
| 494 | |||
| 495 | /** Resolve an URL to a local path | ||
| 496 | * This partially comes from WordPress functions attempting the same | ||
| 497 | * @param String $url The URL to resolve | ||
| 498 | * @return String/Boolean - False is this seems an external domain, otherwise resolved path. | ||
| 499 | */ | ||
| 500 | private function UrlToPath($url) | ||
| 501 | { | ||
| 502 | //$uploadDir = wp_upload_dir(); | ||
| 503 | |||
| 504 | $site_url = str_replace('http:', '', home_url('', 'http')); | ||
| 505 | $url = str_replace(array('http:', 'https:'), '', $url); | ||
| 506 | $fs = $this->getFS(); | ||
| 507 | |||
| 508 | if (strpos($url, $site_url) !== false) | ||
| 509 | { | ||
| 510 | // try to replace URL for Path | ||
| 511 | $abspath = $this->getFS()->getWPAbsPath(); | ||
| 512 | $path = str_replace($site_url, rtrim($abspath->getPath(),'/'), $url); | ||
| 513 | |||
| 514 | |||
| 515 | if (! $fs->pathIsUrl($path)) // test again. | ||
| 516 | { | ||
| 517 | return $path; | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | $this->is_virtual = true; | ||
| 522 | |||
| 523 | // This filter checks if some supplier will be able to handle the file when needed. | ||
| 524 | $path = apply_filters('shortpixel/image/urltopath', false, $url); | ||
| 525 | |||
| 526 | if ($path !== false) | ||
| 527 | { | ||
| 528 | $this->exists = true; | ||
| 529 | $this->is_readable = true; | ||
| 530 | $this->is_file = true; | ||
| 531 | } | ||
| 532 | else | ||
| 533 | { | ||
| 534 | $this->exists = false; | ||
| 535 | $this->is_readable = false; | ||
| 536 | $this->is_file = false; | ||
| 537 | } | ||
| 538 | |||
| 539 | |||
| 540 | return false; // seems URL from other server, use virtual mode. | ||
| 541 | } | ||
| 542 | |||
| 543 | /** Tries to find the full path for a perceived relative path. | ||
| 544 | * | ||
| 545 | * Relative path is detected on basis of WordPress ABSPATH. If this doesn't appear in the file path, it might be a relative path. | ||
| 546 | * Function checks for expections on this rule ( tmp path ) and returns modified - or not - path. | ||
| 547 | * @param $path The path for the file_exists | ||
| 548 | * @returns String The updated path, if that was possible. | ||
| 549 | */ | ||
| 550 | private function relativeToFullPath($path) | ||
| 551 | { | ||
| 552 | $originalPath = $path; // for safe-keeping | ||
| 553 | |||
| 554 | // A file with no path, can never be created to a fullpath. | ||
| 555 | if (strlen($path) == 0) | ||
| 556 | return $path; | ||
| 557 | |||
| 558 | // if the file plainly exists, it's usable /** | ||
| 559 | if (file_exists($path)) | ||
| 560 | { | ||
| 561 | return $path; | ||
| 562 | } | ||
| 563 | |||
| 564 | // Test if our 'relative' path is not a path to /tmp directory. | ||
| 565 | |||
| 566 | // This ini value might not exist. | ||
| 567 | $tempdirini = ini_get('upload_tmp_dir'); | ||
| 568 | if ( (strlen($tempdirini) > 0) && strpos($path, $tempdirini) !== false) | ||
| 569 | return $path; | ||
| 570 | |||
| 571 | $tempdir = sys_get_temp_dir(); | ||
| 572 | if ( (strlen($tempdir) > 0) && strpos($path, $tempdir) !== false) | ||
| 573 | return $path; | ||
| 574 | |||
| 575 | // Path contains upload basedir. This happens when upload dir is outside of usual WP. | ||
| 576 | $fs = $this->getFS(); | ||
| 577 | $uploadDir = $fs->getWPUploadBase(); | ||
| 578 | $abspath = $fs->getWPAbsPath(); | ||
| 579 | |||
| 580 | if (strpos($path, $uploadDir->getPath()) !== false) // If upload Dir is feature in path, consider it ok. | ||
| 581 | { | ||
| 582 | return $path; | ||
| 583 | } | ||
| 584 | elseif (file_exists($abspath->getPath() . $path)) // If upload dir is abspath plus return path. Exceptions. | ||
| 585 | { | ||
| 586 | return $abspath->getPath() . $path; | ||
| 587 | } | ||
| 588 | elseif(file_exists($uploadDir->getPath() . $path)) // This happens when upload_dir is not properly prepended in get_attachment_file due to WP errors | ||
| 589 | { | ||
| 590 | return $uploadDir->getPath() . $path; | ||
| 591 | } | ||
| 592 | |||
| 593 | // this is probably a bit of a sharp corner to take. | ||
| 594 | // if path starts with / remove it due to trailingslashing ABSPATH | ||
| 595 | $path = ltrim($path, '/'); | ||
| 596 | $fullpath = $abspath->getPath() . $path; | ||
| 597 | |||
| 598 | // We can't test for file_exists here, since file_model allows non-existing files. | ||
| 599 | // Test if directory exists, perhaps. Otherwise we are in for a failure anyhow. | ||
| 600 | //if (is_dir(dirname($fullpath))) | ||
| 601 | return $fullpath; | ||
| 602 | //else | ||
| 603 | // return $originalPath; | ||
| 604 | } | ||
| 605 | |||
| 606 | public function getPermissions() | ||
| 607 | { | ||
| 608 | if (is_null($this->permissions)) | ||
| 609 | $this->permissions = fileperms($this->getFullPath()) & 0777; | ||
| 610 | |||
| 611 | return $this->permissions; | ||
| 612 | } | ||
| 613 | |||
| 614 | // @tozo Lazy IMplementation / copy, should be brought in line w/ other attributes. | ||
| 615 | public function setPermissions($permissions) | ||
| 616 | { | ||
| 617 | @chmod($this->fullpath, $permissions); | ||
| 618 | } | ||
| 619 | |||
| 620 | |||
| 621 | /** Fix for multibyte pathnames and pathinfo which doesn't take into regard the locale. | ||
| 622 | * This snippet taken from PHPMailer. | ||
| 623 | */ | ||
| 624 | private function mb_pathinfo($path, $options = null) | ||
| 625 | { | ||
| 626 | $ret = ['dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '']; | ||
| 627 | $pathinfo = []; | ||
| 628 | if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^.\\\\/]+?)|))[\\\\/.]*$#m', $path, $pathinfo)) { | ||
| 629 | if (array_key_exists(1, $pathinfo)) { | ||
| 630 | $ret['dirname'] = $pathinfo[1]; | ||
| 631 | } | ||
| 632 | if (array_key_exists(2, $pathinfo)) { | ||
| 633 | $ret['basename'] = $pathinfo[2]; | ||
| 634 | } | ||
| 635 | if (array_key_exists(5, $pathinfo)) { | ||
| 636 | $ret['extension'] = $pathinfo[5]; | ||
| 637 | } | ||
| 638 | if (array_key_exists(3, $pathinfo)) { | ||
| 639 | $ret['filename'] = $pathinfo[3]; | ||
| 640 | } | ||
| 641 | } | ||
| 642 | switch ($options) { | ||
| 643 | case PATHINFO_DIRNAME: | ||
| 644 | case 'dirname': | ||
| 645 | return $ret['dirname']; | ||
| 646 | case PATHINFO_BASENAME: | ||
| 647 | case 'basename': | ||
| 648 | return $ret['basename']; | ||
| 649 | case PATHINFO_EXTENSION: | ||
| 650 | case 'extension': | ||
| 651 | return $ret['extension']; | ||
| 652 | case PATHINFO_FILENAME: | ||
| 653 | case 'filename': | ||
| 654 | return $ret['filename']; | ||
| 655 | default: | ||
| 656 | return $ret; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | public function __debuginfo() | ||
| 661 | { | ||
| 662 | return [ | ||
| 663 | 'fullpath' => $this->fullpath, | ||
| 664 | 'filename' => $this->filename, | ||
| 665 | 'filebase' => $this->filebase, | ||
| 666 | 'exists' => $this->exists, | ||
| 667 | 'is_writable' => $this->is_writable, | ||
| 668 | 'is_readable' => $this->is_readable, | ||
| 669 | 'is_virtual' => $this->is_virtual, | ||
| 670 | ]; | ||
| 671 | } | ||
| 672 | |||
| 673 | |||
| 674 | } // FileModel Class |
| 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 or object. | ||
| 45 | { | ||
| 46 | $count = false; | ||
| 47 | if (gettype($data) == 'array') | ||
| 48 | $count = count($data); | ||
| 49 | elseif(gettype($data) == 'object') | ||
| 50 | $count = count(get_object_vars($data)); | ||
| 51 | |||
| 52 | $firstLine = ucfirst(gettype($data)) . ':'; | ||
| 53 | if ($count !== false) | ||
| 54 | $firstLine .= ' (' . $count . ')'; | ||
| 55 | |||
| 56 | $this->data[] = $firstLine; | ||
| 57 | |||
| 58 | foreach($data as $index => $item) | ||
| 59 | { | ||
| 60 | if (is_object($item) || is_array($item)) | ||
| 61 | { | ||
| 62 | $this->data[] = print_r($index, true) . ' ( ' . ucfirst(gettype($item)) . ') => ' . print_r($item, true); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | } // if | ||
| 67 | elseif (! is_array($data)) // this leaves out empty default arrays | ||
| 68 | { | ||
| 69 | $this->data[] = print_r($data, true); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | public function getData() | ||
| 74 | { | ||
| 75 | return array('time' => $this->time, 'level' => $this->level, 'message' => $this->message, 'data' => $this->data, 'caller' => $this->caller); | ||
| 76 | } | ||
| 77 | |||
| 78 | /** Test Data Array for possible values | ||
| 79 | * | ||
| 80 | * Data can be a collection of several debug vars, a single var, or just an normal array. Test if array has single types, | ||
| 81 | * which is a sign the array is not a collection. | ||
| 82 | */ | ||
| 83 | protected function getDataType($data) | ||
| 84 | { | ||
| 85 | $single_type = array('integer', 'boolean', 'string'); | ||
| 86 | if (in_array(gettype(reset($data)), $single_type)) | ||
| 87 | { | ||
| 88 | return 1; | ||
| 89 | } | ||
| 90 | else | ||
| 91 | { | ||
| 92 | return 2; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | public function getForFormat() | ||
| 97 | { | ||
| 98 | $data = $this->getData(); | ||
| 99 | switch($this->level) | ||
| 100 | { | ||
| 101 | case self::LEVEL_ERROR: | ||
| 102 | $level = 'ERR'; | ||
| 103 | $color = "\033[31m"; | ||
| 104 | break; | ||
| 105 | case self::LEVEL_WARN: | ||
| 106 | $level = 'WRN'; | ||
| 107 | $color = "\033[33m"; | ||
| 108 | break; | ||
| 109 | case self::LEVEL_INFO: | ||
| 110 | $level = 'INF'; | ||
| 111 | $color = "\033[37m"; | ||
| 112 | break; | ||
| 113 | case self::LEVEL_DEBUG: | ||
| 114 | $level = 'DBG'; | ||
| 115 | $color = "\033[37m"; | ||
| 116 | break; | ||
| 117 | |||
| 118 | } | ||
| 119 | $color_end = "\033[0m"; | ||
| 120 | |||
| 121 | $data['color'] = $color; | ||
| 122 | $data['color_end'] = $color_end; | ||
| 123 | $data['level'] = $level; | ||
| 124 | |||
| 125 | return $data; | ||
| 126 | |||
| 127 | //return array('time' => $this->time, 'level' => $level, 'message' => $this->message, 'data' => $this->data, 'color' => $color, 'color_end' => $color_end, 'caller' => $this->caller); | ||
| 128 | |||
| 129 | } | ||
| 130 | |||
| 131 | protected function setCaller() | ||
| 132 | { | ||
| 133 | if(PHP_VERSION_ID < 50400) { | ||
| 134 | $debug=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); | ||
| 135 | } else { | ||
| 136 | $debug=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,5); | ||
| 137 | } | ||
| 138 | |||
| 139 | $i = 4; | ||
| 140 | if (isset($debug[$i])) | ||
| 141 | { | ||
| 142 | $info = $debug[$i]; | ||
| 143 | $line = isset($info['line']) ? $info['line'] : 'Line unknown'; | ||
| 144 | $file = isset($info['file']) ? basename($info['file']) : 'File not set'; | ||
| 145 | |||
| 146 | $this->caller = array('line' => $line, 'file' => $file, 'function' => $info['function']); | ||
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | } | ||
| 151 | |||
| 152 | |||
| 153 | } |
| 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 | |||
| 28 | private $logFile; // pointer resource to the logFile. | ||
| 29 | /* protected $hooks = array( | ||
| 30 | 'shortpixel_image_exists' => array('numargs' => 3), | ||
| 31 | 'shortpixel_webp_image_base' => array('numargs' => 2), | ||
| 32 | 'shortpixel_image_urls' => array('numargs' => 2), | ||
| 33 | ); // @todo monitor hooks, but this should be more dynamic. Do when moving to module via config. | ||
| 34 | */ | ||
| 35 | |||
| 36 | // utility | ||
| 37 | private $namespace; | ||
| 38 | private $view; | ||
| 39 | |||
| 40 | protected $template = 'view-debug-box'; | ||
| 41 | |||
| 42 | /** Debugger constructor | ||
| 43 | * 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 | ||
| 44 | * 2) Put SHORTPIXEL_DEBUG in the request. Either true or number. | ||
| 45 | */ | ||
| 46 | public function __construct() | ||
| 47 | { | ||
| 48 | $this->start_time = microtime(true); | ||
| 49 | $this->logLevel = DebugItem::LEVEL_WARN; | ||
| 50 | |||
| 51 | $ns = __NAMESPACE__; | ||
| 52 | $this->namespace = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace | ||
| 53 | |||
| 54 | // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form | ||
| 55 | if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants | ||
| 56 | { | ||
| 57 | $this->is_manual_request = true; | ||
| 58 | $this->is_active = true; | ||
| 59 | |||
| 60 | // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form | ||
| 61 | if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true') | ||
| 62 | { | ||
| 63 | $this->logLevel = DebugItem::LEVEL_INFO; | ||
| 64 | } | ||
| 65 | else { | ||
| 66 | // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form | ||
| 67 | $this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']); | ||
| 68 | } | ||
| 69 | |||
| 70 | } | ||
| 71 | else if ( (defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG > 0) ) | ||
| 72 | { | ||
| 73 | $this->is_active = true; | ||
| 74 | if (SHORTPIXEL_DEBUG === true) | ||
| 75 | $this->logLevel = DebugItem::LEVEL_INFO; | ||
| 76 | else { | ||
| 77 | $this->logLevel = intval(SHORTPIXEL_DEBUG); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | if (defined('SHORTPIXEL_DEBUG_TARGET') && SHORTPIXEL_DEBUG_TARGET || $this->is_manual_request) | ||
| 82 | { | ||
| 83 | if (defined('SHORTPIXEL_LOG_OVERWRITE')) // if overwrite, do this on init once. | ||
| 84 | file_put_contents($this->logPath,'-- Log Reset -- ' .PHP_EOL); | ||
| 85 | |||
| 86 | } | ||
| 87 | |||
| 88 | if ($this->is_active) | ||
| 89 | { | ||
| 90 | /* On Early init, this function might not exist, then queue it when needed */ | ||
| 91 | if (! function_exists('wp_get_current_user')) | ||
| 92 | add_action('init', array($this, 'initView')); | ||
| 93 | else | ||
| 94 | $this->initView(); | ||
| 95 | } | ||
| 96 | |||
| 97 | if ($this->is_active && count($this->hooks) > 0) | ||
| 98 | $this->monitorHooks(); | ||
| 99 | } | ||
| 100 | |||
| 101 | /** Init the view when needed. Private function ( public because of WP_HOOK ) | ||
| 102 | * Never call directly */ | ||
| 103 | public function initView() | ||
| 104 | { | ||
| 105 | $user_is_administrator = (current_user_can('manage_options')) ? true : false; | ||
| 106 | |||
| 107 | if ($this->is_active && $this->is_manual_request && $user_is_administrator ) | ||
| 108 | { | ||
| 109 | |||
| 110 | $logPath = $this->logPath; | ||
| 111 | $uploads = wp_get_upload_dir(); | ||
| 112 | |||
| 113 | |||
| 114 | if ( 0 === strpos( $logPath, $uploads['basedir'] ) ) { // Simple as it should, filepath and basedir share. | ||
| 115 | // Replace file location with url location. | ||
| 116 | $logLink = str_replace( $uploads['basedir'], $uploads['baseurl'], $logPath ); | ||
| 117 | } | ||
| 118 | |||
| 119 | |||
| 120 | $this->view = new \stdClass; | ||
| 121 | $this->view->logLink = 'view-source:' . esc_url($logLink); | ||
| 122 | add_action('admin_footer', array($this, 'loadView')); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | public static function getInstance() | ||
| 127 | { | ||
| 128 | if ( self::$instance === null) | ||
| 129 | { | ||
| 130 | self::$instance = new ShortPixelLogger(); | ||
| 131 | } | ||
| 132 | return self::$instance; | ||
| 133 | } | ||
| 134 | |||
| 135 | public function setLogPath($logPath) | ||
| 136 | { | ||
| 137 | $this->logPath = $logPath; | ||
| 138 | $this->getWriteFile(true); // reset the writeFile here. | ||
| 139 | } | ||
| 140 | protected function addLog($message, $level, $data = array()) | ||
| 141 | { | ||
| 142 | // $log = self::getInstance(); | ||
| 143 | |||
| 144 | // don't log anything too low or when not active. | ||
| 145 | if ($this->logLevel < $level || ! $this->is_active) | ||
| 146 | { | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | |||
| 150 | // Force administrator on manuals. | ||
| 151 | if ( $this->is_manual_request ) | ||
| 152 | { | ||
| 153 | if (! function_exists('wp_get_current_user')) // not loaded yet | ||
| 154 | return false; | ||
| 155 | |||
| 156 | $user_is_administrator = (current_user_can('manage_options')) ? true : false; | ||
| 157 | if (! $user_is_administrator) | ||
| 158 | return false; | ||
| 159 | } | ||
| 160 | |||
| 161 | // Check where to log to. | ||
| 162 | if ($this->logPath === false) | ||
| 163 | { | ||
| 164 | $upload_dir = wp_upload_dir(null,false,false); | ||
| 165 | $this->logPath = $this->setLogPath($upload_dir['basedir'] . '/' . $this->namespace . ".log"); | ||
| 166 | } | ||
| 167 | |||
| 168 | $arg = array(); | ||
| 169 | $args['level'] = $level; | ||
| 170 | $args['data'] = $data; | ||
| 171 | |||
| 172 | $newItem = new DebugItem($message, $args); | ||
| 173 | $this->items[] = $newItem; | ||
| 174 | |||
| 175 | if ($this->is_active) | ||
| 176 | { | ||
| 177 | $this->write($newItem); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | /** Writes to log File. */ | ||
| 182 | protected function write($debugItem, $mode = 'file') | ||
| 183 | { | ||
| 184 | $items = $debugItem->getForFormat(); | ||
| 185 | $items['time_passed'] = round ( ($items['time'] - $this->start_time), 5); | ||
| 186 | $items['time'] = date('Y-m-d H:i:s', (int) $items['time'] ); | ||
| 187 | |||
| 188 | if ( ($items['caller']) && is_array($items['caller']) && count($items['caller']) > 0) | ||
| 189 | { | ||
| 190 | $caller = $items['caller']; | ||
| 191 | $items['caller'] = $caller['file'] . ' in ' . $caller['function'] . '(' . $caller['line'] . ')'; | ||
| 192 | } | ||
| 193 | |||
| 194 | $line = $this->formatLine($items); | ||
| 195 | |||
| 196 | $file = $this->getWriteFile(); | ||
| 197 | |||
| 198 | // try to write to file. Don't write if directory doesn't exists (leads to notices) | ||
| 199 | if ($file ) | ||
| 200 | { | ||
| 201 | fwrite($file, $line); | ||
| 202 | // file_put_contents($this->logPath,$line, FILE_APPEND); | ||
| 203 | } | ||
| 204 | else { | ||
| 205 | // error_log($line); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | protected function getWriteFile($reset = false) | ||
| 210 | { | ||
| 211 | if (! is_null($this->logFile) && $reset === false) | ||
| 212 | { | ||
| 213 | return $this->logFile; | ||
| 214 | } | ||
| 215 | elseif(is_object($this->logFile)) | ||
| 216 | { | ||
| 217 | fclose($this->logFile); | ||
| 218 | } | ||
| 219 | |||
| 220 | $logDir = dirname($this->logPath); | ||
| 221 | if (! is_dir($logDir) || ! is_writable($logDir)) | ||
| 222 | { | ||
| 223 | error_log('ShortpixelLogger: Log Directory is not writable'); | ||
| 224 | $this->logFile = false; | ||
| 225 | return false; | ||
| 226 | } | ||
| 227 | |||
| 228 | $file = fopen($this->logPath, 'a'); | ||
| 229 | if ($file === false) | ||
| 230 | { | ||
| 231 | error_log('ShortpixelLogger: File could not be opened / created: ' . $this->logPath); | ||
| 232 | $this->logFile = false; | ||
| 233 | return $file; | ||
| 234 | } | ||
| 235 | |||
| 236 | $this->logFile = $file; | ||
| 237 | return $file; | ||
| 238 | } | ||
| 239 | |||
| 240 | protected function formatLine($args = array() ) | ||
| 241 | { | ||
| 242 | $line= $this->format; | ||
| 243 | foreach($args as $key => $value) | ||
| 244 | { | ||
| 245 | if (! is_array($value) && ! is_object($value)) | ||
| 246 | $line = str_replace('%%' . $key . '%%', $value, $line); | ||
| 247 | } | ||
| 248 | |||
| 249 | $line .= PHP_EOL; | ||
| 250 | |||
| 251 | if (isset($args['data'])) | ||
| 252 | { | ||
| 253 | $data = array_filter($args['data']); | ||
| 254 | if (count($data) > 0) | ||
| 255 | { | ||
| 256 | foreach($data as $item) | ||
| 257 | { | ||
| 258 | $line .= $item . PHP_EOL; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | return $line; | ||
| 264 | } | ||
| 265 | |||
| 266 | protected function setLogLevel($level) | ||
| 267 | { | ||
| 268 | $this->logLevel = $level; | ||
| 269 | } | ||
| 270 | |||
| 271 | protected function getEnv($name) | ||
| 272 | { | ||
| 273 | if (isset($this->{$name})) | ||
| 274 | { | ||
| 275 | return $this->{$name}; | ||
| 276 | } | ||
| 277 | else { | ||
| 278 | return false; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | public static function addError($message, $args = array()) | ||
| 283 | { | ||
| 284 | $level = DebugItem::LEVEL_ERROR; | ||
| 285 | $log = self::getInstance(); | ||
| 286 | $log->addLog($message, $level, $args); | ||
| 287 | } | ||
| 288 | public static function addWarn($message, $args = array()) | ||
| 289 | { | ||
| 290 | $level = DebugItem::LEVEL_WARN; | ||
| 291 | $log = self::getInstance(); | ||
| 292 | $log->addLog($message, $level, $args); | ||
| 293 | } | ||
| 294 | // Alias, since it goes wrong so often. | ||
| 295 | public static function addWarning($message, $args = array()) | ||
| 296 | { | ||
| 297 | self::addWarn($message, $args); | ||
| 298 | } | ||
| 299 | public static function addInfo($message, $args = array()) | ||
| 300 | { | ||
| 301 | $level = DebugItem::LEVEL_INFO; | ||
| 302 | $log = self::getInstance(); | ||
| 303 | $log->addLog($message, $level, $args); | ||
| 304 | } | ||
| 305 | public static function addDebug($message, $args = array()) | ||
| 306 | { | ||
| 307 | $level = DebugItem::LEVEL_DEBUG; | ||
| 308 | $log = self::getInstance(); | ||
| 309 | $log->addLog($message, $level, $args); | ||
| 310 | } | ||
| 311 | |||
| 312 | /** These should be removed every release. They are temporary only for d'bugging the current release */ | ||
| 313 | public static function addTemp($message, $args = array()) | ||
| 314 | { | ||
| 315 | self::addDebug($message, $args); | ||
| 316 | } | ||
| 317 | |||
| 318 | public static function logLevel($level) | ||
| 319 | { | ||
| 320 | $log = self::getInstance(); | ||
| 321 | static::addInfo('Changing Log level' . $level); | ||
| 322 | $log->setLogLevel($level); | ||
| 323 | } | ||
| 324 | |||
| 325 | public static function getLogLevel() | ||
| 326 | { | ||
| 327 | $log = self::getInstance(); | ||
| 328 | return $log->getEnv('logLevel'); | ||
| 329 | } | ||
| 330 | |||
| 331 | public static function isManualDebug() | ||
| 332 | { | ||
| 333 | $log = self::getInstance(); | ||
| 334 | return $log->getEnv('is_manual_request'); | ||
| 335 | } | ||
| 336 | |||
| 337 | public static function getLogPath() | ||
| 338 | { | ||
| 339 | $log = self::getInstance(); | ||
| 340 | return $log->getEnv('logPath'); | ||
| 341 | } | ||
| 342 | |||
| 343 | /** Function to test if the debugger is active | ||
| 344 | * @return boolean true when active. | ||
| 345 | */ | ||
| 346 | public static function debugIsActive() | ||
| 347 | { | ||
| 348 | $log = self::getInstance(); | ||
| 349 | return $log->getEnv('is_active'); | ||
| 350 | } | ||
| 351 | |||
| 352 | protected function monitorHooks() | ||
| 353 | { | ||
| 354 | |||
| 355 | foreach($this->hooks as $hook => $data) | ||
| 356 | { | ||
| 357 | $numargs = isset($data['numargs']) ? $data['numargs'] : 1; | ||
| 358 | $prio = isset($data['priority']) ? $data['priority'] : 10; | ||
| 359 | |||
| 360 | add_filter($hook, function($value) use ($hook) { | ||
| 361 | $args = func_get_args(); | ||
| 362 | return $this->logHook($hook, $value, $args); }, $prio, $numargs); | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | public function logHook($hook, $value, $args) | ||
| 367 | { | ||
| 368 | array_shift($args); | ||
| 369 | self::addInfo('[Hook] - ' . $hook . ' with ' . var_export($value,true), $args); | ||
| 370 | return $value; | ||
| 371 | } | ||
| 372 | |||
| 373 | public function loadView() | ||
| 374 | { | ||
| 375 | // load either param or class template. | ||
| 376 | $template = $this->template; | ||
| 377 | |||
| 378 | $view = $this->view; | ||
| 379 | $view->namespace = $this->namespace; | ||
| 380 | $controller = $this; | ||
| 381 | |||
| 382 | $template_path = __DIR__ . '/' . $this->template . '.php'; | ||
| 383 | if (file_exists($template_path)) | ||
| 384 | { | ||
| 385 | |||
| 386 | include($template_path); | ||
| 387 | } | ||
| 388 | else { | ||
| 389 | self::addError("View $template for ShortPixelLogger could not be found in " . $template_path, | ||
| 390 | array('class' => get_class($this))); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | |||
| 395 | } // 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 esc_html($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 | } |
wp-content/plugins/enable-media-replace/build/shortpixel/notices/src/NoticeController.php
0 → 100644
| 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 | |||
| 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 (isset($_POST['nonce']) && wp_verify_nonce( sanitize_key($_POST['nonce']), 'dismiss') ) | ||
| 216 | { | ||
| 217 | if (isset($_POST['plugin_action']) && 'dismiss' == $_POST['plugin_action'] ) | ||
| 218 | { | ||
| 219 | $id = (isset($_POST['id'])) ? sanitize_text_field( wp_unslash($_POST['id'])) : null; | ||
| 220 | |||
| 221 | if (! is_null($id)) | ||
| 222 | { | ||
| 223 | |||
| 224 | $notice = $this->getNoticeByID($id); | ||
| 225 | } | ||
| 226 | else | ||
| 227 | { | ||
| 228 | $notice = false; | ||
| 229 | } | ||
| 230 | |||
| 231 | if(false !== $notice) | ||
| 232 | { | ||
| 233 | $notice->dismiss(); | ||
| 234 | $this->update(); | ||
| 235 | $response['result'] = true; | ||
| 236 | } | ||
| 237 | else | ||
| 238 | { | ||
| 239 | Log::addError('Notice not found when dismissing -> ' . $id, self::$notices); | ||
| 240 | $response['result'] = false; | ||
| 241 | $response['reason'] = ' Notice ' . $id . ' not found. '; | ||
| 242 | } | ||
| 243 | |||
| 244 | } | ||
| 245 | |||
| 246 | } | ||
| 247 | else | ||
| 248 | { | ||
| 249 | Log::addError('Wrong Nonce when dismissed notice. '); | ||
| 250 | $response['reason'] = 'wrong nonce'; | ||
| 251 | } | ||
| 252 | wp_send_json($response); | ||
| 253 | } | ||
| 254 | |||
| 255 | /** Adds a notice, quick and fast method | ||
| 256 | * @param String $message The Message you want to notify | ||
| 257 | * @param Boolean $unique If unique, check to not repeat notice exact same text in notices. Discard if so | ||
| 258 | * @param int $code A value of messageType as defined in model | ||
| 259 | * @returm Object Instance of noticeModel | ||
| 260 | */ | ||
| 261 | |||
| 262 | public static function addNormal($message, $unique = false) | ||
| 263 | { | ||
| 264 | $noticeController = self::getInstance(); | ||
| 265 | $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_NORMAL, $unique); | ||
| 266 | return $notice; | ||
| 267 | |||
| 268 | } | ||
| 269 | |||
| 270 | public static function addError($message, $unique = false) | ||
| 271 | { | ||
| 272 | $noticeController = self::getInstance(); | ||
| 273 | $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_ERROR, $unique); | ||
| 274 | return $notice; | ||
| 275 | |||
| 276 | } | ||
| 277 | |||
| 278 | public static function addWarning($message, $unique = false) | ||
| 279 | { | ||
| 280 | $noticeController = self::getInstance(); | ||
| 281 | $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_WARNING, $unique); | ||
| 282 | return $notice; | ||
| 283 | } | ||
| 284 | |||
| 285 | public static function addSuccess($message, $unique = false) | ||
| 286 | { | ||
| 287 | $noticeController = self::getInstance(); | ||
| 288 | $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_SUCCESS, $unique); | ||
| 289 | return $notice; | ||
| 290 | |||
| 291 | } | ||
| 292 | |||
| 293 | public static function addDetail($notice, $detail) | ||
| 294 | { | ||
| 295 | $noticeController = self::getInstance(); | ||
| 296 | $notice->addDetail($detail); | ||
| 297 | |||
| 298 | // $notice_id = spl_object_id($notice); | ||
| 299 | |||
| 300 | $noticeController->update(); | ||
| 301 | } | ||
| 302 | |||
| 303 | /** Make a regular notice persistent across multiple page loads | ||
| 304 | * @param $notice NoticeModel The Notice to make Persistent | ||
| 305 | * @param $key String Identifier of the persistent notice. | ||
| 306 | * @param $suppress Int When dismissed, time to stay dismissed | ||
| 307 | * @param $callback Function Callable function | ||
| 308 | */ | ||
| 309 | public static function makePersistent($notice, $key, $suppress = -1, $callback = null) | ||
| 310 | { | ||
| 311 | $noticeController = self::getInstance(); | ||
| 312 | $existing = $noticeController->getNoticeByID($key); | ||
| 313 | |||
| 314 | // if this key already exists, don't allow the new notice to be entered into the array. Remove it since it's already created. | ||
| 315 | if ($existing) | ||
| 316 | { | ||
| 317 | for($i = 0; $i < count(self::$notices); $i++) | ||
| 318 | { | ||
| 319 | $item = self::$notices[$i]; | ||
| 320 | |||
| 321 | if ($item->message == $notice->message && $item->getID() == null) | ||
| 322 | { | ||
| 323 | if ($item->message != $existing->message) // allow the persistent message to be updated, if something else is served on this ID | ||
| 324 | { | ||
| 325 | $existing->message = $item->message; | ||
| 326 | } | ||
| 327 | unset(self::$notices[$i]); | ||
| 328 | } | ||
| 329 | //if ($notice_item ) | ||
| 330 | } | ||
| 331 | } | ||
| 332 | else | ||
| 333 | { | ||
| 334 | $notice->setPersistent($key, $suppress, $callback); // set this notice persistent. | ||
| 335 | } | ||
| 336 | |||
| 337 | $noticeController->update(); | ||
| 338 | } | ||
| 339 | |||
| 340 | public function admin_notices() | ||
| 341 | { | ||
| 342 | if ($this->countNotices() > 0) | ||
| 343 | { | ||
| 344 | if (! self::$cssHookLoaded) | ||
| 345 | { | ||
| 346 | add_action('admin_print_footer_scripts', array($this, 'printNoticeStyle')); | ||
| 347 | self::$cssHookLoaded = true; | ||
| 348 | } | ||
| 349 | foreach($this->getNoticesForDisplay() as $notice) | ||
| 350 | { | ||
| 351 | echo $notice->getForDisplay(); | ||
| 352 | } | ||
| 353 | } | ||
| 354 | $this->update(); // puts views, and updates | ||
| 355 | } | ||
| 356 | |||
| 357 | |||
| 358 | public function printNoticeStyle() | ||
| 359 | { | ||
| 360 | if (file_exists(__DIR__ . '/css/notices.css')) | ||
| 361 | { | ||
| 362 | echo '<style>' . esc_html(file_get_contents(__DIR__ . '/css/notices.css')) . '</style>'; | ||
| 363 | } | ||
| 364 | else { | ||
| 365 | Log::addDebug('Notices : css/notices.css could not be loaded'); | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | |||
| 370 | |||
| 371 | |||
| 372 | } |
| 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 | protected $include_screens = array(); | ||
| 17 | protected $exclude_screens = array(); | ||
| 18 | public $is_removable = true; // if removable, display a notice dialog with red X or so. | ||
| 19 | public $messageType = self::NOTICE_NORMAL; | ||
| 20 | |||
| 21 | public $notice_action; // empty unless for display. Ajax action to talk back to controller. | ||
| 22 | protected $callback; // empty unless callback is needed | ||
| 23 | |||
| 24 | public static $icons = array(); | ||
| 25 | |||
| 26 | private static $jsDismissLoaded; | ||
| 27 | |||
| 28 | const NOTICE_NORMAL = 1; | ||
| 29 | const NOTICE_ERROR = 2; | ||
| 30 | const NOTICE_SUCCESS = 3; | ||
| 31 | const NOTICE_WARNING = 4; | ||
| 32 | |||
| 33 | /** Use this model in conjunction with NoticeController, do not call directly */ | ||
| 34 | public function __construct($message, $messageType = self::NOTICE_NORMAL) | ||
| 35 | { | ||
| 36 | $this->message = $message; | ||
| 37 | $this->messageType = $messageType; | ||
| 38 | } | ||
| 39 | |||
| 40 | public function isDone() | ||
| 41 | { | ||
| 42 | // check suppressed | ||
| 43 | if ($this->is_dismissed && ! is_null($this->suppress_until)) | ||
| 44 | { | ||
| 45 | if (time() >= $this->suppress_until) | ||
| 46 | { | ||
| 47 | $this->is_persistent = false; // unpersist, so it will be cleaned and dropped. | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | if ($this->viewed && ! $this->is_persistent) | ||
| 52 | return true; | ||
| 53 | else | ||
| 54 | return false; | ||
| 55 | } | ||
| 56 | |||
| 57 | public function getID() | ||
| 58 | { | ||
| 59 | return $this->id; | ||
| 60 | } | ||
| 61 | |||
| 62 | public function isPersistent() | ||
| 63 | { | ||
| 64 | return $this->is_persistent; | ||
| 65 | } | ||
| 66 | |||
| 67 | public function isDismissed() | ||
| 68 | { | ||
| 69 | return $this->is_dismissed; | ||
| 70 | } | ||
| 71 | |||
| 72 | public function dismiss() | ||
| 73 | { | ||
| 74 | $this->is_dismissed = true; | ||
| 75 | $this->suppress_until = time() + $this->suppress_period; | ||
| 76 | } | ||
| 77 | |||
| 78 | public function unDismiss() | ||
| 79 | { | ||
| 80 | $this->is_dismissed = false; | ||
| 81 | } | ||
| 82 | |||
| 83 | public function setDismissedUntil($timestamp) | ||
| 84 | { | ||
| 85 | $this->suppress_until = $timestamp; | ||
| 86 | } | ||
| 87 | |||
| 88 | /** Support for extra information beyond the message. | ||
| 89 | * Can help to not overwhelm users w/ the same message but different file /circumstances. | ||
| 90 | */ | ||
| 91 | public function addDetail($detail, $clean = false) | ||
| 92 | { | ||
| 93 | if ($clean) | ||
| 94 | $this->details = array(); | ||
| 95 | |||
| 96 | if (! in_array($detail, $this->details) ) | ||
| 97 | $this->details[] = $detail; | ||
| 98 | } | ||
| 99 | |||
| 100 | /** | ||
| 101 | * @param $method String Include or Exclude | ||
| 102 | * @param $includes String|Array Screen Names to Include / Exclude either string, or array | ||
| 103 | */ | ||
| 104 | public function limitScreens($method, $screens) | ||
| 105 | { | ||
| 106 | if ($method == 'exclude') | ||
| 107 | { | ||
| 108 | $var = 'exclude_screens'; | ||
| 109 | } | ||
| 110 | else { | ||
| 111 | $var = 'include_screens'; | ||
| 112 | } | ||
| 113 | |||
| 114 | if (is_array($screens)) | ||
| 115 | { | ||
| 116 | $this->$var = array_merge($this->$var, $screens); | ||
| 117 | } | ||
| 118 | else { | ||
| 119 | $this->{$var}[] = $screens; // strange syntax is PHP 5.6 compat. | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Checks if Notice is allowed on this screen | ||
| 124 | * @param @screen_id String The screen Id to check ( most likely current one, via EnvironmentModel) | ||
| 125 | */ | ||
| 126 | public function checkScreen($screen_id) | ||
| 127 | { | ||
| 128 | if (in_array($screen_id, $this->exclude_screens)) | ||
| 129 | { | ||
| 130 | return false; | ||
| 131 | } | ||
| 132 | if (in_array($screen_id, $this->include_screens)) | ||
| 133 | { | ||
| 134 | return true; | ||
| 135 | } | ||
| 136 | |||
| 137 | // if include is set, don't show if not screen included. | ||
| 138 | if (count($this->include_screens) == 0) | ||
| 139 | { | ||
| 140 | return true; | ||
| 141 | } | ||
| 142 | else { | ||
| 143 | return false; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | |||
| 148 | |||
| 149 | /** Set a notice persistent. Meaning it shows every page load until dismissed. | ||
| 150 | * @param $key Unique Key of this message. Required | ||
| 151 | * @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 | ||
| 152 | */ | ||
| 153 | public function setPersistent($key, $suppress = -1, $callback = null) | ||
| 154 | { | ||
| 155 | $this->id = $key; | ||
| 156 | $this->is_persistent = true; | ||
| 157 | $this->suppress_period = $suppress; | ||
| 158 | if ( ! is_null($callback) && is_callable($callback)) | ||
| 159 | { | ||
| 160 | $this->callback = $callback; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | public static function setIcon($notice_type, $icon) | ||
| 165 | { | ||
| 166 | switch($notice_type) | ||
| 167 | { | ||
| 168 | case 'error': | ||
| 169 | $type = self::NOTICE_ERROR; | ||
| 170 | break; | ||
| 171 | case 'success': | ||
| 172 | $type = self::NOTICE_SUCCESS; | ||
| 173 | break; | ||
| 174 | case 'warning': | ||
| 175 | $type = self::NOTICE_WARNING; | ||
| 176 | break; | ||
| 177 | case 'normal': | ||
| 178 | default: | ||
| 179 | $type = self::NOTICE_NORMAL; | ||
| 180 | break; | ||
| 181 | } | ||
| 182 | self::$icons[$type] = $icon; | ||
| 183 | } | ||
| 184 | |||
| 185 | public function _debug_getvar($var) | ||
| 186 | { | ||
| 187 | if (property_exists($this, $var)) | ||
| 188 | { | ||
| 189 | return $this->$var; | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 | private function checkIncomplete($var) | ||
| 194 | { | ||
| 195 | return ($var instanceof \__PHP_Incomplete_Class); | ||
| 196 | } | ||
| 197 | |||
| 198 | public function getForDisplay() | ||
| 199 | { | ||
| 200 | $this->viewed = true; | ||
| 201 | $class = 'shortpixel shortpixel-notice '; | ||
| 202 | |||
| 203 | $icon = ''; | ||
| 204 | |||
| 205 | if ($this->callback) | ||
| 206 | { | ||
| 207 | if (is_array($this->callback)) | ||
| 208 | { | ||
| 209 | foreach($this->callback as $part) | ||
| 210 | { | ||
| 211 | if ($this->checkIncomplete($part) === true) | ||
| 212 | { | ||
| 213 | return false; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | } elseif (is_object($this->callback)) | ||
| 217 | { | ||
| 218 | if ($this->checkIncomplete($part) === true) | ||
| 219 | return false; | ||
| 220 | } | ||
| 221 | |||
| 222 | if (! is_callable($this->callback)) | ||
| 223 | { | ||
| 224 | return; | ||
| 225 | } | ||
| 226 | else { | ||
| 227 | $return = call_user_func($this->callback, $this); | ||
| 228 | if ($return === false) // don't display is callback returns false explicitly. | ||
| 229 | return; | ||
| 230 | |||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | switch($this->messageType) | ||
| 235 | { | ||
| 236 | case self::NOTICE_ERROR: | ||
| 237 | $class .= 'notice-error '; | ||
| 238 | $icon = isset(self::$icons[self::NOTICE_ERROR]) ? self::$icons[self::NOTICE_ERROR] : ''; | ||
| 239 | //$icon = 'scared'; | ||
| 240 | break; | ||
| 241 | case self::NOTICE_SUCCESS: | ||
| 242 | $class .= 'notice-success '; | ||
| 243 | $icon = isset(self::$icons[self::NOTICE_SUCCESS]) ? self::$icons[self::NOTICE_SUCCESS] : ''; | ||
| 244 | break; | ||
| 245 | case self::NOTICE_WARNING: | ||
| 246 | $class .= 'notice-warning '; | ||
| 247 | $icon = isset(self::$icons[self::NOTICE_WARNING]) ? self::$icons[self::NOTICE_WARNING] : ''; | ||
| 248 | break; | ||
| 249 | case self::NOTICE_NORMAL: | ||
| 250 | $class .= 'notice-info '; | ||
| 251 | $icon = isset(self::$icons[self::NOTICE_NORMAL]) ? self::$icons[self::NOTICE_NORMAL] : ''; | ||
| 252 | break; | ||
| 253 | default: | ||
| 254 | $class .= 'notice-info '; | ||
| 255 | $icon = ''; | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | if ($this->is_removable) | ||
| 261 | { | ||
| 262 | $class .= 'is-dismissible '; | ||
| 263 | } | ||
| 264 | |||
| 265 | if ($this->is_persistent) | ||
| 266 | { | ||
| 267 | $class .= 'is-persistent '; | ||
| 268 | } | ||
| 269 | |||
| 270 | $id = ! is_null($this->id) ? $this->id : uniqid(); | ||
| 271 | //'id="' . $this->id . '"' | ||
| 272 | $output = "<div id='$id' class='$class'><span class='icon'> " . $icon . "</span> <span class='content'>" . $this->message; | ||
| 273 | if ($this->hasDetails()) | ||
| 274 | { | ||
| 275 | $output .= '<div class="details-wrapper"> | ||
| 276 | <input type="checkbox" name="detailhider" id="check-' . $id .'"> | ||
| 277 | <label for="check-' . $id . '" class="show-details"><span>' . __('See Details', 'shortpixel-image-optimiser') . '</span> | ||
| 278 | </label>'; | ||
| 279 | |||
| 280 | $output .= "<div class='detail-content-wrapper'><p class='detail-content'>" . $this->parseDetails() . "</p></div>"; | ||
| 281 | $output .= '<label for="check-' . $id . '" class="hide-details"><span>' . __('Hide Details', 'shortpixel-image-optimiser') . '</span></label>'; | ||
| 282 | |||
| 283 | $output .= '</div>'; // detail wrapper | ||
| 284 | |||
| 285 | } | ||
| 286 | $output .= "</span>"; | ||
| 287 | |||
| 288 | if ($this->is_removable) | ||
| 289 | { | ||
| 290 | $output .= '<button type="button" id="button-' . $id . '" class="notice-dismiss" data-dismiss="' . $this->suppress_period . '" ><span class="screen-reader-text">' . __('Dismiss this notice', 'shortpixel-image-optimiser') . '</span></button>'; | ||
| 291 | |||
| 292 | if (! $this->is_persistent) | ||
| 293 | { | ||
| 294 | $output .= "<script type='text/javascript'>\n | ||
| 295 | document.getElementById('button-$id').onclick = function() | ||
| 296 | { | ||
| 297 | var el = document.getElementById('$id'); | ||
| 298 | jQuery(el).fadeTo(100,0,function() { | ||
| 299 | jQuery(el).slideUp(100, 0, function () { | ||
| 300 | jQuery(el).remove(); | ||
| 301 | }) | ||
| 302 | }); | ||
| 303 | } </script>"; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | $output .= "</div>"; | ||
| 308 | |||
| 309 | if ($this->is_persistent && $this->is_removable) | ||
| 310 | { | ||
| 311 | $output .= "<script type='text/javascript'>\n" . $this->getDismissJS() . "\n</script>"; | ||
| 312 | } | ||
| 313 | return $output; | ||
| 314 | |||
| 315 | } | ||
| 316 | |||
| 317 | protected function hasDetails() | ||
| 318 | { | ||
| 319 | if (is_array($this->details) && count($this->details) > 0) | ||
| 320 | return true; | ||
| 321 | else | ||
| 322 | return false; | ||
| 323 | } | ||
| 324 | |||
| 325 | protected function parseDetails() | ||
| 326 | { | ||
| 327 | return implode('<BR>', $this->details); | ||
| 328 | } | ||
| 329 | |||
| 330 | private function getDismissJS() | ||
| 331 | { | ||
| 332 | |||
| 333 | $js = ''; | ||
| 334 | if (is_null(self::$jsDismissLoaded)) | ||
| 335 | { | ||
| 336 | $nonce = wp_create_nonce('dismiss'); | ||
| 337 | $url = wp_json_encode(admin_url('admin-ajax.php')); | ||
| 338 | $js = "function shortpixel_notice_dismiss(event) { | ||
| 339 | event.preventDefault(); | ||
| 340 | var ev = event.detail; | ||
| 341 | var target = event.target; | ||
| 342 | var parent = target.parentElement; | ||
| 343 | |||
| 344 | var data = { | ||
| 345 | 'plugin_action': 'dismiss', | ||
| 346 | 'action' : '$this->notice_action', | ||
| 347 | 'nonce' : '$nonce', | ||
| 348 | } | ||
| 349 | data.time = target.getAttribute('data-dismiss'); | ||
| 350 | data.id = parent.getAttribute('id'); | ||
| 351 | jQuery.post($url,data); | ||
| 352 | |||
| 353 | jQuery(parent).fadeTo(100,0,function() { | ||
| 354 | jQuery(parent).slideUp(100, 0, function () { | ||
| 355 | jQuery(parent).remove(); | ||
| 356 | }) | ||
| 357 | }); | ||
| 358 | }"; | ||
| 359 | } | ||
| 360 | |||
| 361 | $js .= ' jQuery("#' . $this->id . '").find(".notice-dismiss").on("click", shortpixel_notice_dismiss); '; | ||
| 362 | |||
| 363 | return "\n jQuery(document).ready(function(){ \n" . $js . "\n});"; | ||
| 364 | } | ||
| 365 | |||
| 366 | } |
| 1 | .shortpixel.shortpixel-notice { | ||
| 2 | min-height: 75px; | ||
| 3 | padding: 8px; | ||
| 4 | display: flex; | ||
| 5 | align-items: center; | ||
| 6 | background: #fff; | ||
| 7 | padding: 1px 12px; | ||
| 8 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); | ||
| 9 | border: 1px solid #c3c4c7; | ||
| 10 | margin: 15px 0; | ||
| 11 | border-left-width: 4px; | ||
| 12 | border-left-color: #72aee6; | ||
| 13 | position: relative; | ||
| 14 | } | ||
| 15 | .shortpixel.shortpixel-notice span { | ||
| 16 | vertical-align: middle; | ||
| 17 | } | ||
| 18 | .shortpixel.shortpixel-notice span.icon { | ||
| 19 | margin: 0 25px 0 0; | ||
| 20 | width: 80px; | ||
| 21 | } | ||
| 22 | .shortpixel.shortpixel-notice span.content { | ||
| 23 | padding: 8px 0; | ||
| 24 | word-wrap: break-word; | ||
| 25 | overflow: hidden; | ||
| 26 | } | ||
| 27 | .shortpixel.shortpixel-notice img { | ||
| 28 | display: inline-block; | ||
| 29 | margin: 0 25px 0 0; | ||
| 30 | max-height: 50px; | ||
| 31 | } | ||
| 32 | .shortpixel.shortpixel-notice .notice-dismiss { | ||
| 33 | margin-top: 6px; | ||
| 34 | } | ||
| 35 | .shortpixel.shortpixel-notice.notice-success { | ||
| 36 | border-left-color: #00a32a; | ||
| 37 | } | ||
| 38 | .shortpixel.shortpixel-notice.notice-warning { | ||
| 39 | border-left-color: #dba617; | ||
| 40 | } | ||
| 41 | .shortpixel.shortpixel-notice.notice-error { | ||
| 42 | border-left-color: #ff0000; | ||
| 43 | } | ||
| 44 | .shortpixel.shortpixel-notice.notice-info { | ||
| 45 | border-left-color: #72aee6; | ||
| 46 | } | ||
| 47 | |||
| 48 | /* In-view notice ( not on top, between the options ) - styled after WP notice */ | ||
| 49 | .view-notice { | ||
| 50 | box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); | ||
| 51 | border: 4px solid #fff; | ||
| 52 | padding: 1px 12px; | ||
| 53 | } | ||
| 54 | .view-notice p { | ||
| 55 | margin: 1em 0 !important; | ||
| 56 | } | ||
| 57 | .view-notice.warning { | ||
| 58 | border-left-color: #ffb900; | ||
| 59 | } | ||
| 60 | |||
| 61 | .view-notice-row { | ||
| 62 | display: none; | ||
| 63 | } | ||
| 64 | |||
| 65 | /*# sourceMappingURL=notices.css.map */ |
| 1 | {"version":3,"sourceRoot":"","sources":["notices.scss"],"names":[],"mappings":"AACA;EAGC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEC;;AACA;EACC;EACA;;AAED;EAEC;EACA;EACA;;AAKA;EAEE;EACA;EACA;;AAEF;EAEE;;AAGH;EAEC;;AAED;EAEC;;AAED;EAEC;;AAED;EAEE;;;AAIJ;AACA;EAGE;EACA;EAEA;;AACA;EACE;;AAEF;EAEE;;;AAIJ;EAEE","file":"notices.css"} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | |||
| 2 | .shortpixel.shortpixel-notice | ||
| 3 | { | ||
| 4 | |||
| 5 | min-height: 75px; | ||
| 6 | padding: 8px; | ||
| 7 | display: flex; | ||
| 8 | align-items: center; | ||
| 9 | background: #fff; | ||
| 10 | padding: 1px 12px; | ||
| 11 | box-shadow: 0 1px 1px rgba(0,0,0,0.04); | ||
| 12 | border: 1px solid #c3c4c7; | ||
| 13 | margin: 15px 0; | ||
| 14 | border-left-width: 4px; | ||
| 15 | border-left-color: #72aee6; | ||
| 16 | position: relative; | ||
| 17 | |||
| 18 | span | ||
| 19 | { | ||
| 20 | vertical-align: middle; | ||
| 21 | &.icon { | ||
| 22 | margin: 0 25px 0 0; | ||
| 23 | width: 80px; | ||
| 24 | } | ||
| 25 | &.content | ||
| 26 | { | ||
| 27 | padding: 8px 0; | ||
| 28 | word-wrap: break-word; | ||
| 29 | overflow: hidden; | ||
| 30 | //display: flex; // magically fixes verticality issues | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | img | ||
| 35 | { | ||
| 36 | display:inline-block; | ||
| 37 | margin: 0 25px 0 0; | ||
| 38 | max-height: 50px; | ||
| 39 | } | ||
| 40 | .notice-dismiss | ||
| 41 | { | ||
| 42 | margin-top: 6px; | ||
| 43 | } | ||
| 44 | |||
| 45 | &.notice-success | ||
| 46 | { | ||
| 47 | border-left-color: #00a32a; | ||
| 48 | } | ||
| 49 | &.notice-warning | ||
| 50 | { | ||
| 51 | border-left-color: #dba617; | ||
| 52 | } | ||
| 53 | &.notice-error | ||
| 54 | { | ||
| 55 | border-left-color: #ff0000; | ||
| 56 | } | ||
| 57 | &.notice-info | ||
| 58 | { | ||
| 59 | border-left-color: #72aee6; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | /* In-view notice ( not on top, between the options ) - styled after WP notice */ | ||
| 64 | .view-notice | ||
| 65 | { | ||
| 66 | |||
| 67 | box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 ); | ||
| 68 | border: 4px solid #fff; | ||
| 69 | |||
| 70 | padding: 1px 12px; | ||
| 71 | p { | ||
| 72 | margin: 1em 0 !important; | ||
| 73 | } | ||
| 74 | &.warning | ||
| 75 | { | ||
| 76 | border-left-color: #ffb900; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | .view-notice-row | ||
| 81 | { | ||
| 82 | display: none; | ||
| 83 | } |
| 1 | { | ||
| 2 | "name": "shortpixel/replacer", | ||
| 3 | "description": "Content Replacer", | ||
| 4 | "version": 1.1, | ||
| 5 | "type": "library", | ||
| 6 | "license": "MIT", | ||
| 7 | "authors": [ | ||
| 8 | { | ||
| 9 | "name": "Bas", | ||
| 10 | "email": "bas@weblogmechanic.com" | ||
| 11 | } | ||
| 12 | ], | ||
| 13 | "minimum-stability": "dev", | ||
| 14 | "require": {}, | ||
| 15 | "autoload": { | ||
| 16 | "psr-4": { "ShortPixel\\Replacer\\" : "src" } | ||
| 17 | } | ||
| 18 | } |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Replacer\Libraries\Unserialize; | ||
| 3 | |||
| 4 | |||
| 5 | /** | ||
| 6 | * Worker implementation for identifying and skipping false-positives | ||
| 7 | * not to be substituted - like nested serializations in string literals. | ||
| 8 | * | ||
| 9 | * @internal This class should only be used by \Brumann\Polyfill\Unserialize | ||
| 10 | */ | ||
| 11 | final class DisallowedClassesSubstitutor | ||
| 12 | { | ||
| 13 | const PATTERN_STRING = '#s:(\d+):(")#'; | ||
| 14 | const PATTERN_OBJECT = '#(^|;)O:\d+:"([^"]*)":(\d+):\{#'; | ||
| 15 | |||
| 16 | /** | ||
| 17 | * @var string | ||
| 18 | */ | ||
| 19 | private $serialized; | ||
| 20 | |||
| 21 | /** | ||
| 22 | * @var string[] | ||
| 23 | */ | ||
| 24 | private $allowedClasses; | ||
| 25 | |||
| 26 | /** | ||
| 27 | * Each array item consists of `[<offset-start>, <offset-end>]` and | ||
| 28 | * marks start and end positions of items to be ignored. | ||
| 29 | * | ||
| 30 | * @var array[] | ||
| 31 | */ | ||
| 32 | private $ignoreItems = array(); | ||
| 33 | |||
| 34 | /** | ||
| 35 | * @param string $serialized | ||
| 36 | * @param string[] $allowedClasses | ||
| 37 | */ | ||
| 38 | public function __construct($serialized, array $allowedClasses) | ||
| 39 | { | ||
| 40 | $this->serialized = $serialized; | ||
| 41 | $this->allowedClasses = $allowedClasses; | ||
| 42 | |||
| 43 | $this->buildIgnoreItems(); | ||
| 44 | $this->substituteObjects(); | ||
| 45 | } | ||
| 46 | |||
| 47 | /** | ||
| 48 | * @return string | ||
| 49 | */ | ||
| 50 | public function getSubstitutedSerialized() | ||
| 51 | { | ||
| 52 | return $this->serialized; | ||
| 53 | } | ||
| 54 | |||
| 55 | /** | ||
| 56 | * Identifies items to be ignored - like nested serializations in string literals. | ||
| 57 | */ | ||
| 58 | private function buildIgnoreItems() | ||
| 59 | { | ||
| 60 | $offset = 0; | ||
| 61 | while (preg_match(self::PATTERN_STRING, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) { | ||
| 62 | $length = (int)$matches[1][0]; // given length in serialized data (e.g. `s:123:"` --> 123) | ||
| 63 | $start = $matches[2][1]; // offset position of quote character | ||
| 64 | $end = $start + $length + 1; | ||
| 65 | $offset = $end + 1; | ||
| 66 | |||
| 67 | // serialized string nested in outer serialized string | ||
| 68 | if ($this->ignore($start, $end)) { | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | |||
| 72 | $this->ignoreItems[] = array($start, $end); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | /** | ||
| 77 | * Substitutes disallowed object class names and respects items to be ignored. | ||
| 78 | */ | ||
| 79 | private function substituteObjects() | ||
| 80 | { | ||
| 81 | $offset = 0; | ||
| 82 | while (preg_match(self::PATTERN_OBJECT, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) { | ||
| 83 | $completeMatch = (string)$matches[0][0]; | ||
| 84 | $completeLength = strlen($completeMatch); | ||
| 85 | $start = $matches[0][1]; | ||
| 86 | $end = $start + $completeLength; | ||
| 87 | $leftBorder = (string)$matches[1][0]; | ||
| 88 | $className = (string)$matches[2][0]; | ||
| 89 | $objectSize = (int)$matches[3][0]; | ||
| 90 | $offset = $end + 1; | ||
| 91 | |||
| 92 | // class name is actually allowed - skip this item | ||
| 93 | if (in_array($className, $this->allowedClasses, true)) { | ||
| 94 | continue; | ||
| 95 | } | ||
| 96 | // serialized object nested in outer serialized string | ||
| 97 | if ($this->ignore($start, $end)) { | ||
| 98 | continue; | ||
| 99 | } | ||
| 100 | |||
| 101 | $incompleteItem = $this->sanitizeItem($className, $leftBorder, $objectSize); | ||
| 102 | $incompleteItemLength = strlen($incompleteItem); | ||
| 103 | $offset = $start + $incompleteItemLength + 1; | ||
| 104 | |||
| 105 | $this->replace($incompleteItem, $start, $end); | ||
| 106 | $this->shift($end, $incompleteItemLength - $completeLength); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Replaces sanitized object class names in serialized data. | ||
| 112 | * | ||
| 113 | * @param string $replacement Sanitized object data | ||
| 114 | * @param int $start Start offset in serialized data | ||
| 115 | * @param int $end End offset in serialized data | ||
| 116 | */ | ||
| 117 | private function replace($replacement, $start, $end) | ||
| 118 | { | ||
| 119 | $this->serialized = substr($this->serialized, 0, $start) | ||
| 120 | . $replacement . substr($this->serialized, $end); | ||
| 121 | } | ||
| 122 | |||
| 123 | /** | ||
| 124 | * Whether given offset positions should be ignored. | ||
| 125 | * | ||
| 126 | * @param int $start | ||
| 127 | * @param int $end | ||
| 128 | * @return bool | ||
| 129 | */ | ||
| 130 | private function ignore($start, $end) | ||
| 131 | { | ||
| 132 | foreach ($this->ignoreItems as $ignoreItem) { | ||
| 133 | if ($ignoreItem[0] <= $start && $ignoreItem[1] >= $end) { | ||
| 134 | return true; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | return false; | ||
| 139 | } | ||
| 140 | |||
| 141 | /** | ||
| 142 | * Shifts offset positions of ignore items by `$size`. | ||
| 143 | * This is necessary whenever object class names have been | ||
| 144 | * substituted which have a different length than before. | ||
| 145 | * | ||
| 146 | * @param int $offset | ||
| 147 | * @param int $size | ||
| 148 | */ | ||
| 149 | private function shift($offset, $size) | ||
| 150 | { | ||
| 151 | foreach ($this->ignoreItems as &$ignoreItem) { | ||
| 152 | // only focus on items starting after given offset | ||
| 153 | if ($ignoreItem[0] < $offset) { | ||
| 154 | continue; | ||
| 155 | } | ||
| 156 | $ignoreItem[0] += $size; | ||
| 157 | $ignoreItem[1] += $size; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * Sanitizes object class item. | ||
| 163 | * | ||
| 164 | * @param string $className | ||
| 165 | * @param int $leftBorder | ||
| 166 | * @param int $objectSize | ||
| 167 | * @return string | ||
| 168 | */ | ||
| 169 | private function sanitizeItem($className, $leftBorder, $objectSize) | ||
| 170 | { | ||
| 171 | return sprintf( | ||
| 172 | '%sO:22:"__PHP_Incomplete_Class":%d:{s:27:"__PHP_Incomplete_Class_Name";%s', | ||
| 173 | $leftBorder, | ||
| 174 | $objectSize + 1, // size of object + 1 for added string | ||
| 175 | \serialize($className) | ||
| 176 | ); | ||
| 177 | } | ||
| 178 | } |
wp-content/plugins/enable-media-replace/build/shortpixel/replacer/src/Libraries/Unserialize/LICENSE
0 → 100644
| 1 | MIT License | ||
| 2 | |||
| 3 | Copyright (c) 2016-2019 Denis Brumann | ||
| 4 | |||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | of this software and associated documentation files (the "Software"), to deal | ||
| 7 | in the Software without restriction, including without limitation the rights | ||
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | copies of the Software, and to permit persons to whom the Software is | ||
| 10 | furnished to do so, subject to the following conditions: | ||
| 11 | |||
| 12 | The above copyright notice and this permission notice shall be included in all | ||
| 13 | copies or substantial portions of the Software. | ||
| 14 | |||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | SOFTWARE. |
| 1 | Polyfill unserialize [](https://travis-ci.org/dbrumann/polyfill-unserialize) | ||
| 2 | === | ||
| 3 | |||
| 4 | Backports unserialize options introduced in PHP 7.0 to older PHP versions. | ||
| 5 | This was originally designed as a Proof of Concept for Symfony Issue | ||
| 6 | [#21090](https://github.com/symfony/symfony/pull/21090). | ||
| 7 | |||
| 8 | You can use this package in projects that rely on PHP versions older than | ||
| 9 | PHP 7.0. In case you are using PHP 7.0+ the original `unserialize()` will be | ||
| 10 | used instead. | ||
| 11 | |||
| 12 | From the [documentation](https://secure.php.net/manual/en/function.unserialize.php): | ||
| 13 | |||
| 14 | > **Warning** | ||
| 15 | > | ||
| 16 | > Do not pass untrusted user input to unserialize() regardless of the options | ||
| 17 | > value of allowed_classes. Unserialization can result in code being loaded and | ||
| 18 | > executed due to object instantiation and autoloading, and a malicious user | ||
| 19 | > may be able to exploit this. Use a safe, standard data interchange format | ||
| 20 | > such as JSON (via json_decode() and json_encode()) if you need to pass | ||
| 21 | > serialized data to the user. | ||
| 22 | |||
| 23 | Requirements | ||
| 24 | ------------ | ||
| 25 | |||
| 26 | - PHP 5.3+ | ||
| 27 | |||
| 28 | Installation | ||
| 29 | ------------ | ||
| 30 | |||
| 31 | You can install this package via composer: | ||
| 32 | |||
| 33 | ```bash | ||
| 34 | composer require brumann/polyfill-unserialize "^2.0" | ||
| 35 | ``` | ||
| 36 | |||
| 37 | Older versions | ||
| 38 | -------------- | ||
| 39 | |||
| 40 | You can find the most recent 1.x versions in the branch with the same name: | ||
| 41 | |||
| 42 | * [dbrumann/polyfill-unserialize/tree/1.x](https://github.com/dbrumann/polyfill-unserialize/tree/1.x) | ||
| 43 | |||
| 44 | Upgrading | ||
| 45 | --------- | ||
| 46 | |||
| 47 | Upgrading from 1.x to 2.0 should be seamless and require no changes to code | ||
| 48 | using the library. There are no changes to the public API, i.e. the names for | ||
| 49 | classes, methods and arguments as well as argument order and types remain the | ||
| 50 | same. Version 2.x uses a completely different approach for substituting | ||
| 51 | disallowed classes, which is why we chose to use a new major release to prevent | ||
| 52 | issues from unknown side effects in existing installations. | ||
| 53 | |||
| 54 | Known Issues | ||
| 55 | ------------ | ||
| 56 | |||
| 57 | There is a mismatch in behavior when `allowed_classes` in `$options` is not | ||
| 58 | of the correct type (array or boolean). PHP 7.0 will not issue a warning that | ||
| 59 | an invalid type was provided. This library will trigger a warning, similar to | ||
| 60 | the one PHP 7.1+ will raise and then continue, assuming `false` to make sure | ||
| 61 | no classes are deserialized by accident. | ||
| 62 | |||
| 63 | Tests | ||
| 64 | ----- | ||
| 65 | |||
| 66 | You can run the test suite using PHPUnit. It is intentionally not bundled as | ||
| 67 | dev dependency to make sure this package has the lowest restrictions on the | ||
| 68 | implementing system as possible. | ||
| 69 | |||
| 70 | Please read the [PHPUnit Manual](https://phpunit.de/manual/current/en/installation.html) | ||
| 71 | for information how to install it on your system. | ||
| 72 | |||
| 73 | Please make sure to pick a compatible version. If you use PHP 5.6 you should | ||
| 74 | use PHPUnit 5.7.27 and for older PHP versions you should use PHPUnit 4.8.36. | ||
| 75 | Older versions of PHPUnit might not support namespaces, meaning they will not | ||
| 76 | work with the tests. Newer versions only support PHP 7.0+, where this library | ||
| 77 | is not needed anymore. | ||
| 78 | |||
| 79 | You can run the test suite as follows: | ||
| 80 | |||
| 81 | ```bash | ||
| 82 | phpunit -c phpunit.xml.dist tests/ | ||
| 83 | ``` | ||
| 84 | |||
| 85 | Contributing | ||
| 86 | ------------ | ||
| 87 | |||
| 88 | This package is considered feature complete. As such I will likely not update | ||
| 89 | it unless there are security issues. | ||
| 90 | |||
| 91 | Should you find any bugs or have questions, feel free to submit an Issue or a | ||
| 92 | Pull Request on GitHub. | ||
| 93 | |||
| 94 | Development setup | ||
| 95 | ----------------- | ||
| 96 | |||
| 97 | This library contains a docker setup for development purposes. This allows | ||
| 98 | running the code on an older PHP version without having to install it locally. | ||
| 99 | |||
| 100 | You can use the setup as follows: | ||
| 101 | |||
| 102 | 1. Go into the project directory | ||
| 103 | |||
| 104 | 1. Build the docker image | ||
| 105 | |||
| 106 | ``` | ||
| 107 | docker build -t polyfill-unserialize . | ||
| 108 | ``` | ||
| 109 | |||
| 110 | This will download a debian/jessie container with PHP 5.6 installed. Then | ||
| 111 | it will download an appropriate version of phpunit for this PHP version. | ||
| 112 | It will also download composer. It will set the working directory to `/opt/app`. | ||
| 113 | The resulting image is tagged as `polyfill-unserialize`, which is the name | ||
| 114 | we will refer to, when running the container. | ||
| 115 | |||
| 116 | 1. You can then run a container based on the image, which will run your tests | ||
| 117 | |||
| 118 | ``` | ||
| 119 | docker run -it --rm --name polyfill-unserialize-dev -v "$PWD":/opt/app polyfill-unserialize | ||
| 120 | ``` | ||
| 121 | |||
| 122 | This will run a docker container based on our previously built image. | ||
| 123 | The container will automatically be removed after phpunit finishes. | ||
| 124 | We name the image `polyfill-unserialize-dev`. This makes sure only one | ||
| 125 | instance is running and that we can easily identify a running container by | ||
| 126 | its name, e.g. in order to remove it manually. | ||
| 127 | We mount our current directory into the container's working directory. | ||
| 128 | This ensures that tests run on our current project's state. | ||
| 129 | |||
| 130 | You can repeat the final step as often as you like in order to run the tests. | ||
| 131 | The output should look something like this: | ||
| 132 | |||
| 133 | ```bash | ||
| 134 | dbr:polyfill-unserialize/ (improvement/dev_setup*) $ docker run -it --rm --name polyfill-unserialize-dev -v "$PWD":/opt/app polyfill-unserialize | ||
| 135 | Loading composer repositories with package information | ||
| 136 | Installing dependencies (including require-dev) from lock file | ||
| 137 | Nothing to install or update | ||
| 138 | Generating autoload files | ||
| 139 | PHPUnit 5.7.27 by Sebastian Bergmann and contributors. | ||
| 140 | |||
| 141 | ...................... 22 / 22 (100%) | ||
| 142 | |||
| 143 | Time: 167 ms, Memory: 13.25MB | ||
| 144 | |||
| 145 | OK (22 tests, 31 assertions) | ||
| 146 | ``` | ||
| 147 | |||
| 148 | When you are done working on the project you can free up disk space by removing | ||
| 149 | the initially built image: | ||
| 150 | |||
| 151 | ``` | ||
| 152 | docker image rm polyfill-unserialize | ||
| 153 | ``` |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Replacer\Libraries\Unserialize; | ||
| 3 | |||
| 4 | // Taken from : https://github.com/dbrumann/polyfill-unserialize/ | ||
| 5 | final class Unserialize | ||
| 6 | { | ||
| 7 | /** | ||
| 8 | * @see https://secure.php.net/manual/en/function.unserialize.php | ||
| 9 | * | ||
| 10 | * @param string $serialized Serialized data | ||
| 11 | * @param array $options Associative array containing options | ||
| 12 | * | ||
| 13 | * @return mixed | ||
| 14 | */ | ||
| 15 | public static function unserialize($serialized, array $options = array()) | ||
| 16 | { | ||
| 17 | if (PHP_VERSION_ID >= 70000) { | ||
| 18 | return \unserialize($serialized, $options); | ||
| 19 | } | ||
| 20 | if (!array_key_exists('allowed_classes', $options) || true === $options['allowed_classes']) { | ||
| 21 | return \unserialize($serialized); | ||
| 22 | } | ||
| 23 | $allowedClasses = $options['allowed_classes']; | ||
| 24 | if (false === $allowedClasses) { | ||
| 25 | $allowedClasses = array(); | ||
| 26 | } | ||
| 27 | if (!is_array($allowedClasses)) { | ||
| 28 | $allowedClasses = array(); | ||
| 29 | trigger_error( | ||
| 30 | 'unserialize(): allowed_classes option should be array or boolean', | ||
| 31 | E_USER_WARNING | ||
| 32 | ); | ||
| 33 | } | ||
| 34 | |||
| 35 | $worker = new DisallowedClassesSubstitutor($serialized, $allowedClasses); | ||
| 36 | |||
| 37 | return \unserialize($worker->getSubstitutedSerialized()); | ||
| 38 | } | ||
| 39 | } |
wp-content/plugins/enable-media-replace/build/shortpixel/replacer/src/Modules/Elementor.php
0 → 100644
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Replacer\Modules; | ||
| 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('shortpixel/replacer/custom_replace_query', array($this, 'addElementor'), 10, 4); // custom query for elementor \ // problem | ||
| 23 | // @todo Fix this for SPIO | ||
| 24 | //add_action('enable-media-replace-upload-done', array($this, 'removeCache') ); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | public function addElementor($items, $base_url, $search_urls, $replace_urls) | ||
| 29 | { | ||
| 30 | $base_url = $this->addSlash($base_url); | ||
| 31 | $el_search_urls = $search_urls; //array_map(array($this, 'addslash'), $search_urls); | ||
| 32 | $el_replace_urls = $replace_urls; //array_map(array($this, 'addslash'), $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 addSlash($value) | ||
| 38 | { | ||
| 39 | global $wpdb; | ||
| 40 | $value= ltrim($value, '/'); // for some reason the left / isn't picked up by Mysql. | ||
| 41 | $value= str_replace('/', '\/', $value); | ||
| 42 | $value = $wpdb->esc_like(($value)); //(wp_slash) / str_replace('/', '\/', $value); | ||
| 43 | |||
| 44 | return $value; | ||
| 45 | } | ||
| 46 | |||
| 47 | protected function elementor_is_active() | ||
| 48 | { | ||
| 49 | $bool = false; | ||
| 50 | |||
| 51 | if (defined('ELEMENTOR_VERSION')) | ||
| 52 | $bool = true; | ||
| 53 | |||
| 54 | return apply_filters('emr/externals/elementor_is_active', $bool); // manual override | ||
| 55 | } | ||
| 56 | |||
| 57 | public function removeCache() | ||
| 58 | { | ||
| 59 | \Elementor\Plugin::$instance->files_manager->clear_cache(); | ||
| 60 | } | ||
| 61 | } |
wp-content/plugins/enable-media-replace/build/shortpixel/replacer/src/Modules/WpBakery.php
0 → 100644
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Replacer\Modules; | ||
| 3 | // Note! This class doubles as integration for both Visual Composer *and* WP Bakery. They both need URLENCODE. | ||
| 4 | class WpBakery | ||
| 5 | { | ||
| 6 | private static $instance; | ||
| 7 | |||
| 8 | protected $queryKey = 'wpbakery'; | ||
| 9 | |||
| 10 | public static function getInstance() | ||
| 11 | { | ||
| 12 | if (is_null(self::$instance)) | ||
| 13 | self::$instance = new WpBakery(); | ||
| 14 | |||
| 15 | return self::$instance; | ||
| 16 | } | ||
| 17 | |||
| 18 | public function __construct() | ||
| 19 | { | ||
| 20 | if ($this->bakery_is_active()) // elementor is active | ||
| 21 | { | ||
| 22 | add_filter('shortpixel/replacer/custom_replace_query', array($this, 'addURLEncoded'), 10, 4); // custom query for elementor \ // problem | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | public function addUrlEncoded($items, $base_url, $search_urls, $replace_urls) | ||
| 27 | { | ||
| 28 | $base_url = $this->addEncode($base_url); | ||
| 29 | $el_search_urls = array_map(array($this, 'addEncode'), $search_urls); | ||
| 30 | $el_replace_urls = array_map(array($this, 'addEncode'), $replace_urls); | ||
| 31 | $items[$this->queryKey] = array('base_url' => $base_url, 'search_urls' => $el_search_urls, 'replace_urls' => $el_replace_urls); | ||
| 32 | return $items; | ||
| 33 | } | ||
| 34 | |||
| 35 | public function addEncode($value) | ||
| 36 | { | ||
| 37 | return urlencode($value); | ||
| 38 | } | ||
| 39 | |||
| 40 | protected function bakery_is_active() | ||
| 41 | { | ||
| 42 | $bool = false; | ||
| 43 | |||
| 44 | // did_action -> wpbakery , VCV_version -> detect Visual Composer | ||
| 45 | if (did_action('vc_plugins_loaded') || defined('VCV_VERSION')) | ||
| 46 | $bool = true; | ||
| 47 | |||
| 48 | return apply_filters('emr/externals/urlencode_is_active', $bool); // manual override | ||
| 49 | } | ||
| 50 | } |
wp-content/plugins/enable-media-replace/build/shortpixel/replacer/src/Modules/YoastSeo.php
0 → 100644
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Replacer\Modules; | ||
| 3 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 4 | |||
| 5 | // Integration to reset indexes of Yoast (used for Og:image) when something is converted. | ||
| 6 | class YoastSeo | ||
| 7 | { | ||
| 8 | |||
| 9 | private $yoastTable; | ||
| 10 | private static $instance; | ||
| 11 | |||
| 12 | public static function getInstance() | ||
| 13 | { | ||
| 14 | if (is_null(self::$instance)) | ||
| 15 | self::$instance = new YoastSeo(); | ||
| 16 | |||
| 17 | return self::$instance; | ||
| 18 | } | ||
| 19 | |||
| 20 | public function __construct() | ||
| 21 | { | ||
| 22 | if (true === $this->yoast_is_active()) // elementor is active | ||
| 23 | { | ||
| 24 | global $wpdb; | ||
| 25 | $this->yoastTable = $wpdb->prefix . 'yoast_indexable'; | ||
| 26 | |||
| 27 | add_action('shortpixel/replacer/replace_urls', array($this, 'removeIndexes'),10,2); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | public function removeIndexes($search_urls, $replace_urls) | ||
| 32 | { | ||
| 33 | global $wpdb; | ||
| 34 | |||
| 35 | $sql = 'DELETE FROM ' . $this->yoastTable . ' WHERE '; | ||
| 36 | $prepare = array(); | ||
| 37 | |||
| 38 | $base = isset($search_urls['base']) ? $search_urls['base'] : null; | ||
| 39 | $file = isset($search_urls['file']) ? $search_urls['file'] : null; | ||
| 40 | |||
| 41 | if (! is_null($base)) | ||
| 42 | { | ||
| 43 | $querySQL = $sql . ' twitter_image like %s or open_graph_image like %s '; | ||
| 44 | $querySQL = $wpdb->prepare($querySQL, '%' . $base . '%', '%' . $base . '%'); | ||
| 45 | |||
| 46 | $wpdb->query($querySQL); | ||
| 47 | } | ||
| 48 | |||
| 49 | if (! is_null($file)) | ||
| 50 | { | ||
| 51 | $querySQL = $sql . ' twitter_image like %s or open_graph_image like %s '; | ||
| 52 | $querySQL = $wpdb->prepare($querySQL, '%' . $file . '%', '%' . $file . '%'); | ||
| 53 | |||
| 54 | $wpdb->query($querySQL); | ||
| 55 | } | ||
| 56 | |||
| 57 | } | ||
| 58 | |||
| 59 | protected function yoast_is_active() | ||
| 60 | { | ||
| 61 | if (defined('WPSEO_VERSION')) | ||
| 62 | { | ||
| 63 | return true; | ||
| 64 | } | ||
| 65 | return false; | ||
| 66 | } | ||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | |||
| 71 | } |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Replacer; | ||
| 3 | |||
| 4 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 5 | use EnableMediaReplace\Replacer\Libraries\Unserialize\Unserialize; | ||
| 6 | |||
| 7 | /** Module: Replacer. | ||
| 8 | * | ||
| 9 | * - Able to replace across database | ||
| 10 | * - Only replace thumbnails feature dependent on media library | ||
| 11 | * - Support for page builders / strange data | ||
| 12 | */ | ||
| 13 | |||
| 14 | class Replacer | ||
| 15 | { | ||
| 16 | |||
| 17 | protected $source_url; | ||
| 18 | protected $target_url; | ||
| 19 | protected $source_metadata = array(); | ||
| 20 | protected $target_metadata = array(); | ||
| 21 | |||
| 22 | public function __construct() | ||
| 23 | { | ||
| 24 | //$this->source_url = $source_url; | ||
| 25 | ///$this->target_url = $target_url; | ||
| 26 | $this->loadFormats(); | ||
| 27 | } | ||
| 28 | |||
| 29 | // Load classes that handle alternative formats that can occur in the metadata / post data. | ||
| 30 | protected function loadFormats() | ||
| 31 | { | ||
| 32 | Modules\Elementor::getInstance(); | ||
| 33 | Modules\WpBakery::getInstance(); | ||
| 34 | Modules\YoastSeo::getInstance(); | ||
| 35 | } | ||
| 36 | |||
| 37 | public function setSource($url) | ||
| 38 | { | ||
| 39 | $this->source_url = $url; | ||
| 40 | } | ||
| 41 | |||
| 42 | public function getSource() | ||
| 43 | { | ||
| 44 | return $this->source_url; | ||
| 45 | } | ||
| 46 | |||
| 47 | public function setTarget($url) | ||
| 48 | { | ||
| 49 | $this->target_url = $url; | ||
| 50 | } | ||
| 51 | |||
| 52 | public function getTarget() | ||
| 53 | { | ||
| 54 | return $this->target_url; | ||
| 55 | } | ||
| 56 | |||
| 57 | public function setSourceMeta($meta) | ||
| 58 | { | ||
| 59 | $this->source_metadata = $meta; | ||
| 60 | } | ||
| 61 | |||
| 62 | public function setTargetMeta($meta) | ||
| 63 | { | ||
| 64 | $this->target_metadata = $meta; | ||
| 65 | } | ||
| 66 | |||
| 67 | public function replace($args = array()) | ||
| 68 | { | ||
| 69 | if (is_null($this->source_url) || is_null($this->target_url)) | ||
| 70 | { | ||
| 71 | Log::addWarn('Replacer called without source or target '); | ||
| 72 | return false; | ||
| 73 | } | ||
| 74 | $defaults = array( | ||
| 75 | 'thumbnails_only' => false, | ||
| 76 | ); | ||
| 77 | |||
| 78 | $errors = array(); | ||
| 79 | $args = wp_parse_args($args, $defaults); | ||
| 80 | |||
| 81 | // Search-and-replace filename in post database | ||
| 82 | // @todo Check this with scaled images. | ||
| 83 | $base_url = parse_url($this->source_url, PHP_URL_PATH);// emr_get_match_url( $this->source_url); | ||
| 84 | $base_url = str_replace('.' . pathinfo($base_url, PATHINFO_EXTENSION), '', $base_url); | ||
| 85 | |||
| 86 | /** Fail-safe if base_url is a whole directory, don't go search/replace */ | ||
| 87 | if (is_dir($base_url)) | ||
| 88 | { | ||
| 89 | Log::addError('Search Replace tried to replace to directory - ' . $base_url); | ||
| 90 | $errors[] = __('Fail Safe :: Source Location seems to be a directory.', 'enable-media-replace'); | ||
| 91 | return $errors; | ||
| 92 | } | ||
| 93 | |||
| 94 | if (strlen(trim($base_url)) == 0) | ||
| 95 | { | ||
| 96 | Log::addError('Current Base URL emtpy - ' . $base_url); | ||
| 97 | $errors[] = __('Fail Safe :: Source Location returned empty string. Not replacing content','enable-media-replace'); | ||
| 98 | return $errors; | ||
| 99 | } | ||
| 100 | |||
| 101 | // get relurls of both source and target. | ||
| 102 | $urls = $this->getRelativeURLS(); | ||
| 103 | |||
| 104 | |||
| 105 | if ($args['thumbnails_only']) | ||
| 106 | { | ||
| 107 | foreach($urls as $side => $data) | ||
| 108 | { | ||
| 109 | if (isset($data['base'])) | ||
| 110 | { | ||
| 111 | unset($urls[$side]['base']); | ||
| 112 | } | ||
| 113 | if (isset($data['file'])) | ||
| 114 | { | ||
| 115 | unset($urls[$side]['file']); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | $search_urls = $urls['source']; | ||
| 121 | $replace_urls = $urls['target']; | ||
| 122 | |||
| 123 | /* If the replacement is much larger than the source, there can be more thumbnails. This leads to disbalance in the search/replace arrays. | ||
| 124 | Remove those from the equation. If the size doesn't exist in the source, it shouldn't be in use either */ | ||
| 125 | foreach($replace_urls as $size => $url) | ||
| 126 | { | ||
| 127 | if (! isset($search_urls[$size])) | ||
| 128 | { | ||
| 129 | Log::addDebug('Dropping size ' . $size . ' - not found in source urls'); | ||
| 130 | unset($replace_urls[$size]); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | Log::addDebug('Source', $this->source_metadata); | ||
| 135 | Log::addDebug('Target', $this->target_metadata); | ||
| 136 | /* If on the other hand, some sizes are available in source, but not in target, try to replace them with something closeby. */ | ||
| 137 | foreach($search_urls as $size => $url) | ||
| 138 | { | ||
| 139 | if (! isset($replace_urls[$size])) | ||
| 140 | { | ||
| 141 | $closest = $this->findNearestSize($size); | ||
| 142 | if ($closest) | ||
| 143 | { | ||
| 144 | $sourceUrl = $search_urls[$size]; | ||
| 145 | $baseurl = trailingslashit(str_replace(wp_basename($sourceUrl), '', $sourceUrl)); | ||
| 146 | Log::addDebug('Nearest size of source ' . $size . ' for target is ' . $closest); | ||
| 147 | $replace_urls[$size] = $baseurl . $closest; | ||
| 148 | } | ||
| 149 | else | ||
| 150 | { | ||
| 151 | Log::addDebug('Unset size ' . $size . ' - no closest found in source'); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | /* If source and target are the same, remove them from replace. This happens when replacing a file with same name, and +/- same dimensions generated. | ||
| 157 | |||
| 158 | After previous loops, for every search there should be a replace size. | ||
| 159 | */ | ||
| 160 | foreach($search_urls as $size => $url) | ||
| 161 | { | ||
| 162 | $replace_url = isset($replace_urls[$size]) ? $replace_urls[$size] : false; | ||
| 163 | if ($url == $replace_url) // if source and target as the same, no need for replacing. | ||
| 164 | { | ||
| 165 | unset($search_urls[$size]); | ||
| 166 | unset($replace_urls[$size]); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | // 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. | ||
| 171 | if (count($search_urls) !== count($replace_urls)) | ||
| 172 | { | ||
| 173 | Log::addError('Unbalanced Replace Arrays, aborting', array($search_urls, $replace_urls, count($search_urls), count($replace_urls) )); | ||
| 174 | $errors[] = __('There was an issue with updating your image URLS: Search and replace have different amount of values. Aborting updating thumbnails', 'enable-media-replace'); | ||
| 175 | return $errors; | ||
| 176 | } | ||
| 177 | |||
| 178 | Log::addDebug('Doing meta search and replace -', array($search_urls, $replace_urls) ); | ||
| 179 | Log::addDebug('Searching with BaseuRL ' . $base_url); | ||
| 180 | |||
| 181 | do_action('shortpixel/replacer/replace_urls', $search_urls, $replace_urls); | ||
| 182 | $updated = 0; | ||
| 183 | |||
| 184 | $updated += $this->doReplaceQuery($base_url, $search_urls, $replace_urls); | ||
| 185 | |||
| 186 | $replaceRuns = apply_filters('shortpixel/replacer/custom_replace_query', array(), $base_url, $search_urls, $replace_urls); | ||
| 187 | Log::addDebug("REPLACE RUNS", $replaceRuns); | ||
| 188 | foreach($replaceRuns as $component => $run) | ||
| 189 | { | ||
| 190 | Log::addDebug('Running additional replace for : '. $component, $run); | ||
| 191 | $updated += $this->doReplaceQuery($run['base_url'], $run['search_urls'], $run['replace_urls']); | ||
| 192 | } | ||
| 193 | |||
| 194 | Log::addDebug("Updated Records : " . $updated); | ||
| 195 | return $updated; | ||
| 196 | } | ||
| 197 | |||
| 198 | private function doReplaceQuery($base_url, $search_urls, $replace_urls) | ||
| 199 | { | ||
| 200 | global $wpdb; | ||
| 201 | /* Search and replace in WP_POSTS */ | ||
| 202 | // Removed $wpdb->remove_placeholder_escape from here, not compatible with WP 4.8 | ||
| 203 | |||
| 204 | $posts_sql = $wpdb->prepare( | ||
| 205 | "SELECT ID, post_content FROM $wpdb->posts WHERE post_status in ('publish', 'future', 'draft', 'pending', 'private') | ||
| 206 | AND post_content LIKE %s", | ||
| 207 | '%' . $base_url . '%'); | ||
| 208 | |||
| 209 | $rs = $wpdb->get_results( $posts_sql, ARRAY_A ); | ||
| 210 | $number_of_updates = 0; | ||
| 211 | |||
| 212 | if ( ! empty( $rs ) ) { | ||
| 213 | foreach ( $rs AS $rows ) { | ||
| 214 | $number_of_updates = $number_of_updates + 1; | ||
| 215 | // replace old URLs with new URLs. | ||
| 216 | |||
| 217 | $post_content = $rows["post_content"]; | ||
| 218 | $post_id = $rows['ID']; | ||
| 219 | $replaced_content = $this->replaceContent($post_content, $search_urls, $replace_urls, false, true); | ||
| 220 | |||
| 221 | if ($replaced_content !== $post_content) | ||
| 222 | { | ||
| 223 | |||
| 224 | // $result = wp_update_post($post_ar); | ||
| 225 | $sql = 'UPDATE ' . $wpdb->posts . ' SET post_content = %s WHERE ID = %d'; | ||
| 226 | $sql = $wpdb->prepare($sql, $replaced_content, $post_id); | ||
| 227 | |||
| 228 | $result = $wpdb->query($sql); | ||
| 229 | |||
| 230 | if ($result === false) | ||
| 231 | { | ||
| 232 | Notice::addError('Something went wrong while replacing' . $result->get_error_message() ); | ||
| 233 | Log::addError('WP-Error during post update', $result); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | $number_of_updates += $this->handleMetaData($base_url, $search_urls, $replace_urls); | ||
| 241 | return $number_of_updates; | ||
| 242 | } | ||
| 243 | |||
| 244 | private function handleMetaData($url, $search_urls, $replace_urls) | ||
| 245 | { | ||
| 246 | global $wpdb; | ||
| 247 | |||
| 248 | $meta_options = apply_filters('shortpixel/replacer/metadata_tables', array('post', 'comment', 'term', 'user')); | ||
| 249 | $number_of_updates = 0; | ||
| 250 | |||
| 251 | foreach($meta_options as $type) | ||
| 252 | { | ||
| 253 | switch($type) | ||
| 254 | { | ||
| 255 | case "post": // special case. | ||
| 256 | $sql = 'SELECT meta_id as id, meta_key, meta_value FROM ' . $wpdb->postmeta . ' | ||
| 257 | WHERE post_id in (SELECT ID from '. $wpdb->posts . ' where post_status in ("publish", "future", "draft", "pending", "private") ) AND meta_value like %s'; | ||
| 258 | $type = 'post'; | ||
| 259 | |||
| 260 | $update_sql = ' UPDATE ' . $wpdb->postmeta . ' SET meta_value = %s WHERE meta_id = %d'; | ||
| 261 | break; | ||
| 262 | default: | ||
| 263 | $table = $wpdb->{$type . 'meta'}; // termmeta, commentmeta etc | ||
| 264 | |||
| 265 | $meta_id = 'meta_id'; | ||
| 266 | if ($type == 'user') | ||
| 267 | $meta_id = 'umeta_id'; | ||
| 268 | |||
| 269 | $sql = 'SELECT ' . $meta_id . ' as id, meta_value FROM ' . $table . ' | ||
| 270 | WHERE meta_value like %s'; | ||
| 271 | |||
| 272 | $update_sql = " UPDATE $table set meta_value = %s WHERE $meta_id = %d "; | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | |||
| 276 | $sql = $wpdb->prepare($sql, '%' . $url . '%'); | ||
| 277 | |||
| 278 | // 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. | ||
| 279 | // $postmeta_sql = str_replace('[JSON_URL]', $json_url, $postmeta_sql); | ||
| 280 | $rsmeta = $wpdb->get_results($sql, ARRAY_A); | ||
| 281 | |||
| 282 | if (! empty($rsmeta)) | ||
| 283 | { | ||
| 284 | foreach ($rsmeta as $row) | ||
| 285 | { | ||
| 286 | $number_of_updates++; | ||
| 287 | $content = $row['meta_value']; | ||
| 288 | |||
| 289 | |||
| 290 | $id = $row['id']; | ||
| 291 | |||
| 292 | $content = $this->replaceContent($content, $search_urls, $replace_urls); //str_replace($search_urls, $replace_urls, $content); | ||
| 293 | |||
| 294 | $prepared_sql = $wpdb->prepare($update_sql, $content, $id); | ||
| 295 | |||
| 296 | Log::addDebug('Update Meta SQl' . $prepared_sql); | ||
| 297 | $result = $wpdb->query($prepared_sql); | ||
| 298 | |||
| 299 | } | ||
| 300 | } | ||
| 301 | } // foreach | ||
| 302 | |||
| 303 | return $number_of_updates; | ||
| 304 | } // function | ||
| 305 | |||
| 306 | |||
| 307 | |||
| 308 | /** | ||
| 309 | * Replaces Content across several levels of possible data | ||
| 310 | * @param $content String The Content to replace | ||
| 311 | * @param $search String Search string | ||
| 312 | * @param $replace String Replacement String | ||
| 313 | * @param $in_deep Boolean. This is use to prevent serialization of sublevels. Only pass back serialized from top. | ||
| 314 | * @param $strict_check Boolean . If true, remove all classes from serialization check and fail. This should be done on post_content, not on metadata. | ||
| 315 | */ | ||
| 316 | private function replaceContent($content, $search, $replace, $in_deep = false, $strict_check = false) | ||
| 317 | { | ||
| 318 | //$is_serial = false; | ||
| 319 | if ( true === is_serialized($content)) | ||
| 320 | { | ||
| 321 | $serialized_content = $content; // use to return content back if incomplete classes are found, prevent destroying the original information | ||
| 322 | |||
| 323 | if (true === $strict_check) | ||
| 324 | { | ||
| 325 | $args = array('allowed_classes' => false); | ||
| 326 | } | ||
| 327 | else | ||
| 328 | { | ||
| 329 | $args = array('allowed_classes' => true); | ||
| 330 | } | ||
| 331 | |||
| 332 | $content = Unserialize::unserialize($content, $args); | ||
| 333 | // bail directly on incomplete classes. In < PHP 7.2 is_object is false on incomplete objects! | ||
| 334 | if (true === $this->checkIncomplete($content)) | ||
| 335 | { | ||
| 336 | return $serialized_content; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | $isJson = $this->isJSON($content); | ||
| 341 | |||
| 342 | if ($isJson) | ||
| 343 | { | ||
| 344 | $content = json_decode($content); | ||
| 345 | Log::addDebug('JSon Content', $content); | ||
| 346 | } | ||
| 347 | |||
| 348 | if (is_string($content)) // let's check the normal one first. | ||
| 349 | { | ||
| 350 | $content = apply_filters('shortpixel/replacer/content', $content, $search, $replace); | ||
| 351 | |||
| 352 | $content = str_replace($search, $replace, $content); | ||
| 353 | } | ||
| 354 | elseif (is_wp_error($content)) // seen this. | ||
| 355 | { | ||
| 356 | //return $content; // do nothing. | ||
| 357 | } | ||
| 358 | elseif (is_array($content) ) // array metadata and such. | ||
| 359 | { | ||
| 360 | foreach($content as $index => $value) | ||
| 361 | { | ||
| 362 | $content[$index] = $this->replaceContent($value, $search, $replace, true); //str_replace($value, $search, $replace); | ||
| 363 | if (is_string($index)) // If the key is the URL (sigh) | ||
| 364 | { | ||
| 365 | $index_replaced = $this->replaceContent($index, $search,$replace, true); | ||
| 366 | if ($index_replaced !== $index) | ||
| 367 | $content = $this->change_key($content, array($index => $index_replaced)); | ||
| 368 | } | ||
| 369 | } | ||
| 370 | } | ||
| 371 | elseif(is_object($content)) // metadata objects, they exist. | ||
| 372 | { | ||
| 373 | // bail directly on incomplete classes. | ||
| 374 | if (true === $this->checkIncomplete($content)) | ||
| 375 | { | ||
| 376 | // if it was serialized, return the original as not to corrupt data. | ||
| 377 | if (isset($serialized_content)) | ||
| 378 | { | ||
| 379 | return $serialized_content; | ||
| 380 | } | ||
| 381 | else { // else just return the content. | ||
| 382 | return $content; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | foreach($content as $key => $value) | ||
| 386 | { | ||
| 387 | $content->{$key} = $this->replaceContent($value, $search, $replace, true); //str_replace($value, $search, $replace); | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | if ($isJson && $in_deep === false) // convert back to JSON, if this was JSON. Different than serialize which does WP automatically. | ||
| 392 | { | ||
| 393 | Log::addDebug('Value was found to be JSON, encoding'); | ||
| 394 | // wp-slash -> WP does stripslashes_deep which destroys JSON | ||
| 395 | $content = json_encode($content, JSON_UNESCAPED_SLASHES); | ||
| 396 | Log::addDebug('Content returning', array($content)); | ||
| 397 | } | ||
| 398 | elseif($in_deep === false && (is_array($content) || is_object($content))) | ||
| 399 | $content = maybe_serialize($content); | ||
| 400 | |||
| 401 | return $content; | ||
| 402 | } | ||
| 403 | |||
| 404 | private function change_key($arr, $set) { | ||
| 405 | if (is_array($arr) && is_array($set)) { | ||
| 406 | $newArr = array(); | ||
| 407 | foreach ($arr as $k => $v) { | ||
| 408 | $key = array_key_exists( $k, $set) ? $set[$k] : $k; | ||
| 409 | $newArr[$key] = is_array($v) ? $this->change_key($v, $set) : $v; | ||
| 410 | } | ||
| 411 | return $newArr; | ||
| 412 | } | ||
| 413 | return $arr; | ||
| 414 | } | ||
| 415 | |||
| 416 | private function getRelativeURLS() | ||
| 417 | { | ||
| 418 | $dataArray = array( | ||
| 419 | 'source' => array('url' => $this->source_url, 'metadata' => $this->getFilesFromMetadata($this->source_metadata) ), | ||
| 420 | 'target' => array('url' => $this->target_url, 'metadata' => $this->getFilesFromMetadata($this->target_metadata) ), | ||
| 421 | ); | ||
| 422 | |||
| 423 | // Log::addDebug('Source Metadata', $this->source_metadata); | ||
| 424 | // Log::addDebug('Target Metadata', $this->target_metadata); | ||
| 425 | |||
| 426 | $result = array(); | ||
| 427 | |||
| 428 | foreach($dataArray as $index => $item) | ||
| 429 | { | ||
| 430 | $result[$index] = array(); | ||
| 431 | $metadata = $item['metadata']; | ||
| 432 | |||
| 433 | $baseurl = parse_url($item['url'], PHP_URL_PATH); | ||
| 434 | $result[$index]['base'] = $baseurl; // this is the relpath of the mainfile. | ||
| 435 | $baseurl = trailingslashit(str_replace( wp_basename($item['url']), '', $baseurl)); // get the relpath of main file. | ||
| 436 | |||
| 437 | foreach($metadata as $name => $filename) | ||
| 438 | { | ||
| 439 | $result[$index][$name] = $baseurl . wp_basename($filename); // filename can have a path like 19/08 etc. | ||
| 440 | } | ||
| 441 | |||
| 442 | } | ||
| 443 | // Log::addDebug('Relative URLS', $result); | ||
| 444 | return $result; | ||
| 445 | } | ||
| 446 | |||
| 447 | |||
| 448 | private function getFilesFromMetadata($meta) | ||
| 449 | { | ||
| 450 | $fileArray = array(); | ||
| 451 | if (isset($meta['file'])) | ||
| 452 | $fileArray['file'] = $meta['file']; | ||
| 453 | |||
| 454 | if (isset($meta['sizes'])) | ||
| 455 | { | ||
| 456 | foreach($meta['sizes'] as $name => $data) | ||
| 457 | { | ||
| 458 | if (isset($data['file'])) | ||
| 459 | { | ||
| 460 | $fileArray[$name] = $data['file']; | ||
| 461 | } | ||
| 462 | } | ||
| 463 | } | ||
| 464 | return $fileArray; | ||
| 465 | } | ||
| 466 | |||
| 467 | /** FindNearestsize | ||
| 468 | * 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. | ||
| 469 | */ | ||
| 470 | private function findNearestSize($sizeName) | ||
| 471 | { | ||
| 472 | |||
| 473 | if (! isset($this->source_metadata['sizes'][$sizeName]) || ! isset($this->target_metadata['width'])) // This can happen with non-image files like PDF. | ||
| 474 | { | ||
| 475 | // Check if metadata-less item is a svg file. Just the main file to replace all thumbnails since SVG's don't need thumbnails. | ||
| 476 | if (strpos($this->target_url, '.svg') !== false) | ||
| 477 | { | ||
| 478 | $svg_file = wp_basename($this->target_url); | ||
| 479 | return $svg_file; // this is the relpath of the mainfile. | ||
| 480 | } | ||
| 481 | |||
| 482 | return false; | ||
| 483 | } | ||
| 484 | $old_width = $this->source_metadata['sizes'][$sizeName]['width']; // the width from size not in new image | ||
| 485 | $new_width = $this->target_metadata['width']; // default check - the width of the main image | ||
| 486 | |||
| 487 | $diff = abs($old_width - $new_width); | ||
| 488 | // $closest_file = str_replace($this->relPath, '', $this->newMeta['file']); | ||
| 489 | $closest_file = wp_basename($this->target_metadata['file']); // mainfile as default | ||
| 490 | |||
| 491 | foreach($this->target_metadata['sizes'] as $sizeName => $data) | ||
| 492 | { | ||
| 493 | $thisdiff = abs($old_width - $data['width']); | ||
| 494 | |||
| 495 | if ( $thisdiff < $diff ) | ||
| 496 | { | ||
| 497 | $closest_file = $data['file']; | ||
| 498 | if(is_array($closest_file)) { $closest_file = $closest_file[0];} // HelpScout case 709692915 | ||
| 499 | if(!empty($closest_file)) { | ||
| 500 | $diff = $thisdiff; | ||
| 501 | $found_metasize = true; | ||
| 502 | } | ||
| 503 | } | ||
| 504 | } | ||
| 505 | |||
| 506 | if(empty($closest_file)) return false; | ||
| 507 | |||
| 508 | return $closest_file; | ||
| 509 | } | ||
| 510 | |||
| 511 | /* Check if given content is JSON format. */ | ||
| 512 | private function isJSON($content) | ||
| 513 | { | ||
| 514 | if (is_array($content) || is_object($content) || is_null($content)) | ||
| 515 | return false; // can never be. | ||
| 516 | |||
| 517 | $json = json_decode($content); | ||
| 518 | return $json && $json != $content; | ||
| 519 | } | ||
| 520 | |||
| 521 | private function checkIncomplete($var) | ||
| 522 | { | ||
| 523 | return ($var instanceof \__PHP_Incomplete_Class); | ||
| 524 | } | ||
| 525 | |||
| 526 | |||
| 527 | } // class |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Controller; | ||
| 3 | use EnableMediaReplace\Notices\NoticeController as Notices; | ||
| 4 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 5 | |||
| 6 | |||
| 7 | if (! defined('ABSPATH')) { | ||
| 8 | exit; // Exit if accessed directly. | ||
| 9 | } | ||
| 10 | |||
| 11 | class RemoteNoticeController | ||
| 12 | { | ||
| 13 | protected static $instance; | ||
| 14 | private $remote_message_endpoint = 'https://api.shortpixel.com/v2/notices.php'; | ||
| 15 | |||
| 16 | |||
| 17 | public function __construct() | ||
| 18 | { | ||
| 19 | $this->doRemoteNotices(); | ||
| 20 | } | ||
| 21 | |||
| 22 | public static function getInstance() | ||
| 23 | { | ||
| 24 | if ( is_null(self::$instance)) | ||
| 25 | { | ||
| 26 | self::$instance = new RemoteNoticeController(); | ||
| 27 | } | ||
| 28 | |||
| 29 | return self::$instance; | ||
| 30 | } | ||
| 31 | |||
| 32 | protected function doRemoteNotices() | ||
| 33 | { | ||
| 34 | $notices = $this->get_remote_notices(); | ||
| 35 | |||
| 36 | if (! is_array($notices)) | ||
| 37 | return; | ||
| 38 | |||
| 39 | foreach($notices as $remoteNotice) | ||
| 40 | { | ||
| 41 | if (! isset($remoteNotice->id) && ! isset($remoteNotice->message)) | ||
| 42 | return; | ||
| 43 | |||
| 44 | if (! isset($remoteNotice->type)) | ||
| 45 | $remoteNotice->type = 'notice'; | ||
| 46 | |||
| 47 | $message = esc_html($remoteNotice->message); | ||
| 48 | $id = sanitize_text_field($remoteNotice->id); | ||
| 49 | |||
| 50 | $noticeController = Notices::getInstance(); | ||
| 51 | $noticeObj = $noticeController->getNoticeByID($id); | ||
| 52 | |||
| 53 | // not added to system yet | ||
| 54 | if ($noticeObj === false) | ||
| 55 | { | ||
| 56 | switch ($remoteNotice->type) | ||
| 57 | { | ||
| 58 | case 'warning': | ||
| 59 | $new_notice = Notices::addWarning($message); | ||
| 60 | break; | ||
| 61 | case 'error': | ||
| 62 | $new_notice = Notices::addError($message); | ||
| 63 | break; | ||
| 64 | case 'notice': | ||
| 65 | default: | ||
| 66 | $new_notice = Notices::addNormal($message); | ||
| 67 | break; | ||
| 68 | } | ||
| 69 | |||
| 70 | Notices::makePersistent($new_notice, $id, MONTH_IN_SECONDS); | ||
| 71 | } | ||
| 72 | |||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | private function get_remote_notices() | ||
| 77 | { | ||
| 78 | $transient_name = 'emr_remote_notice'; | ||
| 79 | $transient_duration = DAY_IN_SECONDS; | ||
| 80 | |||
| 81 | |||
| 82 | // $keyControl = new apiKeyController(); | ||
| 83 | //$keyControl->loadKey(); | ||
| 84 | |||
| 85 | $notices = get_transient($transient_name); | ||
| 86 | $url = $this->remote_message_endpoint; | ||
| 87 | $url = add_query_arg(array( // has url | ||
| 88 | 'version' => EMR_VERSION, | ||
| 89 | 'plugin' => 'enable-media-replace', | ||
| 90 | 'target' => 4, | ||
| 91 | |||
| 92 | ), $url); | ||
| 93 | |||
| 94 | |||
| 95 | if ( $notices === false || $notices == 'none' ) { | ||
| 96 | $notices_response = wp_safe_remote_request( $url ); | ||
| 97 | |||
| 98 | $content = false; | ||
| 99 | if (! is_wp_error( $notices_response ) ) | ||
| 100 | { | ||
| 101 | $notices = json_decode($notices_response['body']); | ||
| 102 | |||
| 103 | if (! is_array($notices)) | ||
| 104 | $notices = 'none'; | ||
| 105 | |||
| 106 | // Save transient anywhere to prevent over-asking when nothing good is there. | ||
| 107 | set_transient( $transient_name, 'true', $transient_duration ); | ||
| 108 | } | ||
| 109 | else | ||
| 110 | { | ||
| 111 | set_transient( $transient_name, false, $transient_duration ); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | return $notices; | ||
| 116 | } | ||
| 117 | |||
| 118 | } // class |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Controller; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 9 | use EnableMediaReplace\Replacer\Replacer as Replacer; | ||
| 10 | use EnableMediaReplace\emrCache as emrCache; | ||
| 11 | |||
| 12 | class ReplaceController | ||
| 13 | { | ||
| 14 | protected $post_id; | ||
| 15 | protected $sourceFile; | ||
| 16 | protected $sourceFileUntranslated; | ||
| 17 | protected $targetFile; | ||
| 18 | |||
| 19 | const MODE_REPLACE = 1; | ||
| 20 | const MODE_SEARCHREPLACE = 2; | ||
| 21 | |||
| 22 | const TIME_UPDATEALL = 1; // replace the date | ||
| 23 | const TIME_UPDATEMODIFIED = 2; // keep the date, update only modified | ||
| 24 | const TIME_CUSTOM = 3; // custom time entry | ||
| 25 | |||
| 26 | const ERROR_TARGET_EXISTS = 20; | ||
| 27 | const ERROR_DESTINATION_FAIL = 21; | ||
| 28 | const ERROR_COPY_FAILED = 22; | ||
| 29 | const ERROR_UPDATE_POST = 23; | ||
| 30 | const ERROR_DIRECTORY_SECURITY = 24; | ||
| 31 | const ERROR_DIRECTORY_NOTEXIST = 25; | ||
| 32 | |||
| 33 | protected $replaceType; | ||
| 34 | /** @var string */ | ||
| 35 | protected $new_location; | ||
| 36 | protected $timeMode; | ||
| 37 | protected $newDate; | ||
| 38 | |||
| 39 | protected $new_filename; | ||
| 40 | |||
| 41 | protected $tmpUploadPath; | ||
| 42 | |||
| 43 | protected $lastError; | ||
| 44 | protected $lastErrorData; // optional extra data for last error. | ||
| 45 | |||
| 46 | public function __construct($post_id) | ||
| 47 | { | ||
| 48 | $this->post_id = $post_id; | ||
| 49 | $this->setupSource(); | ||
| 50 | } | ||
| 51 | |||
| 52 | /* getSourceFile | ||
| 53 | * | ||
| 54 | * @param $untranslated boolean if file is offloaded, this indicates to return remote variant. Used for displaying preview | ||
| 55 | */ | ||
| 56 | public function getSourceFile($untranslated = false) | ||
| 57 | { | ||
| 58 | |||
| 59 | if (true === $untranslated && ! is_null($this->sourceFileUntranslated)) | ||
| 60 | { | ||
| 61 | return $this->sourceFileUntranslated; | ||
| 62 | } | ||
| 63 | return $this->sourceFile; | ||
| 64 | } | ||
| 65 | |||
| 66 | public function setupParams($params) | ||
| 67 | { | ||
| 68 | $this->replaceType = ($params['replace_type'] === 'replace_and_search') ? self::MODE_SEARCHREPLACE : self::MODE_REPLACE; | ||
| 69 | |||
| 70 | if ($this->replaceType == self::MODE_SEARCHREPLACE && true === $params['new_location'] && ! is_null($params['location_dir'])) | ||
| 71 | { | ||
| 72 | $this->new_location = $params['location_dir']; | ||
| 73 | } | ||
| 74 | |||
| 75 | $this->timeMode = $params['timestamp_replace']; | ||
| 76 | $this->newDate = $params['new_date']; | ||
| 77 | |||
| 78 | $this->new_filename = $params['new_filename']; | ||
| 79 | $this->tmpUploadPath = $params['uploadFile']; | ||
| 80 | |||
| 81 | $targetFile = $this->setupTarget(); | ||
| 82 | if (is_null($targetFile)) | ||
| 83 | { | ||
| 84 | return false; | ||
| 85 | } | ||
| 86 | $this->targetFile = $this->fs()->getFile($targetFile); | ||
| 87 | |||
| 88 | return true; | ||
| 89 | } | ||
| 90 | |||
| 91 | public function returnLastError() | ||
| 92 | { | ||
| 93 | return $this->lastError; | ||
| 94 | } | ||
| 95 | |||
| 96 | public function returnLastErrorData() | ||
| 97 | { | ||
| 98 | if (! is_null($this->lastErrorData)) | ||
| 99 | return $this->lastErrorData; | ||
| 100 | else { | ||
| 101 | return array(); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | public function run() | ||
| 106 | { | ||
| 107 | do_action('wp_handle_replace', array('post_id' => $this->post_id)); | ||
| 108 | |||
| 109 | // Set Source / and Source Metadata | ||
| 110 | $Replacer = new Replacer(); | ||
| 111 | $source_url = $this->getSourceUrl(); | ||
| 112 | $Replacer->setSource($source_url); | ||
| 113 | $Replacer->setSourceMeta(wp_get_attachment_metadata( $this->post_id )); | ||
| 114 | |||
| 115 | $targetFileObj = $this->fs()->getFile($this->targetFile); | ||
| 116 | |||
| 117 | $directoryObj = $targetFileObj->getFileDir(); | ||
| 118 | |||
| 119 | $result = $directoryObj->check(); | ||
| 120 | |||
| 121 | if ($result === false) | ||
| 122 | { | ||
| 123 | Log::addError('Directory creation for targetFile failed'); | ||
| 124 | } | ||
| 125 | |||
| 126 | $permissions = ($this->sourceFile->exists() ) ? $this->sourceFile->getPermissions() : -1; | ||
| 127 | |||
| 128 | $this->removeCurrent(); // tries to remove the current files. | ||
| 129 | |||
| 130 | $fileObj = $this->fs()->getFile($this->tmpUploadPath); | ||
| 131 | $copied = $fileObj->copy($targetFileObj); | ||
| 132 | |||
| 133 | if (false === $copied) | ||
| 134 | { | ||
| 135 | if ($targetFileObj->exists()) | ||
| 136 | { | ||
| 137 | Log::addDebug('Copy declared failed, but target available'); | ||
| 138 | } | ||
| 139 | else { | ||
| 140 | $this->lastError = self::ERROR_COPY_FAILED; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | $deleted = $fileObj->delete(); | ||
| 145 | if (false === $deleted) | ||
| 146 | { | ||
| 147 | Log::addWarn('Temp file could not be removed. Permission issues?'); | ||
| 148 | } | ||
| 149 | |||
| 150 | $this->targetFile->resetStatus(); // reinit target file because it came into existence. | ||
| 151 | |||
| 152 | if ($permissions > 0) | ||
| 153 | chmod( $this->targetFile->getFullPath(), $permissions ); // restore permissions | ||
| 154 | else { | ||
| 155 | Log::addWarn('Setting permissions failed'); | ||
| 156 | } | ||
| 157 | |||
| 158 | // Uspdate the file attached. This is required for wp_get_attachment_url to work. | ||
| 159 | // Using RawFullPath because FullPath does normalize path, which update_attached_file doesn't so in case of windows / strange Apspaths it fails. | ||
| 160 | $updated = update_attached_file($this->post_id, $this->targetFile->getRawFullPath() ); | ||
| 161 | if (! $updated) | ||
| 162 | { | ||
| 163 | Log::addError('Update Attached File reports as not updated or same value'); | ||
| 164 | } | ||
| 165 | |||
| 166 | // Run the filter, so other plugins can hook if needed. | ||
| 167 | $filtered = apply_filters( 'wp_handle_upload', array( | ||
| 168 | 'file' => $this->targetFile->getFullPath(), | ||
| 169 | 'url' => $this->getTargetURL(), | ||
| 170 | 'type' => $this->targetFile->getMime(), | ||
| 171 | ), 'sideload'); | ||
| 172 | |||
| 173 | // check if file changed during filter. Set changed to attached file meta properly. | ||
| 174 | if (isset($filtered['file']) && $filtered['file'] != $this->targetFile->getFullPath() ) | ||
| 175 | { | ||
| 176 | update_attached_file($this->post_id, $filtered['file'] ); | ||
| 177 | $this->targetFile = $this->fs()->getFile($filtered['file']); // handle as a new file | ||
| 178 | Log::addInfo('WP_Handle_upload filter returned different file', $filtered); | ||
| 179 | } | ||
| 180 | |||
| 181 | $target_url = $this->getTargetURL(); | ||
| 182 | $Replacer->setTarget($target_url); | ||
| 183 | |||
| 184 | // Check and update post mimetype, otherwise badly coded plugins cry. | ||
| 185 | $post_mime = get_post_mime_type($this->post_id); | ||
| 186 | $target_mime = $this->targetFile->getMime(); | ||
| 187 | |||
| 188 | // update DB post mime type, if somebody decided to mess it up, and the target one is not empty. | ||
| 189 | if ($target_mime !== $post_mime && strlen($target_mime) > 0) | ||
| 190 | { | ||
| 191 | \wp_update_post(array('post_mime_type' => $this->targetFile->getMime(), 'ID' => $this->post_id)); | ||
| 192 | } | ||
| 193 | |||
| 194 | do_action('emr/converter/prevent-offload', $this->post_id); | ||
| 195 | $target_metadata = wp_generate_attachment_metadata( $this->post_id, $this->targetFile->getFullPath() ); | ||
| 196 | do_action('emr/converter/prevent-offload-off', $this->post_id); | ||
| 197 | wp_update_attachment_metadata( $this->post_id, $target_metadata ); | ||
| 198 | |||
| 199 | |||
| 200 | $Replacer->setTargetMeta($target_metadata); | ||
| 201 | //$this->target_metadata = $metadata; | ||
| 202 | |||
| 203 | /** If author is different from replacer, note this */ | ||
| 204 | $post_author = get_post_field( 'post_author', $this->post_id ); | ||
| 205 | $author_id = get_post_meta($this->post_id, '_emr_replace_author', true); | ||
| 206 | |||
| 207 | if ( intval($post_author) !== get_current_user_id()) | ||
| 208 | { | ||
| 209 | update_post_meta($this->post_id, '_emr_replace_author', get_current_user_id()); | ||
| 210 | } | ||
| 211 | elseif ($author_id) | ||
| 212 | { | ||
| 213 | delete_post_meta($this->post_id, '_emr_replace_author'); | ||
| 214 | } | ||
| 215 | |||
| 216 | |||
| 217 | if ($this->replaceType == self::MODE_SEARCHREPLACE) | ||
| 218 | { | ||
| 219 | // Write new image title. | ||
| 220 | $title = $this->getNewTitle($target_metadata); | ||
| 221 | $excerpt = $this->getNewExcerpt($target_metadata); | ||
| 222 | $update_ar = array('ID' => $this->post_id); | ||
| 223 | $update_ar['post_title'] = $title; | ||
| 224 | $update_ar['post_name'] = sanitize_title($title); | ||
| 225 | if ($excerpt !== false) | ||
| 226 | { | ||
| 227 | $update_ar['post_excerpt'] = $excerpt; | ||
| 228 | } | ||
| 229 | $update_ar['guid'] = $target_url; //wp_get_attachment_url($this->post_id); | ||
| 230 | |||
| 231 | $post_id = \wp_update_post($update_ar, true); | ||
| 232 | |||
| 233 | global $wpdb; | ||
| 234 | // update post doesn't update GUID on updates. | ||
| 235 | $wpdb->update( $wpdb->posts, array( 'guid' => $target_url), array('ID' => $this->post_id) ); | ||
| 236 | //enable-media-replace-upload-done | ||
| 237 | |||
| 238 | // @todo This error in general ever happens? | ||
| 239 | if (is_wp_error($post_id)) | ||
| 240 | { | ||
| 241 | $this->lastError = self::ERROR_UPDATE_POST; | ||
| 242 | } | ||
| 243 | |||
| 244 | } | ||
| 245 | |||
| 246 | /// Here run the Replacer Module | ||
| 247 | $args = array( | ||
| 248 | 'thumbnails_only' => ($this->replaceType == self::MODE_SEARCHREPLACE) ? false : true, | ||
| 249 | ); | ||
| 250 | |||
| 251 | $Replacer->replace($args); | ||
| 252 | |||
| 253 | // Here Updatedata and a ffew others. | ||
| 254 | $this->updateDate(); | ||
| 255 | |||
| 256 | // Give the caching a kick. Off pending specifics. | ||
| 257 | $cache_args = array( | ||
| 258 | 'flush_mode' => 'post', | ||
| 259 | 'post_id' => $this->post_id, | ||
| 260 | ); | ||
| 261 | |||
| 262 | $cache = new emrCache(); | ||
| 263 | $cache->flushCache($cache_args); | ||
| 264 | |||
| 265 | do_action("enable-media-replace-upload-done", $target_url, $source_url, $this->post_id); | ||
| 266 | |||
| 267 | return true; | ||
| 268 | } // run | ||
| 269 | |||
| 270 | |||
| 271 | protected function setupSource() | ||
| 272 | { | ||
| 273 | $source_file = false; | ||
| 274 | |||
| 275 | // The main image as registered in attached_file metadata. This can be regular or -scaled. | ||
| 276 | $source_file_main = trim(get_attached_file($this->post_id, apply_filters( 'emr_unfiltered_get_attached_file', true ))); | ||
| 277 | |||
| 278 | // If available it -needs- to use the main image when replacing since treating a -scaled images as main will create a resursion in the filename when not replacing that one . Ie image-scaled-scaled.jpg or image-scaled-100x100.jpg . | ||
| 279 | if (function_exists('wp_get_original_image_path')) // WP 5.3+ | ||
| 280 | { | ||
| 281 | $source_file = wp_get_original_image_path($this->post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )); | ||
| 282 | // For offload et al to change path if wrong. Somehow this happens? | ||
| 283 | $source_file = apply_filters('emr/replace/original_image_path', $source_file, $this->post_id); | ||
| 284 | |||
| 285 | } | ||
| 286 | |||
| 287 | if (false === $source_file) // If not scaled, use the main one. | ||
| 288 | { | ||
| 289 | $source_file = $source_file_main; | ||
| 290 | } | ||
| 291 | |||
| 292 | |||
| 293 | $sourceFileObj = $this->fs()->getFile($source_file); | ||
| 294 | $isVirtual = false; | ||
| 295 | if ($sourceFileObj->is_virtual()) | ||
| 296 | { | ||
| 297 | $isVirtual = true; | ||
| 298 | |||
| 299 | /*** | ||
| 300 | *** Either here the table should check scaled - non-scaled ** or ** the original_path should be updated. | ||
| 301 | *** | ||
| 302 | |||
| 303 | */ | ||
| 304 | |||
| 305 | $this->sourceFileUntranslated = $this->fs()->getFile($source_file); | ||
| 306 | $sourcePath = apply_filters('emr/file/virtual/translate', $sourceFileObj->getFullPath(), $sourceFileObj, $this->post_id); | ||
| 307 | |||
| 308 | if (false !== $sourcePath && $sourceFileObj->getFullPath() !== $sourcePath) | ||
| 309 | { | ||
| 310 | $sourceFileObj = $this->fs()->getFile($sourcePath); | ||
| 311 | $source_file = $sourcePath; | ||
| 312 | } | ||
| 313 | |||
| 314 | } | ||
| 315 | |||
| 316 | |||
| 317 | /* It happens that the SourceFile returns relative / incomplete when something messes up get_upload_dir with an error something. | ||
| 318 | This case shoudl be detected here and create a non-relative path anyhow.. | ||
| 319 | */ | ||
| 320 | if ( | ||
| 321 | false === $isVirtual && | ||
| 322 | false === file_exists($source_file) && | ||
| 323 | $source_file && 0 !== strpos( $source_file, '/' ) | ||
| 324 | && ! preg_match( '|^.:\\\|', $source_file ) ) | ||
| 325 | { | ||
| 326 | $file = get_post_meta( $this->post_id, '_wp_attached_file', true ); | ||
| 327 | $uploads = wp_get_upload_dir(); | ||
| 328 | $source_file = $uploads['basedir'] . "/$source_file"; | ||
| 329 | } | ||
| 330 | |||
| 331 | Log::addDebug('SetupSource SourceFile Path ' . $source_file); | ||
| 332 | $this->sourceFile = $this->fs()->getFile($source_file); | ||
| 333 | } | ||
| 334 | |||
| 335 | /** Returns a full target path to place to new file. Including the file name! **/ | ||
| 336 | protected function setupTarget() | ||
| 337 | { | ||
| 338 | $targetPath = null; | ||
| 339 | if ($this->replaceType == self::MODE_REPLACE) | ||
| 340 | { | ||
| 341 | $targetFile = $this->getSourceFile()->getFullPath(); // overwrite source | ||
| 342 | } | ||
| 343 | elseif ($this->replaceType == self::MODE_SEARCHREPLACE) | ||
| 344 | { | ||
| 345 | $path = (string) $this->getSourceFile()->getFileDir(); | ||
| 346 | $targetLocation = $this->getNewTargetLocation(); | ||
| 347 | if (false === $targetLocation) | ||
| 348 | { | ||
| 349 | return null; | ||
| 350 | } | ||
| 351 | |||
| 352 | if (false === is_null($this->new_location)) // Replace to another path. | ||
| 353 | { | ||
| 354 | $otherTarget = $this->fs()->getFile($targetLocation . $this->new_filename); | ||
| 355 | // Halt if new target exists, but not if it's the same ( overwriting itself ) | ||
| 356 | |||
| 357 | if ($otherTarget->exists() && $otherTarget->getFullPath() !== $this->getSourceFile()->getFullPath() ) | ||
| 358 | { | ||
| 359 | $this->lastError = self::ERROR_TARGET_EXISTS; | ||
| 360 | return null; | ||
| 361 | } | ||
| 362 | |||
| 363 | $path = $targetLocation; // $this->target_location; // if all went well. | ||
| 364 | } | ||
| 365 | //if ($this->sourceFile->getFileName() == $this->targetName) | ||
| 366 | $targetpath = $path . $this->new_filename; | ||
| 367 | |||
| 368 | // If the source and target path AND filename are identical, user has wrong mode, just overwrite the sourceFile. | ||
| 369 | if ($targetpath == $this->sourceFile->getFullPath()) | ||
| 370 | { | ||
| 371 | $unique = $this->sourceFile->getFileName(); | ||
| 372 | $this->replaceType == self::MODE_REPLACE; | ||
| 373 | } | ||
| 374 | else | ||
| 375 | { | ||
| 376 | $unique = wp_unique_filename($path, $this->new_filename); | ||
| 377 | } | ||
| 378 | $new_filename = apply_filters( 'emr_unique_filename', $unique, $path, $this->post_id ); | ||
| 379 | $targetFile = trailingslashit($path) . $new_filename; | ||
| 380 | } | ||
| 381 | if (is_dir($targetFile)) // this indicates an error with the source. | ||
| 382 | { | ||
| 383 | Log::addWarn('TargetFile is directory ' . $targetFile ); | ||
| 384 | $upload_dir = wp_upload_dir(); | ||
| 385 | if (isset($upload_dir['path'])) | ||
| 386 | { | ||
| 387 | $targetFile = trailingslashit($upload_dir['path']) . wp_unique_filename($targetFile, $this->new_filename); | ||
| 388 | } | ||
| 389 | else { | ||
| 390 | |||
| 391 | $this->lastError = self::ERROR_DESTINATION_FAIL; | ||
| 392 | return null; | ||
| 393 | } | ||
| 394 | } | ||
| 395 | return $targetFile; | ||
| 396 | } | ||
| 397 | |||
| 398 | protected function getNewTitle($meta) | ||
| 399 | { | ||
| 400 | // get basename without extension | ||
| 401 | $title = basename($this->targetFile->getFileName(), '.' . $this->targetFile->getExtension()); | ||
| 402 | // $meta = $this->target_metadata; | ||
| 403 | |||
| 404 | if (isset($meta['image_meta'])) | ||
| 405 | { | ||
| 406 | if (isset($meta['image_meta']['title'])) | ||
| 407 | { | ||
| 408 | if (strlen($meta['image_meta']['title']) > 0) | ||
| 409 | { | ||
| 410 | $title = $meta['image_meta']['title']; | ||
| 411 | } | ||
| 412 | } | ||
| 413 | } | ||
| 414 | |||
| 415 | // Thanks Jonas Lundman (http://wordpress.org/support/topic/add-filter-hook-suggestion-to) | ||
| 416 | $title = apply_filters( 'enable_media_replace_title', $title ); | ||
| 417 | |||
| 418 | return $title; | ||
| 419 | } | ||
| 420 | |||
| 421 | protected function getNewExcerpt($meta) | ||
| 422 | { | ||
| 423 | // $meta = $this->target_metadata; | ||
| 424 | $excerpt = false; | ||
| 425 | |||
| 426 | if (isset($meta['image_meta'])) | ||
| 427 | { | ||
| 428 | if (isset($meta['image_meta']['caption'])) | ||
| 429 | { | ||
| 430 | if (strlen($meta['image_meta']['caption']) > 0) | ||
| 431 | { | ||
| 432 | $excerpt = $meta['image_meta']['caption']; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | return $excerpt; | ||
| 438 | } | ||
| 439 | |||
| 440 | public function getSourceUrl() | ||
| 441 | { | ||
| 442 | if (function_exists('wp_get_original_image_url')) // WP 5.3+ | ||
| 443 | { | ||
| 444 | $source_url = wp_get_original_image_url($this->post_id); | ||
| 445 | if ($source_url === false) // not an image, or borked, try the old way | ||
| 446 | $source_url = wp_get_attachment_url($this->post_id); | ||
| 447 | |||
| 448 | $source_url = $source_url; | ||
| 449 | } | ||
| 450 | else | ||
| 451 | $source_url = wp_get_attachment_url($this->post_id); | ||
| 452 | |||
| 453 | return $source_url; | ||
| 454 | } | ||
| 455 | |||
| 456 | /** Handle new dates for the replacement */ | ||
| 457 | protected function updateDate() | ||
| 458 | { | ||
| 459 | global $wpdb; | ||
| 460 | $post_date = $this->newDate; | ||
| 461 | $post_date_gmt = get_gmt_from_date($post_date); | ||
| 462 | |||
| 463 | $update_ar = array('ID' => $this->post_id); | ||
| 464 | if ($this->timeMode == static::TIME_UPDATEALL || $this->timeMode == static::TIME_CUSTOM) | ||
| 465 | { | ||
| 466 | $update_ar['post_date'] = $post_date; | ||
| 467 | $update_ar['post_date_gmt'] = $post_date_gmt; | ||
| 468 | } | ||
| 469 | else { | ||
| 470 | |||
| 471 | } | ||
| 472 | $update_ar['post_modified'] = $post_date; | ||
| 473 | $update_ar['post_modified_gmt'] = $post_date_gmt; | ||
| 474 | |||
| 475 | $updated = $wpdb->update( $wpdb->posts, $update_ar , array('ID' => $this->post_id) ); | ||
| 476 | |||
| 477 | wp_cache_delete($this->post_id, 'posts'); | ||
| 478 | |||
| 479 | } | ||
| 480 | |||
| 481 | /** Tries to remove all of the old image, without touching the metadata in database | ||
| 482 | * This might fail on certain files, but this is not an indication of success ( remove might fail, but overwrite can still work) | ||
| 483 | */ | ||
| 484 | protected function removeCurrent() | ||
| 485 | { | ||
| 486 | $meta = \wp_get_attachment_metadata( $this->post_id ); | ||
| 487 | $backup_sizes = get_post_meta( $this->post_id, '_wp_attachment_backup_sizes', true ); | ||
| 488 | |||
| 489 | // 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. | ||
| 490 | $file = $this->sourceFile->getFullPath(); | ||
| 491 | $result = \wp_delete_attachment_files($this->post_id, $meta, $backup_sizes, $file ); | ||
| 492 | |||
| 493 | // If Attached file is not the same path as file, this indicates a -scaled images is in play. | ||
| 494 | // Also plugins like Polylang tend to block delete image while there is translation / duplicate item somewhere | ||
| 495 | // 10/06/22 : Added a hard delete if file still exists. Be gone, hard way. | ||
| 496 | $attached_file = get_attached_file($this->post_id); | ||
| 497 | if (file_exists($attached_file)) | ||
| 498 | { | ||
| 499 | @unlink($attached_file); | ||
| 500 | } | ||
| 501 | |||
| 502 | do_action( 'emr_after_remove_current', $this->post_id, $meta, $backup_sizes, $this->sourceFile, $this->targetFile ); | ||
| 503 | } | ||
| 504 | |||
| 505 | /** Since WP functions also can't be trusted here in certain cases, create the URL by ourselves */ | ||
| 506 | protected function getTargetURL() | ||
| 507 | { | ||
| 508 | if (is_null($this->targetFile)) | ||
| 509 | { | ||
| 510 | Log::addError('TargetFile NULL ', debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10)); | ||
| 511 | return false; | ||
| 512 | } | ||
| 513 | //$uploads['baseurl'] | ||
| 514 | $url = wp_get_attachment_url($this->post_id); | ||
| 515 | $url_basename = basename($url); | ||
| 516 | |||
| 517 | // Seems all worked as normal. | ||
| 518 | if (strpos($url, '://') >= 0 && $this->targetFile->getFileName() == $url_basename) | ||
| 519 | return $url; | ||
| 520 | |||
| 521 | // Relative path for some reason | ||
| 522 | if (strpos($url, '://') === false) | ||
| 523 | { | ||
| 524 | $uploads = wp_get_upload_dir(); | ||
| 525 | $url = str_replace($uploads['basedir'], $uploads['baseurl'], $this->targetFile->getFullPath()); | ||
| 526 | } | ||
| 527 | // This can happen when WordPress is not taking from attached file, but wrong /old GUID. Try to replace it to the new one. | ||
| 528 | elseif ($this->targetFile->getFileName() != $url_basename) | ||
| 529 | { | ||
| 530 | $url = str_replace($url_basename, $this->targetFile->getFileName(), $url); | ||
| 531 | } | ||
| 532 | |||
| 533 | return $url; | ||
| 534 | |||
| 535 | } | ||
| 536 | |||
| 537 | protected function getNewTargetLocation() | ||
| 538 | { | ||
| 539 | $uploadDir = wp_upload_dir(); | ||
| 540 | $new_rel_location = $this->new_location; | ||
| 541 | $newPath = trailingslashit($uploadDir['basedir']) . $new_rel_location; | ||
| 542 | |||
| 543 | $realPath = realpath($newPath); | ||
| 544 | $basedir = realpath($uploadDir['basedir']); // both need to go to realpath, otherwise some servers will have issues with it. | ||
| 545 | |||
| 546 | // Detect traversal by making sure the canonical path starts with uploads' basedir. | ||
| 547 | if ( strpos($realPath, $basedir) !== 0) | ||
| 548 | { | ||
| 549 | $this->lastError = self::ERROR_DIRECTORY_SECURITY; | ||
| 550 | $this->lastErrorData = array('path' => $realPath, 'basedir' => $basedir); | ||
| 551 | return false; | ||
| 552 | } | ||
| 553 | |||
| 554 | if (! is_dir($newPath)) | ||
| 555 | { | ||
| 556 | $this->lastError = self::ERROR_DIRECTORY_NOTEXIST; | ||
| 557 | return false; | ||
| 558 | } | ||
| 559 | return trailingslashit($newPath); | ||
| 560 | } | ||
| 561 | |||
| 562 | |||
| 563 | private function fs() | ||
| 564 | { | ||
| 565 | return emr()->filesystem(); | ||
| 566 | } | ||
| 567 | } |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | use EnableMediaReplace as emr; | ||
| 9 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 10 | |||
| 11 | |||
| 12 | abstract class ViewController | ||
| 13 | { | ||
| 14 | |||
| 15 | abstract function load(); | ||
| 16 | |||
| 17 | |||
| 18 | const ERROR_UPLOAD_PERMISSION = 1; | ||
| 19 | const ERROR_IMAGE_PERMISSION = 2; | ||
| 20 | const ERROR_FORM = 3; | ||
| 21 | const ERROR_TIME = 4; | ||
| 22 | const ERROR_UPDATE_FAILED = 5; | ||
| 23 | const ERROR_SECURITY = 6; | ||
| 24 | const ERROR_UPLOAD_FAILED = 7; | ||
| 25 | const ERROR_NONCE = 8; | ||
| 26 | const ERROR_KEY = 9; // Missing key when replacing backgrounds. | ||
| 27 | |||
| 28 | // These synced with ReplaceController | ||
| 29 | const ERROR_TARGET_EXISTS = 20; | ||
| 30 | const ERROR_DESTINATION_FAIL = 21; | ||
| 31 | const ERROR_COPY_FAILED = 22; | ||
| 32 | const ERROR_UPDATE_POST = 23; | ||
| 33 | const ERROR_DIRECTORY_SECURITY = 24; | ||
| 34 | const ERROR_DIRECTORY_NOTEXIST = 25; | ||
| 35 | |||
| 36 | // Remove Background | ||
| 37 | const ERROR_DOWNLOAD_FAILED = 31; | ||
| 38 | |||
| 39 | protected static $viewsLoaded = array(); | ||
| 40 | |||
| 41 | protected $view; // object to use in the view. | ||
| 42 | protected $url; // if controller is home to a page, sets the URL here. For redirects and what not. | ||
| 43 | |||
| 44 | |||
| 45 | public function __construct() | ||
| 46 | { | ||
| 47 | $this->view = new \stdClass; | ||
| 48 | } | ||
| 49 | |||
| 50 | protected function loadView($template = null, $unique = true) | ||
| 51 | { | ||
| 52 | if (is_null($template) ) | ||
| 53 | { | ||
| 54 | return false; | ||
| 55 | } | ||
| 56 | elseif (strlen(trim($template)) == 0) | ||
| 57 | { | ||
| 58 | return false; | ||
| 59 | } | ||
| 60 | |||
| 61 | $view = $this->view; | ||
| 62 | $controller = $this; | ||
| 63 | $template_path = emr()->plugin_path('views/' . $template . '.php'); | ||
| 64 | |||
| 65 | if (file_exists($template_path) === false) | ||
| 66 | { | ||
| 67 | Log::addError("View $template could not be found in " . $template_path, | ||
| 68 | array('class' => get_class($this))); | ||
| 69 | } | ||
| 70 | elseif ($unique === false || ! in_array($template, self::$viewsLoaded)) | ||
| 71 | { | ||
| 72 | include($template_path); | ||
| 73 | self::$viewsLoaded[] = $template; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | protected function viewError($errorCode, $errorData = array()) | ||
| 78 | { | ||
| 79 | $message = $description = false; | ||
| 80 | switch($errorCode) | ||
| 81 | { | ||
| 82 | case self::ERROR_UPLOAD_PERMISSION: | ||
| 83 | $message = __('You don\'t have permission to upload images. Please refer to your administrator', 'enable-media-replace'); | ||
| 84 | break; | ||
| 85 | case self::ERROR_IMAGE_PERMISSION: | ||
| 86 | $message = __('You don\'t have permission to edit this image', 'enable-media-replace'); | ||
| 87 | break; | ||
| 88 | case self::ERROR_FORM: | ||
| 89 | $message = __('The form submitted is missing various fields', 'enable-media-replace'); | ||
| 90 | break; | ||
| 91 | case self::ERROR_TIME: | ||
| 92 | $message = __('The custom time format submitted is invalid', 'enable-media-replace'); | ||
| 93 | break; | ||
| 94 | case self::ERROR_UPDATE_FAILED: | ||
| 95 | $message = __('Updating the WordPress attachment failed', 'enable-media-replace'); | ||
| 96 | break; | ||
| 97 | case self::ERROR_SECURITY: | ||
| 98 | $message = __('The file upload has been rejected for security reason. WordPress might not allow uploading this extension or filetype', 'enable-media-replace'); | ||
| 99 | break; | ||
| 100 | case self::ERROR_UPLOAD_FAILED: | ||
| 101 | $message = __('The upload from your browser seem to have failed', 'enable-media-replace'); | ||
| 102 | break; | ||
| 103 | case self::ERROR_TARGET_EXISTS: | ||
| 104 | $message = __('The target file already exists in this directory. Please try another name / directory', 'enable-media-replace'); | ||
| 105 | $description = __('This error is shown because you try to move the image to another folder, which already has this file', 'enable-media-replace'); | ||
| 106 | break; | ||
| 107 | case self::ERROR_DESTINATION_FAIL: | ||
| 108 | $message = __('Something went wrong while writing the file or directory', 'enable-media-replace'); | ||
| 109 | break; | ||
| 110 | case self::ERROR_COPY_FAILED: | ||
| 111 | $message = __('Copying replacement file to destination failed', 'enable-media-replace'); | ||
| 112 | break; | ||
| 113 | case self::ERROR_UPDATE_POST: | ||
| 114 | $message = __('Error updating WordPress post in the database', 'enable-media-replace'); | ||
| 115 | break; | ||
| 116 | case self::ERROR_DIRECTORY_SECURITY: | ||
| 117 | $message = __('Specificed directory is outside the upload directory. This is not allowed for security reasons', 'enable-media-replace'); | ||
| 118 | $path = isset($errorData['path']) ? $errorData['path'] : false; | ||
| 119 | $basedir = isset($errorData['basedir']) ? $errorData['basedir'] : false; | ||
| 120 | |||
| 121 | if ($path !== false && $basedir !== false) | ||
| 122 | { | ||
| 123 | $description = sprintf(__('Path: %s is not within basedir reported as: %s', 'shortpixel-image-optimiser'), $path, $basedir); | ||
| 124 | } | ||
| 125 | break; | ||
| 126 | case self::ERROR_DIRECTORY_NOTEXIST: | ||
| 127 | $message = __('Specificed new directory does not exist. Path must be a relative path from the upload directory and exist', 'enable-media-replace'); | ||
| 128 | break; | ||
| 129 | |||
| 130 | case self::ERROR_NONCE: | ||
| 131 | $message = __('Fail to validate form nonce. Please try again', 'enable-media-replace'); | ||
| 132 | $description = __('This can happen when the window is open for a long time and/or there has been a timeout. You can go back to previous screen and try again. If this happens each time when replacing, contact us', 'enable-media-replace'); | ||
| 133 | break; | ||
| 134 | |||
| 135 | // Remove Background | ||
| 136 | case self::ERROR_DOWNLOAD_FAILED: | ||
| 137 | $message = __('Replacement Image could not be downloaded or does not exist', 'enable-media-replace'); | ||
| 138 | break; | ||
| 139 | |||
| 140 | default: | ||
| 141 | $message = __('An unknown error has occured', 'enable-media-replace'); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | |||
| 145 | if( false !== $message) | ||
| 146 | $this->view->errorMessage = $message; | ||
| 147 | |||
| 148 | |||
| 149 | if (false !== $description) | ||
| 150 | { | ||
| 151 | $this->view->errorDescription = $description; | ||
| 152 | } | ||
| 153 | |||
| 154 | |||
| 155 | $this->loadView('error'); | ||
| 156 | exit(); | ||
| 157 | } | ||
| 158 | |||
| 159 | |||
| 160 | protected function viewSuccess() | ||
| 161 | { | ||
| 162 | wp_enqueue_script('emr_success'); | ||
| 163 | $this->loadView('success'); | ||
| 164 | exit(); | ||
| 165 | } | ||
| 166 | |||
| 167 | } |
wp-content/plugins/enable-media-replace/classes/ViewController/RemoveBackgroundViewController.php
0 → 100644
| 1 | <?php | ||
| 2 | |||
| 3 | namespace EnableMediaReplace\ViewController; | ||
| 4 | |||
| 5 | use EnableMediaReplace\Replacer\Libraries\Unserialize\Unserialize; | ||
| 6 | |||
| 7 | |||
| 8 | if (! defined('ABSPATH')) { | ||
| 9 | exit; // Exit if accessed directly. | ||
| 10 | } | ||
| 11 | |||
| 12 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 13 | use EnableMediaReplace\Controller\ReplaceController as ReplaceController; | ||
| 14 | use EnableMediaReplace\Api as Api; | ||
| 15 | |||
| 16 | class RemoveBackGroundViewController extends \EnableMediaReplace\ViewController | ||
| 17 | { | ||
| 18 | static $instance; | ||
| 19 | |||
| 20 | public function __construct() | ||
| 21 | { | ||
| 22 | parent::__construct(); | ||
| 23 | } | ||
| 24 | |||
| 25 | public static function getInstance() | ||
| 26 | { | ||
| 27 | if (is_null(self::$instance)) | ||
| 28 | self::$instance = new RemoveBackgroundViewController(); | ||
| 29 | |||
| 30 | return self::$instance; | ||
| 31 | } | ||
| 32 | |||
| 33 | public function load() | ||
| 34 | { | ||
| 35 | if (!current_user_can('upload_files')) { | ||
| 36 | $this->viewError(self::ERROR_UPLOAD_PERMISSION); | ||
| 37 | // wp_die(esc_html__('You do not have permission to upload files.', 'enable-media-replace')); | ||
| 38 | } | ||
| 39 | |||
| 40 | |||
| 41 | $attachment_id = intval($_REQUEST['attachment_id']); | ||
| 42 | $attachment = get_post($attachment_id); | ||
| 43 | |||
| 44 | $uiHelper = \emr()->uiHelper(); | ||
| 45 | $uiHelper->setPreviewSizes(); | ||
| 46 | $uiHelper->setSourceSizes($attachment_id); | ||
| 47 | |||
| 48 | $replacer = new ReplaceController($attachment_id); | ||
| 49 | $file = $replacer->getSourceFile(true); // for display only | ||
| 50 | |||
| 51 | $defaults = array( | ||
| 52 | 'bg_type' => 'transparent', | ||
| 53 | 'bg_color' => '#ffffff', | ||
| 54 | 'bg_transparency' => 100, | ||
| 55 | ); | ||
| 56 | $settings = get_option('enable_media_replace', $defaults); | ||
| 57 | $settings = array_merge($defaults, $settings); // might miss some | ||
| 58 | |||
| 59 | $this->view->attachment = $attachment; | ||
| 60 | $this->view->settings = $settings; | ||
| 61 | $this->view->sourceFile = $file; | ||
| 62 | |||
| 63 | $this->loadView('prepare-remove-background'); | ||
| 64 | |||
| 65 | } | ||
| 66 | |||
| 67 | // When the background has been posted - process. | ||
| 68 | public function loadPost() | ||
| 69 | { | ||
| 70 | if ( ! isset( $_POST['emr_nonce'] ) | ||
| 71 | || ! wp_verify_nonce( $_POST['emr_nonce'], 'media_remove_background' )) | ||
| 72 | { | ||
| 73 | $this->viewError(self::ERROR_NONCE); | ||
| 74 | } | ||
| 75 | |||
| 76 | $key = isset($_POST['key']) ? sanitize_text_field($_POST['key']) : null; | ||
| 77 | if (is_null($key) || strlen($key) == 0) | ||
| 78 | { | ||
| 79 | $this->viewError(self::ERROR_KEY); | ||
| 80 | //wp_die(esc_html__('Error while sending form (no key). Please try again.', 'enable-media-replace')); | ||
| 81 | } | ||
| 82 | |||
| 83 | $post_id = isset($_POST['ID']) ? intval($_POST['ID']) : null; // sanitize, post_id. | ||
| 84 | if (is_null($post_id)) { | ||
| 85 | $this->viewError(self::ERROR_FORM); | ||
| 86 | // wp_die(esc_html__('Error in request. Please try again', 'enable-media-replace')); | ||
| 87 | } | ||
| 88 | |||
| 89 | $this->setView($post_id); | ||
| 90 | $result = $this->replaceBackground($post_id, $key); | ||
| 91 | |||
| 92 | if (false === $result->success) | ||
| 93 | { | ||
| 94 | $this->view->errorMessage = $result->message; | ||
| 95 | $this->viewError(); | ||
| 96 | } | ||
| 97 | elseif (! file_exists($result->image)) | ||
| 98 | { | ||
| 99 | $this->viewError(self::ERROR_DOWNLOAD_FAILED); | ||
| 100 | } | ||
| 101 | |||
| 102 | // $result = $replacer->replaceWith($result->image, $source->getFileName() , true); | ||
| 103 | //$params = array(); | ||
| 104 | $replaceController = new ReplaceController($post_id); | ||
| 105 | $sourceFile = $replaceController->getSourceFile(); | ||
| 106 | |||
| 107 | $datetime = current_time('mysql'); | ||
| 108 | |||
| 109 | $params = array( | ||
| 110 | 'post_id' => $post_id, | ||
| 111 | 'replace_type' => ReplaceController::MODE_REPLACE, | ||
| 112 | 'timestamp_replace' => ReplaceController::TIME_UPDATEMODIFIED, | ||
| 113 | 'new_date' => $datetime, | ||
| 114 | 'is_custom_date' => false, | ||
| 115 | 'remove_background' => true, | ||
| 116 | 'uploadFile' => $result->image, | ||
| 117 | 'new_filename' => $sourceFile->getFileName(), | ||
| 118 | ); | ||
| 119 | |||
| 120 | |||
| 121 | $check = $replaceController->setupParams($params); | ||
| 122 | $this->setView($post_id, $params); | ||
| 123 | |||
| 124 | if (false === $check) | ||
| 125 | { | ||
| 126 | $error = $replaceController->returnLastError(); | ||
| 127 | $this->viewError($error); | ||
| 128 | } | ||
| 129 | |||
| 130 | $result = $replaceController->run(); | ||
| 131 | if (true == $result) | ||
| 132 | { | ||
| 133 | $this->viewSuccess(); | ||
| 134 | } | ||
| 135 | |||
| 136 | } | ||
| 137 | |||
| 138 | // Low init might only be w/ post_id ( error handling et al ), most advanced / nicer with params. | ||
| 139 | protected function setView($post_id, $params = array()) | ||
| 140 | { | ||
| 141 | $uiHelper = \emr()->uiHelper(); | ||
| 142 | $this->view->post_id = $post_id; | ||
| 143 | $this->view->postUrl = $uiHelper->getSuccesRedirect($post_id); | ||
| 144 | $this->view->emrUrl = $uiHelper->getFailedRedirect($post_id); | ||
| 145 | |||
| 146 | } | ||
| 147 | |||
| 148 | |||
| 149 | protected function replaceBackground($post_id, $key) | ||
| 150 | { | ||
| 151 | $api = new Api(); | ||
| 152 | $result = $api->handleDownload($key); | ||
| 153 | |||
| 154 | return $result; | ||
| 155 | } | ||
| 156 | |||
| 157 | |||
| 158 | |||
| 159 | } // class |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\ViewController; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | use EnableMediaReplace as emr; | ||
| 9 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 10 | use EnableMediaReplace\Controller\ReplaceController as ReplaceController; | ||
| 11 | |||
| 12 | class ReplaceViewController extends \EnableMediaReplace\ViewController | ||
| 13 | { | ||
| 14 | static $instance; | ||
| 15 | |||
| 16 | public function __construct() | ||
| 17 | { | ||
| 18 | parent::__construct(); | ||
| 19 | } | ||
| 20 | |||
| 21 | public static function getInstance() | ||
| 22 | { | ||
| 23 | if (is_null(self::$instance)) | ||
| 24 | self::$instance = new ReplaceViewController(); | ||
| 25 | |||
| 26 | return self::$instance; | ||
| 27 | } | ||
| 28 | |||
| 29 | public function load() | ||
| 30 | { | ||
| 31 | |||
| 32 | $attachment_id = intval($_GET['attachment_id']); | ||
| 33 | $attachment = get_post($attachment_id); | ||
| 34 | |||
| 35 | if (! \emr()->checkImagePermission($attachment)) | ||
| 36 | { | ||
| 37 | $this->viewError(self::ERROR_IMAGE_PERMISSION); | ||
| 38 | wp_die( esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace') ); | ||
| 39 | } | ||
| 40 | |||
| 41 | $replacer = new ReplaceController($attachment_id); | ||
| 42 | |||
| 43 | $file = $replacer->getSourceFile(true); | ||
| 44 | /* $filepath = $file->getFullPath(); | ||
| 45 | $filename = $file->getFileName(); | ||
| 46 | $filetype = $file->getExtension(); */ | ||
| 47 | $source_mime = get_post_mime_type($attachment_id); | ||
| 48 | |||
| 49 | $uiHelper = \emr()->uiHelper(); | ||
| 50 | $uiHelper->setPreviewSizes(); | ||
| 51 | $uiHelper->setSourceSizes($attachment_id); | ||
| 52 | |||
| 53 | $defaults = array( | ||
| 54 | 'replace_type' => 'replace', | ||
| 55 | 'timestamp_replace' => ReplaceController::TIME_UPDATEMODIFIED, | ||
| 56 | 'custom_date' => date("Y-m-d H:i:s"), | ||
| 57 | 'new_location' => false, | ||
| 58 | 'new_location_dir' => false, | ||
| 59 | ); | ||
| 60 | $settings = get_option('enable_media_replace', $defaults); | ||
| 61 | |||
| 62 | $this->view->attachment = $attachment; | ||
| 63 | $this->view->sourceFile = $file; | ||
| 64 | $this->view->sourceMime = $source_mime; | ||
| 65 | $this->view->settings = array_merge($defaults, $settings); // might miss some | ||
| 66 | |||
| 67 | // Indicates if file can be moved to other location. Can't be done when offloaded. | ||
| 68 | $this->view->is_movable = apply_filters('emr/replace/file_is_movable', true, $attachment_id); | ||
| 69 | |||
| 70 | $uploadDir = wp_upload_dir(); | ||
| 71 | $basedir = trailingslashit($uploadDir['basedir']); | ||
| 72 | |||
| 73 | $this->view->custom_basedir = $basedir; | ||
| 74 | |||
| 75 | |||
| 76 | $this->loadView('screen'); | ||
| 77 | |||
| 78 | } | ||
| 79 | |||
| 80 | } |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\ViewController; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | use EnableMediaReplace as emr; | ||
| 9 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 10 | use EnableMediaReplace\Controller\UploadController as UploadController; | ||
| 11 | use EnableMediaReplace\Controller\ReplaceController as ReplaceController; | ||
| 12 | |||
| 13 | |||
| 14 | class UploadViewController extends \EnableMediaReplace\ViewController | ||
| 15 | { | ||
| 16 | static $instance; | ||
| 17 | |||
| 18 | |||
| 19 | public function __construct() | ||
| 20 | { | ||
| 21 | parent::__construct(); | ||
| 22 | } | ||
| 23 | |||
| 24 | public static function getInstance() | ||
| 25 | { | ||
| 26 | if (is_null(self::$instance)) | ||
| 27 | self::$instance = new UploadViewController(); | ||
| 28 | |||
| 29 | return self::$instance; | ||
| 30 | } | ||
| 31 | |||
| 32 | public function load() | ||
| 33 | { | ||
| 34 | |||
| 35 | // No form submit? | ||
| 36 | if (count($_POST) == 0) | ||
| 37 | { | ||
| 38 | $post_id = isset($_REQUEST['attachment_id']) ? intval($_REQUEST['attachment_id']) : null; | ||
| 39 | $this->setView($post_id); | ||
| 40 | |||
| 41 | if (isset($_GET['emr_success'])) | ||
| 42 | { | ||
| 43 | $this->viewSuccess(); | ||
| 44 | } | ||
| 45 | |||
| 46 | } | ||
| 47 | |||
| 48 | if ( ! isset( $_POST['emr_nonce'] ) | ||
| 49 | || ! wp_verify_nonce( $_POST['emr_nonce'], 'media_replace_upload' )) | ||
| 50 | { | ||
| 51 | $this->viewError(self::ERROR_NONCE); | ||
| 52 | } | ||
| 53 | |||
| 54 | if (!current_user_can('upload_files')) { | ||
| 55 | $this->viewError(self::ERROR_UPLOAD_PERMISSION); | ||
| 56 | // wp_die(esc_html__('You do not have permission to upload files.', 'enable-media-replace')); | ||
| 57 | } | ||
| 58 | |||
| 59 | $post_id = isset($_POST['ID']) ? intval($_POST['ID']) : null; // sanitize, post_id. | ||
| 60 | if (is_null($post_id)) { | ||
| 61 | $this->viewError(self::ERROR_FORM); | ||
| 62 | // wp_die(esc_html__('Error in request. Please try again', 'enable-media-replace')); | ||
| 63 | } | ||
| 64 | $attachment = get_post($post_id); | ||
| 65 | |||
| 66 | if (! emr()->checkImagePermission($attachment)) { | ||
| 67 | $this->viewError(self::ERROR_IMAGE_PERMISSION); | ||
| 68 | // wp_die(esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace')); | ||
| 69 | } | ||
| 70 | |||
| 71 | $params = $this->getPost(); | ||
| 72 | |||
| 73 | // UploadController here / replacerController here with save Settings as well? s | ||
| 74 | $this->updateSettings($params); | ||
| 75 | $this->setView($post_id, $params); // set variables needed for view. | ||
| 76 | |||
| 77 | $replaceController = new ReplaceController($post_id); | ||
| 78 | $check = $replaceController->setupParams($params); | ||
| 79 | |||
| 80 | if (false === $check) | ||
| 81 | { | ||
| 82 | $error = $replaceController->returnLastError(); | ||
| 83 | $data = $replaceController->returnLastErrorData(); | ||
| 84 | $this->viewError($error, $data); | ||
| 85 | } | ||
| 86 | |||
| 87 | $result = $replaceController->run(); | ||
| 88 | |||
| 89 | if (true == $result) | ||
| 90 | { | ||
| 91 | $this->viewSuccess(); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | |||
| 96 | protected function getPost() | ||
| 97 | { | ||
| 98 | $ID = intval($_POST["ID"]); // legacy | ||
| 99 | $replace_type = isset($_POST["replace_type"]) ? sanitize_text_field($_POST["replace_type"]) : false; | ||
| 100 | $timestamp_replace = isset($_POST['timestamp_replace']) ? intval($_POST['timestamp_replace']) : ReplaceController::TIME_UPDATEMODIFIED; | ||
| 101 | |||
| 102 | $remove_background = ( isset( $_POST['remove_after_progress'] ) ) ? true : false; | ||
| 103 | |||
| 104 | $do_new_location = isset($_POST['new_location']) ? true : false; | ||
| 105 | $do_new_location = apply_filters('emr/replace/file_is_movable', $do_new_location, $ID); | ||
| 106 | $new_location_dir = isset($_POST['location_dir']) ? sanitize_text_field($_POST['location_dir']) : null; | ||
| 107 | |||
| 108 | $is_custom_date = false; | ||
| 109 | |||
| 110 | switch ($timestamp_replace) { | ||
| 111 | case ReplaceController::TIME_UPDATEALL: | ||
| 112 | case ReplaceController::TIME_UPDATEMODIFIED: | ||
| 113 | $datetime = current_time('mysql'); | ||
| 114 | break; | ||
| 115 | case ReplaceController::TIME_CUSTOM: | ||
| 116 | $custom_date = $_POST['custom_date_formatted']; | ||
| 117 | $custom_hour = str_pad($_POST['custom_hour'], 2, 0, STR_PAD_LEFT); | ||
| 118 | $custom_minute = str_pad($_POST['custom_minute'], 2, 0, STR_PAD_LEFT); | ||
| 119 | |||
| 120 | // create a mysql time representation from what we have. | ||
| 121 | Log::addDebug('Custom Date - ' . $custom_date . ' ' . $custom_hour . ':' . $custom_minute); | ||
| 122 | $custom_date = \DateTime::createFromFormat('Y-m-d G:i', $custom_date . ' ' . $custom_hour . ':' . $custom_minute); | ||
| 123 | if ($custom_date === false) { | ||
| 124 | $this->viewError(self::ERROR_TIME); | ||
| 125 | } | ||
| 126 | $datetime = $custom_date->format("Y-m-d H:i:s"); | ||
| 127 | $is_custom_date = true; | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | |||
| 131 | list($uploadFile, $new_filename) = $this->getUpload(); | ||
| 132 | |||
| 133 | return array( | ||
| 134 | 'post_id' => $ID, | ||
| 135 | 'replace_type' => $replace_type, | ||
| 136 | 'timestamp_replace' => $timestamp_replace, | ||
| 137 | 'new_date' => $datetime, | ||
| 138 | 'new_location' => $do_new_location, | ||
| 139 | 'location_dir' => $new_location_dir, | ||
| 140 | 'is_custom_date' => $is_custom_date, | ||
| 141 | 'remove_background' => $remove_background, | ||
| 142 | 'uploadFile' => $uploadFile, | ||
| 143 | 'new_filename' => $new_filename, | ||
| 144 | ); | ||
| 145 | |||
| 146 | } | ||
| 147 | |||
| 148 | // Low init might only be w/ post_id ( error handling et al ), most advanced / nicer with params. | ||
| 149 | protected function setView($post_id, $params = array()) | ||
| 150 | { | ||
| 151 | $uiHelper = \emr()->uiHelper(); | ||
| 152 | $this->view->post_id = $post_id; | ||
| 153 | $this->view->postUrl = $uiHelper->getSuccesRedirect($post_id); | ||
| 154 | $this->view->emrUrl = $uiHelper->getFailedRedirect($post_id); | ||
| 155 | |||
| 156 | if (isset($params['remove_background']) && true === $params['remove_background']) | ||
| 157 | { | ||
| 158 | $this->view->postUrl = $uiHelper->getBackgroundRemoveRedirect($post_id); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | |||
| 163 | protected function updateSettings($params) | ||
| 164 | { | ||
| 165 | $settings = get_option('enable_media_replace', array()); // save settings and show last loaded. | ||
| 166 | $settings['replace_type'] = $params['replace_type']; | ||
| 167 | $settings['timestamp_replace'] = $params['timestamp_replace']; | ||
| 168 | $settings['new_location'] = $params['new_location']; | ||
| 169 | $settings['new_location_dir'] = $params['location_dir']; | ||
| 170 | |||
| 171 | if (true === $params['is_custom_date']) | ||
| 172 | { | ||
| 173 | $settings['custom_date'] = $params['new_date']; | ||
| 174 | } | ||
| 175 | update_option('enable_media_replace', $settings, false); | ||
| 176 | |||
| 177 | } | ||
| 178 | |||
| 179 | protected function getUpload() | ||
| 180 | { | ||
| 181 | if (is_uploaded_file($_FILES["userfile"]["tmp_name"])) { | ||
| 182 | Log::addDebug('Uploaded Files', $_FILES['userfile']); | ||
| 183 | |||
| 184 | // New method for validating that the uploaded file is allowed, using WP:s internal wp_check_filetype_and_ext() function. | ||
| 185 | $filedata = wp_check_filetype_and_ext($_FILES["userfile"]["tmp_name"], $_FILES["userfile"]["name"]); | ||
| 186 | |||
| 187 | Log::addDebug('Data after check', $filedata); | ||
| 188 | if (isset($_FILES['userfile']['error']) && $_FILES['userfile']['error'] > 0) { | ||
| 189 | //$e = new RunTimeException('File Uploaded Failed'); | ||
| 190 | //Notices::addError($e->getMessage()); | ||
| 191 | // wp_safe_redirect($redirect_error); | ||
| 192 | $this->viewError(self::ERROR_UPDATE_FAILED); | ||
| 193 | // exit(); | ||
| 194 | } | ||
| 195 | |||
| 196 | if ($filedata["ext"] == false && ! current_user_can('unfiltered_upload')) { | ||
| 197 | $this->viewError(self::ERROR_SECURITY); | ||
| 198 | } | ||
| 199 | |||
| 200 | // Here we have the uploaded file | ||
| 201 | $new_filename = $_FILES["userfile"]["name"]; | ||
| 202 | $new_filetype = $filedata["type"] ? $filedata["type"] : $_FILES['userfile']['type']; | ||
| 203 | |||
| 204 | return array($_FILES["userfile"]["tmp_name"], $new_filename); | ||
| 205 | // Execute hook actions - thanks rubious for the suggestion! | ||
| 206 | } | ||
| 207 | $this->viewError(self::ERROR_UPLOAD_FAILED); | ||
| 208 | } | ||
| 209 | |||
| 210 | |||
| 211 | |||
| 212 | |||
| 213 | } // class |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace; | ||
| 3 | |||
| 4 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 5 | use EnableMediaReplace\Api as Api; | ||
| 6 | |||
| 7 | class Ajax { | ||
| 8 | public function __construct() { | ||
| 9 | $endpoints = array( | ||
| 10 | 'remove_background', | ||
| 11 | |||
| 12 | ); | ||
| 13 | foreach ( $endpoints as $action ) { | ||
| 14 | add_action( "wp_ajax_emr_{$action}", array( $this, $action ) ); | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | public function remove_background() { | ||
| 19 | if ( $this->check_nonce() ) { | ||
| 20 | $api = new Api; | ||
| 21 | $response = $api->request( $_POST ); | ||
| 22 | wp_send_json($response); | ||
| 23 | } | ||
| 24 | else { | ||
| 25 | die('Wrong nonce'); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | private function check_nonce() { | ||
| 30 | $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | ||
| 31 | $action = isset( $_POST['action'] ) ? sanitize_text_field( $_POST['action'] ) : ''; | ||
| 32 | return wp_verify_nonce( $nonce, $action ); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | |||
| 37 | new Ajax(); |
| 1 | <?php | ||
| 2 | /** | ||
| 3 | * This page contains api class. | ||
| 4 | */ | ||
| 5 | namespace EnableMediaReplace; | ||
| 6 | |||
| 7 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 8 | use EnableMediaReplace\Controller\ReplaceController as ReplaceController; | ||
| 9 | |||
| 10 | |||
| 11 | use Exception; | ||
| 12 | use stdClass; | ||
| 13 | /** | ||
| 14 | * This class contains api methods | ||
| 15 | */ | ||
| 16 | class Api { | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Request Counter | ||
| 20 | * | ||
| 21 | * @var int $counter | ||
| 22 | */ | ||
| 23 | private $counter = 0; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * ShortPixel api url | ||
| 27 | * | ||
| 28 | * @var string $url | ||
| 29 | */ | ||
| 30 | private $url = 'http://api.shortpixel.com/v2/free-reducer.php'; | ||
| 31 | |||
| 32 | /** | ||
| 33 | * ShortPixel api request headers | ||
| 34 | * | ||
| 35 | * @var array $headers | ||
| 36 | */ | ||
| 37 | private $headers = array( | ||
| 38 | 'Content-Type: application/json', | ||
| 39 | 'Accept: application/json', | ||
| 40 | ); | ||
| 41 | |||
| 42 | private $refresh = true; // only first request should be fresh | ||
| 43 | |||
| 44 | |||
| 45 | |||
| 46 | public function __construct() | ||
| 47 | { | ||
| 48 | |||
| 49 | } | ||
| 50 | /** | ||
| 51 | * Create ShortPixel api request | ||
| 52 | * | ||
| 53 | * @param array $data | ||
| 54 | * @return stdClass $result | ||
| 55 | */ | ||
| 56 | public function request( array $posted_data ) { | ||
| 57 | $bg_remove = '1'; | ||
| 58 | $compression_level = 0; // intval($posted_data['compression_level']); // off for now. | ||
| 59 | |||
| 60 | $attachment_id = isset($_POST['attachment_id']) ? intval($_POST['attachment_id']) : null; | ||
| 61 | $attachment = get_post($attachment_id); | ||
| 62 | |||
| 63 | |||
| 64 | if (is_null($attachment_id)) | ||
| 65 | { | ||
| 66 | $result = $this->getResponseObject(); | ||
| 67 | $result->success = false; | ||
| 68 | $result->message = __('No attachment ID given', 'enable-media-replace'); | ||
| 69 | return $result; | ||
| 70 | } | ||
| 71 | |||
| 72 | if (! emr()->checkImagePermission($attachment)) { | ||
| 73 | $result = $this->getResponseObject(); | ||
| 74 | $result->success = false; | ||
| 75 | $result->message = __('No permission for user', 'enable-media-replace'); | ||
| 76 | return $result; | ||
| 77 | } | ||
| 78 | |||
| 79 | $replaceController = new ReplaceController($attachment_id); | ||
| 80 | $url = $replaceController->getSourceUrl(); | ||
| 81 | |||
| 82 | $settings = get_option('enable_media_replace', array()); // save settings and show last loaded. | ||
| 83 | $settings['bg_type'] = isset($_POST['background']['type']) ? sanitize_text_field($_POST['background']['type']) : false; | ||
| 84 | $settings['bg_color'] = isset($_POST['background']['color']) ? sanitize_text_field($_POST['background']['color']) : '#ffffff'; // default to white. | ||
| 85 | $settings['bg_transparency'] = isset($_POST['background']['transparency']) ? sanitize_text_field($_POST['background']['transparency']) : false; | ||
| 86 | |||
| 87 | update_option('enable_media_replace', $settings, false); | ||
| 88 | |||
| 89 | |||
| 90 | if ( 'solid' === $posted_data['background']['type'] ) { | ||
| 91 | $bg_remove = $posted_data['background']['color']; | ||
| 92 | |||
| 93 | $transparency = isset($posted_data['background']['transparency']) ? intval($posted_data['background']['transparency']) : -1; | ||
| 94 | // if transparancy without acceptable boundaries, add it to color ( as rgba I presume ) | ||
| 95 | if ($transparency >= 0 && $transparency < 100) | ||
| 96 | { | ||
| 97 | if ($transparency == 100) | ||
| 98 | $transparency = 'FF'; | ||
| 99 | |||
| 100 | // Strpad for lower than 10 should add 09, 08 etc. | ||
| 101 | $bg_remove .= str_pad($transparency, 2, '0', STR_PAD_LEFT); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | |||
| 106 | |||
| 107 | $data = array( | ||
| 108 | 'plugin_version' => EMR_VERSION, | ||
| 109 | 'bg_remove' => $bg_remove, | ||
| 110 | 'urllist' => array( urlencode( esc_url($url) ) ), | ||
| 111 | 'lossy' => $compression_level, | ||
| 112 | 'refresh' => $this->refresh, | ||
| 113 | ); | ||
| 114 | |||
| 115 | $request = array( | ||
| 116 | 'method' => 'POST', | ||
| 117 | 'timeout' => 60, | ||
| 118 | 'headers' => $this->headers, | ||
| 119 | 'body' => json_encode( $data ), | ||
| 120 | |||
| 121 | ); | ||
| 122 | |||
| 123 | $settingsData = ''; | ||
| 124 | //unset($settingsData['url']); | ||
| 125 | |||
| 126 | foreach($data as $key => $val) | ||
| 127 | { | ||
| 128 | if ($key == 'urllist' || $key == 'refresh') | ||
| 129 | { | ||
| 130 | continue; | ||
| 131 | } | ||
| 132 | $settingsData .= " $key:$val "; | ||
| 133 | } | ||
| 134 | |||
| 135 | |||
| 136 | //we need to wait a bit until we try to check if the image is ready | ||
| 137 | if ($this->counter > 0) | ||
| 138 | sleep( $this->counter + 3 ); | ||
| 139 | |||
| 140 | $this->counter++; | ||
| 141 | |||
| 142 | $result = $this->getResponseObject(); | ||
| 143 | |||
| 144 | if ( $this->counter < 10 ) { | ||
| 145 | try { | ||
| 146 | |||
| 147 | Log::addDebug('Sending request', $request); | ||
| 148 | $response = wp_remote_post( $this->url, $request ); | ||
| 149 | |||
| 150 | $this->refresh = false; | ||
| 151 | |||
| 152 | if ( is_wp_error( $response ) ) { | ||
| 153 | $result->message = $response->get_error_message(); | ||
| 154 | } else { | ||
| 155 | |||
| 156 | $json = json_decode( $response['body'] ); | ||
| 157 | |||
| 158 | Log::addDebug('Response Json', $json); | ||
| 159 | if ( is_array( $json ) && '2' === $json[0]->Status->Code ) { | ||
| 160 | $result->success = true; | ||
| 161 | |||
| 162 | if ( '1' === $compression_level || '2' === $compression_level ) { | ||
| 163 | $result->image = $json[0]->LossyURL; | ||
| 164 | } else { | ||
| 165 | $result->image = $json[0]->LosslessURL; | ||
| 166 | } | ||
| 167 | |||
| 168 | $key = $this->handleSuccess($result); | ||
| 169 | $result->key = $key; | ||
| 170 | $result->url = $url; | ||
| 171 | $result->image = add_query_arg('ts', time(), $result->image); | ||
| 172 | |||
| 173 | $result->settings = $settingsData; | ||
| 174 | |||
| 175 | // $this->handleSuccess($result); | ||
| 176 | } elseif ( is_array( $json ) && '1' === $json[0]->Status->Code ) { | ||
| 177 | return $this->request( $posted_data ); | ||
| 178 | } else { | ||
| 179 | if (is_array($json)) | ||
| 180 | { | ||
| 181 | $result->message = $json[0]->Status->Message; | ||
| 182 | } | ||
| 183 | elseif (is_object($json) && property_exists($json, 'Status')) | ||
| 184 | { | ||
| 185 | $result->message = $json->Status->Message; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } | ||
| 189 | } catch ( Exception $e ) { | ||
| 190 | $result->message = $e->getMessage(); | ||
| 191 | } | ||
| 192 | } else { | ||
| 193 | $result->message = __( 'The background could not be removed in a reasonable amount of time. The file might be too big, or the API could be busy. Please try again later!', 'enable-media-replace' ); | ||
| 194 | } | ||
| 195 | |||
| 196 | return $result; | ||
| 197 | } | ||
| 198 | |||
| 199 | public function handleSuccess($result) | ||
| 200 | { | ||
| 201 | // $fs = emr()->filesystem(); | ||
| 202 | // $result = $fs->downloadFile($result->image, wp_tempnam($result->image)); | ||
| 203 | $nonce = isset($_POST['nonce']) ? sanitize_text_field($_POST['nonce']) : wp_create_nonce(); | ||
| 204 | $key = wp_hash($nonce . $result->image, 'logged_in'); | ||
| 205 | |||
| 206 | set_transient('emr_' . $key, $result->image, 30 * MINUTE_IN_SECONDS); | ||
| 207 | return $key; | ||
| 208 | } | ||
| 209 | |||
| 210 | public function handleDownload($key) | ||
| 211 | { | ||
| 212 | $url = get_transient('emr_' . $key); | ||
| 213 | $result = $this->getResponseObject(); | ||
| 214 | |||
| 215 | if ($url === false) | ||
| 216 | { | ||
| 217 | $result->message = __('This file seems not available anymore. Please try again', 'enable-media-replace'); | ||
| 218 | return $result; | ||
| 219 | } | ||
| 220 | |||
| 221 | $fs = emr()->filesystem(); | ||
| 222 | $target = wp_tempnam($url); | ||
| 223 | |||
| 224 | $bool = $fs->downloadFile($url, $target); | ||
| 225 | |||
| 226 | if ($bool === false) | ||
| 227 | { | ||
| 228 | $result->message = __('Download failed', 'enable-media-replace'); | ||
| 229 | } | ||
| 230 | else { | ||
| 231 | $result->success = true; | ||
| 232 | $result->image = $target; | ||
| 233 | } | ||
| 234 | return $result; | ||
| 235 | } | ||
| 236 | |||
| 237 | protected function getResponseObject() | ||
| 238 | { | ||
| 239 | $result = new stdClass; | ||
| 240 | $result->success = false; | ||
| 241 | $result->image = null; | ||
| 242 | $result->message = null; | ||
| 243 | |||
| 244 | return $result; | ||
| 245 | } | ||
| 246 | |||
| 247 | } |
| 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 ($args['flush_mode'] === 'post' && $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 | |||
| 4 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 5 | use EnableMediaReplace\Notices\NoticeController as Notices; | ||
| 6 | use EnableMediaReplace\FileSystem\Controller\FileSystemController as FileSystem; | ||
| 7 | use EnableMediaReplace\Controller\RemoteNoticeController as RemoteNoticeController; | ||
| 8 | use EnableMediaReplace\Ajax; | ||
| 9 | |||
| 10 | // Does what a plugin does. | ||
| 11 | class EnableMediaReplacePlugin | ||
| 12 | { | ||
| 13 | |||
| 14 | protected $plugin_path; | ||
| 15 | private static $instance; | ||
| 16 | |||
| 17 | private $user_cap = false; | ||
| 18 | private $general_cap = false; | ||
| 19 | |||
| 20 | private $features = array(); | ||
| 21 | |||
| 22 | public function __construct() | ||
| 23 | { | ||
| 24 | add_action('plugins_loaded', array($this, 'runtime')); //lowInit, before theme setup! | ||
| 25 | add_action('admin_init', array($this, 'adminInit')); // adminInit, after functions.php | ||
| 26 | } | ||
| 27 | |||
| 28 | public function runtime() | ||
| 29 | { | ||
| 30 | $this->nopriv_plugin_actions(); | ||
| 31 | |||
| 32 | if (EMR_CAPABILITY !== false) { | ||
| 33 | if (is_array(EMR_CAPABILITY)) { | ||
| 34 | $this->general_cap = EMR_CAPABILITY[0]; | ||
| 35 | $this->user_cap = EMR_CAPABILITY[1]; | ||
| 36 | |||
| 37 | if (! current_user_can($this->general_cap) && ! current_user_can($this->user_cap)) { | ||
| 38 | return; | ||
| 39 | } | ||
| 40 | } else { | ||
| 41 | $this->general_cap = EMR_CAPABILITY; | ||
| 42 | if (! current_user_can($this->general_cap)) { | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } elseif (! current_user_can('upload_files')) { | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | |||
| 50 | new Externals(); | ||
| 51 | |||
| 52 | $this->plugin_actions(); // init | ||
| 53 | } | ||
| 54 | |||
| 55 | public function adminInit() | ||
| 56 | { | ||
| 57 | $this->features['replace'] = true; // does nothing just for completeness | ||
| 58 | $this->features['background'] = apply_filters('emr/feature/background', true); | ||
| 59 | |||
| 60 | load_plugin_textdomain('enable-media-replace', false, basename(dirname(EMR_ROOT_FILE)) . '/languages'); | ||
| 61 | |||
| 62 | // Load Submodules | ||
| 63 | new Ajax(); | ||
| 64 | } | ||
| 65 | |||
| 66 | public function filesystem() | ||
| 67 | { | ||
| 68 | return new FileSystem(); | ||
| 69 | } | ||
| 70 | |||
| 71 | public function uiHelper() | ||
| 72 | { | ||
| 73 | return Uihelper::getInstance(); | ||
| 74 | } | ||
| 75 | |||
| 76 | public function useFeature($name) | ||
| 77 | { | ||
| 78 | // If for some obscure reason, it's called earlier or out of admin, still load the features. | ||
| 79 | if (count($this->features) === 0) | ||
| 80 | { | ||
| 81 | $this->adminInit(); | ||
| 82 | } | ||
| 83 | |||
| 84 | switch($name) | ||
| 85 | { | ||
| 86 | case 'background': | ||
| 87 | $bool = $this->features['background']; | ||
| 88 | break; | ||
| 89 | default: | ||
| 90 | $bool = false; | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | return $bool; | ||
| 94 | } | ||
| 95 | |||
| 96 | public static function get() | ||
| 97 | { | ||
| 98 | if (is_null(self::$instance)) { | ||
| 99 | self::$instance = new EnableMediaReplacePlugin(); | ||
| 100 | } | ||
| 101 | |||
| 102 | $log = Log::getInstance(); | ||
| 103 | if (Log::debugIsActive()) { | ||
| 104 | $uploaddir = wp_upload_dir(null, false, false); | ||
| 105 | if (isset($uploaddir['basedir'])) { | ||
| 106 | $log->setLogPath( trailingslashit($uploaddir['basedir']) . "emr_log"); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | return self::$instance; | ||
| 110 | } | ||
| 111 | |||
| 112 | // Actions for EMR that always need to hook | ||
| 113 | protected function nopriv_plugin_actions() | ||
| 114 | { | ||
| 115 | // shortcode | ||
| 116 | add_shortcode('file_modified', array($this, 'get_modified_date')); | ||
| 117 | } | ||
| 118 | |||
| 119 | |||
| 120 | public function plugin_actions() | ||
| 121 | { | ||
| 122 | $this->plugin_path = plugin_dir_path(EMR_ROOT_FILE); | ||
| 123 | //$this->plugin_url = plugin_dir_url(EMR_ROOT_FILE); | ||
| 124 | |||
| 125 | // loads the dismiss hook. | ||
| 126 | $notices = Notices::getInstance(); | ||
| 127 | |||
| 128 | // init plugin | ||
| 129 | add_action('admin_menu', array($this,'menu')); | ||
| 130 | add_action('submenu_file', array($this, 'hide_sub_menu')); | ||
| 131 | |||
| 132 | add_action( 'current_screen', array($this, 'setScreen') ); // annoying workaround for notices in edit-attachment screen | ||
| 133 | add_action('admin_enqueue_scripts', array($this,'admin_scripts')); | ||
| 134 | |||
| 135 | |||
| 136 | // content filters | ||
| 137 | add_filter('media_row_actions', array($this,'add_media_action'), 10, 2); | ||
| 138 | add_action('attachment_submitbox_misc_actions', array($this,'admin_date_replaced_media_on_edit_media_screen'), 91); | ||
| 139 | //add_filter('upload_mimes', array($this,'add_mime_types'), 1, 1); | ||
| 140 | |||
| 141 | // notices | ||
| 142 | |||
| 143 | // editors | ||
| 144 | add_action('add_meta_boxes_attachment', array($this, 'add_meta_boxes'), 10, 2); | ||
| 145 | add_filter('attachment_fields_to_edit', array($this, 'attachment_editor'), 10, 2); | ||
| 146 | |||
| 147 | /** Just after an image is replaced, try to browser decache the images */ | ||
| 148 | if (isset($_GET['emr_replaced']) && intval($_GET['emr_replaced'] == 1)) { | ||
| 149 | add_filter('wp_get_attachment_image_src', array($this, 'attempt_uncache_image'), 10, 4); | ||
| 150 | |||
| 151 | // adds a metabox to list thumbnails. This is a cache reset hidden as feature. | ||
| 152 | //add_action( 'add_meta_boxes', function () { ); | ||
| 153 | add_filter('postbox_classes_attachment_emr-showthumbs-box', function ($classes) { | ||
| 154 | $classes[] = 'closed'; | ||
| 155 | return $classes; | ||
| 156 | }); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | /** | ||
| 161 | * Register this file in WordPress so we can call it with a ?page= GET var. | ||
| 162 | * To suppress it in the menu we give it an empty menu title. | ||
| 163 | */ | ||
| 164 | public function menu() | ||
| 165 | { | ||
| 166 | $title = esc_html__("Replace media", "enable-media-replace"); | ||
| 167 | $title = (isset($_REQUEST['action']) && ($_REQUEST['action'] === 'emr_prepare_remove')) ? esc_html__("Remove background", "enable-media-replace") : $title; | ||
| 168 | add_submenu_page('upload.php',$title, $title, 'upload_files', 'enable-media-replace/enable-media-replace.php', array($this, 'route')); | ||
| 169 | |||
| 170 | } | ||
| 171 | |||
| 172 | public function hide_sub_menu($submenu_file) | ||
| 173 | { | ||
| 174 | global $plugin_page; | ||
| 175 | // Select another submenu item to highlight (optional). | ||
| 176 | if ( $plugin_page && $plugin_page == 'enable-media-replace/enable-media-replace.php' ) { | ||
| 177 | $submenu_file = 'upload.php'; | ||
| 178 | } | ||
| 179 | |||
| 180 | // Hide the submenu. | ||
| 181 | |||
| 182 | remove_submenu_page( 'upload.php', 'enable-media-replace/enable-media-replace.php' ); | ||
| 183 | |||
| 184 | return $submenu_file; | ||
| 185 | } | ||
| 186 | |||
| 187 | |||
| 188 | public function setScreen() | ||
| 189 | { | ||
| 190 | $screen = get_current_screen(); | ||
| 191 | |||
| 192 | $notice_pages = array('attachment', 'media_page_enable-media-replace/enable-media-replace', 'upload' ); | ||
| 193 | if ( in_array($screen->id, $notice_pages) && true === emr()->useFeature('background')) | ||
| 194 | { | ||
| 195 | |||
| 196 | RemoteNoticeController::getInstance(); // check for remote stuff | ||
| 197 | $notices = Notices::getInstance(); | ||
| 198 | $notices->loadIcons(array( | ||
| 199 | 'normal' => '<img class="emr-notice-icon" src="' . plugins_url('img/notices/slider.png', EMR_ROOT_FILE) . '">', | ||
| 200 | 'success' => '<img class="emr-notice-icon" src="' . plugins_url('img/notices/robo-cool.png', EMR_ROOT_FILE) . '">', | ||
| 201 | 'warning' => '<img class="emr-notice-icon" src="' . plugins_url('img/notices/robo-scared.png', EMR_ROOT_FILE) . '">', | ||
| 202 | 'error' => '<img class="emr-notice-icon" src="' . plugins_url('img/notices/robo-scared.png', EMR_ROOT_FILE) . '">', | ||
| 203 | )); | ||
| 204 | |||
| 205 | add_action('admin_notices', array($notices, 'admin_notices')); // previous page / init time | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | /** Load EMR views based on request */ | ||
| 210 | public function route() | ||
| 211 | { | ||
| 212 | global $plugin_page; | ||
| 213 | switch ($plugin_page) { | ||
| 214 | case 'enable-media-replace/enable-media-replace.php': | ||
| 215 | $action = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : ''; | ||
| 216 | wp_enqueue_style('emr_style'); | ||
| 217 | wp_enqueue_script('jquery-ui-datepicker'); | ||
| 218 | wp_enqueue_style('jquery-ui-datepicker'); | ||
| 219 | wp_enqueue_script('emr_admin'); | ||
| 220 | |||
| 221 | $this->uiHelper()->featureNotice(); | ||
| 222 | |||
| 223 | if ($action == 'media_replace') { | ||
| 224 | if (array_key_exists("attachment_id", $_GET) && intval($_GET["attachment_id"]) > 0) { | ||
| 225 | wp_enqueue_script('emr_upsell'); | ||
| 226 | |||
| 227 | $controller = \EnableMediaReplace\ViewController\ReplaceViewController::getInstance(); | ||
| 228 | $controller->load(); | ||
| 229 | // require_once($this->plugin_path . "views/popup.php"); // warning variables like $action be overwritten here. | ||
| 230 | } | ||
| 231 | } | ||
| 232 | elseif ($action == 'media_replace_upload') { | ||
| 233 | |||
| 234 | $controller = \EnableMediaReplace\ViewController\UploadViewController::getInstance(); | ||
| 235 | $controller->load(); | ||
| 236 | // require_once($this->plugin_path . 'views/upload.php'); | ||
| 237 | } | ||
| 238 | elseif ('emr_prepare_remove' === $action && $this->useFeature('background')) { | ||
| 239 | // $attachment_id = intval($_GET['attachment_id']); | ||
| 240 | // $attachment = get_post($attachment_id); | ||
| 241 | //We're adding a timestamp to the image URL for cache busting | ||
| 242 | |||
| 243 | wp_enqueue_script('emr_remove_bg'); | ||
| 244 | |||
| 245 | wp_enqueue_style('emr_style'); | ||
| 246 | wp_enqueue_style('emr-remove-background'); | ||
| 247 | wp_enqueue_script('emr_upsell'); | ||
| 248 | |||
| 249 | $controller = \EnableMediaReplace\ViewController\RemoveBackgroundViewController::getInstance(); | ||
| 250 | $controller->load(); | ||
| 251 | |||
| 252 | // require_once($this->plugin_path . "views/prepare-remove-background.php"); | ||
| 253 | |||
| 254 | } elseif ('do_background_replace' === $action && | ||
| 255 | $this->useFeature('background') | ||
| 256 | ) { | ||
| 257 | $controller = \EnableMediaReplace\ViewController\RemoveBackgroundViewController::getInstance(); | ||
| 258 | $controller->loadPost(); | ||
| 259 | |||
| 260 | // require_once($this->plugin_path . 'views/do-replace-background.php'); | ||
| 261 | } | ||
| 262 | else { | ||
| 263 | |||
| 264 | exit('Something went wrong loading page, please try again'); | ||
| 265 | } | ||
| 266 | break; | ||
| 267 | } // Route | ||
| 268 | } | ||
| 269 | |||
| 270 | public function getPluginURL($path = '') | ||
| 271 | { | ||
| 272 | return plugins_url($path, EMR_ROOT_FILE); | ||
| 273 | } | ||
| 274 | |||
| 275 | public function plugin_path($path = '') | ||
| 276 | { | ||
| 277 | $plugin_path = trailingslashit(plugin_dir_path(EMR_ROOT_FILE)); | ||
| 278 | if ( strlen( $path ) > 0 ) { | ||
| 279 | $plugin_path .= $path; | ||
| 280 | } | ||
| 281 | return $plugin_path; | ||
| 282 | } | ||
| 283 | |||
| 284 | /** register styles and scripts | ||
| 285 | * | ||
| 286 | * Nothing should ever by -enqueued- here, just registered. | ||
| 287 | */ | ||
| 288 | public function admin_scripts() | ||
| 289 | { | ||
| 290 | if (is_rtl()) { | ||
| 291 | wp_register_style('emr_style', plugins_url('css/admin.rtl.css', EMR_ROOT_FILE)); | ||
| 292 | } else { | ||
| 293 | wp_register_style('emr_style', plugins_url('css/admin.css', EMR_ROOT_FILE)); | ||
| 294 | } | ||
| 295 | |||
| 296 | wp_register_style('emr_edit-attachment', plugins_url('css/edit_attachment.css', EMR_ROOT_FILE)); | ||
| 297 | |||
| 298 | wp_register_style('emr-remove-background', plugins_url('css/remove_background.css', EMR_ROOT_FILE)); | ||
| 299 | |||
| 300 | $mimes = array_values(get_allowed_mime_types()); | ||
| 301 | |||
| 302 | wp_register_script('emr_admin', plugins_url('js/emr_admin.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true); | ||
| 303 | $emr_options = array( | ||
| 304 | 'dateFormat' => $this->convertdate(get_option('date_format')), | ||
| 305 | 'maxfilesize' => wp_max_upload_size(), | ||
| 306 | 'allowed_mime' => $mimes, | ||
| 307 | ); | ||
| 308 | |||
| 309 | wp_register_script('emr_upsell', plugins_url('js/upsell.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true); | ||
| 310 | |||
| 311 | wp_localize_script('emr_upsell', 'emr_upsell', array( | ||
| 312 | 'ajax' => admin_url('admin-ajax.php'), | ||
| 313 | 'installing' => __('Installing ...', 'enable-media-replace'), | ||
| 314 | |||
| 315 | )); | ||
| 316 | |||
| 317 | $ts = time(); | ||
| 318 | $ajax_url = admin_url('admin-ajax.php'); | ||
| 319 | |||
| 320 | |||
| 321 | wp_register_script('emr_remove_bg', plugins_url('js/remove_bg.js', EMR_ROOT_FILE), array('jquery'), EMR_VERSION, true); | ||
| 322 | wp_localize_script('emr_remove_bg', 'emrObject', array( | ||
| 323 | 'ajax_url' => $ajax_url, | ||
| 324 | 'nonce' => wp_create_nonce('emr_remove_background') | ||
| 325 | )); | ||
| 326 | |||
| 327 | |||
| 328 | if (Log::debugIsActive()) { | ||
| 329 | $emr_options['is_debug'] = true; | ||
| 330 | } | ||
| 331 | |||
| 332 | wp_localize_script('emr_admin', 'emr_options', $emr_options); | ||
| 333 | |||
| 334 | wp_register_script('emr_success', plugins_url('js/emr_success.js', EMR_ROOT_FILE), array(), EMR_VERSION, true); | ||
| 335 | |||
| 336 | wp_localize_script('emr_success', 'emr_success_options', array( | ||
| 337 | 'timeout' => apply_filters('emr/success/timeout', 5), | ||
| 338 | )); | ||
| 339 | } | ||
| 340 | |||
| 341 | /** Utility function for the Jquery UI Datepicker */ | ||
| 342 | public function convertdate($sFormat) | ||
| 343 | { | ||
| 344 | switch ($sFormat) { | ||
| 345 | //Predefined WP date formats | ||
| 346 | case 'F j, Y': | ||
| 347 | return( 'MM dd, yy' ); | ||
| 348 | break; | ||
| 349 | case 'Y/m/d': | ||
| 350 | return( 'yy/mm/dd' ); | ||
| 351 | break; | ||
| 352 | case 'm/d/Y': | ||
| 353 | return( 'mm/dd/yy' ); | ||
| 354 | break; | ||
| 355 | case 'd/m/Y': | ||
| 356 | default: | ||
| 357 | return( 'dd/mm/yy' ); | ||
| 358 | break; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | public function checkImagePermission($post) | ||
| 363 | { | ||
| 364 | if (! is_object($post)) | ||
| 365 | { | ||
| 366 | return false; | ||
| 367 | } | ||
| 368 | $post_id = $post->ID; | ||
| 369 | $post_type = $post->post_type; | ||
| 370 | $author_id = $post->post_author; | ||
| 371 | |||
| 372 | if ($post_type !== 'attachment') | ||
| 373 | return false; | ||
| 374 | |||
| 375 | if (is_null($post_id) || intval($post_id) >! 0) | ||
| 376 | { | ||
| 377 | return false; | ||
| 378 | } | ||
| 379 | |||
| 380 | if ($this->general_cap === false && $this->user_cap === false) { | ||
| 381 | if (current_user_can('edit_post', $post_id) === true) { | ||
| 382 | return true; | ||
| 383 | } | ||
| 384 | } elseif (current_user_can($this->general_cap)) { | ||
| 385 | return true; | ||
| 386 | } elseif (current_user_can($this->user_cap) && $author_id == get_current_user_id()) { | ||
| 387 | return true; | ||
| 388 | } | ||
| 389 | |||
| 390 | return false; | ||
| 391 | } | ||
| 392 | |||
| 393 | /** Get the URL to the media replace page | ||
| 394 | * @param $attach_id The attachment ID to replace | ||
| 395 | * @return Admin URL to the page. | ||
| 396 | */ | ||
| 397 | protected function getMediaReplaceURL($attach_id) | ||
| 398 | { | ||
| 399 | $url = admin_url("upload.php"); | ||
| 400 | $url = add_query_arg(array( | ||
| 401 | 'page' => 'enable-media-replace/enable-media-replace.php', | ||
| 402 | 'action' => 'media_replace', | ||
| 403 | 'attachment_id' => $attach_id, | ||
| 404 | ), $url); | ||
| 405 | |||
| 406 | return $url; | ||
| 407 | } | ||
| 408 | |||
| 409 | protected function getRemoveBgURL($attach_id) | ||
| 410 | { | ||
| 411 | $url = admin_url("upload.php"); | ||
| 412 | $url = add_query_arg(array( | ||
| 413 | 'page' => 'enable-media-replace/enable-media-replace.php', | ||
| 414 | 'action' => 'emr_prepare_remove', | ||
| 415 | 'attachment_id' => $attach_id, | ||
| 416 | ), $url); | ||
| 417 | |||
| 418 | return $url; | ||
| 419 | } | ||
| 420 | |||
| 421 | public function add_meta_boxes($post) | ||
| 422 | { | ||
| 423 | // Because some plugins don't like to play by the rules. | ||
| 424 | if (is_null($post) || ! is_object($post) ) { | ||
| 425 | return false; | ||
| 426 | } | ||
| 427 | |||
| 428 | if (! $this->checkImagePermission($post)) { | ||
| 429 | return; | ||
| 430 | } | ||
| 431 | |||
| 432 | add_meta_box('emr-replace-box', __('Replace Media', 'enable-media-replace'), array($this, 'replace_meta_box'), 'attachment', 'side', 'low'); | ||
| 433 | |||
| 434 | if (isset($_GET['emr_replaced']) && intval($_GET['emr_replaced'] == 1)) { | ||
| 435 | add_meta_box('emr-showthumbs-box', __('Replaced Thumbnails Preview', 'enable-media-replace'), array($this, 'show_thumbs_box'), 'attachment', 'side', 'low'); | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | public function replace_meta_box($post) | ||
| 440 | { | ||
| 441 | |||
| 442 | //Replace media button | ||
| 443 | $replace_url = $this->getMediaReplaceURL($post->ID); | ||
| 444 | |||
| 445 | $replace_action = "media_replace"; | ||
| 446 | $replace_editurl = wp_nonce_url($replace_url, $replace_action); | ||
| 447 | |||
| 448 | $replace_link = "href=\"$replace_editurl\""; | ||
| 449 | |||
| 450 | echo "<p><a class='button-secondary' $replace_link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a></p><p>" . esc_html__("To replace the current file, click the link and upload a replacement file.", "enable-media-replace") . "</p>"; | ||
| 451 | //Remove background button | ||
| 452 | $removeBg_url = $this->getRemoveBgURL($post->ID); | ||
| 453 | |||
| 454 | $removeBg_action = "emr_prepare_remove"; | ||
| 455 | $removeBg_editurl = wp_nonce_url($removeBg_url, $removeBg_action); | ||
| 456 | |||
| 457 | $removeBg_link = "href=\"$removeBg_editurl\""; | ||
| 458 | |||
| 459 | if ($this->uiHelper()->isBackgroundRemovable($post)) | ||
| 460 | { | ||
| 461 | echo "<p><a class='button-secondary' $removeBg_link>" . esc_html__("Remove background", "enable-media-replace") . "</a></p><p>" . esc_html__("To remove the background, click the link and select the options.", "enable-media-replace") . "</p>"; | ||
| 462 | } | ||
| 463 | } | ||
| 464 | |||
| 465 | public function show_thumbs_box($post) | ||
| 466 | { | ||
| 467 | if (! $this->checkImagePermission($post)) { | ||
| 468 | return; | ||
| 469 | } | ||
| 470 | |||
| 471 | wp_enqueue_style('emr_edit-attachment'); | ||
| 472 | |||
| 473 | $meta = wp_get_attachment_metadata($post->ID); | ||
| 474 | |||
| 475 | if (! isset($meta['sizes'])) { | ||
| 476 | echo __('Thumbnails were not generated', 'enable-media-replace'); | ||
| 477 | return false; | ||
| 478 | } | ||
| 479 | |||
| 480 | if (function_exists('wp_get_original_image_url')) { // indicating WP 5.3+ | ||
| 481 | $source_url = wp_get_original_image_url($post->ID); | ||
| 482 | // oldway will give -scaled in case of scaling. | ||
| 483 | $source_url_oldway = wp_get_attachment_url($post->ID); | ||
| 484 | |||
| 485 | if ($source_url !== $source_url_oldway) { | ||
| 486 | echo "<div class='original previewwrapper'><img src='" . $source_url_oldway . "'><span class='label'>" . __('Original') . "</span></div>"; | ||
| 487 | } | ||
| 488 | } | ||
| 489 | |||
| 490 | |||
| 491 | foreach ($meta['sizes'] as $size => $data) { | ||
| 492 | $display_size = ucfirst(str_replace("_", " ", $size)); | ||
| 493 | $img = wp_get_attachment_image_src($post->ID, $size); | ||
| 494 | echo "<div class='$size previewwrapper'><img src='" . $img[0] . "'><span class='label'>$display_size</span></div>"; | ||
| 495 | } | ||
| 496 | } | ||
| 497 | |||
| 498 | public function attachment_editor($form_fields, $post) | ||
| 499 | { | ||
| 500 | $screen = null; | ||
| 501 | |||
| 502 | if (! $this->checkImagePermission($post)) { | ||
| 503 | return $form_fields; | ||
| 504 | } | ||
| 505 | |||
| 506 | if (function_exists('get_current_screen')) { | ||
| 507 | $screen = get_current_screen(); | ||
| 508 | if (! is_null($screen) && $screen->id == 'attachment') { // hide on edit attachment screen. | ||
| 509 | return $form_fields; | ||
| 510 | } | ||
| 511 | } | ||
| 512 | |||
| 513 | $url = $this->getMediaReplaceURL($post->ID); | ||
| 514 | $action = "media_replace"; | ||
| 515 | $editurl = wp_nonce_url($url, $action); | ||
| 516 | |||
| 517 | $link = "href=\"$editurl\""; | ||
| 518 | $form_fields["enable-media-replace"] = array( | ||
| 519 | "label" => esc_html__("Replace media", "enable-media-replace"), | ||
| 520 | "input" => "html", | ||
| 521 | "html" => "<a class='button-secondary' $link>" . esc_html__("Upload a new file", "enable-media-replace") . "</a>", "helps" => esc_html__("To replace the current file, click the link and upload a replacement file.", "enable-media-replace") | ||
| 522 | ); | ||
| 523 | |||
| 524 | if ($this->uiHelper()->isBackgroundRemovable($post)) | ||
| 525 | { | ||
| 526 | $link = $this->getRemoveBgURL($post->ID); | ||
| 527 | $link = "href='" . wp_nonce_url($link, 'emr_prepare_remove') . "'"; | ||
| 528 | $form_fields["emr-remove-background"] = array( | ||
| 529 | "label" => esc_html__("Remove background", "enable-media-replace"), | ||
| 530 | "input" => "html", | ||
| 531 | "html" => "<a class='button-secondary' $link>" . esc_html__("Remove background", "enable-media-replace") . "</a>", "helps" => esc_html__("To remove the background, click the link.", "enable-media-replace") | ||
| 532 | ); | ||
| 533 | } | ||
| 534 | return $form_fields; | ||
| 535 | } | ||
| 536 | |||
| 537 | /** | ||
| 538 | * @param array $mime_types | ||
| 539 | * @return array | ||
| 540 | */ | ||
| 541 | /* Off, no clue why this is here. | ||
| 542 | public function add_mime_types($mime_types) | ||
| 543 | { | ||
| 544 | $mime_types['dat'] = 'text/plain'; // Adding .dat extension | ||
| 545 | return $mime_types; | ||
| 546 | } | ||
| 547 | */ | ||
| 548 | /** | ||
| 549 | * Function called by filter 'media_row_actions' | ||
| 550 | * Enables linking to EMR straight from the media library | ||
| 551 | */ | ||
| 552 | public function add_media_action($actions, $post) | ||
| 553 | { | ||
| 554 | |||
| 555 | if (! $this->checkImagePermission($post)) { | ||
| 556 | return $actions; | ||
| 557 | } | ||
| 558 | |||
| 559 | $media_replace_editurl = $this->getMediaReplaceURL($post->ID); | ||
| 560 | $media_replace_action = "media_replace"; | ||
| 561 | // $media_replace_editurl = wp_nonce_url($url, $media_replace_action); | ||
| 562 | $url = $this->getRemoveBgURL($post->ID); | ||
| 563 | $background_remove_action = "emr_prepare_remove"; | ||
| 564 | $background_remove_editurl = wp_nonce_url($url, $background_remove_action); | ||
| 565 | |||
| 566 | /* See above, not needed. | ||
| 567 | if (FORCE_SSL_ADMIN) { | ||
| 568 | $editurl = str_replace("http:", "https:", $editurl); | ||
| 569 | } */ | ||
| 570 | $media_replace_link = "href=\"$media_replace_editurl\""; | ||
| 571 | $background_remove_link = "href=\"$background_remove_editurl\""; | ||
| 572 | |||
| 573 | $newaction['media_replace'] = '<a ' . $media_replace_link . ' aria-label="' . esc_attr__("Replace media", "enable-media-replace") . '" rel="permalink">' . esc_html__("Replace media", "enable-media-replace") . '</a>'; | ||
| 574 | |||
| 575 | if ($this->uiHelper()->isBackgroundRemovable($post)) | ||
| 576 | { | ||
| 577 | $newaction['remove_background'] = '<a ' . $background_remove_link . ' aria-label="' . esc_attr__("Remove background", "enable-media-replace") . '" rel="permalink">' . esc_html__("Remove background", "enable-media-replace") . '</a>'; | ||
| 578 | |||
| 579 | } | ||
| 580 | return array_merge($actions, $newaction); | ||
| 581 | } | ||
| 582 | |||
| 583 | |||
| 584 | |||
| 585 | /** Outputs the replaced date of the media on the edit_attachment screen | ||
| 586 | * | ||
| 587 | * @param $post Obj Post Object | ||
| 588 | */ | ||
| 589 | function admin_date_replaced_media_on_edit_media_screen($post) | ||
| 590 | { | ||
| 591 | |||
| 592 | // Fallback for before version 4.9, doens't pass post. | ||
| 593 | if (! is_object($post)) { | ||
| 594 | global $post; | ||
| 595 | } | ||
| 596 | |||
| 597 | if (! is_object($post)) { // try to global, if it doesn't work - return. | ||
| 598 | return false; | ||
| 599 | } | ||
| 600 | |||
| 601 | $post_id = $post->ID; | ||
| 602 | if ($post->post_modified !== $post->post_date) { | ||
| 603 | $modified = date_i18n(__('M j, Y @ H:i'), strtotime($post->post_modified)); | ||
| 604 | ?> | ||
| 605 | <div class="misc-pub-section curtime"> | ||
| 606 | <span id="timestamp"><?php echo esc_html__('Revised', 'enable-media-replace'); ?>: <b><?php echo $modified; ?></b></span> | ||
| 607 | </div> | ||
| 608 | |||
| 609 | <?php | ||
| 610 | } | ||
| 611 | $author_id = get_post_meta($post_id, '_emr_replace_author', true); | ||
| 612 | |||
| 613 | if ($author_id) { | ||
| 614 | $display_name = get_the_author_meta('display_name', $author_id); | ||
| 615 | ?> | ||
| 616 | <div class="misc-pub-section replace_author"> | ||
| 617 | <span><?php echo esc_html__('Replaced By', 'enable-media-replace'); ?>: <b><?php echo $display_name; ?></b></span> | ||
| 618 | </div> | ||
| 619 | <?php | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | /** When an image is just replaced, it can stuck in the browser cache making a look like it was not replaced. Try | ||
| 624 | * undo that effect by adding a timestamp to the query string */ | ||
| 625 | public function attempt_uncache_image($image, $attachment_id, $size, $icon) | ||
| 626 | { | ||
| 627 | if ($image === false) { | ||
| 628 | return $image; | ||
| 629 | } | ||
| 630 | |||
| 631 | // array with image src on 0 | ||
| 632 | $image[0] = add_query_arg('time', time(), $image[0]); | ||
| 633 | return $image; | ||
| 634 | } | ||
| 635 | |||
| 636 | /** | ||
| 637 | * Shorttag function to show the media file modification date/time. | ||
| 638 | * @param array shorttag attributes | ||
| 639 | * @return string content / replacement shorttag | ||
| 640 | * @todo Note this returns the wrong date, ie. server date not corrected for timezone. Function could be removed altogether, not sure about purpose. | ||
| 641 | */ | ||
| 642 | public function get_modified_date($atts) | ||
| 643 | { | ||
| 644 | $id=0; | ||
| 645 | $format= ''; | ||
| 646 | |||
| 647 | extract(shortcode_atts(array( | ||
| 648 | 'id' => '', | ||
| 649 | 'format' => get_option('date_format') . " " . get_option('time_format'), | ||
| 650 | ), $atts)); | ||
| 651 | |||
| 652 | if ($id == '') { | ||
| 653 | return false; | ||
| 654 | } | ||
| 655 | |||
| 656 | // Get path to file | ||
| 657 | $current_file = get_attached_file($id); | ||
| 658 | |||
| 659 | if (! file_exists($current_file)) { | ||
| 660 | return false; | ||
| 661 | } | ||
| 662 | |||
| 663 | // Get file modification time | ||
| 664 | $filetime = filemtime($current_file); | ||
| 665 | |||
| 666 | if (false !== $filetime) { | ||
| 667 | // do date conversion | ||
| 668 | return date($format, $filetime); | ||
| 669 | } | ||
| 670 | |||
| 671 | return false; | ||
| 672 | } | ||
| 673 | } // 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 | namespace EnableMediaReplace\Externals; | ||
| 3 | |||
| 4 | |||
| 5 | class SiteOrigin | ||
| 6 | { | ||
| 7 | protected static $instance; | ||
| 8 | |||
| 9 | public function __construct() | ||
| 10 | { | ||
| 11 | if (defined('SITEORIGIN_PANELS_VERSION')) | ||
| 12 | { | ||
| 13 | add_filter('emr/replacer/option_fields', array($this, 'addOption')); | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | public static function getInstance() | ||
| 18 | { | ||
| 19 | if (is_null(self::$instance)) | ||
| 20 | { | ||
| 21 | self::$instance = new SiteOrigin(); | ||
| 22 | } | ||
| 23 | |||
| 24 | return self::$instance; | ||
| 25 | } | ||
| 26 | |||
| 27 | public function addOption($options) | ||
| 28 | { | ||
| 29 | $options[] = 'widget_siteorigin-panels-builder'; | ||
| 30 | return $options; | ||
| 31 | } | ||
| 32 | } // class |
| 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( print_r( $errors, true ) ); | ||
| 85 | |||
| 86 | die; | ||
| 87 | } | ||
| 88 | |||
| 89 | } | ||
| 90 | |||
| 91 | /** | ||
| 92 | * Empty out the feedback method to prevent outputting HTML strings as the install | ||
| 93 | * is progressing. | ||
| 94 | * | ||
| 95 | * @since 1.0.0 | ||
| 96 | * | ||
| 97 | * @param string $string The feedback string. | ||
| 98 | * @param array ...$args The args. | ||
| 99 | */ | ||
| 100 | public function feedback( $string, ...$args ) {} | ||
| 101 | |||
| 102 | } |
| 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 | if ( ! current_user_can('install_plugins')) | ||
| 13 | { | ||
| 14 | // Send back a response. | ||
| 15 | wp_send_json(array('result'=> false)); | ||
| 16 | die; | ||
| 17 | } | ||
| 18 | |||
| 19 | switch($plugin) | ||
| 20 | { | ||
| 21 | case "envira": | ||
| 22 | $download_url = 'https://downloads.wordpress.org/plugin/envira-gallery-lite.zip'; | ||
| 23 | break; | ||
| 24 | case 'spio': | ||
| 25 | $download_url = 'https://downloads.wordpress.org/plugin/shortpixel-image-optimiser.zip'; | ||
| 26 | break; | ||
| 27 | case 'spai': | ||
| 28 | $download_url = 'https://downloads.wordpress.org/plugin/shortpixel-adaptive-images.zip'; | ||
| 29 | break; | ||
| 30 | } | ||
| 31 | |||
| 32 | // Install the addon. | ||
| 33 | if ( ! is_null($download_url ) ) { | ||
| 34 | |||
| 35 | //$download_url = esc_url_raw( wp_unslash( $_POST['plugin'] ) ); | ||
| 36 | global $hook_suffix; | ||
| 37 | |||
| 38 | // Set the current screen to avoid undefined notices. | ||
| 39 | set_current_screen(); | ||
| 40 | |||
| 41 | // Prepare variables. | ||
| 42 | $method = ''; | ||
| 43 | $url = add_query_arg( | ||
| 44 | array( | ||
| 45 | // 'page' => 'envira-gallery-settings', | ||
| 46 | ), | ||
| 47 | admin_url( 'admin.php' ) | ||
| 48 | ); | ||
| 49 | $url = esc_url( $url ); | ||
| 50 | |||
| 51 | // Start output bufferring to catch the filesystem form if credentials are needed. | ||
| 52 | ob_start(); | ||
| 53 | $creds = request_filesystem_credentials( $url, $method, false, false, null ); | ||
| 54 | if ( false === $creds ) { | ||
| 55 | $form = ob_get_clean(); | ||
| 56 | echo wp_json_encode( array( 'form' => $form ) ); | ||
| 57 | die; | ||
| 58 | } | ||
| 59 | |||
| 60 | // If we are not authenticated, make it happen now. | ||
| 61 | if ( ! WP_Filesystem( $creds ) ) { | ||
| 62 | ob_start(); | ||
| 63 | request_filesystem_credentials( $url, $method, true, false, null ); | ||
| 64 | $form = ob_get_clean(); | ||
| 65 | echo wp_json_encode( array( 'form' => $form ) ); | ||
| 66 | die; | ||
| 67 | } | ||
| 68 | |||
| 69 | // We do not need any extra credentials if we have gotten this far, so let's install the plugin. | ||
| 70 | require_once (ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'); | ||
| 71 | require_once (plugin_dir_path( EMR_ROOT_FILE ) . 'classes/external/upgrader_skin.php'); | ||
| 72 | |||
| 73 | // Create the plugin upgrader with our custom skin. | ||
| 74 | $skin = new EMR_Envira_Gallery_Skin(); | ||
| 75 | $installer = new Plugin_Upgrader( $skin ); | ||
| 76 | $installer->install( $download_url ); | ||
| 77 | |||
| 78 | // Flush the cache and return the newly installed plugin basename. | ||
| 79 | wp_cache_flush(); | ||
| 80 | |||
| 81 | if ( $installer->plugin_info() ) { | ||
| 82 | $plugin_basename = $installer->plugin_info(); | ||
| 83 | |||
| 84 | ob_clean(); | ||
| 85 | |||
| 86 | |||
| 87 | wp_send_json_success( array( 'plugin' => $plugin_basename ) ); | ||
| 88 | |||
| 89 | die(); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | // Send back a response. | ||
| 94 | wp_send_json(array('result'=> false)); | ||
| 95 | die; | ||
| 96 | |||
| 97 | } | ||
| 98 | |||
| 99 | add_action( 'wp_ajax_emr_plugin_activate', 'emr_activate' ); | ||
| 100 | |||
| 101 | /** | ||
| 102 | * Activates an Envira addon. | ||
| 103 | * | ||
| 104 | * @since 1.0.0 | ||
| 105 | */ | ||
| 106 | function emr_activate() { | ||
| 107 | |||
| 108 | // Run a security check first. | ||
| 109 | check_admin_referer( 'emr-plugin-activate', 'nonce' ); | ||
| 110 | |||
| 111 | $plugin = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : null; | ||
| 112 | |||
| 113 | if ( ! current_user_can('activate_plugins')) | ||
| 114 | { | ||
| 115 | // Send back a response. | ||
| 116 | wp_send_json(array('result'=> false)); | ||
| 117 | die; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | switch($plugin) | ||
| 122 | { | ||
| 123 | case "envira": | ||
| 124 | $plugin = 'envira-gallery-lite/envira-gallery-lite.php'; | ||
| 125 | break; | ||
| 126 | case 'spio': | ||
| 127 | $plugin = 'shortpixel-image-optimiser/wp-shortpixel.php'; | ||
| 128 | break; | ||
| 129 | case 'spai': | ||
| 130 | $plugin = 'shortpixel-adaptive-images/short-pixel-ai.php'; | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | |||
| 134 | // Activate the addon. | ||
| 135 | if ( ! is_null($plugin) ) { | ||
| 136 | $activate = activate_plugin( $plugin ); | ||
| 137 | if ( is_wp_error( $activate ) ) { | ||
| 138 | echo json_encode( array( 'error' => $activate->get_error_message() ) ); | ||
| 139 | die; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | echo json_encode( true ); | ||
| 144 | die; | ||
| 145 | |||
| 146 | } |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace\Externals; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 9 | use EnableMediaReplace\Notices\NoticeController as Notices; | ||
| 10 | |||
| 11 | |||
| 12 | class WPOffload | ||
| 13 | { | ||
| 14 | private static $instance; | ||
| 15 | |||
| 16 | private $as3cf; | ||
| 17 | private $sources; // cache for url > source_id lookup, to prevent duplicate queries. | ||
| 18 | |||
| 19 | private static $offloadPrevented = array(); | ||
| 20 | |||
| 21 | private $post_id; // source_id. The plugin has this, so why so tricky checks. | ||
| 22 | |||
| 23 | |||
| 24 | public function __construct() | ||
| 25 | { | ||
| 26 | add_action('as3cf_init', array($this, 'init')); | ||
| 27 | |||
| 28 | add_action('emr/converter/prevent-offload', array($this, 'preventOffload'), 10); | ||
| 29 | add_action('emr/converter/prevent-offload-off', array($this, 'preventOffloadOff'), 10); | ||
| 30 | add_filter('as3cf_pre_update_attachment_metadata', array($this, 'preventUpdateMetaData'), 10,4); | ||
| 31 | |||
| 32 | |||
| 33 | } | ||
| 34 | |||
| 35 | public static function getInstance() | ||
| 36 | { | ||
| 37 | if (is_null(self::$instance)) | ||
| 38 | { | ||
| 39 | self::$instance = new WPOffload(); | ||
| 40 | } | ||
| 41 | |||
| 42 | return self::$instance; | ||
| 43 | } | ||
| 44 | |||
| 45 | public function init($as3cf) | ||
| 46 | { | ||
| 47 | if (! class_exists('\DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item')) | ||
| 48 | { | ||
| 49 | Notices::addWarning(__('Your S3-Offload plugin version doesn\'t seem to be compatible. Please upgrade the S3-Offload plugin', 'enable-media-replace'), true); | ||
| 50 | return false; | ||
| 51 | } | ||
| 52 | |||
| 53 | $this->as3cf = $as3cf; | ||
| 54 | |||
| 55 | if (method_exists($as3cf, 'get_item_handler')) | ||
| 56 | { | ||
| 57 | } | ||
| 58 | else { | ||
| 59 | Notices::addWarning(__('Your S3-Offload plugin version doesn\'t seem to be compatible. Please upgrade the S3-Offload plugin', 'enable-media-replace'), true); | ||
| 60 | return false; | ||
| 61 | } | ||
| 62 | |||
| 63 | // @todo This all is begging for the creating of an enviroment model / controller. | ||
| 64 | if( !function_exists('is_plugin_active') ) { | ||
| 65 | |||
| 66 | include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); | ||
| 67 | |||
| 68 | } | ||
| 69 | $spio_active = \is_plugin_active('shortpixel-image-optimiser/wp-shortpixel.php'); | ||
| 70 | |||
| 71 | // Let spio handle this. | ||
| 72 | if (false === $spio_active) | ||
| 73 | { | ||
| 74 | add_filter('shortpixel/image/urltopath', array($this, 'checkIfOffloaded'), 10,2); | ||
| 75 | } | ||
| 76 | |||
| 77 | add_action('emr_after_remove_current', array($this, 'removeRemote'), 10, 5); | ||
| 78 | add_filter('emr/file/virtual/translate', array($this, 'getLocalPath'), 10, 3); | ||
| 79 | add_filter('emr/replace/file_is_movable', array($this, 'isFileMovable'), 10, 2); | ||
| 80 | |||
| 81 | add_filter('emr/replace/original_image_path', array($this, 'checkScaledUrl'), 10,2); | ||
| 82 | |||
| 83 | add_action('enable-media-replace-upload-done', array($this, 'updateOriginalPath'), 10, 3); | ||
| 84 | } | ||
| 85 | |||
| 86 | /* | ||
| 87 | * @param $post_id int The post ID | ||
| 88 | * @param $meta array Old Metadata before remove | ||
| 89 | * @param $backup_sizes array WP Backup sizes | ||
| 90 | * @param $sourceFile Object Source File | ||
| 91 | * @param $targetFile Object Target File | ||
| 92 | */ | ||
| 93 | public function removeRemote($post_id, $meta, $backup_sizes, $sourceFile, $targetFile ) | ||
| 94 | { | ||
| 95 | // Always remove because also thumbnails can be different. | ||
| 96 | $a3cfItem = $this->getItemById($post_id); // MediaItem is AS3CF Object | ||
| 97 | if ($a3cfItem === false) | ||
| 98 | { | ||
| 99 | Log::addDebug('S3-Offload MediaItem not remote - ' . $post_id); | ||
| 100 | return false; | ||
| 101 | } | ||
| 102 | |||
| 103 | $remove = \DeliciousBrains\WP_Offload_Media\Items\Remove_Provider_Handler::get_item_handler_key_name(); | ||
| 104 | $itemHandler = $this->as3cf->get_item_handler($remove); | ||
| 105 | |||
| 106 | $result = $itemHandler->handle($a3cfItem, array( 'verify_exists_on_local' => false)); //handle it then. | ||
| 107 | |||
| 108 | } | ||
| 109 | |||
| 110 | // @param s3 based URL that which is needed for finding local path | ||
| 111 | // @return String Filepath. Translated file path | ||
| 112 | public function getLocalPath($url, $sourceFileObj, $source_id) | ||
| 113 | { | ||
| 114 | $item = $this->getItemById($source_id); | ||
| 115 | |||
| 116 | if ($item === false) | ||
| 117 | { | ||
| 118 | $source_id = $this->getSourceIDByURL($url); | ||
| 119 | if (false !== $source_id) | ||
| 120 | $item = $this->getItemById($source_id); | ||
| 121 | } | ||
| 122 | |||
| 123 | if ($source_id == false) | ||
| 124 | { | ||
| 125 | Log::addError('Get Local Path: No source id for URL (Offload) ' . $url); | ||
| 126 | return false; | ||
| 127 | } | ||
| 128 | |||
| 129 | $original_path = $item->original_source_path(); // $values['original_source_path']; | ||
| 130 | |||
| 131 | if (wp_basename($url) !== wp_basename($original_path)) // thumbnails translate to main file. | ||
| 132 | { | ||
| 133 | $original_path = str_replace(wp_basename($original_path), wp_basename($url), $original_path); | ||
| 134 | } | ||
| 135 | |||
| 136 | $fs = emr()->filesystem(); | ||
| 137 | $base = $fs->getWPUploadBase(); | ||
| 138 | |||
| 139 | $file = $base . $original_path; | ||
| 140 | return $file; | ||
| 141 | } | ||
| 142 | |||
| 143 | |||
| 144 | |||
| 145 | public function isFileMovable($bool, $attach_id) | ||
| 146 | { | ||
| 147 | $item = $this->getItemById($attach_id); | ||
| 148 | if ($item === false) | ||
| 149 | { | ||
| 150 | return $bool; | ||
| 151 | } | ||
| 152 | |||
| 153 | // Can't move offloaded items. | ||
| 154 | if (is_object($item)) | ||
| 155 | { | ||
| 156 | return false; | ||
| 157 | } | ||
| 158 | |||
| 159 | } | ||
| 160 | |||
| 161 | public function checkIfOffloaded($bool, $url) | ||
| 162 | { | ||
| 163 | |||
| 164 | $source_id = $this->sourceCache($url); | ||
| 165 | |||
| 166 | if (false === $source_id) | ||
| 167 | { | ||
| 168 | $extension = substr($url, strrpos($url, '.') + 1); | ||
| 169 | // If these filetypes are not in the cache, they cannot be found via geSourceyIDByUrl method ( not in path DB ), so it's pointless to try. If they are offloaded, at some point the extra-info might load. | ||
| 170 | if ($extension == 'webp' || $extension == 'avif') | ||
| 171 | { | ||
| 172 | return false; | ||
| 173 | } | ||
| 174 | |||
| 175 | $source_id = $this->getSourceIDByURL($url); | ||
| 176 | } | ||
| 177 | |||
| 178 | if ($source_id !== false) | ||
| 179 | { | ||
| 180 | return true; | ||
| 181 | } | ||
| 182 | else | ||
| 183 | { | ||
| 184 | return false; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | // This is used in the converted. Might be deployed elsewhere for better control. | ||
| 189 | public function preventOffload($attach_id) | ||
| 190 | { | ||
| 191 | self::$offloadPrevented[$attach_id] = true; | ||
| 192 | } | ||
| 193 | |||
| 194 | public function preventOffloadOff($attach_id) | ||
| 195 | { | ||
| 196 | unset(self::$offloadPrevented[$attach_id]); | ||
| 197 | } | ||
| 198 | |||
| 199 | public function updateOriginalPath($source_url, $target_url, $post_id) | ||
| 200 | { | ||
| 201 | $item = $this->getItemById($post_id); | ||
| 202 | |||
| 203 | // If no item comes back, probably it's not offloaded | ||
| 204 | if (false === $item) | ||
| 205 | { | ||
| 206 | return; | ||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 210 | $original_path = $item->original_path(); // Original path (non-scaled-) | ||
| 211 | $original_source_path = $item->original_source_path(); | ||
| 212 | $path = $item->path(); | ||
| 213 | $source_path = $item->source_path(); | ||
| 214 | |||
| 215 | $wp_original = wp_get_original_image_path($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true )); | ||
| 216 | $wp_original = apply_filters('emr/replace/original_image_path', $wp_original, $post_id); | ||
| 217 | $wp_source = trim(get_attached_file($post_id, apply_filters( 'emr_unfiltered_get_attached_file', true ))); | ||
| 218 | |||
| 219 | $updated = false; | ||
| 220 | |||
| 221 | // If image is replaced with another name, the original soruce path will not match. This could also happen when an image is with -scaled as main is replaced by an image that doesn't have it. In all cases update the table to reflect proper changes. | ||
| 222 | if (wp_basename($wp_original) !== wp_basename($original_path)) | ||
| 223 | { | ||
| 224 | |||
| 225 | $newpath = str_replace( wp_basename( $original_path ), wp_basename($wp_original), $original_path ); | ||
| 226 | |||
| 227 | $item->set_original_path($newpath); | ||
| 228 | |||
| 229 | $newpath = str_replace( wp_basename( $original_source_path ), wp_basename($wp_original), $original_source_path ); | ||
| 230 | $updated = true; | ||
| 231 | |||
| 232 | $item->set_original_source_path($newpath); | ||
| 233 | |||
| 234 | $item->save(); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | // When Offload is not offloaded but is created during the process of generate metadata in WP, wp_create_image_subsizes fires an update metadata after just moving the upload, before making any thumbnails. If this is the case and the file has an -scaled / original image setup, the original_source_path becomes the same as the source_path which creates issue later on when dealing with optimizing it, if the file is deleted on local server. Prevent this, and lean on later update metadata. | ||
| 239 | public function preventUpdateMetaData($bool, $data, $post_id, $old_provider_object) | ||
| 240 | { | ||
| 241 | if (isset(self::$offloadPrevented[$post_id])) | ||
| 242 | { | ||
| 243 | return true ; // return true to cancel. | ||
| 244 | } | ||
| 245 | |||
| 246 | return $bool; | ||
| 247 | |||
| 248 | } | ||
| 249 | |||
| 250 | |||
| 251 | |||
| 252 | // WP Offload -for some reason - returns the same result of get_attached_file and wp_get_original_image_path , which are different files (one scaled) which then causes a wrong copy action after optimizing the image ( wrong destination download of the remote file ). This happens if offload with delete is on. Attempt to fix the URL to reflect the differences between -scaled and not. | ||
| 253 | public function checkScaledUrl($filepath, $id) | ||
| 254 | { | ||
| 255 | // Original filepath can never have a scaled in there. | ||
| 256 | // @todo This should probably check -scaled.<extension> as string end preventing issues. | ||
| 257 | if (strpos($filepath, '-scaled') !== false) | ||
| 258 | { | ||
| 259 | $filepath = str_replace('-scaled', '', $filepath); | ||
| 260 | } | ||
| 261 | return $filepath; | ||
| 262 | } | ||
| 263 | |||
| 264 | /** @return Returns S3Ofload MediaItem, or false when this does not exist */ | ||
| 265 | protected function getItemById($id, $create = false) | ||
| 266 | { | ||
| 267 | $class = $this->getMediaClass(); | ||
| 268 | $mediaItem = $class::get_by_source_id($id); | ||
| 269 | |||
| 270 | if (true === $create && $mediaItem === false) | ||
| 271 | { | ||
| 272 | $mediaItem = $class::create_from_source_id($id); | ||
| 273 | } | ||
| 274 | |||
| 275 | return $mediaItem; | ||
| 276 | } | ||
| 277 | |||
| 278 | protected function getSourceIDByURL($url) | ||
| 279 | { | ||
| 280 | $source_id = $this->sourceCache($url); // check cache first. | ||
| 281 | |||
| 282 | if (false === $source_id) // check on the raw url. | ||
| 283 | { | ||
| 284 | $class = $this->getMediaClass(); | ||
| 285 | |||
| 286 | $parsedUrl = parse_url($url); | ||
| 287 | |||
| 288 | if (! isset($parsedUrl['scheme']) || ! in_array($parsedUrl['scheme'], array('http','https'))) | ||
| 289 | { | ||
| 290 | $url = 'http://' . $url; //str_replace($parsedUrl['scheme'], 'https', $url); | ||
| 291 | } | ||
| 292 | |||
| 293 | $source = $class::get_item_source_by_remote_url($url); | ||
| 294 | |||
| 295 | $source_id = isset($source['id']) ? intval($source['id']) : false; | ||
| 296 | } | ||
| 297 | |||
| 298 | if (false === $source_id) // check now via the thumbnail hocus. | ||
| 299 | { | ||
| 300 | $pattern = '/(.*)-\d+[xX]\d+(\.\w+)/m'; | ||
| 301 | $url = preg_replace($pattern, '$1$2', $url); | ||
| 302 | |||
| 303 | $source_id = $this->sourceCache($url); // check cache first. | ||
| 304 | |||
| 305 | if (false === $source_id) | ||
| 306 | { | ||
| 307 | $source = $class::get_item_source_by_remote_url($url); | ||
| 308 | $source_id = isset($source['id']) ? intval($source['id']) : false; | ||
| 309 | } | ||
| 310 | |||
| 311 | } | ||
| 312 | |||
| 313 | // Check issue with double extensions. If say double webp/avif is on, the double extension causes the URL not to be found (ie .jpg) | ||
| 314 | if (false === $source_id) | ||
| 315 | { | ||
| 316 | if (substr_count($parsedUrl['path'], '.') > 1) | ||
| 317 | { | ||
| 318 | // Get extension | ||
| 319 | $ext = substr(strrchr($url, '.'), 1); | ||
| 320 | |||
| 321 | // Remove all extensions from the URL | ||
| 322 | $checkurl = substr($url, 0, strpos($url,'.')) ; | ||
| 323 | |||
| 324 | // Add back the last one. | ||
| 325 | $checkurl .= '.' . $ext; | ||
| 326 | |||
| 327 | // Retry | ||
| 328 | $source_id = $this->sourceCache($checkurl); // check cache first. | ||
| 329 | |||
| 330 | if (false === $source_id) | ||
| 331 | { | ||
| 332 | $source = $class::get_item_source_by_remote_url($url); | ||
| 333 | $source_id = isset($source['id']) ? intval($source['id']) : false; | ||
| 334 | } | ||
| 335 | |||
| 336 | |||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | if ($source_id !== false) | ||
| 341 | { | ||
| 342 | |||
| 343 | $this->sourceCache($url, $source_id); // cache it. | ||
| 344 | |||
| 345 | // get item | ||
| 346 | $item = $this->getItemById($source_id); | ||
| 347 | if (is_object($item) && method_exists($item, 'extra_info')) | ||
| 348 | { | ||
| 349 | $baseUrl = str_replace(basename($url),'', $url); | ||
| 350 | $extra_info = $item->extra_info(); | ||
| 351 | |||
| 352 | if (isset($extra_info['objects'])) | ||
| 353 | { | ||
| 354 | foreach($extra_info['objects'] as $extraItem) | ||
| 355 | { | ||
| 356 | if (is_array($extraItem) && isset($extraItem['source_file'])) | ||
| 357 | { | ||
| 358 | // Add source stuff into cache. | ||
| 359 | $this->sourceCache($baseUrl . $extraItem['source_file'], $source_id); | ||
| 360 | } | ||
| 361 | } | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | return $source_id; | ||
| 366 | } | ||
| 367 | |||
| 368 | return false; | ||
| 369 | } | ||
| 370 | |||
| 371 | private function sourceCache($url, $source_id = null) | ||
| 372 | { | ||
| 373 | if ($source_id === null && isset($this->sources[$url])) | ||
| 374 | { | ||
| 375 | $source_id = $this->sources[$url]; | ||
| 376 | return $source_id; | ||
| 377 | } | ||
| 378 | elseif ($source_id !== null) | ||
| 379 | { | ||
| 380 | if (! isset($this->sources[$url])) | ||
| 381 | { | ||
| 382 | $this->sources[$url] = $source_id; | ||
| 383 | } | ||
| 384 | return $source_id; | ||
| 385 | } | ||
| 386 | |||
| 387 | return false; | ||
| 388 | } | ||
| 389 | |||
| 390 | |||
| 391 | private function getMediaClass() | ||
| 392 | { | ||
| 393 | $class = $this->as3cf->get_source_type_class('media-library'); | ||
| 394 | return $class; | ||
| 395 | } | ||
| 396 | |||
| 397 | } |
| 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 | use EnableMediaReplace\Externals\SiteOrigin as SiteOrigin; | ||
| 9 | use EnableMediaReplace\Externals\WPOffload as WPOffload; | ||
| 10 | |||
| 11 | |||
| 12 | class Externals | ||
| 13 | { | ||
| 14 | protected $replaceType = null; | ||
| 15 | protected $replaceSearchType = null; | ||
| 16 | |||
| 17 | protected $messages = array(); | ||
| 18 | |||
| 19 | public function __construct() | ||
| 20 | { | ||
| 21 | // These hooks prevent loading of options when plugin conflicts arise. | ||
| 22 | add_filter('emr_display_replace_type_options', array($this, 'get_replace_type')); | ||
| 23 | add_filter('emr_enable_replace_and_search', array($this, 'get_replacesearch_type')); | ||
| 24 | add_action('emr_after_replace_type_options', array($this, 'get_messages')); | ||
| 25 | |||
| 26 | $this->check(); | ||
| 27 | |||
| 28 | // integrations | ||
| 29 | $this->loadElementor(); | ||
| 30 | $this->loadBakery(); // in case of urlencoded issues, this class should be used probably. | ||
| 31 | $this->loadSiteOrigins(); | ||
| 32 | $this->loadWpOffload(); | ||
| 33 | } | ||
| 34 | |||
| 35 | protected function check() // check if any of the options should be disabled due to conflicts | ||
| 36 | { | ||
| 37 | /*if (class_exists('FLBuilder')) | ||
| 38 | { | ||
| 39 | $this->replaceSearchType = false; | ||
| 40 | $this->messages[] return true; | ||
| 41 | = __('Replace and Search feature is not compatible with Beaver Builder.', 'enable-media-replace'); | ||
| 42 | } */ | ||
| 43 | } | ||
| 44 | |||
| 45 | public function get_replace_type($bool) | ||
| 46 | { | ||
| 47 | if ($this->replaceType === null) | ||
| 48 | return $bool; | ||
| 49 | |||
| 50 | return $this->replaceType; | ||
| 51 | } | ||
| 52 | |||
| 53 | public function get_replacesearch_type($bool) | ||
| 54 | { | ||
| 55 | if ($this->replaceSearchType === null) | ||
| 56 | return $bool; | ||
| 57 | |||
| 58 | return $this->replaceSearchType; | ||
| 59 | } | ||
| 60 | |||
| 61 | public function get_messages() | ||
| 62 | { | ||
| 63 | foreach($this->messages as $message) | ||
| 64 | { | ||
| 65 | echo '<span class="nofeature-notice"><p>'. $message . '</p></span>'; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | public function loadElementor() | ||
| 70 | { | ||
| 71 | Elementor::getInstance(); | ||
| 72 | } | ||
| 73 | |||
| 74 | public function loadBakery() | ||
| 75 | { | ||
| 76 | WpBakery::getInstance(); | ||
| 77 | } | ||
| 78 | |||
| 79 | public function loadSiteOrigins() | ||
| 80 | { | ||
| 81 | SiteOrigin::getInstance(); | ||
| 82 | } | ||
| 83 | |||
| 84 | public function loadWPOffload() | ||
| 85 | { | ||
| 86 | WPOffload::getInstance(); | ||
| 87 | } | ||
| 88 | |||
| 89 | } // class |
| 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\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 4 | use EnableMediaReplace\Notices\NoticeController as Notices; | ||
| 5 | |||
| 6 | class InstallHelper | ||
| 7 | { | ||
| 8 | |||
| 9 | public static function unInstallPlugin() | ||
| 10 | { | ||
| 11 | delete_option( 'enable_media_replace' ); | ||
| 12 | delete_option( 'emr_news' ); | ||
| 13 | delete_option( 'emr_url_cache'); | ||
| 14 | } | ||
| 15 | |||
| 16 | public static function deactivatePlugin() | ||
| 17 | { | ||
| 18 | Notices::resetNotices(); | ||
| 19 | } | ||
| 20 | } |
| 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_width = 600; | ||
| 14 | protected $preview_max_height = 600; | ||
| 15 | |||
| 16 | protected $full_width = 0; | ||
| 17 | protected $full_height = 0; | ||
| 18 | |||
| 19 | private static $instance; | ||
| 20 | |||
| 21 | const NOTICE_NEW_FEATURE = 'EMR001'; | ||
| 22 | |||
| 23 | public function __construct() | ||
| 24 | { | ||
| 25 | |||
| 26 | } | ||
| 27 | |||
| 28 | public static function getInstance() | ||
| 29 | { | ||
| 30 | if (is_null(self::$instance)) | ||
| 31 | { | ||
| 32 | self::$instance = new UiHelper(); | ||
| 33 | } | ||
| 34 | |||
| 35 | return self::$instance; | ||
| 36 | } | ||
| 37 | |||
| 38 | // @todo Add nonce URL to this url as well, in popup / prepare-remove-background | ||
| 39 | public function getFormUrl($attach_id, $action = null) | ||
| 40 | { | ||
| 41 | $action = (! is_null($action)) ? $action : 'media_replace_upload'; | ||
| 42 | |||
| 43 | $url = admin_url('upload.php'); | ||
| 44 | $url = add_query_arg(array( | ||
| 45 | 'page' => 'enable-media-replace/enable-media-replace.php', | ||
| 46 | // 'noheader' => true, | ||
| 47 | 'action' => $action, | ||
| 48 | 'attachment_id' => $attach_id, | ||
| 49 | )); | ||
| 50 | |||
| 51 | if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) | ||
| 52 | { | ||
| 53 | $spdebug = $_REQUEST['SHORTPIXEL_DEBUG']; | ||
| 54 | if (is_numeric($spdebug)) | ||
| 55 | $spdebug = intval($spdebug); | ||
| 56 | else { | ||
| 57 | $spdebug = sanitize_text_field($spdebug); | ||
| 58 | } | ||
| 59 | |||
| 60 | $url = add_query_arg('SHORTPIXEL_DEBUG', $spdebug, $url); | ||
| 61 | } | ||
| 62 | |||
| 63 | return $url; | ||
| 64 | |||
| 65 | } | ||
| 66 | |||
| 67 | public function getSuccesRedirect($attach_id) | ||
| 68 | { | ||
| 69 | $url = admin_url('post.php'); | ||
| 70 | $url = add_query_arg(array('action' => 'edit', 'post' => $attach_id, 'emr_replaced' => '1'), $url); | ||
| 71 | |||
| 72 | if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) | ||
| 73 | { | ||
| 74 | $spdebug = $_REQUEST['SHORTPIXEL_DEBUG']; | ||
| 75 | if (is_numeric($spdebug)) | ||
| 76 | $spdebug = intval($spdebug); | ||
| 77 | else { | ||
| 78 | $spdebug = sanitize_text_field($spdebug); | ||
| 79 | } | ||
| 80 | |||
| 81 | $url = add_query_arg('SHORTPIXEL_DEBUG', $spdebug, $url); | ||
| 82 | } | ||
| 83 | |||
| 84 | $url = apply_filters('emr_returnurl', $url); | ||
| 85 | |||
| 86 | return $url; | ||
| 87 | |||
| 88 | } | ||
| 89 | |||
| 90 | public function getBackgroundRemoveRedirect($attach_id) | ||
| 91 | { | ||
| 92 | //if ( isset( $_POST['remove_after_progress'] ) ) { | ||
| 93 | $url = admin_url("upload.php"); | ||
| 94 | $url = add_query_arg(array( | ||
| 95 | 'page' => 'enable-media-replace/enable-media-replace.php', | ||
| 96 | 'action' => 'emr_prepare_remove', | ||
| 97 | 'attachment_id' => $attach_id, | ||
| 98 | ), $url); | ||
| 99 | |||
| 100 | // $redirect_success = $url; | ||
| 101 | return $url; | ||
| 102 | // } | ||
| 103 | } | ||
| 104 | |||
| 105 | public function getFailedRedirect($attach_id) | ||
| 106 | { | ||
| 107 | $url = admin_url('upload.php'); | ||
| 108 | $url = add_query_arg(array( | ||
| 109 | 'page' => 'enable-media-replace/enable-media-replace.php', | ||
| 110 | 'action' => 'media_replace', | ||
| 111 | 'attachment_id' => $attach_id, | ||
| 112 | '_wpnonce' => wp_create_nonce('media_replace'), | ||
| 113 | ), $url | ||
| 114 | ); | ||
| 115 | |||
| 116 | $url = apply_filters('emr_returnurl_failed', $url); | ||
| 117 | return $url; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | |||
| 122 | public function setPreviewSizes() | ||
| 123 | { | ||
| 124 | |||
| 125 | list($this->preview_size, $this->preview_width, $this->preview_height) = $this->findImageSizeByMax($this->preview_max_width); | ||
| 126 | } | ||
| 127 | |||
| 128 | public function setSourceSizes($attach_id) | ||
| 129 | { | ||
| 130 | $data = $this->getImageSizes($attach_id, 'full'); // wp_get_attachment_image_src($attach_id, 'full'); | ||
| 131 | // $file = get_attached_file($attach_id); | ||
| 132 | |||
| 133 | if (is_array($data)) | ||
| 134 | { | ||
| 135 | |||
| 136 | $this->full_width = $data[1]; | ||
| 137 | $this->full_height = $data[2]; | ||
| 138 | } | ||
| 139 | |||
| 140 | } | ||
| 141 | |||
| 142 | protected function getImageSizes($attach_id, $size = 'thumbnail') | ||
| 143 | { | ||
| 144 | // We are not using this function, because depending on the theme, it can mess with the dimensions - https://wordpress.stackexchange.com/questions/167525/why-is-wp-get-attachment-image-src-returning-wrong-dimensions | ||
| 145 | // $data = wp_get_attachment_image_src($attach_id, $size); | ||
| 146 | $meta = wp_get_attachment_metadata($attach_id); | ||
| 147 | |||
| 148 | $data = false; | ||
| 149 | |||
| 150 | if (isset($meta['sizes'])) | ||
| 151 | { | ||
| 152 | foreach($meta['sizes'] as $sizeName => $metaData) | ||
| 153 | { | ||
| 154 | if ($sizeName == $size) | ||
| 155 | { | ||
| 156 | $width = isset($metaData['width']) ? $metaData['width'] : 0; | ||
| 157 | $height = isset($metaData['height']) ? $metaData['height'] : 0; | ||
| 158 | $imgData = image_downsize($attach_id, $size); // return whole array w/ possible wrong dimensions. | ||
| 159 | $data = array($imgData[0], $width, $height); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | if ($data === false) | ||
| 165 | { | ||
| 166 | $data = wp_get_attachment_image_src($attach_id, $size); | ||
| 167 | $width = isset($data[1]) ? $data[1] : 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | $file = get_attached_file($attach_id, true); | ||
| 171 | if (! file_exists($file)) | ||
| 172 | return $data; | ||
| 173 | |||
| 174 | $mime_type = wp_get_image_mime($file); | ||
| 175 | |||
| 176 | if (strpos($mime_type, 'svg') !== false && $width <= 5) | ||
| 177 | { | ||
| 178 | $file = get_attached_file($attach_id); | ||
| 179 | $data = $this->fixSVGSize($data, $file); | ||
| 180 | } | ||
| 181 | |||
| 182 | |||
| 183 | return $data; | ||
| 184 | } | ||
| 185 | |||
| 186 | protected function fixSVGSize($data, $file) | ||
| 187 | { | ||
| 188 | if (! function_exists('simplexml_load_file')) | ||
| 189 | return $data; | ||
| 190 | |||
| 191 | $xml = simplexml_load_file($file); | ||
| 192 | //Log::addDebug('XML LOAD FILE', $xml); | ||
| 193 | if ($xml) | ||
| 194 | { // stolen from SVG Upload plugin | ||
| 195 | $attr = $xml->attributes(); | ||
| 196 | $viewbox = explode(' ', $attr->viewBox); | ||
| 197 | $data[1] = isset($attr->width) && preg_match('/\d+/', $attr->width, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[2] : null); | ||
| 198 | $data[2] = isset($attr->height) && preg_match('/\d+/', $attr->height, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[3] : null); | ||
| 199 | } | ||
| 200 | |||
| 201 | return $data; | ||
| 202 | } | ||
| 203 | |||
| 204 | // Returns Preview Image HTML Output. | ||
| 205 | public function getPreviewImage($attach_id,$file, $args = array()) | ||
| 206 | { | ||
| 207 | $data = false; | ||
| 208 | |||
| 209 | if ($attach_id > 0) | ||
| 210 | { | ||
| 211 | $data = $this->getImageSizes($attach_id, $this->preview_size); //wp_get_attachment_image_src($attach_id, $this->preview_size); | ||
| 212 | } | ||
| 213 | |||
| 214 | $mime_type = get_post_mime_type($attach_id); | ||
| 215 | |||
| 216 | if (! is_array($data) || (! $file->exists() && ! $file->is_virtual()) ) | ||
| 217 | { | ||
| 218 | // if attachid higher than zero ( exists ) but not the image, fail, that's an error state. | ||
| 219 | $icon = ($attach_id < 0) ? '' : 'dashicons-no'; | ||
| 220 | $is_document = false; | ||
| 221 | |||
| 222 | $defaults = array( | ||
| 223 | 'width' => $this->preview_width, | ||
| 224 | 'height' => $this->preview_height, | ||
| 225 | 'is_image' => false, | ||
| 226 | 'is_document' => $is_document, | ||
| 227 | 'is_upload' => false, | ||
| 228 | 'icon' => $icon, | ||
| 229 | 'mime_type' => null, | ||
| 230 | ); | ||
| 231 | $args = wp_parse_args($args, $defaults); | ||
| 232 | |||
| 233 | // failed, it might be this server doens't support PDF thumbnails. Fallback to File preview. | ||
| 234 | if ($mime_type == 'application/pdf') | ||
| 235 | { | ||
| 236 | return $this->getPreviewFile($attach_id, $file); | ||
| 237 | } | ||
| 238 | |||
| 239 | return $this->getPlaceHolder($args); | ||
| 240 | } | ||
| 241 | |||
| 242 | $url = $data[0]; | ||
| 243 | $width = $data[1]; | ||
| 244 | $height = $data[2]; | ||
| 245 | |||
| 246 | // width | ||
| 247 | $width_ratio = $height_ratio = 0; | ||
| 248 | if ($width > $this->preview_max_width) | ||
| 249 | { | ||
| 250 | $width_ratio = $width / $this->preview_max_width; | ||
| 251 | } | ||
| 252 | if ($height > $this->preview_max_height) // height | ||
| 253 | { | ||
| 254 | $height_ratio = $height / $this->preview_max_height; | ||
| 255 | } | ||
| 256 | |||
| 257 | $ratio = ($width_ratio > $height_ratio) ? $width_ratio : $height_ratio; | ||
| 258 | |||
| 259 | if ($ratio > 0) | ||
| 260 | { | ||
| 261 | |||
| 262 | $width = floor($width / $ratio); | ||
| 263 | $height = floor($height / $ratio); | ||
| 264 | } | ||
| 265 | |||
| 266 | // SVG's without any helpers return around 0 for width / height. Fix preview. | ||
| 267 | |||
| 268 | |||
| 269 | // preview width, if source if found, should be set to source. | ||
| 270 | $this->preview_width = $width; | ||
| 271 | $this->preview_height = $height; | ||
| 272 | |||
| 273 | $image = "<img src='$url' width='$width' height='$height' class='image' style='max-width:100%; max-height: 100%;' />"; | ||
| 274 | // $image = "<span class='the-image' style='background: url(\"" . $url . "\")';> </span>"; | ||
| 275 | |||
| 276 | $defaults = array( | ||
| 277 | 'width' => $width, | ||
| 278 | 'height' => $height, | ||
| 279 | 'image' => $image, | ||
| 280 | 'mime_type' => $mime_type, | ||
| 281 | 'is_upload' => false, | ||
| 282 | 'file_size' => $file->getFileSize(), | ||
| 283 | ); | ||
| 284 | |||
| 285 | $args = wp_parse_args($args, $defaults); | ||
| 286 | |||
| 287 | $output = $this->getPlaceHolder($args); | ||
| 288 | return $output; | ||
| 289 | } | ||
| 290 | |||
| 291 | public function getPreviewError($attach_id) | ||
| 292 | { | ||
| 293 | $args = array( | ||
| 294 | 'width' => $this->preview_width, | ||
| 295 | 'height' => $this->preview_height, | ||
| 296 | 'icon' => 'dashicons-no', | ||
| 297 | 'is_image' => false, | ||
| 298 | ); | ||
| 299 | $output = $this->getPlaceHolder($args); | ||
| 300 | return $output; | ||
| 301 | } | ||
| 302 | |||
| 303 | public function getPreviewFile($attach_id, $file, $args = array()) | ||
| 304 | { | ||
| 305 | if ($attach_id > 0) | ||
| 306 | { | ||
| 307 | //$filepath = get_attached_file($attach_id); | ||
| 308 | $filename = $file->getFileName(); | ||
| 309 | } | ||
| 310 | else { | ||
| 311 | $filename = false; | ||
| 312 | } | ||
| 313 | |||
| 314 | $mime_type = $file->getMime(); | ||
| 315 | if (false === $mime_type) // If server is not supporting this, go w/ the post mime type one. | ||
| 316 | { | ||
| 317 | $mime_type = get_post_mime_type($attach_id); | ||
| 318 | } | ||
| 319 | |||
| 320 | $defaults = array( | ||
| 321 | 'width' => 300, | ||
| 322 | 'height' => 300, | ||
| 323 | 'is_image' => false, | ||
| 324 | 'is_document' => true, | ||
| 325 | 'is_upload' => false, | ||
| 326 | 'layer' => $filename, | ||
| 327 | 'mime_type' => $mime_type, | ||
| 328 | 'file_size' => $file->getFileSize(), | ||
| 329 | ); | ||
| 330 | $args = wp_parse_args($args, $defaults); | ||
| 331 | |||
| 332 | |||
| 333 | $output = $this->getPlaceHolder($args); | ||
| 334 | return $output; | ||
| 335 | } | ||
| 336 | |||
| 337 | public function findImageSizeByMax($maxwidth) | ||
| 338 | { | ||
| 339 | $image_sizes = $this->wp_get_image_sizes(); | ||
| 340 | |||
| 341 | $match_width = 0; | ||
| 342 | $match_height = 0; | ||
| 343 | $match = ''; | ||
| 344 | |||
| 345 | foreach($image_sizes as $sizeName => $sizeItem) | ||
| 346 | { | ||
| 347 | |||
| 348 | $width = $sizeItem['width']; | ||
| 349 | if ($width > $match_width && $width <= $maxwidth) | ||
| 350 | { | ||
| 351 | $match = $sizeName; | ||
| 352 | $match_width = $width; | ||
| 353 | $match_height = $sizeItem['height']; | ||
| 354 | } | ||
| 355 | } | ||
| 356 | return array($match, $match_width, $match_height); | ||
| 357 | } | ||
| 358 | |||
| 359 | public function getPlaceHolder($args) | ||
| 360 | { | ||
| 361 | $defaults = array( | ||
| 362 | 'width' => 150, | ||
| 363 | 'height' => 150, | ||
| 364 | 'image' => '', | ||
| 365 | 'icon' => 'dashicons-media-document', | ||
| 366 | 'layer' => $this->full_width . ' x ' . $this->full_height, | ||
| 367 | 'is_image' => true, | ||
| 368 | 'is_document' => false, | ||
| 369 | 'is_upload' => false, // indicating right-side upload interface for image. | ||
| 370 | 'mime_type' => false, | ||
| 371 | 'file_size' => false, | ||
| 372 | 'remove_bg_ui' => false, // In process icons et al when removing background, for preview pane. | ||
| 373 | |||
| 374 | ); | ||
| 375 | |||
| 376 | $args = wp_parse_args($args, $defaults); | ||
| 377 | |||
| 378 | $w = $args['width']; | ||
| 379 | $h = $args['height']; | ||
| 380 | |||
| 381 | if ($w < 150) // minimum | ||
| 382 | $w = 150; | ||
| 383 | if ($h < 150) | ||
| 384 | $h = 150; | ||
| 385 | |||
| 386 | $icon = $args['icon']; | ||
| 387 | |||
| 388 | if ($args['is_image']) | ||
| 389 | { | ||
| 390 | $placeholder_class = 'is_image'; | ||
| 391 | } | ||
| 392 | else { | ||
| 393 | $placeholder_class = 'not_image'; | ||
| 394 | } | ||
| 395 | |||
| 396 | if ($args['is_document']) | ||
| 397 | { | ||
| 398 | $placeholder_class .= ' is_document'; | ||
| 399 | } | ||
| 400 | |||
| 401 | if (true == $args['is_upload']) | ||
| 402 | { | ||
| 403 | $placeholder_class .= ' upload-file-action'; | ||
| 404 | } | ||
| 405 | |||
| 406 | $filetype = ''; | ||
| 407 | if ($args['mime_type']) | ||
| 408 | { | ||
| 409 | $filetype = 'data-filetype="' . $args['mime_type'] . '"'; | ||
| 410 | } | ||
| 411 | |||
| 412 | $filesize = ($args['file_size']) ? $args['file_size'] : ''; | ||
| 413 | |||
| 414 | $is_backgroundremove_ui = (isset($args['remove_bg_ui']) && $args['remove_bg_ui'] == true); | ||
| 415 | $background_remove_ui = ($is_backgroundremove_ui) ? $this->getBgremoveUI() : ''; | ||
| 416 | |||
| 417 | $output = "<div class='image_placeholder $placeholder_class' $filetype style='width:" . $w . "px; height:". $h ."px'> "; | ||
| 418 | if (true === $args['is_upload']) | ||
| 419 | { | ||
| 420 | $output .= "<span class='upload-title'>" . __('New', 'enable-media-replace') . "</span>"; | ||
| 421 | $output .= '<input type="file" name="userfile" id="upload-file" />'; | ||
| 422 | $output .= '<div class="drag-and-drop-title"> | ||
| 423 | <span>' . __('Click here to upload or drop file in area', 'enable-media-replace') . '</span> | ||
| 424 | </div>'; | ||
| 425 | } | ||
| 426 | else | ||
| 427 | { | ||
| 428 | $title = (true === $is_backgroundremove_ui ) ? __('Preview', 'enable-media-replace') : __('Current', 'enable-media-replace'); | ||
| 429 | $output .= "<span class='upload-title'>" . $title . "</span>"; | ||
| 430 | $output .= $args['image']; | ||
| 431 | } | ||
| 432 | $output .= "<div class='dashicons $icon'> </div>"; | ||
| 433 | $output .= "<span class='textlayer'>" . $args['layer'] . "</span>"; | ||
| 434 | $output .= $background_remove_ui; | ||
| 435 | $output .= "<div class='image_size'>" . $this->convertFileSize($filesize). "</div>"; | ||
| 436 | $output .= "</div>"; | ||
| 437 | |||
| 438 | return $output; | ||
| 439 | } | ||
| 440 | |||
| 441 | public function isBackgroundRemovable($post) | ||
| 442 | { | ||
| 443 | if (false === wp_attachment_is_image($post)) | ||
| 444 | return false; | ||
| 445 | |||
| 446 | if (false === emr()->useFeature('background')) | ||
| 447 | return false; | ||
| 448 | |||
| 449 | $extensions = array('jpg', 'png','jpeg'); | ||
| 450 | |||
| 451 | $mime = get_post_mime_type($post); | ||
| 452 | foreach($extensions as $extension) | ||
| 453 | { | ||
| 454 | if (strpos($mime, $extension) !== false ) | ||
| 455 | return true; | ||
| 456 | } | ||
| 457 | |||
| 458 | return false; | ||
| 459 | |||
| 460 | } | ||
| 461 | |||
| 462 | private function getBgremoveUI() | ||
| 463 | { | ||
| 464 | $output = '<div class="overlay" id="overlay"> | ||
| 465 | <div class="lds-spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>'; | ||
| 466 | |||
| 467 | $output .= '<h3>' . esc_html__('Removing background...', 'enable-media-replace') . '</h3>'; | ||
| 468 | $output .= '</div>'; | ||
| 469 | |||
| 470 | return $output; | ||
| 471 | } | ||
| 472 | |||
| 473 | private function convertFileSize($filesize) | ||
| 474 | { | ||
| 475 | return size_format($filesize); | ||
| 476 | } | ||
| 477 | |||
| 478 | /** | ||
| 479 | * Get size information for all currently-registered image sizes. | ||
| 480 | * Directly stolen from - https://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes | ||
| 481 | * @global $_wp_additional_image_sizes | ||
| 482 | * @uses get_intermediate_image_sizes() | ||
| 483 | * @return array $sizes Data for all currently-registered image sizes. | ||
| 484 | */ | ||
| 485 | private function wp_get_image_sizes() { | ||
| 486 | global $_wp_additional_image_sizes; | ||
| 487 | |||
| 488 | $sizes = array(); | ||
| 489 | |||
| 490 | foreach ( get_intermediate_image_sizes() as $_size ) { | ||
| 491 | if ( in_array( $_size, array('thumbnail', 'medium', 'medium_large', 'large') ) ) { | ||
| 492 | $sizes[ $_size ]['width'] = get_option( "{$_size}_size_w" ); | ||
| 493 | $sizes[ $_size ]['height'] = get_option( "{$_size}_size_h" ); | ||
| 494 | } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) { | ||
| 495 | $sizes[ $_size ] = array( | ||
| 496 | 'width' => $_wp_additional_image_sizes[ $_size ]['width'], | ||
| 497 | 'height' => $_wp_additional_image_sizes[ $_size ]['height'], | ||
| 498 | ); | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | return $sizes; | ||
| 503 | } | ||
| 504 | |||
| 505 | /** For Location Dir replacement. Get the Subdir that is in use now. */ | ||
| 506 | public function getRelPathNow() | ||
| 507 | { | ||
| 508 | $uploadDir = wp_upload_dir(); | ||
| 509 | if (isset($uploadDir['subdir'])) | ||
| 510 | return ltrim($uploadDir['subdir'], '/'); | ||
| 511 | else | ||
| 512 | return false; | ||
| 513 | } | ||
| 514 | |||
| 515 | public function featureNotice() | ||
| 516 | { | ||
| 517 | // @todo Remove in 2023. | ||
| 518 | $message = sprintf(__('%s New Beta Feature! %s %s Enable Media Replace now gives you the ability to remove the background of any image. Try it out in the Media Library: hover over an image and click on Remove Background. Or just click on Remove background from the image editing window! %s ', 'enable-media-replace' ), '<h3>', '</h3>', | ||
| 519 | '<p>', '</p>'); | ||
| 520 | |||
| 521 | $notice = Notices::addNormal($message, true); | ||
| 522 | Notices::makePersistent($notice, self::NOTICE_NEW_FEATURE, 2 * YEAR_IN_SECONDS); | ||
| 523 | } | ||
| 524 | |||
| 525 | } // 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 | .enable-media-replace.emr-screen { | ||
| 988 | width: 90%; | ||
| 989 | background: #fff; | ||
| 990 | border: 1px solid #fff; | ||
| 991 | position: relative; | ||
| 992 | margin: 30px 0; | ||
| 993 | } | ||
| 994 | .enable-media-replace.emr-screen h3 { | ||
| 995 | font-size: 24px; | ||
| 996 | position: absolute; | ||
| 997 | top: -15px; | ||
| 998 | left: 30px; | ||
| 999 | padding: 16px 8px; | ||
| 1000 | border: 1px solid #000; | ||
| 1001 | background: #fff; | ||
| 1002 | margin: 0; | ||
| 1003 | } | ||
| 1004 | .enable-media-replace.emr-screen .content { | ||
| 1005 | padding: 32px; | ||
| 1006 | } | ||
| 1007 | .enable-media-replace.emr-screen h1 { | ||
| 1008 | font-weight: 700; | ||
| 1009 | } | ||
| 1010 | .enable-media-replace.emr-screen p { | ||
| 1011 | font-size: 14px; | ||
| 1012 | } | ||
| 1013 | .enable-media-replace.emr-screen .hide { | ||
| 1014 | display: none; | ||
| 1015 | } | ||
| 1016 | .enable-media-replace.emr-screen.error-screen h1 { | ||
| 1017 | color: #ff0000; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | #emr-drop-area-active { | ||
| 1021 | position: fixed; | ||
| 1022 | left: 0; | ||
| 1023 | right: 0; | ||
| 1024 | top: 0; | ||
| 1025 | bottom: 0; | ||
| 1026 | z-index: 9999; | ||
| 1027 | display: block; | ||
| 1028 | background: rgba(0, 0, 0, 0.5); | ||
| 1029 | border: 6px dashed #AAA; | ||
| 1030 | } | ||
| 1031 | #emr-drop-area-active h3 { | ||
| 1032 | font-size: 36px; | ||
| 1033 | color: #ddd; | ||
| 1034 | width: 200px; | ||
| 1035 | left: 50%; | ||
| 1036 | top: 50%; | ||
| 1037 | position: absolute; | ||
| 1038 | } | ||
| 1039 | #emr-drop-area-active .drop-wrapper { | ||
| 1040 | margin: 0 auto; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | .emr_upload_form form { | ||
| 1044 | display: flex; | ||
| 1045 | } | ||
| 1046 | .emr_upload_form form .upsell-wrapper { | ||
| 1047 | margin-left: 10px; | ||
| 1048 | } | ||
| 1049 | .emr_upload_form .editor-wrapper { | ||
| 1050 | width: 100%; | ||
| 1051 | } | ||
| 1052 | .emr_upload_form .emr_drop_area { | ||
| 1053 | display: none; | ||
| 1054 | } | ||
| 1055 | .emr_upload_form .wrapper { | ||
| 1056 | padding: 18px; | ||
| 1057 | border: 1px solid #ccc; | ||
| 1058 | } | ||
| 1059 | .emr_upload_form .wrapper .section-header { | ||
| 1060 | font-size: 18px; | ||
| 1061 | border-bottom: 1px solid #ccc; | ||
| 1062 | padding: 6px 0; | ||
| 1063 | margin: 0 0 15px 0; | ||
| 1064 | } | ||
| 1065 | .emr_upload_form .explainer { | ||
| 1066 | font-size: 14px; | ||
| 1067 | color: #555; | ||
| 1068 | max-width: 800px; | ||
| 1069 | margin: 20px 0; | ||
| 1070 | } | ||
| 1071 | .emr_upload_form .explainer .underline { | ||
| 1072 | text-decoration-style: dotted; | ||
| 1073 | text-decoration-line: underline; | ||
| 1074 | } | ||
| 1075 | .emr_upload_form .image_chooser.wrapper { | ||
| 1076 | min-height: 350px; | ||
| 1077 | } | ||
| 1078 | .emr_upload_form .image_chooser.wrapper .image_previews { | ||
| 1079 | margin: 15px 0; | ||
| 1080 | position: relative; | ||
| 1081 | } | ||
| 1082 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder { | ||
| 1083 | position: relative; | ||
| 1084 | display: inline-block; | ||
| 1085 | margin-right: 25px; | ||
| 1086 | margin-bottom: 10px; | ||
| 1087 | border: 1px solid #ddd; | ||
| 1088 | vertical-align: top; | ||
| 1089 | box-sizing: border-box; | ||
| 1090 | background: #fff; | ||
| 1091 | max-width: calc(50% - 25px); | ||
| 1092 | } | ||
| 1093 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder img { | ||
| 1094 | object-fit: contain; | ||
| 1095 | } | ||
| 1096 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .upload-title { | ||
| 1097 | text-align: center; | ||
| 1098 | position: absolute; | ||
| 1099 | padding-top: 8px; | ||
| 1100 | line-height: 20px; | ||
| 1101 | font-weight: 700; | ||
| 1102 | width: 100%; | ||
| 1103 | left: 0; | ||
| 1104 | top: 0; | ||
| 1105 | } | ||
| 1106 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder #upload-file { | ||
| 1107 | display: none; | ||
| 1108 | } | ||
| 1109 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .textlayer { | ||
| 1110 | font-size: 25px; | ||
| 1111 | line-height: 25px; | ||
| 1112 | opacity: 0.7; | ||
| 1113 | position: absolute; | ||
| 1114 | color: #ccc; | ||
| 1115 | left: 48%; | ||
| 1116 | top: 50%; | ||
| 1117 | transform: translate(-50%, -50%); | ||
| 1118 | border: 1px dashed #eee; | ||
| 1119 | background-color: #333; | ||
| 1120 | padding: 8px; | ||
| 1121 | z-index: 5; | ||
| 1122 | } | ||
| 1123 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .dashicons { | ||
| 1124 | font-size: 60px; | ||
| 1125 | position: absolute; | ||
| 1126 | top: 50%; | ||
| 1127 | margin-top: -30px; | ||
| 1128 | left: 50%; | ||
| 1129 | margin-left: -30px; | ||
| 1130 | opacity: 0.5; | ||
| 1131 | } | ||
| 1132 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .image_size { | ||
| 1133 | text-align: center; | ||
| 1134 | position: absolute; | ||
| 1135 | bottom: -25px; | ||
| 1136 | width: 100%; | ||
| 1137 | } | ||
| 1138 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .drag-and-drop-title { | ||
| 1139 | text-align: center; | ||
| 1140 | font-weight: 400; | ||
| 1141 | font-size: 14px; | ||
| 1142 | width: 100%; | ||
| 1143 | height: 100%; | ||
| 1144 | position: absolute; | ||
| 1145 | cursor: pointer; | ||
| 1146 | top: 0; | ||
| 1147 | left: 0; | ||
| 1148 | z-index: 1; | ||
| 1149 | } | ||
| 1150 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder .drag-and-drop-title span { | ||
| 1151 | position: absolute; | ||
| 1152 | top: 50%; | ||
| 1153 | transform: translate(-50%, -50%); | ||
| 1154 | padding: 5px 10px; | ||
| 1155 | width: 100%; | ||
| 1156 | } | ||
| 1157 | .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 { | ||
| 1158 | display: none; | ||
| 1159 | } | ||
| 1160 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image img { | ||
| 1161 | display: none; | ||
| 1162 | } | ||
| 1163 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image .textlayer { | ||
| 1164 | display: none; | ||
| 1165 | } | ||
| 1166 | .emr_upload_form .image_chooser.wrapper .image_previews .image_placeholder.not_image.is_document .textlayer { | ||
| 1167 | font-size: 18px; | ||
| 1168 | line-height: 20px; | ||
| 1169 | display: block; | ||
| 1170 | } | ||
| 1171 | .emr_upload_form .form-error, .emr_upload_form .form-warning { | ||
| 1172 | background: #fff; | ||
| 1173 | padding: 8px; | ||
| 1174 | border-left: 4px solid #ff0000; | ||
| 1175 | margin: 10px 0; | ||
| 1176 | display: none; | ||
| 1177 | } | ||
| 1178 | .emr_upload_form .form-error p, .emr_upload_form .form-warning p { | ||
| 1179 | margin: 0; | ||
| 1180 | font-size: 12px; | ||
| 1181 | font-weight: 700; | ||
| 1182 | } | ||
| 1183 | .emr_upload_form .form-warning { | ||
| 1184 | border-left: 4px solid #ffb900; | ||
| 1185 | } | ||
| 1186 | .emr_upload_form .option-flex-wrapper { | ||
| 1187 | display: flex; | ||
| 1188 | } | ||
| 1189 | .emr_upload_form .replace_type.wrapper { | ||
| 1190 | flex: 1; | ||
| 1191 | border: 1px solid #ccc; | ||
| 1192 | margin: 15px 0; | ||
| 1193 | } | ||
| 1194 | .emr_upload_form .replace_type.wrapper .option { | ||
| 1195 | position: relative; | ||
| 1196 | z-index: 1; | ||
| 1197 | } | ||
| 1198 | .emr_upload_form .replace_type.wrapper .option label { | ||
| 1199 | font-size: 1.2em; | ||
| 1200 | } | ||
| 1201 | .emr_upload_form .replace_type.wrapper .option .nofeature-notice { | ||
| 1202 | border: 1px solid #ccc; | ||
| 1203 | padding: 8px; | ||
| 1204 | margin: 0; | ||
| 1205 | position: absolute; | ||
| 1206 | left: 0; | ||
| 1207 | right: 0; | ||
| 1208 | top: 0; | ||
| 1209 | bottom: 0; | ||
| 1210 | opacity: 0.8; | ||
| 1211 | z-index: 9; | ||
| 1212 | background: #444; | ||
| 1213 | } | ||
| 1214 | .emr_upload_form .replace_type.wrapper .option .nofeature-notice p { | ||
| 1215 | text-align: center; | ||
| 1216 | color: #fff; | ||
| 1217 | margin: 15px 0; | ||
| 1218 | } | ||
| 1219 | .emr_upload_form .options.wrapper { | ||
| 1220 | flex: 1; | ||
| 1221 | border: 1px solid #ccc; | ||
| 1222 | padding: 15px; | ||
| 1223 | margin: 15px 0 15px 35px; | ||
| 1224 | } | ||
| 1225 | .emr_upload_form .options.wrapper .custom_date .emr_datepicker { | ||
| 1226 | width: 150px; | ||
| 1227 | } | ||
| 1228 | .emr_upload_form .options.wrapper .custom_date .emr_hour, .emr_upload_form .options.wrapper .custom_date .emr_minute { | ||
| 1229 | width: 45px; | ||
| 1230 | } | ||
| 1231 | .emr_upload_form .options.wrapper .replace_custom_date { | ||
| 1232 | margin-left: 5px; | ||
| 1233 | } | ||
| 1234 | .emr_upload_form .options.wrapper .replace_custom_date:hover { | ||
| 1235 | text-decoration: underline; | ||
| 1236 | cursor: pointer; | ||
| 1237 | } | ||
| 1238 | .emr_upload_form .options.wrapper ul li input { | ||
| 1239 | margin-right: 8px; | ||
| 1240 | } | ||
| 1241 | .emr_upload_form .options.wrapper .option label { | ||
| 1242 | vertical-align: top; | ||
| 1243 | } | ||
| 1244 | .emr_upload_form .options.wrapper .small { | ||
| 1245 | font-size: 10px; | ||
| 1246 | vertical-align: top; | ||
| 1247 | margin-left: 8px; | ||
| 1248 | } | ||
| 1249 | .emr_upload_form .options.wrapper .custom_date { | ||
| 1250 | margin: 8px 0 0 25px; | ||
| 1251 | visibility: hidden; | ||
| 1252 | opacity: 0; | ||
| 1253 | } | ||
| 1254 | .emr_upload_form .options.wrapper .custom_date span.field-title { | ||
| 1255 | display: inline-block; | ||
| 1256 | margin-bottom: 4px; | ||
| 1257 | color: #444; | ||
| 1258 | font-size: 12px; | ||
| 1259 | width: 100%; | ||
| 1260 | text-align: left; | ||
| 1261 | vertical-align: middle; | ||
| 1262 | line-height: 26px; | ||
| 1263 | } | ||
| 1264 | .emr_upload_form .options.wrapper .custom_date span.field-title::before { | ||
| 1265 | font-size: 20px; | ||
| 1266 | vertical-align: top; | ||
| 1267 | margin-right: 4px; | ||
| 1268 | } | ||
| 1269 | .emr_upload_form .options.wrapper .location_option { | ||
| 1270 | display: none; | ||
| 1271 | margin-top: 12px; | ||
| 1272 | } | ||
| 1273 | .emr_upload_form .options.wrapper .location_option label { | ||
| 1274 | vertical-align: baseline; | ||
| 1275 | margin-right: 8px; | ||
| 1276 | } | ||
| 1277 | .emr_upload_form .form_controls.wrapper { | ||
| 1278 | clear: both; | ||
| 1279 | margin: 8px 0 15px 0; | ||
| 1280 | border: 0; | ||
| 1281 | padding: 0; | ||
| 1282 | } | ||
| 1283 | .emr_upload_form .form_controls.wrapper .button { | ||
| 1284 | padding-left: 20px; | ||
| 1285 | padding-right: 20px; | ||
| 1286 | } | ||
| 1287 | .emr_upload_form .shortpixel.notice { | ||
| 1288 | padding: 12px; | ||
| 1289 | } | ||
| 1290 | .emr_upload_form .shortpixel-offer { | ||
| 1291 | background: #fff; | ||
| 1292 | width: 250px; | ||
| 1293 | min-height: 270px; | ||
| 1294 | border: 1px solid #ccc; | ||
| 1295 | padding: 10px; | ||
| 1296 | margin-bottom: 10px; | ||
| 1297 | float: right; | ||
| 1298 | clear: both; | ||
| 1299 | background-color: #dcfdff; | ||
| 1300 | } | ||
| 1301 | .emr_upload_form .shortpixel-offer h3 { | ||
| 1302 | color: #00d0e5; | ||
| 1303 | font-size: 18px; | ||
| 1304 | text-align: center; | ||
| 1305 | margin: 0; | ||
| 1306 | line-height: 1.3em; | ||
| 1307 | } | ||
| 1308 | .emr_upload_form .shortpixel-offer h4 { | ||
| 1309 | font-size: 16px; | ||
| 1310 | text-align: center; | ||
| 1311 | } | ||
| 1312 | .emr_upload_form .shortpixel-offer .red { | ||
| 1313 | color: #ff0000; | ||
| 1314 | } | ||
| 1315 | .emr_upload_form .shortpixel-offer .cyan { | ||
| 1316 | color: #00d0e5; | ||
| 1317 | } | ||
| 1318 | .emr_upload_form .shortpixel-offer .grey { | ||
| 1319 | color: grey; | ||
| 1320 | } | ||
| 1321 | .emr_upload_form .shortpixel-offer .ucase { | ||
| 1322 | text-transform: uppercase; | ||
| 1323 | } | ||
| 1324 | .emr_upload_form .shortpixel-offer a { | ||
| 1325 | text-decoration: none; | ||
| 1326 | } | ||
| 1327 | .emr_upload_form .shortpixel-offer .button-wrapper { | ||
| 1328 | text-align: center; | ||
| 1329 | margin-top: 35px; | ||
| 1330 | } | ||
| 1331 | .emr_upload_form .shortpixel-offer .button-wrapper a { | ||
| 1332 | background-color: #ff0000; | ||
| 1333 | color: #fff; | ||
| 1334 | display: inline-block; | ||
| 1335 | padding: 8px; | ||
| 1336 | text-decoration: none; | ||
| 1337 | font-weight: 700; | ||
| 1338 | font-size: 20px; | ||
| 1339 | text-transform: uppercase; | ||
| 1340 | } | ||
| 1341 | .emr_upload_form .shortpixel-offer .hidden { | ||
| 1342 | display: none !important; | ||
| 1343 | } | ||
| 1344 | .emr_upload_form .shortpixel-offer .img-wrapper { | ||
| 1345 | text-align: center; | ||
| 1346 | margin: 0 0 25px 0; | ||
| 1347 | } | ||
| 1348 | .emr_upload_form .shortpixel-offer .img-wrapper img { | ||
| 1349 | max-width: 140px; | ||
| 1350 | max-height: 140px; | ||
| 1351 | margin: 0; | ||
| 1352 | } | ||
| 1353 | .emr_upload_form .shortpixel-offer.envira-shortpixel-install { | ||
| 1354 | background: #fff; | ||
| 1355 | } | ||
| 1356 | .emr_upload_form .shortpixel-offer.theme-offer { | ||
| 1357 | background: #fff; | ||
| 1358 | } | ||
| 1359 | .emr_upload_form .shortpixel-offer.theme-offer img { | ||
| 1360 | max-width: 100%; | ||
| 1361 | } | ||
| 1362 | @media (max-width: 1200px) { | ||
| 1363 | .emr_upload_form .image_previews { | ||
| 1364 | text-align: center; | ||
| 1365 | } | ||
| 1366 | .emr_upload_form .option-flex-wrapper { | ||
| 1367 | flex-direction: column; | ||
| 1368 | } | ||
| 1369 | .emr_upload_form .option-flex-wrapper .options.wrapper { | ||
| 1370 | margin-left: 0; | ||
| 1371 | } | ||
| 1372 | } | ||
| 1373 | @media (max-width: 960px) { | ||
| 1374 | .emr_upload_form .upsell-wrapper { | ||
| 1375 | display: none; | ||
| 1376 | } | ||
| 1377 | } | ||
| 1378 | @media (max-width: 450px) { | ||
| 1379 | .emr_upload_form .replace_custom_date_wrapper { | ||
| 1380 | display: block; | ||
| 1381 | margin-top: 15px; | ||
| 1382 | font-size: 16px; | ||
| 1383 | } | ||
| 1384 | .emr_upload_form .location_option label { | ||
| 1385 | margin: 25px 0; | ||
| 1386 | display: inline-block; | ||
| 1387 | } | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | /*# sourceMappingURL=admin.css.map */ |
| 1 | {"version":3,"sourceRoot":"","sources":["../scss/_datepicker.scss","../scss/_screens.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;;;AClaD;EAGC;EACA;EACA;EACA;EACA;;AAEA;EACE;EACD;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EAEC;;AAGD;EACE;;AAGF;EAAI;;AAGJ;EAAQ;;AAGN;EAAK;;;AChCR;EAIC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;;AAGD;EAEC;;;AAOA;EAEE;;AACA;EAEE;;AAIL;EAEC;;AAED;EACC;;AAGD;EAGG;EACA;;AAEA;EAEE;EAEA;EACA;EACA;;AAIL;EACC;EACA;EACA;EACA;;AACA;EACC;EACA;;AAMD;EAEE;;AAGA;EAEE;EACH;;AAEG;EAEE;EACA;EACA;EACA;EACA;EACA;EACJ;EACA;EACA;;AAEA;EAAM;;AAEN;EAEC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EACC;;AAEG;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACL;;AAGG;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EAEG;EACA;EACA;EACA;;AAEP;EAEC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EAEA;EACA;EACA;EACA;;AAMG;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;;AAIH;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;;AAU/C;EAEE;;AAEF;EAEE;;AACA;EACC;;AAKH;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 | #remove-background-form form { | ||
| 2 | display: flex; | ||
| 3 | } | ||
| 4 | #remove-background-form .image_chooser.wrapper { | ||
| 5 | min-height: 0; | ||
| 6 | } | ||
| 7 | #remove-background-form .image_placeholder.is_image { | ||
| 8 | border: none; | ||
| 9 | width: 45%; | ||
| 10 | height: auto; | ||
| 11 | } | ||
| 12 | #remove-background-form .image_placeholder.is_image .textlayer, #remove-background-form .image_placeholder.is_image .image_size { | ||
| 13 | display: none; | ||
| 14 | } | ||
| 15 | #remove-background-form .bad-button { | ||
| 16 | text-align: right; | ||
| 17 | margin-right: 25px; | ||
| 18 | } | ||
| 19 | #remove-background-form .bad-button a { | ||
| 20 | visibility: hidden; | ||
| 21 | } | ||
| 22 | #remove-background-form .overlay { | ||
| 23 | visibility: hidden; | ||
| 24 | display: flex; | ||
| 25 | flex-direction: column; | ||
| 26 | justify-content: center; | ||
| 27 | align-items: center; | ||
| 28 | width: 100%; | ||
| 29 | height: 100%; | ||
| 30 | background-color: rgba(0, 0, 0, 0.2); | ||
| 31 | position: absolute; | ||
| 32 | top: 0; | ||
| 33 | } | ||
| 34 | #remove-background-form .lds-spinner { | ||
| 35 | color: official; | ||
| 36 | display: inline-block; | ||
| 37 | position: relative; | ||
| 38 | width: 80px; | ||
| 39 | height: 80px; | ||
| 40 | } | ||
| 41 | #remove-background-form .lds-spinner div { | ||
| 42 | transform-origin: 40px 40px; | ||
| 43 | animation: lds-spinner 1.2s linear infinite; | ||
| 44 | } | ||
| 45 | #remove-background-form .lds-spinner div:after { | ||
| 46 | content: " "; | ||
| 47 | display: block; | ||
| 48 | position: absolute; | ||
| 49 | top: 3px; | ||
| 50 | left: 37px; | ||
| 51 | width: 6px; | ||
| 52 | height: 18px; | ||
| 53 | border-radius: 20%; | ||
| 54 | background: #fff; | ||
| 55 | } | ||
| 56 | #remove-background-form .lds-spinner div:nth-child(1) { | ||
| 57 | transform: rotate(0deg); | ||
| 58 | animation-delay: -1.1s; | ||
| 59 | } | ||
| 60 | #remove-background-form .lds-spinner div:nth-child(2) { | ||
| 61 | transform: rotate(30deg); | ||
| 62 | animation-delay: -1s; | ||
| 63 | } | ||
| 64 | #remove-background-form .lds-spinner div:nth-child(3) { | ||
| 65 | transform: rotate(60deg); | ||
| 66 | animation-delay: -0.9s; | ||
| 67 | } | ||
| 68 | #remove-background-form .lds-spinner div:nth-child(4) { | ||
| 69 | transform: rotate(90deg); | ||
| 70 | animation-delay: -0.8s; | ||
| 71 | } | ||
| 72 | #remove-background-form .lds-spinner div:nth-child(5) { | ||
| 73 | transform: rotate(120deg); | ||
| 74 | animation-delay: -0.7s; | ||
| 75 | } | ||
| 76 | #remove-background-form .lds-spinner div:nth-child(6) { | ||
| 77 | transform: rotate(150deg); | ||
| 78 | animation-delay: -0.6s; | ||
| 79 | } | ||
| 80 | #remove-background-form .lds-spinner div:nth-child(7) { | ||
| 81 | transform: rotate(180deg); | ||
| 82 | animation-delay: -0.5s; | ||
| 83 | } | ||
| 84 | #remove-background-form .lds-spinner div:nth-child(8) { | ||
| 85 | transform: rotate(210deg); | ||
| 86 | animation-delay: -0.4s; | ||
| 87 | } | ||
| 88 | #remove-background-form .lds-spinner div:nth-child(9) { | ||
| 89 | transform: rotate(240deg); | ||
| 90 | animation-delay: -0.3s; | ||
| 91 | } | ||
| 92 | #remove-background-form .lds-spinner div:nth-child(10) { | ||
| 93 | transform: rotate(270deg); | ||
| 94 | animation-delay: -0.2s; | ||
| 95 | } | ||
| 96 | #remove-background-form .lds-spinner div:nth-child(11) { | ||
| 97 | transform: rotate(300deg); | ||
| 98 | animation-delay: -0.1s; | ||
| 99 | } | ||
| 100 | #remove-background-form .lds-spinner div:nth-child(12) { | ||
| 101 | transform: rotate(330deg); | ||
| 102 | animation-delay: 0s; | ||
| 103 | } | ||
| 104 | @keyframes lds-spinner { | ||
| 105 | 0% { | ||
| 106 | opacity: 1; | ||
| 107 | } | ||
| 108 | 100% { | ||
| 109 | opacity: 0; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | #remove-background-form * { | ||
| 113 | box-sizing: border-box; | ||
| 114 | } | ||
| 115 | #remove-background-form .img-comp-container { | ||
| 116 | position: relative; | ||
| 117 | height: 200px; | ||
| 118 | /*should be the same height as the images*/ | ||
| 119 | } | ||
| 120 | #remove-background-form .img-comp-img { | ||
| 121 | position: absolute; | ||
| 122 | width: auto; | ||
| 123 | height: auto; | ||
| 124 | overflow: hidden; | ||
| 125 | } | ||
| 126 | #remove-background-form .img-comp-img img { | ||
| 127 | display: block; | ||
| 128 | } | ||
| 129 | #remove-background-form .img-comp-slider { | ||
| 130 | position: absolute; | ||
| 131 | z-index: 9; | ||
| 132 | cursor: ew-resize; | ||
| 133 | /*set the appearance of the slider:*/ | ||
| 134 | width: 20px; | ||
| 135 | height: 20px; | ||
| 136 | background-color: #2196F3; | ||
| 137 | opacity: 0.7; | ||
| 138 | border-radius: 50%; | ||
| 139 | } | ||
| 140 | #remove-background-form .preview-area { | ||
| 141 | display: flex; | ||
| 142 | justify-content: center; | ||
| 143 | align-items: center; | ||
| 144 | width: 100%; | ||
| 145 | height: 100%; | ||
| 146 | } | ||
| 147 | #remove-background-form .preview-area h1 { | ||
| 148 | color: red !important; | ||
| 149 | } | ||
| 150 | |||
| 151 | /*# sourceMappingURL=remove_background.css.map */ |
| 1 | {"version":3,"sourceRoot":"","sources":["../scss/remove_background.scss"],"names":[],"mappings":"AAEG;EACA;;AAGD;EACE;;AAEF;EAEE;EACA;EACA;;AACA;EACE;;AAIJ;EAEE;EACA;;AACA;EACC;;AAIH;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAED;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;;AAEF;EACC;IACC;;EAED;IACC;;;AAMH;EACC;;AAGD;EACC;EACA;AAAe;;AAGhB;EACC;EACA;EACA;EACA;;AAGD;EACC;;AAGD;EACC;EACA;EACA;AACA;EACA;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA;;AAED;EACC","file":"remove_background.css"} | ||
| ... | \ 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: 4.1.4 | ||
| 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 | define( 'EMR_VERSION', '4.1.4' ); | ||
| 29 | |||
| 30 | if ( ! defined( 'ABSPATH' ) ) { | ||
| 31 | exit; // Exit if accessed directly. | ||
| 32 | } | ||
| 33 | |||
| 34 | /* Not sure why we define this? | ||
| 35 | if(!defined("S3_UPLOADS_AUTOENABLE")) { | ||
| 36 | define('S3_UPLOADS_AUTOENABLE', true); | ||
| 37 | } */ | ||
| 38 | |||
| 39 | if ( ! defined( 'EMR_ROOT_FILE' ) ) { | ||
| 40 | define( 'EMR_ROOT_FILE', __FILE__ ); | ||
| 41 | } | ||
| 42 | |||
| 43 | if ( ! defined( 'SHORTPIXEL_AFFILIATE_CODE' ) ) { | ||
| 44 | define( 'SHORTPIXEL_AFFILIATE_CODE', 'VKG6LYN28044' ); | ||
| 45 | } | ||
| 46 | |||
| 47 | /** Usage: | ||
| 48 | * Define in wp-config.php | ||
| 49 | * // User must have this capability to replace all | ||
| 50 | * define('EMR_CAPABILITY' ,'edit_upload_all' ); | ||
| 51 | * // User must have first capability to replace all OR second capability to replace only own files | ||
| 52 | * define('EMR_CAPABILITY' ,array('edit_upload_all', 'edit_upload_user') ); | ||
| 53 | * | ||
| 54 | * | ||
| 55 | **/ | ||
| 56 | if ( ! defined( 'EMR_CAPABILITY' ) ) { | ||
| 57 | define( 'EMR_CAPABILITY', false ); | ||
| 58 | } | ||
| 59 | |||
| 60 | /* if (! defined('EMR_CAPABILITY_USERONLY')) | ||
| 61 | define('EMR_CAPABILITY_USERONLY', false); */ | ||
| 62 | |||
| 63 | $plugin_path = plugin_dir_path( EMR_ROOT_FILE ); | ||
| 64 | |||
| 65 | require_once( $plugin_path . 'build/shortpixel/autoload.php' ); | ||
| 66 | require_once( $plugin_path . 'classes/compat.php' ); | ||
| 67 | require_once( $plugin_path . 'classes/functions.php' ); | ||
| 68 | //require_once( $plugin_path . 'classes/replacer.php' ); | ||
| 69 | require_once( $plugin_path . 'classes/uihelper.php' ); | ||
| 70 | //require_once( $plugin_path . 'classes/file.php' ); | ||
| 71 | require_once( $plugin_path . 'classes/cache.php' ); | ||
| 72 | require_once( $plugin_path . 'classes/api.php' ); | ||
| 73 | require_once( $plugin_path . 'classes/ajax.php' ); | ||
| 74 | require_once( $plugin_path . 'classes/emr-plugin.php' ); | ||
| 75 | require_once( $plugin_path . 'classes/installHelper.php' ); | ||
| 76 | |||
| 77 | // @todo Needs replacing with PSR-4 | ||
| 78 | require_once( $plugin_path . 'classes/Controller/ReplaceController.php'); | ||
| 79 | require_once( $plugin_path . 'classes/Controller/RemoteNoticeController.php'); | ||
| 80 | |||
| 81 | require_once( $plugin_path . 'classes/ViewController.php'); | ||
| 82 | require_once( $plugin_path . 'classes/ViewController/UploadViewController.php'); | ||
| 83 | require_once( $plugin_path . 'classes/ViewController/ReplaceViewController.php'); | ||
| 84 | require_once( $plugin_path . 'classes/ViewController/RemoveBackgroundViewController.php'); | ||
| 85 | |||
| 86 | require_once( $plugin_path . 'classes/externals.php' ); | ||
| 87 | require_once( $plugin_path . 'classes/external/elementor.php' ); | ||
| 88 | require_once( $plugin_path . 'classes/external/wpbakery.php' ); | ||
| 89 | require_once( $plugin_path . 'classes/external/upsell_installer.php' ); | ||
| 90 | require_once( $plugin_path . 'classes/external/siteorigin.php' ); | ||
| 91 | require_once( $plugin_path . 'classes/external/wp-offload.php' ); | ||
| 92 | |||
| 93 | require_once( $plugin_path . 'thumbnail_updater.php' ); | ||
| 94 | |||
| 95 | function emr() | ||
| 96 | { | ||
| 97 | return EnableMediaReplace\EnableMediaReplacePlugin::get(); | ||
| 98 | } | ||
| 99 | emr(); // runtime. | ||
| 100 | |||
| 101 | //register_uninstall_hook( __FILE__, '\EnableMediaReplace\emr_uninstall' ); | ||
| 102 | register_deactivation_hook( __FILE__, array('\EnableMediaReplace\InstallHelper','deactivatePlugin') ); | ||
| 103 | register_uninstall_hook(__FILE__, array('\EnableMediaReplace\InstallHelper','uninstallPlugin') ); |
10.5 KB
| 1 | <?php // Silence is golden | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
5.51 KB
6.42 KB
4.63 KB
116 KB
| 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 |
6.83 KB
6.82 KB
7.72 KB
| 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 | var is_dragging = false; | ||
| 12 | |||
| 13 | this.init = function() | ||
| 14 | { | ||
| 15 | |||
| 16 | if ( emr_options.is_debug) | ||
| 17 | { | ||
| 18 | this.is_debug = true; | ||
| 19 | this.debug('EMR Debug is active'); | ||
| 20 | } | ||
| 21 | |||
| 22 | $('input[name="timestamp_replace"]').on('change', $.proxy(this.checkCustomDate, this)); | ||
| 23 | $('input[name="replace_type"]').on('change', $.proxy(this.showReplaceOptions, this)); | ||
| 24 | $('input[name="userfile"]').on('change', $.proxy(this.handleImage, this)); | ||
| 25 | $('.replace_custom_date').on('click', $.proxy(this.updateCustomDate, this)); | ||
| 26 | |||
| 27 | // DragDrop | ||
| 28 | //$(document).on('dragover', $.proxy(this.dragOverArea, this)); | ||
| 29 | //$(document).on('dragleave', $.proxy(this.dragOutArea, this)); | ||
| 30 | document.addEventListener('dragover', this.dragOverArea.bind(this), false ); | ||
| 31 | document.addEventListener('dragleave', this.dragOutArea.bind(this), false ); | ||
| 32 | |||
| 33 | |||
| 34 | |||
| 35 | $('.emr_drop_area').on('drop', $.proxy(this.fileDrop, this)); | ||
| 36 | $('.upload-file-action').on('click', function () { | ||
| 37 | var input = document.getElementById('upload-file').click(); | ||
| 38 | }); | ||
| 39 | |||
| 40 | this.checkCustomDate(); | ||
| 41 | this.loadDatePicker(); | ||
| 42 | |||
| 43 | var source = $('.image_placeholder').first(); | ||
| 44 | if (typeof( $(source).data('filetype') ) !== 'undefined') | ||
| 45 | { | ||
| 46 | source_type = $(source).data('filetype').trim(); | ||
| 47 | this.debug('detected type - ' + source_type); | ||
| 48 | } | ||
| 49 | else | ||
| 50 | source_type = ''; // error state | ||
| 51 | |||
| 52 | if (source.hasClass('is_image')) | ||
| 53 | { | ||
| 54 | source_is_image = true; | ||
| 55 | } | ||
| 56 | |||
| 57 | this.updateTextLayer(source, false); | ||
| 58 | this.showReplaceOptions(); | ||
| 59 | |||
| 60 | |||
| 61 | } | ||
| 62 | |||
| 63 | this.loadDatePicker = function() | ||
| 64 | { | ||
| 65 | $('#emr_datepicker').datepicker({ | ||
| 66 | dateFormat: emr_options.dateFormat, | ||
| 67 | onClose: function() { | ||
| 68 | var date = $(this).datepicker( 'getDate' ); | ||
| 69 | if (date) { | ||
| 70 | var formattedDate = (date.getFullYear()) + "-" + | ||
| 71 | (date.getMonth()+1) + "-" + | ||
| 72 | date.getDate(); | ||
| 73 | $('input[name="custom_date_formatted"]').val(formattedDate); | ||
| 74 | //$('input[name="custom_date"]').val($.datepicker.parseDate( emr_options.dateFormat, date)); | ||
| 75 | } | ||
| 76 | }, | ||
| 77 | }); | ||
| 78 | } | ||
| 79 | |||
| 80 | this.checkCustomDate = function() | ||
| 81 | { | ||
| 82 | if ($('input[name="timestamp_replace"]:checked').val() == 3) | ||
| 83 | this.showCustomDate(); | ||
| 84 | else | ||
| 85 | this.hideCustomDate(); | ||
| 86 | } | ||
| 87 | this.showCustomDate = function() | ||
| 88 | { | ||
| 89 | $('.custom_date').css('visibility', 'visible').fadeTo(100, 1); | ||
| 90 | } | ||
| 91 | this.hideCustomDate = function() | ||
| 92 | { | ||
| 93 | $('.custom_date').fadeTo(100,0, | ||
| 94 | function () | ||
| 95 | { | ||
| 96 | $('.custom_date').css('visibility', 'hidden'); | ||
| 97 | }); | ||
| 98 | } | ||
| 99 | this.handleImage = function(e) | ||
| 100 | { | ||
| 101 | this.toggleErrors(false); | ||
| 102 | var target = e.target; | ||
| 103 | var file = target.files[0]; | ||
| 104 | |||
| 105 | if (! target.files || target.files.length <= 0) // FileAPI appears to be not present, handle files on backend. | ||
| 106 | { | ||
| 107 | if ($('input[name="userfile"]').val().length > 0) | ||
| 108 | this.checkSubmit(); | ||
| 109 | console.log('FileAPI not detected'); | ||
| 110 | return false; | ||
| 111 | } | ||
| 112 | |||
| 113 | var status = this.checkUpload(file); | ||
| 114 | this.debug('check upload status ' + status); | ||
| 115 | this.debug('file size:' + file.size); | ||
| 116 | |||
| 117 | if (status) | ||
| 118 | { | ||
| 119 | this.updatePreview(file); | ||
| 120 | } | ||
| 121 | else { | ||
| 122 | this.updatePreview(null); | ||
| 123 | } | ||
| 124 | this.checkSubmit(); | ||
| 125 | } | ||
| 126 | this.updatePreview = function(file) | ||
| 127 | { | ||
| 128 | var preview = $('.image_placeholder').last(); | ||
| 129 | |||
| 130 | $(preview).find('img').remove(); | ||
| 131 | $(preview).removeClass('is_image not_image is_document'); | ||
| 132 | var is_empty = false; | ||
| 133 | |||
| 134 | if (file !== null) /// file is null when empty, or error | ||
| 135 | { | ||
| 136 | target_is_image = (file.type.indexOf('image') >= 0) ? true : false; | ||
| 137 | target_type = file.type.trim(); | ||
| 138 | } | ||
| 139 | else | ||
| 140 | { | ||
| 141 | is_empty = true; | ||
| 142 | } | ||
| 143 | // If image, load thumbnail and get dimensions. | ||
| 144 | if (file && target_is_image) | ||
| 145 | { | ||
| 146 | var img = new Image(); | ||
| 147 | img.src = window.URL.createObjectURL(file); | ||
| 148 | self = this; | ||
| 149 | |||
| 150 | img.addEventListener("load", function () { | ||
| 151 | // with formats like svg it can be rough. | ||
| 152 | |||
| 153 | var width = img.naturalWidth; | ||
| 154 | var height = img.naturalHeight; | ||
| 155 | |||
| 156 | if (width == 0) | ||
| 157 | width = img.width; | ||
| 158 | if (height == 0) | ||
| 159 | height = img.height; | ||
| 160 | |||
| 161 | img.setAttribute('style', 'z-index:2; position: relative; max-width:100%; max-height: 100%; width: ' + width + 'px; height: ' + height + 'px;'); | ||
| 162 | |||
| 163 | self.updateTextLayer(preview, width + ' x ' + height); | ||
| 164 | self.updateFileSize(preview, file); | ||
| 165 | }); | ||
| 166 | |||
| 167 | $(preview).prepend(img); | ||
| 168 | $(preview).addClass('is_image'); | ||
| 169 | } | ||
| 170 | else if(file === null) | ||
| 171 | { | ||
| 172 | $(preview).addClass('not_image'); | ||
| 173 | $(preview).find('.dashicons').removeClass().addClass('dashicons dashicons-no'); | ||
| 174 | //$(preview).find('.textlayer').text(''); | ||
| 175 | this.updateTextLayer(preview, ''); | ||
| 176 | this.updateFileSize(preview, null); | ||
| 177 | this.debug('File is null'); | ||
| 178 | } | ||
| 179 | else { // not an image | ||
| 180 | $(preview).addClass('not_image is_document'); | ||
| 181 | $(preview).find('.dashicons').removeClass().addClass('dashicons dashicons-media-document'); | ||
| 182 | //$(preview).find('.textlayer').text(file.name); | ||
| 183 | this.updateTextLayer(preview, file.name); | ||
| 184 | this.updateFileSize(preview, file); | ||
| 185 | this.debug('Not image, media document'); | ||
| 186 | } | ||
| 187 | |||
| 188 | if (! is_empty && target_type != source_type) | ||
| 189 | { | ||
| 190 | this.debug(target_type + ' not ' + source_type); | ||
| 191 | var falsePositive = this.checkFalsePositiveType(source_type, target_type); | ||
| 192 | if (! falsePositive) | ||
| 193 | this.warningFileType(source_type, target_type); | ||
| 194 | } | ||
| 195 | |||
| 196 | if (! is_empty && emr_options.allowed_mime.indexOf(target_type) == -1) | ||
| 197 | { | ||
| 198 | this.debug(target_type + ' not ' + ' in allowed types '); | ||
| 199 | var falsePositive = this.checkFalsePositiveType(source_type, target_type); | ||
| 200 | |||
| 201 | if (! falsePositive) | ||
| 202 | this.warningMimeType(); | ||
| 203 | } | ||
| 204 | // this.debug(emr_options.allowed_mime); | ||
| 205 | |||
| 206 | } | ||
| 207 | this.checkFalsePositiveType = function(source_type, target_type) | ||
| 208 | { | ||
| 209 | // windows (sigh) reports application/zip as application/x-zip-compressed. Or something else, why not. | ||
| 210 | if (source_type.indexOf('zip') >= 0 && target_type.indexOf('zip') >= 0) | ||
| 211 | { | ||
| 212 | this.debug('Finding ' + source_type + ' ' + target_type + ' close enough, false positive'); | ||
| 213 | return true; | ||
| 214 | } | ||
| 215 | return false; | ||
| 216 | } | ||
| 217 | // replace the text, check if text is there ( or hide ), and fix the layout. | ||
| 218 | this.updateTextLayer = function (preview, newtext) | ||
| 219 | { | ||
| 220 | textlayer = $(preview).find('.textlayer'); | ||
| 221 | textlayer.css('opacity', '0'); | ||
| 222 | if (newtext !== false) | ||
| 223 | textlayer.text(newtext); | ||
| 224 | |||
| 225 | if (textlayer.text() !== '') | ||
| 226 | { | ||
| 227 | textlayer.css('opacity', '0.7'); | ||
| 228 | // textlayer.css('margin-left', '-' + (textlayer.width() / 2 ) + 'px'); | ||
| 229 | } | ||
| 230 | |||
| 231 | } | ||
| 232 | this.updateFileSize = function(preview, file) | ||
| 233 | { | ||
| 234 | if (file === null) | ||
| 235 | { | ||
| 236 | $(preview).find('.image_size').text(''); | ||
| 237 | return; | ||
| 238 | } | ||
| 239 | var bytes = file.size; | ||
| 240 | if (bytes == 0) { return "0.00 B"; } | ||
| 241 | var e = Math.floor(Math.log(bytes) / Math.log(1024)); | ||
| 242 | var size = (bytes/Math.pow(1024, e)).toFixed(2)+' '+' KMGTP'.charAt(e)+'B'; | ||
| 243 | |||
| 244 | $(preview).find('.image_size').text(size); | ||
| 245 | } | ||
| 246 | this.updateCustomDate = function(e) | ||
| 247 | { | ||
| 248 | var $target = $(e.target); | ||
| 249 | var min = $target.data('min'); | ||
| 250 | var hour = $target.data('hour'); | ||
| 251 | var date = $target.data('date'); | ||
| 252 | var format = $target.data('format'); | ||
| 253 | |||
| 254 | $('input[name="custom_date"]').val(date); | ||
| 255 | $('input[name="custom_hour"]').val(hour); | ||
| 256 | $('input[name="custom_minute"]').val(min); | ||
| 257 | $('input[name="custom_date_formatted"]').val(format); | ||
| 258 | } | ||
| 259 | this.checkSubmit = function() | ||
| 260 | { | ||
| 261 | var check = ($('input[name="userfile"]').val().length > 0) ? true : false; | ||
| 262 | |||
| 263 | if (check) | ||
| 264 | { | ||
| 265 | $('input[type="submit"]').prop('disabled', false); | ||
| 266 | } | ||
| 267 | else { | ||
| 268 | $('input[type="submit"]').prop('disabled', true); | ||
| 269 | } | ||
| 270 | } | ||
| 271 | this.toggleErrors = function(toggle) | ||
| 272 | { | ||
| 273 | $('.form-error').fadeOut(); | ||
| 274 | $('.form-warning').fadeOut(); | ||
| 275 | } | ||
| 276 | this.checkUpload = function(fileItem) | ||
| 277 | { | ||
| 278 | var maxsize = emr_options.maxfilesize; | ||
| 279 | |||
| 280 | if ($('input[name="userfile"]').val().length <= 0) | ||
| 281 | { | ||
| 282 | console.info('[EMR] - Upload file value not set in form. Pick a file'); | ||
| 283 | $('input[name="userfile"]').val(''); | ||
| 284 | return false; | ||
| 285 | } | ||
| 286 | |||
| 287 | if (fileItem.size > maxsize) | ||
| 288 | { | ||
| 289 | console.info('[EMR] - File too big for uploading - exceeds upload limits'); | ||
| 290 | this.errorFileSize(fileItem); | ||
| 291 | $('input[name="userfile"]').val(''); | ||
| 292 | return false; | ||
| 293 | } | ||
| 294 | return true; | ||
| 295 | } | ||
| 296 | this.errorFileSize = function(fileItem) | ||
| 297 | { | ||
| 298 | $('.form-error.filesize').find('.fn').text(fileItem.name); | ||
| 299 | $('.form-error.filesize').fadeIn(); | ||
| 300 | } | ||
| 301 | this.warningFileType = function(source_type, target_type) | ||
| 302 | { | ||
| 303 | $('.form-warning.filetype').find('.source_type').text(source_type); | ||
| 304 | $('.form-warning.filetype').find('.target_type').text(target_type); | ||
| 305 | $('.form-warning.filetype').fadeIn(); | ||
| 306 | } | ||
| 307 | this.warningMimeType = function(fileItem) | ||
| 308 | { | ||
| 309 | $('.form-warning.mimetype').fadeIn(); | ||
| 310 | } | ||
| 311 | this.debug = function(message) | ||
| 312 | { | ||
| 313 | console.debug(message); | ||
| 314 | } | ||
| 315 | this.showReplaceOptions = function(e) | ||
| 316 | { | ||
| 317 | $('section.options .location_option').hide(); | ||
| 318 | var replace_option = $('input[name="replace_type"]:checked').val(); | ||
| 319 | if (replace_option == 'replace_and_search') | ||
| 320 | { | ||
| 321 | $('section.options .location_option').show(); | ||
| 322 | } | ||
| 323 | |||
| 324 | } | ||
| 325 | this.dragOverArea = function(e) | ||
| 326 | { | ||
| 327 | e.preventDefault(); | ||
| 328 | e.stopPropagation(); | ||
| 329 | console.log(e); | ||
| 330 | |||
| 331 | if (true == this.is_dragging) | ||
| 332 | return; | ||
| 333 | |||
| 334 | var el = document.getElementById('emr-drop-area'); | ||
| 335 | var showEl = el.cloneNode(true); | ||
| 336 | showEl.id = 'emr-drop-area-active'; | ||
| 337 | |||
| 338 | var child = document.body.appendChild(showEl); | ||
| 339 | |||
| 340 | child.addEventListener('drop', this.fileDrop.bind(this), false); | ||
| 341 | |||
| 342 | child.addEventListener('dragover', function(event){ | ||
| 343 | event.preventDefault(); | ||
| 344 | }) | ||
| 345 | |||
| 346 | |||
| 347 | this.is_dragging = true; | ||
| 348 | } | ||
| 349 | |||
| 350 | this.dragOutArea = function(e) | ||
| 351 | { | ||
| 352 | |||
| 353 | // event is not passed on filedrop. remove overlay then. | ||
| 354 | if (typeof e !== 'undefined') | ||
| 355 | { | ||
| 356 | e.preventDefault(); | ||
| 357 | e.stopPropagation(); | ||
| 358 | |||
| 359 | if (e.clientX != 0 || e.clientY != 0) { | ||
| 360 | return false; | ||
| 361 | } | ||
| 362 | } | ||
| 363 | var removeEl = document.getElementById('emr-drop-area-active'); | ||
| 364 | if (removeEl !== null) | ||
| 365 | document.getElementById('emr-drop-area-active').remove(); | ||
| 366 | |||
| 367 | this.is_dragging = false; | ||
| 368 | } | ||
| 369 | this.fileDrop = function (e) | ||
| 370 | { | ||
| 371 | // var ev = e.originalEvent; | ||
| 372 | this.dragOutArea(); | ||
| 373 | //ev.preventDefault(); | ||
| 374 | e.stopPropagation(); | ||
| 375 | e.preventDefault(); | ||
| 376 | |||
| 377 | if (e.dataTransfer.items) { | ||
| 378 | // Use DataTransferItemList interface to access the file(s) | ||
| 379 | document.getElementById('upload-file').files = e.dataTransfer.files; | ||
| 380 | $('input[name="userfile"]').trigger('change'); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | } // emrIf | ||
| 384 | |||
| 385 | jQuery(document).ready(function($) | ||
| 386 | { | ||
| 387 | window.enableMediaReplace = new emrIf($); | ||
| 388 | window.enableMediaReplace.init(); | ||
| 389 | }); | ||
| 390 | |||
| 391 | |||
| 392 | function emrDelayedInit() { | ||
| 393 | console.log('Checking delayed init '); | ||
| 394 | if(typeof window.enableMediaReplace == "undefined") { | ||
| 395 | console.log(emrIf); | ||
| 396 | window.enableMediaReplace = new emrIf(jQuery); | ||
| 397 | window.enableMediaReplace.init(); | ||
| 398 | } | ||
| 399 | else if (typeof window.enableMediaReplace !== 'undefined') | ||
| 400 | { | ||
| 401 | // All fine. | ||
| 402 | } | ||
| 403 | else { // Nothing yet, try again. | ||
| 404 | setTimeout(emrdelayedInit, 3000); | ||
| 405 | } | ||
| 406 | } | ||
| 407 | setTimeout(emrDelayedInit, 3000); |
| 1 | window.addEventListener('load', function(event) { | ||
| 2 | |||
| 3 | var url = new URL(window.location.href); | ||
| 4 | url.searchParams.set('emr_success', 1); | ||
| 5 | |||
| 6 | var timeout = 10; | ||
| 7 | if (emr_success_options.timeout) | ||
| 8 | timeout = emr_success_options.timeout; | ||
| 9 | var counter = document.getElementById('redirect_counter'); | ||
| 10 | var redirectUrl = document.getElementById('redirect_url'); | ||
| 11 | var redirected = false; | ||
| 12 | |||
| 13 | counter.textContent = timeout; | ||
| 14 | |||
| 15 | var t = window.setInterval(function () { | ||
| 16 | counter.textContent = timeout; | ||
| 17 | timeout--; | ||
| 18 | if (timeout <= 0 && false == redirected) | ||
| 19 | { | ||
| 20 | window.location.href = redirectUrl; | ||
| 21 | redirected = true; | ||
| 22 | window.clearInterval(t); | ||
| 23 | } | ||
| 24 | }, 1000); | ||
| 25 | |||
| 26 | }); |
| 1 | jQuery(document).ready(function ($) { | ||
| 2 | |||
| 3 | // Init | ||
| 4 | $('input[type=radio][name=background_type]').on('change', backgroundInputs); | ||
| 5 | $('#bg_transparency').on('input', transparancyOptions); | ||
| 6 | |||
| 7 | backgroundInputs(); // init initial | ||
| 8 | transparancyOptions(); | ||
| 9 | |||
| 10 | $('.replace_type.wrapper input').on('change', function () { | ||
| 11 | $('#replace_image_button').prop('disabled', 'disabled'); | ||
| 12 | }); | ||
| 13 | |||
| 14 | // Remove bg click | ||
| 15 | $('#remove_background_button').on('click', () => { | ||
| 16 | const method = 'POST' | ||
| 17 | const url = emrObject.ajax_url; | ||
| 18 | // const image = emrObject.base_url; | ||
| 19 | const nonce = emrObject.nonce; | ||
| 20 | const attachment_id = $('input[name="ID"]').val(); | ||
| 21 | const action = 'emr_remove_background'; | ||
| 22 | const bgType = $('input[type=radio][name="background_type"]:checked').val(); | ||
| 23 | const cLvl = $('input[type=radio][name="compression_level"]:checked').val(); | ||
| 24 | let background = { | ||
| 25 | type: "transparent" | ||
| 26 | } | ||
| 27 | |||
| 28 | background = { | ||
| 29 | type: bgType, | ||
| 30 | color: $('#bg_color').val(), | ||
| 31 | transparency: $('#bg_transparency').val() | ||
| 32 | } | ||
| 33 | |||
| 34 | $.ajax({ | ||
| 35 | method, | ||
| 36 | url, | ||
| 37 | data: { | ||
| 38 | action, | ||
| 39 | nonce, | ||
| 40 | attachment_id, | ||
| 41 | background, | ||
| 42 | compression_level : cLvl | ||
| 43 | }, | ||
| 44 | beforeSend: function () { | ||
| 45 | $('html, body').animate({ | ||
| 46 | scrollTop: $(".emr_upload_form").offset().top | ||
| 47 | }, 1000); | ||
| 48 | $('input[type=radio][name=background_type]').attr('disabled', 'disabled'); | ||
| 49 | $('input[type=radio][name=compression_level]').attr('disabled', 'disabled'); | ||
| 50 | $('#remove_background_button').attr('disabled', 'disabled'); | ||
| 51 | $('h1.response').remove(); | ||
| 52 | $('#overlay').css('visibility', 'visible'); | ||
| 53 | var preview = $('.image_placeholder').last(); | ||
| 54 | preview.find('img').remove(); | ||
| 55 | // $('#preview-area').hide(); | ||
| 56 | }, | ||
| 57 | success: function (response) { | ||
| 58 | var preview = $('.image_placeholder').last(); | ||
| 59 | |||
| 60 | if (response.success) { | ||
| 61 | |||
| 62 | |||
| 63 | $('#overlay').css('visibility', 'hidden'); | ||
| 64 | preview.find('img').remove(); | ||
| 65 | preview.removeClass('is_image not_image is_document'); | ||
| 66 | |||
| 67 | $('#replace_image_button').prop('disabled', false); | ||
| 68 | |||
| 69 | var img = new Image(); | ||
| 70 | img.src = response.image; | ||
| 71 | img.setAttribute('style', 'height: inherit;'); | ||
| 72 | |||
| 73 | preview.prepend(img); | ||
| 74 | // preview.removeClass('not_image'); | ||
| 75 | preview.addClass('is_image'); | ||
| 76 | |||
| 77 | $('input[name="key"]').val(response.key); | ||
| 78 | $('input[type=radio][name=background_type]').attr('disabled', false); | ||
| 79 | $('input[type=radio][name=compression_level]').attr('disabled', false); | ||
| 80 | $('#remove_background_button').attr('disabled', false); | ||
| 81 | |||
| 82 | var badBg = document.getElementById('bad-background-link'); | ||
| 83 | var href = badBg.dataset.link; | ||
| 84 | href = href.replace('{url}', response.url); | ||
| 85 | href = href.replace('{settings}', response.settings); | ||
| 86 | |||
| 87 | badBg.setAttribute('href', href); | ||
| 88 | |||
| 89 | badBg.style.visibility = 'visible'; | ||
| 90 | /* $('#removed_image').html(` | ||
| 91 | <div class="img-comp-container"> | ||
| 92 | <div class="img-comp-img"> | ||
| 93 | <img src="${image}" width="${width}" height="${height}" /> | ||
| 94 | </div> | ||
| 95 | |||
| 96 | </div> | ||
| 97 | `); */ | ||
| 98 | // initComparisons(); | ||
| 99 | }else{ | ||
| 100 | |||
| 101 | preview.prepend(`<h1 class='response'>${response.message}</h1>`); | ||
| 102 | $('#remove_background_button').attr('disabled', false) | ||
| 103 | $('input[type=radio][name=background_type]').attr('disabled', false) | ||
| 104 | $('input[type=radio][name=compression_level]').attr('disabled', false) | ||
| 105 | $('#overlay').css('visibility', 'hidden'); | ||
| 106 | //$('#preview-area').show(); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | }) | ||
| 110 | }); | ||
| 111 | |||
| 112 | function backgroundInputs () { | ||
| 113 | const bgInputs = $('#solid_selecter'); | ||
| 114 | var input = $('input[type=radio][name=background_type]:checked'); | ||
| 115 | if (input.val() === 'solid') { | ||
| 116 | bgInputs.show(); | ||
| 117 | } else { | ||
| 118 | bgInputs.hide(); | ||
| 119 | } | ||
| 120 | |||
| 121 | }; | ||
| 122 | |||
| 123 | $('#bg_display_picker').on('input', function () { | ||
| 124 | $('#color_range').html($(this).val()); | ||
| 125 | $('#bg_color').val($(this).val()); | ||
| 126 | }); | ||
| 127 | |||
| 128 | function transparancyOptions() { | ||
| 129 | $('#transparency_range').html($('#bg_transparency').val()); | ||
| 130 | }; | ||
| 131 | |||
| 132 | }); |
| 1 | jQuery(document).ready(function($) | ||
| 2 | { | ||
| 3 | $('.emr-installer').on('click', function(e){ | ||
| 4 | e.preventDefault(); | ||
| 5 | var button = $(this); | ||
| 6 | var plugin = button.data('plugin'); | ||
| 7 | var nonce = $('#upsell-nonce').val(); | ||
| 8 | |||
| 9 | button.text(emr_upsell.installing); | ||
| 10 | |||
| 11 | var enr_eg_opts = { | ||
| 12 | url: emr_upsell.ajax, | ||
| 13 | type: 'post', | ||
| 14 | async: true, | ||
| 15 | cache: false, | ||
| 16 | dataType: 'json', | ||
| 17 | data: { | ||
| 18 | action: 'emr_plugin_install', | ||
| 19 | nonce: nonce, | ||
| 20 | plugin: plugin //'https://downloads.wordpress.org/plugin/envira-gallery-lite.zip', | ||
| 21 | }, | ||
| 22 | success: function(response) { | ||
| 23 | $(button).addClass('hidden'); | ||
| 24 | |||
| 25 | $('.emr-activate[data-plugin="' + plugin + '"]').removeClass('hidden'); | ||
| 26 | |||
| 27 | }, | ||
| 28 | error: function(xhr, textStatus, e) { | ||
| 29 | }, | ||
| 30 | }; | ||
| 31 | |||
| 32 | $.ajax(enr_eg_opts); | ||
| 33 | }); | ||
| 34 | |||
| 35 | $('.emr-activate').on('click', function(e){ | ||
| 36 | e.preventDefault(); | ||
| 37 | |||
| 38 | var button = $(this); | ||
| 39 | var plugin = button.data('plugin'); | ||
| 40 | var nonce = $('#upsell-nonce-activate').val(); | ||
| 41 | |||
| 42 | var enr_eg_opts = { | ||
| 43 | url: emr_upsell.ajax, | ||
| 44 | type: 'post', | ||
| 45 | async: true, | ||
| 46 | cache: false, | ||
| 47 | dataType: 'json', | ||
| 48 | data: { | ||
| 49 | action: 'emr_plugin_activate', | ||
| 50 | nonce: nonce, | ||
| 51 | plugin: plugin, | ||
| 52 | }, | ||
| 53 | success: function(response) { | ||
| 54 | $(button).addClass('hidden') | ||
| 55 | $('.emr-activate-done[data-plugin="' + plugin + '"]').removeClass('hidden'); | ||
| 56 | |||
| 57 | }, | ||
| 58 | error: function(xhr, textStatus, e) { | ||
| 59 | }, | ||
| 60 | }; | ||
| 61 | $.ajax(enr_eg_opts); | ||
| 62 | }); | ||
| 63 | |||
| 64 | }); |
No preview for this file type
| 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 |
No preview for this file type
| 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 |
No preview for this file type
| 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 |
No preview for this file type
| 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 |
No preview for this file type
| 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 | "が置換されますのでご注意ください。" |
No preview for this file type
| 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 |
No preview for this file type
| 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" |
No preview for this file type
| 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" |
No preview for this file type
| 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 "Загрузка файла для замены" |
No preview for this file type
| 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" |
No preview for this file type
| 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 |
No preview for this file type
| 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, remove background, replace jpg, change media, replace media, image, file | ||
| 5 | Requires at least: 4.9.7 | ||
| 6 | Tested up to: 6.4 | ||
| 7 | Requires PHP: 5.6 | ||
| 8 | Stable tag: 4.1.4 | ||
| 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! Now fully compatible with <a href="https://wordpress.org/plugins/amazon-s3-and-cloudfront/" target="_blank">WP Offload Media!</a> | ||
| 15 | New beta feature! You can now remove the background of your images for better integration with eCommerce solutions! | ||
| 16 | Supported by the friendly team that created <a href="https://wordpress.org/plugins/shortpixel-image-optimiser/" target="_blank">ShortPixel</a> :)** | ||
| 17 | |||
| 18 | #### A real timesaver | ||
| 19 | |||
| 20 | Don't you find it tedious and complicated to first delete a file and then upload another one with the exact same name every time you want to update an image or other uploaded file in the WordPress media library? | ||
| 21 | |||
| 22 | Well, no longer! | ||
| 23 | |||
| 24 | Now you can replace any uploaded file in the Edit Media view, where it should be. Replacing Media can be done in two ways: | ||
| 25 | |||
| 26 | #### It's simple to replace a file | ||
| 27 | |||
| 28 | 1. Simply replace the file. This option requires you to upload a file of the same type as the file you want to replace. The attachment name remains the same regardless of what the file you upload is called. | ||
| 29 | 2. Replace the file, use the new file name, and update all links. If you check this option, the old file will be replaced with the name and type of the file you are uploading. All links pointing to the current file will be updated to point to the new file name. Additional options for the folder to put the new file in or the date of the new file are also available on the replace screen. | ||
| 30 | |||
| 31 | This plugin is very powerful and a must-have for all major websites built with WordPress. It also offers a preview of the replaced image! | ||
| 32 | |||
| 33 | #### New beta feature: You can now remove the background of any image! | ||
| 34 | Similar to replacing media, you can also remove the background of the images from the Media Library! The background removal feature sends the images to ShortPixel's API, removes the background and sends them back in a preview window. If everything looks good, just replace the image with the one that has the background removed! If the source image is a PNG file, you will get a transparent background, while the other images default to a solid white background. You also have the option to choose a different color with an embedded color picker. | ||
| 35 | The background removal feature is still in beta and will be free of charge for a reasonable usage. | ||
| 36 | |||
| 37 | If you don't want to use the background removal feature, add this line to your theme's functions.php file, or use a plugin like <a href="https://wordpress.org/plugins/code-snippets/" target="_blank">Code Snippets</a>: | ||
| 38 | |||
| 39 | ```add_filter( 'emr/feature/background', '__return_false' );``` | ||
| 40 | |||
| 41 | To shorten the wait time before redirecting to the media editing screen, use the following filter and specify the wait time in seconds (0 means that redirection is immediate, but may cause problems in certain configurations): | ||
| 42 | |||
| 43 | ```add_filter('emr/success/timeout', function () { return 3; });``` | ||
| 44 | |||
| 45 | #### Show file modification time | ||
| 46 | |||
| 47 | There is a shortcode that takes the file modification date and displays it in a post or on a page. The code is: | ||
| 48 | `[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. | ||
| 49 | |||
| 50 | So `[file_modified id=870]` would show the last time the file with ID 870 was updated on your site. To get the ID for a file, check the URL when editing a file in the media library (see screenshot #4) | ||
| 51 | |||
| 52 | If you want more control over the format in which the time is shown, you can use the format option. So `[file_modified id=870 format=Y-m-d]` would show the date the file was modified but not the time. The format string uses [the standard PHP date() formatting tags](http://php.net/manual/en/function.date.php). | ||
| 53 | |||
| 54 | **Other plugins by [ShortPixel](https://shortpixel.com):** | ||
| 55 | |||
| 56 | * [ShortPixel Image Optimizer](https://wordpress.org/plugins/shortpixel-image-optimiser/) - Image optimization & compression for all the images on your website, including WebP & AVIF delivery | ||
| 57 | * [ShortPixel Adaptive Images](https://wordpress.org/plugins/shortpixel-adaptive-images/) - On-the-fly image optimization & CDN delivery | ||
| 58 | * [Resize Image After Upload](https://wordpress.org/plugins/resize-image-after-upload/) - Automatically resize each uploaded image | ||
| 59 | * [reGenerate Thumbnails Advanced](https://wordpress.org/plugins/regenerate-thumbnails-advanced/) - Easily regenerate thumbnails | ||
| 60 | * [WP SVG Images](https://wordpress.org/plugins/wp-svg-images/) - Secure upload of SVG files to Media Library | ||
| 61 | * [ShortPixel Critical CSS](https://wordpress.org/plugins/shortpixel-critical-css/) - Automatically generate above-the-fold CSS for fatster loading times and better SEO scores | ||
| 62 | |||
| 63 | **Get in touch!** | ||
| 64 | |||
| 65 | * Email <a href="https://shortpixel.com/contact" target="_blank">https://shortpixel.com/contact</a> | ||
| 66 | * Twitter <a href="https://twitter.com/shortpixel" target="_blank">https://twitter.com/shortpixel</a> | ||
| 67 | * Facebook <a href="https://www.facebook.com/ShortPixel" target="_blank">https://www.facebook.com/ShortPixel</a> | ||
| 68 | * LinkedIn <a href="https://www.linkedin.com/company/shortpixel" target="_blank">https://www.linkedin.com/company/shortpixel</a> | ||
| 69 | |||
| 70 | == Changelog == | ||
| 71 | |||
| 72 | = 4.1.4 = | ||
| 73 | |||
| 74 | Release date: September 22, 2023 | ||
| 75 | * Fix: The latest security fix was breaking the replacements made with Beaver Builder (and possibly other builders); | ||
| 76 | |||
| 77 | = 4.1.3 = | ||
| 78 | |||
| 79 | Release date: September 14, 2023 | ||
| 80 | * Fix: A possible PHP Object Injection was patched, which could be exploited under certain conditions; | ||
| 81 | * Fix: ShortPixel Image Optimizer handles offloading when both plugins are used with WP Offload Media. | ||
| 82 | |||
| 83 | = 4.1.2 = | ||
| 84 | |||
| 85 | Release date: April 24, 2023 | ||
| 86 | * Tweak: Reduced the wait time before redirecting to the media edit page to half (5s); | ||
| 87 | * Fix: If an item is not offloaded, no attempt is made to update its data; | ||
| 88 | * Fix: Removed some double spaces from the plugin strings (thanks to @Presskopp). | ||
| 89 | |||
| 90 | = 4.1.1 = | ||
| 91 | |||
| 92 | Release date: April 13, 2023 | ||
| 93 | * Tweak: Added a filter to reduce or remove the wait time before redirecting to the media edit page; | ||
| 94 | * Fix: Replacement works again on multisite setups where the plugin reported the path outside the uploads folder; | ||
| 95 | * Fix: In some cases, replacement didn't work when images were offloaded; | ||
| 96 | * Fix: Some translation strings were corrected (thanks @alexclassroom !). | ||
| 97 | |||
| 98 | = 4.1.0 = | ||
| 99 | |||
| 100 | Release date: March 28, 2023 | ||
| 101 | * New: Integration with WP Offload Media; items that are offloaded can now be replaced correctly; | ||
| 102 | * New: Switch to a Replacer module that improves the code and makes it more robust; | ||
| 103 | * New: Adding an intermediate confirmation page to solve possible redirection issues; | ||
| 104 | * Tweak: The new image can now be dragged and dropped directly into the preview area; | ||
| 105 | * Tweak: Improved the display of both the original image and the new image on the replacement screen; | ||
| 106 | * Tweak: Improved the notification system and added a mechanism for remote notifications; | ||
| 107 | * Tweak: Updated the texts and banners to look better on the replacement screen; | ||
| 108 | * Fix: Added documentation in the readme to disable the background removal feature (kudos to @jstask82); | ||
| 109 | * Fix: Increased the security of the plugin by adding checks for various AJAX calls; | ||
| 110 | |||
| 111 | = 4.0.3 = | ||
| 112 | |||
| 113 | Release date: February 21, 2023 | ||
| 114 | * Fix: background removal notification is no longer displayed when this feature is disabled with the filter; | ||
| 115 | * Compat: improved compatibility with PHP 8.1 and 8.2 | ||
| 116 | * Tweak: updated the banners on the replace page. | ||
| 117 | |||
| 118 | = 4.0.2 = | ||
| 119 | |||
| 120 | Release date: January 13, 2023 | ||
| 121 | * Fix: patched a security vulnerability that could allow loading an unauthorized file during the replace operation; | ||
| 122 | * Fix: finish the replace operation even if the tmp file cannot be removed due to file permissions issues; | ||
| 123 | * Fix: when replacing a scaled file with a non-scaled file, some links were broken; | ||
| 124 | * Fix: under certain conditions a PHP warning about an undefined array key was displayed. | ||
| 125 | |||
| 126 | = 4.0.1 = | ||
| 127 | |||
| 128 | Release date: November 23, 2022 | ||
| 129 | * Fix: files are now replaced correctly in environments running on Windows/IIC servers; | ||
| 130 | * Fix: the mime type is now correctly detected, so that a warning is no longer displayed when replacing PDFs; | ||
| 131 | * Fix: the plugin no longer tries to load its code for post IDs that are not attachments, like comments; | ||
| 132 | * Fix: some warnings were displayed when using the Members plugin; | ||
| 133 | * Compat: added integration for SiteOrigin Page Builder to correctly replace files in its widgets; | ||
| 134 | * Compat: added `emr_after_remove_current` action hook (thanks @luistar15); | ||
| 135 | * Tweak: added filter to disable the background replace functionality. | ||
| 136 | |||
| 137 | = 4.0.0 = | ||
| 138 | |||
| 139 | Release date: September 5th, 2022 | ||
| 140 | * New: added the functionality to remove the background for any image; | ||
| 141 | * Fix: images added to the new block-style widgets were not replaced; | ||
| 142 | * Fix: the original file was not removed after replacement if a multilingual plugin was installed; | ||
| 143 | * Fix: additional checks were added to the new upload path for replacements, to avoid possible vulnerabilities, kudos to @soulseekah; | ||
| 144 | * Fix: an object cache flush was added after an image was replaced to prevent the content from still being cached in the post editor; | ||
| 145 | * Fix: if there was no `_wp_attached_file` in the postmeta table a fatal error was thrown; | ||
| 146 | * Fix: the time zone was not displayed correctly on the Replace Media screen; | ||
| 147 | * Fix: added some additional checks for file path to avoid `open_basedir` restrictions; | ||
| 148 | * Fix: added titles for the Replace Media and Remove Background screens; | ||
| 149 | * Fix: various small CSS/JS fixes, wording updates and code cleanups; | ||
| 150 | |||
| 151 | = 3.6.3 = | ||
| 152 | |||
| 153 | Release date: November 25th, 2021 | ||
| 154 | * Fix: the shortcode `file-modified` works again for non-privileged visitors as well; | ||
| 155 | * Compat: if other plugins don't properly use WP Hooks, don't return errors; | ||
| 156 | * Tweak: updated banners list from the EMR screen. | ||
| 157 | |||
| 158 | = 3.6.2 = | ||
| 159 | |||
| 160 | Release date: November 8th, 2021 | ||
| 161 | * 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); | ||
| 162 | * Fix: if target mime type returns empty, don't store that; | ||
| 163 | * Tweak: removed old notification about SPIO. | ||
| 164 | |||
| 165 | = 3.6.1 = | ||
| 166 | |||
| 167 | Release date: October 27th, 2021 | ||
| 168 | * Fix: there was a broken image in one of the plugin notices; | ||
| 169 | * Fix: added a check for the function `mime_content_type`, which doesn't seem to always be available on various hosts; | ||
| 170 | * 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; | ||
| 171 | |||
| 172 | = 3.6.0 = | ||
| 173 | |||
| 174 | Release date: October 11th, 2021 | ||
| 175 | * New: Constant EMR_CAPABILITY can define extra user roles to allow and deny replacements; | ||
| 176 | * New: Replacing an usual image with an SVG file will just replace all thumbnails by the main file; | ||
| 177 | * New: Also replaces caption when set in Exif data (when replacing with updating all links); | ||
| 178 | * Tweak: Added Now and Original options to Custom Date for usability; | ||
| 179 | * Tweak: changes/updates to the banners from the EMR screen; | ||
| 180 | * Fix: EMR now respects edit_other_posts permissions using default permissions; | ||
| 181 | * Fix: EMR with ALLOW_UNFILTERED_UPLOADS enabled (and allowed role) will not limit non-allowed uploads; | ||
| 182 | * Fix: some missing and wrong text-domains are now corrected (thanks @alexclassroom); | ||
| 183 | * Fix: a missing dot in the plugin description was preventing the transaltions to properly work; | ||
| 184 | * Fix: the plugin can now be uninstalled/deleted on PHP 8. | ||
| 185 | |||
| 186 | = 3.5.0 = | ||
| 187 | |||
| 188 | Release date: October 29th 2020 | ||
| 189 | * New: EMR now replaces across all meta tables; | ||
| 190 | * New: the plugin remembers last used settings; | ||
| 191 | * New: integration with the LiteSpeed cache plugin and webserver; | ||
| 192 | * Tweak: manual Logging will no longer work if user is not logged as administrator; | ||
| 193 | * Tweak: added `post_id` to `enable-media-replace-upload-done` action args, props to @Jan Stiegler; | ||
| 194 | * Fix: fully works now with Elementor; | ||
| 195 | * Fix: the issue for WP-Bakery and URL-Encoded links is now fixed; | ||
| 196 | * Fix: the plugin should now work with images added through Visual Composer; | ||
| 197 | * Fix: EMR now uses queries instead of WordPress functions, correctly handling slashes and JSON formats; | ||
| 198 | * Fix: `-scaled` images generated by WordPress are now removed when replacing an image; | ||
| 199 | |||
| 200 | = 3.4.2 = | ||
| 201 | |||
| 202 | Release date: August 17th 2020 | ||
| 203 | * New - Also display files size in the replacement windows; | ||
| 204 | * Fix - Replacing image with pdf file would cause noticesi; | ||
| 205 | * 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; | ||
| 206 | * 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; | ||
| 207 | * Fix - Wording clarification for the situation when the filename is changed, which will lead to broken links from external sites; | ||
| 208 | * Fix - Added hard paths to require_once satements in order to prevent WP-CLI errrors; | ||
| 209 | * Fix - If source image doesn't exist or in error state, replacement would be prevented by Javascript issue. | ||
| 210 | |||
| 211 | = 3.4.1 = | ||
| 212 | |||
| 213 | Release date: June 18th 2020 | ||
| 214 | * Fix - PHP Error when settings permissions failed. | ||
| 215 | |||
| 216 | = 3.4.0 = | ||
| 217 | |||
| 218 | Release date: June 9th 2020 | ||
| 219 | * New - In edit media screen EMR notes user who replaced file if this was not uploader; | ||
| 220 | * New - Added Drag and Drop area for files; | ||
| 221 | * New - When replacing with new file name, now also possible to update upload path; | ||
| 222 | * Fix - Various minor CSS tweaks and fixes; | ||
| 223 | * Update of Underlying libraries | ||
| 224 | |||
| 225 | = 3.3.12 = | ||
| 226 | |||
| 227 | Release date: 27th April 2020 | ||
| 228 | * Fixed - When trying to upload over-limit file would show too many error messages; | ||
| 229 | * Language – 2 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted. | ||
| 230 | |||
| 231 | = 3.3.11 = | ||
| 232 | |||
| 233 | Release date: 10th March 2020 | ||
| 234 | * Fix the crashing of certain frontend builders when the plugin is active. | ||
| 235 | |||
| 236 | = 3.3.10 = | ||
| 237 | |||
| 238 | Release date: 23rd February 2020 | ||
| 239 | * Fix issue with JSON encoding which was interfering with Advanced Custom Fields and other plugins | ||
| 240 | |||
| 241 | = 3.3.9 = | ||
| 242 | |||
| 243 | Release date: 23rd February 2020 | ||
| 244 | * Fix issue with JSON encoded strings | ||
| 245 | * Language – 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted | ||
| 246 | |||
| 247 | Release date: 19th February 2020 | ||
| 248 | * Fix issue with search/replacing non-image attachments and query | ||
| 249 | * Language – 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted | ||
| 250 | |||
| 251 | = 3.3.8 = | ||
| 252 | |||
| 253 | Release date: 18th February 2020 | ||
| 254 | * Fixes for WP 5.3+ -scaled images system. Will now replace those as well. | ||
| 255 | * Updating and replacing images and thumbnails should now work for serialized (and such) metadata. | ||
| 256 | - For Beaver Builder | ||
| 257 | * Add extra warning if mimetype is not allowed by WordPress for upload | ||
| 258 | * Put Javascript version in wp_register_script | ||
| 259 | * Hidden double 'replace media' | ||
| 260 | * Replace Image label to Replace Media | ||
| 261 | * Removed constant S3_UPLOADS_AUTOENABLE | ||
| 262 | * Improved detection of SVG image sizes | ||
| 263 | * Fixed - Logger doesn't call wp_upload_dir when not debugging | ||
| 264 | * Extra - Javascript tries to resume after external errors. | ||
| 265 | * Language – 0 new strings added, 2 updated, 0 fuzzied, and 0 obsoleted | ||
| 266 | |||
| 267 | = 3.3.7 = | ||
| 268 | |||
| 269 | Release date: 13th November 2019 | ||
| 270 | * call the hook enable-media-replace-upload-done on both modes | ||
| 271 | * fix JSON compatibility for hostings that don't have JSON module activated | ||
| 272 | * Language – 0 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted | ||
| 273 | |||
| 274 | = 3.3.6 = | ||
| 275 | |||
| 276 | Release date: 5th September 2019 | ||
| 277 | * fix JSON compatibility for hostings that don't have JSON module activated | ||
| 278 | |||
| 279 | = 3.3.5 = | ||
| 280 | |||
| 281 | Release date: 25th July 2019 | ||
| 282 | * fix Replace button on the MediaLibrary image details popup | ||
| 283 | |||
| 284 | = 3.3.4 = | ||
| 285 | |||
| 286 | Release date: 23rd July 2019 | ||
| 287 | * compatibility fixes for WP version 4.8 and below | ||
| 288 | * cache killer | ||
| 289 | |||
| 290 | = 3.3.3 = | ||
| 291 | |||
| 292 | Release date: 19th July 2019 | ||
| 293 | * Fix error "using $this when not in object context" on some PHP versions | ||
| 294 | |||
| 295 | = 3.3.2 = | ||
| 296 | |||
| 297 | Release date: 17th July 2019 | ||
| 298 | * Check if medium size !> 400px, display that one, otherwise smallest. | ||
| 299 | * Fixed: Links not updated when using Advanced Custom Fields | ||
| 300 | * Fixed: Fails silently when file is too big for upload | ||
| 301 | * When source file does not exist, show placeholder instead of failed image load | ||
| 302 | * Fixed: Fatal error when replacing images | ||
| 303 | * Fixed: Not the right time zone on replace | ||
| 304 | * Fixed Beaver Builder incompatibility by not allowing replace with rename. | ||
| 305 | * Fixed: Cannot replace non default Wordpress file types, even those allowed to upload [ Media Library Assistant compat ] | ||
| 306 | * Fixed: error when trying to remove a file that doesn't exist - because the files are actually on another server | ||
| 307 | |||
| 308 | = 3.3.1 = | ||
| 309 | |||
| 310 | Release date: 18th June 2019 | ||
| 311 | * Fix error class not found on WPEngine | ||
| 312 | |||
| 313 | = 3.3.0 = | ||
| 314 | * When replacing an image and changing the name, Search / Replace is now also done on the meta_value of postmeta. | ||
| 315 | * Replace PDF thumbnails too | ||
| 316 | * Copy title from EXIF | ||
| 317 | * RTL View incorporated into the CSS | ||
| 318 | * ‘wp_handle_upload’ filter should be treated as such (and not as action) | ||
| 319 | * Use wp_attached_file instead of the GUID | ||
| 320 | * Fix: replace missing file | ||
| 321 | * Fix: aphostrophe breaking the upload | ||
| 322 | * Fix: broken "before" image | ||
| 323 | * Fix: update properly the date | ||
| 324 | * Fix: errors for non-image items in Media Library | ||
| 325 | * Fix: empty admin menu item created | ||
| 326 | * Refactored all the code | ||
| 327 | |||
| 328 | = 3.2.9 = | ||
| 329 | * 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. | ||
| 330 | |||
| 331 | = 3.2.8 = | ||
| 332 | * fix for failures in link updating when replacing file because of addslashes - use prepared query instead | ||
| 333 | * replace basename with wp_basename because basename doesn't work well with UTF8 | ||
| 334 | |||
| 335 | = 3.2.7 = | ||
| 336 | * Add minimum required php version to run the plugin. | ||
| 337 | * Security: Prevent direct access to php files. | ||
| 338 | * Security: Prevent direct access to directories. | ||
| 339 | * Security: Escape translation strings using `esc_attr__()` and `esc_html__()` functions. | ||
| 340 | * Fix RTL issues. | ||
| 341 | |||
| 342 | = 3.2.6 = | ||
| 343 | * no more 404 error if no image was selected when trying to replace it | ||
| 344 | * added preview so you can check the image being replaced and also the image that's being replaced with | ||
| 345 | * .dat files can be replaced (functionality accidentally removed in the previous version) | ||
| 346 | * added compatibility with S3 upload plugin | ||
| 347 | * when an image is replaced the date is also updated | ||
| 348 | |||
| 349 | = 3.2.5 = | ||
| 350 | * remove the leftover setcookie and the plugins recommendations. | ||
| 351 | |||
| 352 | = 3.2.4 = | ||
| 353 | * Fix PDF thumbnails not replaced when replacing a PDF | ||
| 354 | * Fix not replacing text files with .dat extension | ||
| 355 | |||
| 356 | = 3.2.3 = | ||
| 357 | * disable ShortPixel recommendation on secondary sites of a multisite install when it was network activated. | ||
| 358 | |||
| 359 | = 3.2.2 = | ||
| 360 | * Fixed compatibility with ShortPixel and Resize Image After Upload | ||
| 361 | * Added ShortPixel links and images, fixed the problem of ShortPixel recommendation not dismissing. | ||
| 362 | |||
| 363 | = 3.2.1 = | ||
| 364 | * Bugfix, typo made metadata changes (thanks GitHub user icecandy!) | ||
| 365 | * Removed Shortpixel links and images | ||
| 366 | |||
| 367 | = 3.2 = | ||
| 368 | * Tested with WP 4.9.4 | ||
| 369 | * Added Shortpixel link in replace media screen | ||
| 370 | |||
| 371 | = 3.1.1 = | ||
| 372 | * Fixed bug introduced in an earlier version, preventing the updating of URLs on pages/posts if the link did not contain the domain name | ||
| 373 | |||
| 374 | = 3.1 = | ||
| 375 | * Got rid of some pesky old code, and added some better filtering options, thanks to GitHub users speerface, aaemnnosttv, and ururk | ||
| 376 | * Brand new, shiny code to replace other image sizes in embedded media, thanks to GitHub user ianmjones! | ||
| 377 | * Tested with WP 4.8 | ||
| 378 | |||
| 379 | = 3.0.6 = | ||
| 380 | * Tested with WP 4.7.2 | ||
| 381 | * New PT translations (thanks Pedro Mendonca! https://github.com/mansj/enable-media-replace/commit/b6e63b9a8a3ae46b3a6664bd5bbf19b2beaf9d3f) | ||
| 382 | |||
| 383 | = 3.0.5 = | ||
| 384 | * Tested with WP 4.6.1 | ||
| 385 | |||
| 386 | = 3.0.4 = | ||
| 387 | * Fixed typo in .pt translations (https://github.com/mansj/enable-media-replace/pull/18) | ||
| 388 | * Fixed better error handling in modification date functions (https://github.com/mansj/enable-media-replace/pull/16) | ||
| 389 | * Tested with WP 4.4.1 | ||
| 390 | |||
| 391 | = 3.0.3 = | ||
| 392 | * Scrapped old method of detecting media screen, button to replace media will now show up in more places, yay! | ||
| 393 | * Made sure the call to get_attached_file() no longer skips filters, in response to several users wishes. | ||
| 394 | * Suppressed error messages on chmod() | ||
| 395 | * Added Japanese translation (Thank you, chacomv!) | ||
| 396 | |||
| 397 | = 3.0.2 = | ||
| 398 | * Cleaned up language files | ||
| 399 | * Added Portuguese translation (Thanks pedro-mendonca!) | ||
| 400 | * Tested with WP 4.1 | ||
| 401 | * Added missing Swedish translation strings | ||
| 402 | |||
| 403 | = 3.0.1 = | ||
| 404 | * Tiny fix to re-insert the EMR link in the media list view. | ||
| 405 | |||
| 406 | = 3.0 = | ||
| 407 | * Updated for WordPress 4.0 | ||
| 408 | * Now inheriting permissions of the replaced files, [Thank you Fiwad](https://github.com/fiwad) | ||
| 409 | |||
| 410 | = 2.9.7RC1 = | ||
| 411 | * Moved localization files into their own directory. [Thank you Michael](https://github.com/michael-cannon) | ||
| 412 | * Moved screenshots into their own directory. [Thank you Michael](https://github.com/michael-cannon) | ||
| 413 | |||
| 414 | = 2.9.6 = | ||
| 415 | * Added fix by Grant K Norwood to address a possible security problem in SQL statements. Thanks Grant! | ||
| 416 | * Created GitHub repo for this plugin, please feel free to contribute at github.com/mansj/enable-media-replace | ||
| 417 | |||
| 418 | = 2.9.5 = | ||
| 419 | * Bug fix for the short code displaying the modification date of a file | ||
| 420 | * Updated all database queries in preparation for WP 3.9 | ||
| 421 | |||
| 422 | = 2.9.4 = | ||
| 423 | * Bug fix for timezone changes in WordPress | ||
| 424 | * Minor UI change to inform the user about what actually happens when replacing an image and using a new file name | ||
| 425 | |||
| 426 | = 2.9.3 = | ||
| 427 | * 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) | ||
| 428 | * Suppressed possible error in new hook added in 2.9.2 | ||
| 429 | |||
| 430 | = 2.9.2 = | ||
| 431 | * Small bug fix | ||
| 432 | * Added hook for developers to enable purging possible CDN when updating files - thanks rubious for the suggestion! | ||
| 433 | |||
| 434 | = 2.9.1 = | ||
| 435 | * Added Brazilian Portuguese translation, thanks Roger Nobrega! | ||
| 436 | * Added filter hook for file name creation, thanks to Jonas Lundman for the code! | ||
| 437 | * Added modification date to the edit attachment screen, thanks to Jonas Lundman for the code! | ||
| 438 | * Enhanced the deletion method for old file/image thumbnails to never give unnecessary error messages and more accurately delete orphaned thumbs | ||
| 439 | |||
| 440 | = 2.9 = | ||
| 441 | * Added Portuguese translation, thanks Bruno Miguel Bras Silva! | ||
| 442 | * New edit link from media library | ||
| 443 | * After uploading, the plugin now takes you back to edit screen instead of library | ||
| 444 | |||
| 445 | = 2.8.2 = | ||
| 446 | * 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! | ||
| 447 | * Added a new, supposedly better Russian translation from "Vlad". | ||
| 448 | |||
| 449 | = 2.8.1 = | ||
| 450 | * Fixed a small bug which could create error messages on some systems when deleting old image files. | ||
| 451 | |||
| 452 | = 2.8 = | ||
| 453 | * New and safer method for deleting thumbnails when a new image file is uploaded. | ||
| 454 | * New translations for simplified Chinese (thanks Tunghsiao Liu) and Italian (grazie Marco Chiesi) | ||
| 455 | * Added method for detecting upload screen to ensure backward compatibility with versions pre 3.5 | ||
| 456 | |||
| 457 | = 2.7 = | ||
| 458 | * A couple of changes made to ensure compatibility with WordPress 3.5. Thanks to Elizabeth Powell for the fixes! | ||
| 459 | |||
| 460 | = 2.6 = | ||
| 461 | * 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. | ||
| 462 | |||
| 463 | = 2.5.2 = | ||
| 464 | * 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! | ||
| 465 | |||
| 466 | = 2.5.1 = | ||
| 467 | * 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. | ||
| 468 | * New translation to Danish - thanks to Michael Bering Petersen! | ||
| 469 | |||
| 470 | = 2.5 = | ||
| 471 | * Tested with WordPress 3.2.1 | ||
| 472 | * New translation to German - thanks to Martin Lettner! | ||
| 473 | * New translation to French - thanks to François Collette! | ||
| 474 | |||
| 475 | = 2.4.1 = | ||
| 476 | * Bug fix for WordPress 3.1 RC. Now properly tested and should be working with 3.1 whenever it finally comes out. :) | ||
| 477 | |||
| 478 | = 2.4 = | ||
| 479 | * Bug fixes, security fixes. Thanks to my old pal Ulf "Årsta" Härnhammar for pointing them out! | ||
| 480 | * New method for uploading avoids going around WP, for greater security. | ||
| 481 | |||
| 482 | = 2.3 = | ||
| 483 | * Lots of code trimmed and enhanced, thanks to Ben ter Stal! Now working properly with Windows systems, better security, optimized loading, and much more. | ||
| 484 | * Added Dutch translation by Ben ter Stal. | ||
| 485 | |||
| 486 | = 2.2 = | ||
| 487 | * Bug fix, fixed typo in popup.php, thanks to Bill Dennen and others for pointing this out! | ||
| 488 | |||
| 489 | = 2.1 = | ||
| 490 | * New shortcode - display file modification date on your site (see description for more info) | ||
| 491 | * A couple of bug fixes for final release of 3.0 - Thanks to Jim Isaacs for pointing them out! | ||
| 492 | |||
| 493 | = 2.0.1 = | ||
| 494 | * Added support for SSL admin | ||
| 495 | |||
| 496 | = 2.0 = | ||
| 497 | * Replaced popup with inline navigation when replacing media | ||
| 498 | * Added instructions in admin link under Media | ||
| 499 | |||
| 500 | = 1.4.1 = | ||
| 501 | * Tested with WordPress 3.0 beta 2 | ||
| 502 | |||
| 503 | = 1.4 = | ||
| 504 | * Removed short tags for better compatibility. | ||
| 505 | |||
| 506 | = 1.3 = | ||
| 507 | * Added support for wp_config setting "FORCE_SSL_ADMIN" | ||
| 508 | |||
| 509 | = 1.2 = | ||
| 510 | * Added Russian translation, thanks to Fat Cower. | ||
| 511 | |||
| 512 | = 1.1 = | ||
| 513 | * Minor bugfix, now working with IE8 too! | ||
| 514 | |||
| 515 | = 1.0 = | ||
| 516 | * First stable version of plugin. | ||
| 517 | |||
| 518 | == Installation == | ||
| 519 | |||
| 520 | Quick and easy installation: | ||
| 521 | |||
| 522 | 1. Upload the folder `enable-media-replace` to your plugin directory | ||
| 523 | 1. Activate the plugin through the 'Plugins' menu in WordPress | ||
| 524 | 1. Done! | ||
| 525 | |||
| 526 | == Frequently Asked Questions == | ||
| 527 | |||
| 528 | = What does this plugin actually do? = | ||
| 529 | |||
| 530 | This plugin makes it easy to update/replace files that have been uploaded to the WordPress Media Library. | ||
| 531 | |||
| 532 | = How does it work? = | ||
| 533 | |||
| 534 | 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. | ||
| 535 | |||
| 536 | = I replaced a file, but it didn't change! = | ||
| 537 | |||
| 538 | There are two main reasons this would happen. | ||
| 539 | |||
| 540 | 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. | ||
| 541 | |||
| 542 | 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. | ||
| 543 | |||
| 544 | == Screenshots == | ||
| 545 | |||
| 546 | 1. The new link in the media library. | ||
| 547 | 2. The replace media-button as seen in the "Edit media" view. | ||
| 548 | 3. The upload options. | ||
| 549 | 4. Get the file ID in the edit file URL | ||
| 550 | |||
| 551 | == Wishlist / Coming attractions == | ||
| 552 | |||
| 553 | Do you have suggestions? Feel free to contact ShortPixel <a href="https://shortpixel.com/contact" target="_blank">here</a> | ||
| 554 | |||
| 555 | |||
| 556 | == Contribute == | ||
| 557 | |||
| 558 | 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 | |||
| 2 | .enable-media-replace.emr-screen | ||
| 3 | { | ||
| 4 | |||
| 5 | width: 90%; | ||
| 6 | background: #fff; | ||
| 7 | border: 1px solid #fff; | ||
| 8 | position: relative; | ||
| 9 | margin: 30px 0; | ||
| 10 | |||
| 11 | h3 { | ||
| 12 | font-size: 24px; | ||
| 13 | position: absolute; | ||
| 14 | top: -15px; | ||
| 15 | left: 30px; | ||
| 16 | padding: 16px 8px; | ||
| 17 | border: 1px solid #000; | ||
| 18 | background: #fff; | ||
| 19 | margin: 0; | ||
| 20 | } | ||
| 21 | .content | ||
| 22 | { | ||
| 23 | padding: 32px; | ||
| 24 | |||
| 25 | } | ||
| 26 | h1 { | ||
| 27 | font-weight: 700; | ||
| 28 | } | ||
| 29 | |||
| 30 | p { font-size: 14px; } | ||
| 31 | |||
| 32 | |||
| 33 | .hide { display: none; } | ||
| 34 | |||
| 35 | &.error-screen { | ||
| 36 | h1 { color: #ff0000; } | ||
| 37 | } | ||
| 38 | |||
| 39 | } |
| 1 | @import 'datepicker'; | ||
| 2 | @import 'screens'; | ||
| 3 | |||
| 4 | #emr-drop-area-active | ||
| 5 | { | ||
| 6 | // border: 4px dashed #b4b9be; | ||
| 7 | // max-width: 600px; | ||
| 8 | position: fixed; | ||
| 9 | left: 0; | ||
| 10 | right: 0; | ||
| 11 | top: 0; | ||
| 12 | bottom: 0; | ||
| 13 | z-index: 9999; | ||
| 14 | display: block; | ||
| 15 | background: rgba(0,0,0,0.5); | ||
| 16 | border: 6px dashed #AAA; | ||
| 17 | |||
| 18 | h3 { | ||
| 19 | font-size: 36px; | ||
| 20 | color: #ddd; | ||
| 21 | width: 200px; | ||
| 22 | left: 50%; | ||
| 23 | top: 50%; | ||
| 24 | position:absolute; | ||
| 25 | } | ||
| 26 | |||
| 27 | .drop-wrapper | ||
| 28 | { | ||
| 29 | margin: 0 auto; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | // The main form. | ||
| 34 | .emr_upload_form | ||
| 35 | { | ||
| 36 | form | ||
| 37 | { | ||
| 38 | display: flex; //editor and upsell | ||
| 39 | .upsell-wrapper | ||
| 40 | { | ||
| 41 | margin-left: 10px; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | .editor-wrapper | ||
| 46 | { | ||
| 47 | width: 100%; | ||
| 48 | } | ||
| 49 | .emr_drop_area { | ||
| 50 | display: none; | ||
| 51 | } | ||
| 52 | |||
| 53 | .wrapper | ||
| 54 | { | ||
| 55 | // margin: 15px 0; | ||
| 56 | padding: 18px; | ||
| 57 | border: 1px solid #ccc; | ||
| 58 | |||
| 59 | .section-header | ||
| 60 | { | ||
| 61 | font-size: 18px; | ||
| 62 | //text-align: center; | ||
| 63 | border-bottom: 1px solid #ccc; | ||
| 64 | padding: 6px 0; | ||
| 65 | margin: 0 0 15px 0; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | .explainer { | ||
| 70 | font-size: 14px; | ||
| 71 | color: #555; | ||
| 72 | max-width: 800px; | ||
| 73 | margin: 20px 0; | ||
| 74 | .underline { | ||
| 75 | text-decoration-style: dotted; | ||
| 76 | text-decoration-line: underline; | ||
| 77 | } | ||
| 78 | |||
| 79 | |||
| 80 | } | ||
| 81 | |||
| 82 | .image_chooser.wrapper | ||
| 83 | { | ||
| 84 | min-height: 350px; | ||
| 85 | |||
| 86 | |||
| 87 | .image_previews | ||
| 88 | { | ||
| 89 | margin: 15px 0; | ||
| 90 | position: relative; | ||
| 91 | |||
| 92 | .image_placeholder | ||
| 93 | { | ||
| 94 | position: relative; | ||
| 95 | display: inline-block; | ||
| 96 | margin-right: 25px; | ||
| 97 | margin-bottom: 10px; | ||
| 98 | border: 1px solid #ddd; | ||
| 99 | vertical-align: top; | ||
| 100 | box-sizing: border-box; | ||
| 101 | background: #fff; | ||
| 102 | max-width: calc(50% - 25px); | ||
| 103 | |||
| 104 | img { object-fit: contain; } | ||
| 105 | |||
| 106 | .upload-title | ||
| 107 | { | ||
| 108 | text-align: center; | ||
| 109 | position: absolute; | ||
| 110 | padding-top: 8px; | ||
| 111 | line-height: 20px; | ||
| 112 | font-weight: 700; | ||
| 113 | width: 100%; | ||
| 114 | left: 0; | ||
| 115 | top: 0; | ||
| 116 | } | ||
| 117 | #upload-file { | ||
| 118 | display: none; | ||
| 119 | } | ||
| 120 | .textlayer | ||
| 121 | { | ||
| 122 | font-size: 25px; | ||
| 123 | line-height: 25px; | ||
| 124 | opacity: 0.7; | ||
| 125 | position: absolute; | ||
| 126 | color: #ccc; | ||
| 127 | left: 48%; | ||
| 128 | top: 50%; | ||
| 129 | transform: translate(-50%, -50%); | ||
| 130 | border: 1px dashed #eee; | ||
| 131 | background-color: #333; | ||
| 132 | padding: 8px; | ||
| 133 | z-index: 5; | ||
| 134 | //max-width: 100%; | ||
| 135 | } | ||
| 136 | .dashicons | ||
| 137 | { | ||
| 138 | font-size: 60px; | ||
| 139 | position: absolute; | ||
| 140 | top: 50%; | ||
| 141 | margin-top: -30px; | ||
| 142 | left: 50%; | ||
| 143 | margin-left: -30px; | ||
| 144 | opacity: 0.5; | ||
| 145 | |||
| 146 | } | ||
| 147 | .image_size | ||
| 148 | { | ||
| 149 | text-align: center; | ||
| 150 | position: absolute; | ||
| 151 | bottom: -25px; | ||
| 152 | width: 100%; | ||
| 153 | } | ||
| 154 | .drag-and-drop-title | ||
| 155 | { | ||
| 156 | text-align: center; | ||
| 157 | font-weight: 400; | ||
| 158 | font-size: 14px; | ||
| 159 | width: 100%; | ||
| 160 | height: 100%; | ||
| 161 | position: absolute; | ||
| 162 | cursor: pointer; | ||
| 163 | top: 0; | ||
| 164 | left: 0; | ||
| 165 | z-index: 1; | ||
| 166 | span { | ||
| 167 | position: absolute; | ||
| 168 | // left: 46%; | ||
| 169 | top: 50%; | ||
| 170 | transform: translate(-50%,-50%); | ||
| 171 | padding: 5px 10px; | ||
| 172 | width: 100%; | ||
| 173 | |||
| 174 | } | ||
| 175 | } | ||
| 176 | &.is_image | ||
| 177 | { | ||
| 178 | .dashicons::before, .dashicons { display: none } | ||
| 179 | |||
| 180 | |||
| 181 | } | ||
| 182 | &.not_image | ||
| 183 | { | ||
| 184 | img { display: none; } | ||
| 185 | .textlayer { display: none; } | ||
| 186 | &.is_document{ | ||
| 187 | .textlayer { | ||
| 188 | font-size: 18px; | ||
| 189 | line-height: 20px; | ||
| 190 | display: block; | ||
| 191 | |||
| 192 | } | ||
| 193 | } | ||
| 194 | } // not_image | ||
| 195 | } // image_placeholder | ||
| 196 | } // image_previews | ||
| 197 | } // wrapper | ||
| 198 | |||
| 199 | .form-error, .form-warning | ||
| 200 | { | ||
| 201 | background: #fff; | ||
| 202 | padding: 8px; | ||
| 203 | border-left: 4px solid #ff0000; | ||
| 204 | // display: inline-block; | ||
| 205 | margin: 10px 0; | ||
| 206 | display: none; | ||
| 207 | p { | ||
| 208 | margin: 0; | ||
| 209 | font-size: 12px; | ||
| 210 | font-weight: 700; | ||
| 211 | } | ||
| 212 | |||
| 213 | } | ||
| 214 | .form-warning | ||
| 215 | { | ||
| 216 | border-left: 4px solid #ffb900; | ||
| 217 | } | ||
| 218 | |||
| 219 | .option-flex-wrapper | ||
| 220 | { | ||
| 221 | display: flex; | ||
| 222 | } | ||
| 223 | |||
| 224 | .replace_type.wrapper | ||
| 225 | { | ||
| 226 | flex: 1; | ||
| 227 | border: 1px solid #ccc; | ||
| 228 | margin: 15px 0; | ||
| 229 | .option | ||
| 230 | { | ||
| 231 | position: relative; | ||
| 232 | z-index: 1; | ||
| 233 | &.disabled | ||
| 234 | { | ||
| 235 | // color: #eee; | ||
| 236 | } | ||
| 237 | label | ||
| 238 | { | ||
| 239 | font-size: 1.2em; | ||
| 240 | } | ||
| 241 | .nofeature-notice | ||
| 242 | { | ||
| 243 | border: 1px solid #ccc; | ||
| 244 | padding: 8px; | ||
| 245 | margin: 0; | ||
| 246 | position: absolute; | ||
| 247 | left: 0; | ||
| 248 | right: 0; | ||
| 249 | top: 0; | ||
| 250 | bottom: 0; | ||
| 251 | opacity: 0.8; | ||
| 252 | z-index: 9; | ||
| 253 | background: #444; | ||
| 254 | p { | ||
| 255 | text-align: center; | ||
| 256 | color: #fff; | ||
| 257 | margin: 15px 0; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | } | ||
| 263 | |||
| 264 | .options.wrapper | ||
| 265 | { | ||
| 266 | flex: 1; | ||
| 267 | border: 1px solid #ccc; | ||
| 268 | padding: 15px; | ||
| 269 | margin: 15px 0 15px 35px; | ||
| 270 | .custom_date | ||
| 271 | { | ||
| 272 | .emr_datepicker { | ||
| 273 | width: 150px; | ||
| 274 | } | ||
| 275 | .emr_hour, .emr_minute | ||
| 276 | { | ||
| 277 | width: 45px; | ||
| 278 | } | ||
| 279 | } | ||
| 280 | .replace_custom_date | ||
| 281 | { | ||
| 282 | margin-left: 5px; | ||
| 283 | &:hover { | ||
| 284 | text-decoration: underline; | ||
| 285 | cursor: pointer | ||
| 286 | } | ||
| 287 | } | ||
| 288 | ul | ||
| 289 | { | ||
| 290 | li | ||
| 291 | { | ||
| 292 | input | ||
| 293 | { | ||
| 294 | margin-right: 8px; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | } | ||
| 298 | .option | ||
| 299 | { | ||
| 300 | label { vertical-align: top; } | ||
| 301 | } | ||
| 302 | .small | ||
| 303 | { | ||
| 304 | font-size: 10px; | ||
| 305 | vertical-align: top; | ||
| 306 | margin-left: 8px; | ||
| 307 | } | ||
| 308 | .custom_date | ||
| 309 | { | ||
| 310 | margin: 8px 0 0 25px; | ||
| 311 | visibility: hidden; | ||
| 312 | opacity: 0; | ||
| 313 | span.field-title { | ||
| 314 | display: inline-block; | ||
| 315 | margin-bottom: 4px; | ||
| 316 | color: #444; | ||
| 317 | //margin-left: 8px; | ||
| 318 | font-size: 12px; | ||
| 319 | width: 100%; | ||
| 320 | text-align: left; | ||
| 321 | vertical-align: middle; | ||
| 322 | line-height: 26px; | ||
| 323 | &::before | ||
| 324 | { | ||
| 325 | font-size: 20px; | ||
| 326 | vertical-align: top; | ||
| 327 | margin-right: 4px; | ||
| 328 | } | ||
| 329 | } | ||
| 330 | } // custom_date | ||
| 331 | .location_option | ||
| 332 | { | ||
| 333 | display: none; | ||
| 334 | margin-top: 12px; | ||
| 335 | label | ||
| 336 | { | ||
| 337 | vertical-align: baseline; | ||
| 338 | margin-right: 8px; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | .form_controls.wrapper | ||
| 344 | { | ||
| 345 | clear: both; | ||
| 346 | margin: 8px 0 15px 0; | ||
| 347 | border: 0; | ||
| 348 | padding: 0; | ||
| 349 | .button | ||
| 350 | { | ||
| 351 | padding-left: 20px; | ||
| 352 | padding-right: 20px; | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | .shortpixel.notice | ||
| 357 | { | ||
| 358 | padding: 12px; | ||
| 359 | } | ||
| 360 | |||
| 361 | // *** UPSELL SNIPPET | ||
| 362 | .shortpixel-offer | ||
| 363 | { | ||
| 364 | background: #fff; | ||
| 365 | width: 250px; | ||
| 366 | min-height: 270px; | ||
| 367 | border: 1px solid #ccc; | ||
| 368 | padding: 10px; | ||
| 369 | //margin: 0 0 10px 25px; | ||
| 370 | margin-bottom: 10px; | ||
| 371 | float: right; | ||
| 372 | clear: both; | ||
| 373 | background-color: #dcfdff; | ||
| 374 | h3 { | ||
| 375 | color: #00d0e5; | ||
| 376 | font-size: 18px; | ||
| 377 | text-align: center; | ||
| 378 | margin: 0; | ||
| 379 | line-height: 1.3em; | ||
| 380 | } | ||
| 381 | h4 { | ||
| 382 | // margin: 0; | ||
| 383 | font-size: 16px; | ||
| 384 | text-align: center; | ||
| 385 | } | ||
| 386 | .red { color: #ff0000; } | ||
| 387 | .cyan { color: #00d0e5; } | ||
| 388 | .grey { color: grey; } | ||
| 389 | .ucase { text-transform: uppercase; } | ||
| 390 | a { | ||
| 391 | text-decoration: none | ||
| 392 | } | ||
| 393 | .button-wrapper | ||
| 394 | { | ||
| 395 | text-align: center; | ||
| 396 | margin-top: 35px; | ||
| 397 | a { | ||
| 398 | background-color: #ff0000; | ||
| 399 | color: #fff; | ||
| 400 | display: inline-block; | ||
| 401 | padding: 8px; | ||
| 402 | text-decoration: none; | ||
| 403 | font-weight: 700; | ||
| 404 | font-size: 20px; | ||
| 405 | text-transform: uppercase; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | .hidden { display: none !important; } | ||
| 409 | |||
| 410 | .img-wrapper | ||
| 411 | { | ||
| 412 | text-align: center; | ||
| 413 | margin: 0 0 25px 0; | ||
| 414 | img { max-width: 140px; max-height: 140px; margin: 0; } | ||
| 415 | } | ||
| 416 | |||
| 417 | |||
| 418 | &.spio // shortpixel | ||
| 419 | { | ||
| 420 | } | ||
| 421 | &.site-speed // Site speed | ||
| 422 | { | ||
| 423 | } | ||
| 424 | &.envira-shortpixel-install // envira | ||
| 425 | { | ||
| 426 | background: #fff; | ||
| 427 | } | ||
| 428 | &.theme-offer | ||
| 429 | { | ||
| 430 | background: #fff; | ||
| 431 | img { | ||
| 432 | max-width: 100%; | ||
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | @media( max-width: 1200px) | ||
| 438 | { | ||
| 439 | .image_previews | ||
| 440 | { | ||
| 441 | text-align: center; | ||
| 442 | } | ||
| 443 | .option-flex-wrapper { | ||
| 444 | flex-direction: column; | ||
| 445 | .options.wrapper | ||
| 446 | { margin-left: 0;} | ||
| 447 | } | ||
| 448 | } | ||
| 449 | @media (max-width: 960px) | ||
| 450 | { | ||
| 451 | .upsell-wrapper { display: none; } | ||
| 452 | } | ||
| 453 | @media (max-width: 450px ) | ||
| 454 | { | ||
| 455 | .replace_custom_date_wrapper { | ||
| 456 | display: block; | ||
| 457 | margin-top: 15px; | ||
| 458 | font-size: 16px; | ||
| 459 | |||
| 460 | } | ||
| 461 | .location_option { | ||
| 462 | label { | ||
| 463 | margin: 25px 0; | ||
| 464 | display: inline-block; | ||
| 465 | } | ||
| 466 | |||
| 467 | } | ||
| 468 | } | ||
| 469 | } // 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 | #remove-background-form | ||
| 2 | { | ||
| 3 | form { | ||
| 4 | display: flex; | ||
| 5 | |||
| 6 | } | ||
| 7 | .image_chooser.wrapper { | ||
| 8 | min-height: 0; | ||
| 9 | } | ||
| 10 | .image_placeholder.is_image | ||
| 11 | { | ||
| 12 | border:none; | ||
| 13 | width:45%; | ||
| 14 | height:auto; | ||
| 15 | .textlayer, .image_size { | ||
| 16 | display: none; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | .bad-button | ||
| 21 | { | ||
| 22 | text-align: right; | ||
| 23 | margin-right: 25px; | ||
| 24 | a { | ||
| 25 | visibility: hidden; | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | .overlay{ | ||
| 30 | visibility: hidden; | ||
| 31 | display: flex; | ||
| 32 | flex-direction: column; | ||
| 33 | justify-content: center; | ||
| 34 | align-items: center; | ||
| 35 | width: 100%; | ||
| 36 | height: 100%; | ||
| 37 | background-color: rgba(0,0,0,0.2); | ||
| 38 | position: absolute; | ||
| 39 | top: 0; | ||
| 40 | } | ||
| 41 | .lds-spinner { | ||
| 42 | color: official; | ||
| 43 | display: inline-block; | ||
| 44 | position: relative; | ||
| 45 | width: 80px; | ||
| 46 | height: 80px; | ||
| 47 | } | ||
| 48 | .lds-spinner div { | ||
| 49 | transform-origin: 40px 40px; | ||
| 50 | animation: lds-spinner 1.2s linear infinite; | ||
| 51 | } | ||
| 52 | .lds-spinner div:after { | ||
| 53 | content: " "; | ||
| 54 | display: block; | ||
| 55 | position: absolute; | ||
| 56 | top: 3px; | ||
| 57 | left: 37px; | ||
| 58 | width: 6px; | ||
| 59 | height: 18px; | ||
| 60 | border-radius: 20%; | ||
| 61 | background: #fff; | ||
| 62 | } | ||
| 63 | .lds-spinner div:nth-child(1) { | ||
| 64 | transform: rotate(0deg); | ||
| 65 | animation-delay: -1.1s; | ||
| 66 | } | ||
| 67 | .lds-spinner div:nth-child(2) { | ||
| 68 | transform: rotate(30deg); | ||
| 69 | animation-delay: -1s; | ||
| 70 | } | ||
| 71 | .lds-spinner div:nth-child(3) { | ||
| 72 | transform: rotate(60deg); | ||
| 73 | animation-delay: -0.9s; | ||
| 74 | } | ||
| 75 | .lds-spinner div:nth-child(4) { | ||
| 76 | transform: rotate(90deg); | ||
| 77 | animation-delay: -0.8s; | ||
| 78 | } | ||
| 79 | .lds-spinner div:nth-child(5) { | ||
| 80 | transform: rotate(120deg); | ||
| 81 | animation-delay: -0.7s; | ||
| 82 | } | ||
| 83 | .lds-spinner div:nth-child(6) { | ||
| 84 | transform: rotate(150deg); | ||
| 85 | animation-delay: -0.6s; | ||
| 86 | } | ||
| 87 | .lds-spinner div:nth-child(7) { | ||
| 88 | transform: rotate(180deg); | ||
| 89 | animation-delay: -0.5s; | ||
| 90 | } | ||
| 91 | .lds-spinner div:nth-child(8) { | ||
| 92 | transform: rotate(210deg); | ||
| 93 | animation-delay: -0.4s; | ||
| 94 | } | ||
| 95 | .lds-spinner div:nth-child(9) { | ||
| 96 | transform: rotate(240deg); | ||
| 97 | animation-delay: -0.3s; | ||
| 98 | } | ||
| 99 | .lds-spinner div:nth-child(10) { | ||
| 100 | transform: rotate(270deg); | ||
| 101 | animation-delay: -0.2s; | ||
| 102 | } | ||
| 103 | .lds-spinner div:nth-child(11) { | ||
| 104 | transform: rotate(300deg); | ||
| 105 | animation-delay: -0.1s; | ||
| 106 | } | ||
| 107 | .lds-spinner div:nth-child(12) { | ||
| 108 | transform: rotate(330deg); | ||
| 109 | animation-delay: 0s; | ||
| 110 | } | ||
| 111 | @keyframes lds-spinner { | ||
| 112 | 0% { | ||
| 113 | opacity: 1; | ||
| 114 | } | ||
| 115 | 100% { | ||
| 116 | opacity: 0; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 121 | |||
| 122 | * { | ||
| 123 | box-sizing: border-box; | ||
| 124 | } | ||
| 125 | |||
| 126 | .img-comp-container { | ||
| 127 | position: relative; | ||
| 128 | height: 200px; /*should be the same height as the images*/ | ||
| 129 | } | ||
| 130 | |||
| 131 | .img-comp-img { | ||
| 132 | position: absolute; | ||
| 133 | width: auto; | ||
| 134 | height: auto; | ||
| 135 | overflow:hidden; | ||
| 136 | } | ||
| 137 | |||
| 138 | .img-comp-img img { | ||
| 139 | display:block; | ||
| 140 | } | ||
| 141 | |||
| 142 | .img-comp-slider { | ||
| 143 | position: absolute; | ||
| 144 | z-index:9; | ||
| 145 | cursor: ew-resize; | ||
| 146 | /*set the appearance of the slider:*/ | ||
| 147 | width: 20px; | ||
| 148 | height: 20px; | ||
| 149 | background-color: #2196F3; | ||
| 150 | opacity: 0.7; | ||
| 151 | border-radius: 50%; | ||
| 152 | } | ||
| 153 | |||
| 154 | .preview-area{ | ||
| 155 | display:flex; | ||
| 156 | justify-content: center; | ||
| 157 | align-items: center; | ||
| 158 | width: 100%; | ||
| 159 | height: 100%; | ||
| 160 | } | ||
| 161 | .preview-area h1{ | ||
| 162 | color : red !important; | ||
| 163 | } | ||
| 164 | |||
| 165 | } |
| 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 | <?php | ||
| 2 | namespace EnableMediaReplace; | ||
| 3 | |||
| 4 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 5 | use EnableMediaReplace\Notices\NoticeController as Notices; | ||
| 6 | //use \EnableMediaReplace\Replacer as Replacer; | ||
| 7 | use \EnableMediaReplace\Controller\ReplaceController as ReplaceController; | ||
| 8 | |||
| 9 | if (! defined('ABSPATH')) { | ||
| 10 | exit; // Exit if accessed directly. | ||
| 11 | } | ||
| 12 | |||
| 13 | $key = isset($_POST['key']) ? sanitize_text_field($_POST['key']) : null; | ||
| 14 | if (is_null($key) || strlen($key) == 0) | ||
| 15 | { | ||
| 16 | wp_die(esc_html__('Error while sending form (no key). Please try again.', 'enable-media-replace')); | ||
| 17 | } | ||
| 18 | |||
| 19 | $post_id = isset($_POST['ID']) ? intval($_POST['ID']) : null; // sanitize, post_id. | ||
| 20 | if (is_null($post_id)) { | ||
| 21 | wp_die(esc_html__('Error in request. Please try again', 'enable-media-replace')); | ||
| 22 | } | ||
| 23 | |||
| 24 | $attachment = get_post($post_id); | ||
| 25 | |||
| 26 | if (! emr()->checkImagePermission($attachment)) { | ||
| 27 | wp_die(esc_html__('You do not have permission to upload files for this author.', 'enable-media-replace')); | ||
| 28 | } | ||
| 29 | |||
| 30 | $uiHelper = emr()->uiHelper(); | ||
| 31 | |||
| 32 | $replaceController = new ReplaceController($post_id); | ||
| 33 | |||
| 34 | //$replacer->setMode(\EnableMediaReplace\Replacer::MODE_REPLACE); | ||
| 35 | |||
| 36 | //$datetime = current_time('mysql'); | ||
| 37 | //$replacer->setTimeMode( \EnableMediaReplace\Replacer::TIME_UPDATEMODIFIED, $datetime); | ||
| 38 | |||
| 39 | $api = new Api(); | ||
| 40 | $result = $api->handleDownload($key); | ||
| 41 | |||
| 42 | if (! $result->success) | ||
| 43 | { | ||
| 44 | die($result->message); | ||
| 45 | } | ||
| 46 | |||
| 47 | // When are 1-1 replacing. | ||
| 48 | $source = $replacer->getSourceFile(); | ||
| 49 | |||
| 50 | $redirect_error = $uiHelper->getFailedRedirect($post_id); | ||
| 51 | $redirect_success = $uiHelper->getSuccesRedirect($post_id); | ||
| 52 | |||
| 53 | if (! file_exists($result->image)) | ||
| 54 | { | ||
| 55 | Log::addError('Download File not here', $result->image); | ||
| 56 | exit(__('Temp file does not exist', 'enable-media-replace')); | ||
| 57 | } | ||
| 58 | |||
| 59 | |||
| 60 | $params = array( | ||
| 61 | 'replace_type' => \EnableMediaReplace\Replacer::MODE_REPLACE, | ||
| 62 | 'timestamp_replace' => \EnableMediaReplace\Replacer::TIME_UPDATEMODIFIED, | ||
| 63 | 'new_date' => current_time('mysql'), | ||
| 64 | 'updateFile' => $result->image, | ||
| 65 | |||
| 66 | ); | ||
| 67 | $replaceController->setupParams($params); | ||
| 68 | |||
| 69 | |||
| 70 | try { | ||
| 71 | $result = $replaceController->run(); | ||
| 72 | } catch (\RunTimeException $e) { | ||
| 73 | print_r($e->getMessage()); | ||
| 74 | Log::addError($e->getMessage()); | ||
| 75 | die; | ||
| 76 | |||
| 77 | } | ||
| 78 | |||
| 79 | if (is_null($result)) { | ||
| 80 | wp_safe_redirect($redirect_error); | ||
| 81 | exit(); | ||
| 82 | } | ||
| 83 | |||
| 84 | $noticeController = Notices::getInstance(); | ||
| 85 | $notice = Notices::addSuccess('<p>' . __('File successfully replaced', 'enable-media-replace') . '</p>'); | ||
| 86 | $notice->is_removable = false; | ||
| 87 | $noticeController->update(); | ||
| 88 | |||
| 89 | wp_redirect($redirect_success); | ||
| 90 | exit(); |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | //use \EnableMediaReplace\UIHelper; | ||
| 9 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 10 | |||
| 11 | |||
| 12 | ?> | ||
| 13 | |||
| 14 | <div class='enable-media-replace emr-screen error-screen'> | ||
| 15 | <h3 class='title'><?php _e('Enable Media Replace', 'enable-media-replace'); ?></h3> | ||
| 16 | |||
| 17 | <div class='content'> | ||
| 18 | <h1><?php _e('An error occured', 'enable-media-replace'); ?></h1> | ||
| 19 | <p class="error-message"> <?php echo $view->errorMessage; ?> </p> | ||
| 20 | |||
| 21 | <?php if (property_exists($view, 'errorDescription')) | ||
| 22 | { | ||
| 23 | echo '<p class="description">' . $view->errorDescription . '</p>'; | ||
| 24 | } ?> | ||
| 25 | |||
| 26 | <p><?php printf(esc_html__('You can return to %s previous page %s','enable-media-replace'), | ||
| 27 | '<a href="javascript:history.back()">', '</a>'); ?></p> | ||
| 28 | |||
| 29 | |||
| 30 | <p><?php printf(esc_html__('If you need help, please see the plugin %sdocumentation%s. It contains clear solutions to most of the problems you may encounter when using our plugin.', 'enable-media-replace'), '<a href="https://shortpixel.com/knowledge-base/category/308-enable-media-replace" target="_blank">', '</a>'); ?></p> | ||
| 31 | </div> | ||
| 32 | </div> <!--- screen --> | ||
| 33 | |||
| 34 | |||
| 35 | <?php | ||
| 36 | require_once ABSPATH . 'wp-admin/admin-footer.php'; |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace; | ||
| 3 | |||
| 4 | use EnableMediaReplace\EnableMediaReplacePlugin; | ||
| 5 | use EnableMediaReplace\UIHelper; | ||
| 6 | |||
| 7 | if (! defined('ABSPATH')) { | ||
| 8 | exit; // Exit if accessed directly. | ||
| 9 | } | ||
| 10 | |||
| 11 | $date = new \dateTime(); | ||
| 12 | $uiHelper = emr()->uiHelper(); | ||
| 13 | |||
| 14 | $attachment_id = $view->attachment->ID; | ||
| 15 | //$attachment_id = intval($_GET['attachment_id']); | ||
| 16 | //$attachment = get_post($attachment_id); | ||
| 17 | |||
| 18 | //$replacer = new Replacer($attachment_id); | ||
| 19 | //$file = $replacer->getSourceFile(); | ||
| 20 | |||
| 21 | $uiHelper->setPreviewSizes(); | ||
| 22 | $uiHelper->setSourceSizes($attachment_id); | ||
| 23 | |||
| 24 | $base_image = $uiHelper->getPreviewImage($attachment_id, $view->sourceFile ); | ||
| 25 | $replace_image = $uiHelper->getPreviewImage(-1, $view->sourceFile, array('remove_bg_ui' => true) ); | ||
| 26 | |||
| 27 | $formurl = $uiHelper->getFormUrl($attachment_id, 'do_background_replace'); | ||
| 28 | //$formurl = wp_nonce_url( $formurl, "do_background_replace" ); | ||
| 29 | |||
| 30 | $linebreak = '%0D%0A'; | ||
| 31 | $linebreak_double = $linebreak . $linebreak; | ||
| 32 | $email_subject = __('Bad remove of background report', 'enable-media-replace'); | ||
| 33 | $email_body = sprintf(__('Hello! %s This is a report of a background removal that did not go well %s Url: {url} %s Settings : {settings} %s Thank you! %s', 'enable-media-replace'), $linebreak_double, $linebreak_double, $linebreak, $linebreak_double, $linebreak_double); | ||
| 34 | |||
| 35 | $replace_url = add_query_arg(array( | ||
| 36 | 'page' => 'enable-media-replace/enable-media-replace.php', | ||
| 37 | 'action' => 'media_replace', | ||
| 38 | 'attachment_id' => $attachment_id, | ||
| 39 | ), admin_url("upload.php")); | ||
| 40 | |||
| 41 | ?> | ||
| 42 | |||
| 43 | <div class="wrap emr_upload_form" id="remove-background-form"> | ||
| 44 | |||
| 45 | <form id="emr_replace_form" enctype="multipart/form-data" method="POST" action="<?php | ||
| 46 | echo $formurl; ?>" > | ||
| 47 | |||
| 48 | <?php wp_nonce_field('media_remove_background', 'emr_nonce'); ?> | ||
| 49 | |||
| 50 | |||
| 51 | <input type="hidden" name="ID" value="<?php echo intval($attachment_id); ?>" /> | ||
| 52 | <input type='hidden' name='key' value='' /> | ||
| 53 | |||
| 54 | <div class="editor-wrapper" > | ||
| 55 | <section class='image_chooser wrapper'> | ||
| 56 | <div class='section-header'> <?php esc_html_e( 'Remove Media Background', 'enable-media-replace' ); ?></div> | ||
| 57 | <div class='image_previews'> | ||
| 58 | <?php echo $base_image; ?> | ||
| 59 | <?php echo $replace_image ?> | ||
| 60 | |||
| 61 | </div> | ||
| 62 | |||
| 63 | <div class='bad-button'> | ||
| 64 | <a href="" data-link="mailto:support@shortpixel.com?subject=<?php echo esc_attr($email_subject) ?>&body=<?php echo esc_attr($email_body) ?>" id="bad-background-link" class="button"><?php esc_html_e('Report bad background removal','enable-media-replace'); ?></a> | ||
| 65 | |||
| 66 | </div> | ||
| 67 | |||
| 68 | </section> | ||
| 69 | |||
| 70 | <p><a href="<?php echo esc_attr(wp_nonce_url($replace_url, 'media_replace')); ?>"> | ||
| 71 | <?php esc_html_e('Replace this image with another one instead!', 'enable-media-replace'); ?> | ||
| 72 | </a></p> | ||
| 73 | <div class="option-flex-wrapper"> | ||
| 74 | <section class="replace_type wrapper"> | ||
| 75 | <div class="section-header"><?php esc_html_e('Background Removal Options', 'enable-media-replace'); ?></div> | ||
| 76 | <div class="option replace "> | ||
| 77 | <p> | ||
| 78 | <?php esc_html_e('If a CDN is used, remember to clear the cache for this image!', 'enable-media-replace'); ?> | ||
| 79 | </p> | ||
| 80 | <label for="transparent_background"> | ||
| 81 | <input id="transparent_background" type="radio" name="background_type" value="transparent" <?php checked('transparent', $view->settings['bg_type']); ?> > | ||
| 82 | <?php esc_html_e('Transparent/white background', 'enable-media-replace'); ?> | ||
| 83 | </label> | ||
| 84 | <p class="howto"> | ||
| 85 | <?php esc_html_e('Returns a transparent background if it is a PNG image, or a white one if it is a JPG image.', 'enable-media-replace'); ?> | ||
| 86 | </p> | ||
| 87 | </div> | ||
| 88 | <div class="option searchreplace"> | ||
| 89 | <label for="solid_background"> | ||
| 90 | <input id="solid_background" type="radio" name="background_type" value="solid" <?php checked('solid', $view->settings['bg_type']); ?>> | ||
| 91 | <?php esc_html_e('Solid background', 'enable-media-replace'); ?> | ||
| 92 | </label> | ||
| 93 | <p class="howto"> | ||
| 94 | <?php esc_html_e('If you select this option, the image will have a solid color background and you can choose the color code from the color picker below.', 'enable-media-replace'); ?> | ||
| 95 | </p> | ||
| 96 | <div id="solid_selecter" style="display:none;"> | ||
| 97 | <label for="bg_display_picker"> | ||
| 98 | <p><?php esc_html_e('Background Color:','enable-media-replace'); ?> <strong> | ||
| 99 | <span style="text-transform: uppercase;" id="color_range"> | ||
| 100 | <?php echo esc_attr($view->settings['bg_color']); ?></span> | ||
| 101 | </strong> | ||
| 102 | </p> | ||
| 103 | <input type="color" value="<?php echo esc_attr($view->settings['bg_color']); ?>" name="bg_display_picker" id="bg_display_picker" /> | ||
| 104 | <input type="hidden" value="<?php echo esc_attr($view->settings['bg_color']); ?>" name="bg_color" id="bg_color" /> | ||
| 105 | </label> | ||
| 106 | <hr> | ||
| 107 | <label for="bg_transparency"> | ||
| 108 | <p><?php esc_html_e('Opacity:', 'enable-media-replace'); ?> | ||
| 109 | <strong> | ||
| 110 | <span id="transparency_range"><?php echo esc_attr($view->settings['bg_transparency']); ?></span>%</strong> | ||
| 111 | </p> | ||
| 112 | <input type="range" min="0" max="100" value="<?php echo esc_attr($view->settings['bg_transparency']); ?>" id="bg_transparency" /> | ||
| 113 | </label> | ||
| 114 | </div> | ||
| 115 | </div> | ||
| 116 | </section> | ||
| 117 | |||
| 118 | |||
| 119 | </div> | ||
| 120 | <button type="button" class="button button-primary" id="remove_background_button"><?php esc_html_e('Preview', 'enable-media-replace'); ?></button> | ||
| 121 | <button type="submit" class="button button-primary" id="replace_image_button" disabled><?php esc_html_e('Replace', 'enable-media-replace'); ?></button> | ||
| 122 | <a class="button" href="javascript:history.back()"><?php esc_html_e('Cancel', 'enable-media-replace'); ?></a> | ||
| 123 | </div> <!--- editor wrapper --> | ||
| 124 | <?php include_once( 'upsell.php' ); ?> | ||
| 125 | </form> | ||
| 126 | </div> |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | //use \EnableMediaReplace\UIHelper; | ||
| 9 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 10 | use EnableMediaReplace\Notices\NoticeController as Notices; | ||
| 11 | use EnableMediaReplace\Controller\ReplaceController as ReplaceController; | ||
| 12 | |||
| 13 | |||
| 14 | /** | ||
| 15 | * Uploadscreen for selecting and uploading new media file | ||
| 16 | * | ||
| 17 | * @author Måns Jonasson <http://www.mansjonasson.se> | ||
| 18 | * @copyright Måns Jonasson 13 sep 2010 | ||
| 19 | * @version $Revision: 2303 $ | $Date: 2010-09-13 11:12:35 +0200 (ma, 13 sep 2010) $ | ||
| 20 | * @package wordpress | ||
| 21 | * @subpackage enable-media-replace | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | if ( ! defined( 'ABSPATH' ) ) | ||
| 25 | exit; // Exit if accessed directly. | ||
| 26 | |||
| 27 | if (!current_user_can('upload_files')) | ||
| 28 | wp_die( esc_html__('You do not have permission to upload files.', 'enable-media-replace') ); | ||
| 29 | |||
| 30 | |||
| 31 | $attachment_id = $view->attachment->ID; | ||
| 32 | $settings = $view->settings; | ||
| 33 | $sourceFile = $view->sourceFile; | ||
| 34 | |||
| 35 | $uiHelper = emr()->uiHelper(); | ||
| 36 | |||
| 37 | ?> | ||
| 38 | |||
| 39 | <div class="wrap emr_upload_form"> | ||
| 40 | |||
| 41 | <div class='emr_drop_area' id='emr-drop-area'><h3><?php _e('Drop File', 'enable-media-replace'); ?></h3></div> | ||
| 42 | |||
| 43 | <h1><?php echo esc_html__("Replace Media Upload", "enable-media-replace"); ?></h1> | ||
| 44 | |||
| 45 | <?php | ||
| 46 | |||
| 47 | $formurl = $uiHelper->getFormUrl($attachment_id); | ||
| 48 | //$formurl = wp_nonce_url( $url, "media_replace_upload" ); | ||
| 49 | |||
| 50 | if (FORCE_SSL_ADMIN) { | ||
| 51 | $formurl = str_replace("http:", "https:", $formurl); | ||
| 52 | } | ||
| 53 | ?> | ||
| 54 | |||
| 55 | <form enctype="multipart/form-data" method="POST" action="<?php echo $formurl; ?>"> | ||
| 56 | <?php wp_nonce_field('media_replace_upload', 'emr_nonce'); ?> | ||
| 57 | |||
| 58 | <div class='editor-wrapper'> | ||
| 59 | <section class='image_chooser wrapper'> | ||
| 60 | <div class='section-header'> <?php _e('Select Replacement Media', 'enable-media-replace'); ?></div> | ||
| 61 | |||
| 62 | <!-- | ||
| 63 | <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"), $sourceFile->getFileName() ); ?></strong></div> | ||
| 64 | --> | ||
| 65 | |||
| 66 | <input type="hidden" name="ID" value="<?php echo $attachment_id ?>" /> | ||
| 67 | |||
| 68 | <p class='explainer'> | ||
| 69 | <?php printf(esc_html__(' You are about to replace %s in your media library. This will be %spermanent%s. %s You can click on the new image panel and select a file from your computer. You can also drag and drop a file into this window', 'enable-media-replace'), '<b class="underline" title="' . $sourceFile->getFullPath() . '">' . $sourceFile->getFileName() . '</b>', '<b>','</b>', '<br>' ); | ||
| 70 | ?> | ||
| 71 | </p> | ||
| 72 | |||
| 73 | <p><?php printf(__('Maximum file size: <strong>%s</strong>','enable-media-replace'), size_format(wp_max_upload_size() ) ) ?></p> | ||
| 74 | <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> | ||
| 75 | </div> | ||
| 76 | |||
| 77 | <div class='form-warning filetype'><p><?php printf(__('The replacement file does not have the same file type. This can lead to unexpected issues ( %s )', 'enable-media-replace'), '<span class="source_type"></span> - <span class="target_type"></span>'); ?> | ||
| 78 | |||
| 79 | </p></div> | ||
| 80 | |||
| 81 | <div class='form-warning mimetype'><p><?php printf(__('The replacement file type does not seem to be allowed by WordPress. This can lead to unexpected issues')); ?></p></div> | ||
| 82 | |||
| 83 | <div class='image_previews'> | ||
| 84 | |||
| 85 | <?php | ||
| 86 | |||
| 87 | if (wp_attachment_is('image', $attachment_id) || $view->sourceMime == 'application/pdf') | ||
| 88 | { | ||
| 89 | echo $uiHelper->getPreviewImage($attachment_id, $sourceFile); | ||
| 90 | echo $uiHelper->getPreviewImage(-1, $sourceFile, array('is_upload' => true)); | ||
| 91 | } | ||
| 92 | else { | ||
| 93 | |||
| 94 | if (strlen($sourceFile->getFullPath()) == 0) // check if image in error state. | ||
| 95 | { | ||
| 96 | echo $uiHelper->getPreviewError(-1); | ||
| 97 | echo $uiHelper->getPreviewImage(-1, $sourceFile, array('is_upload' => true)); | ||
| 98 | } | ||
| 99 | else { | ||
| 100 | echo $uiHelper->getPreviewFile($attachment_id, $sourceFile); | ||
| 101 | echo $uiHelper->getPreviewFile(-1, $sourceFile, array('is_upload' => true)); | ||
| 102 | } | ||
| 103 | |||
| 104 | } | ||
| 105 | ?> | ||
| 106 | </div> | ||
| 107 | <?php | ||
| 108 | $url = admin_url("upload.php"); | ||
| 109 | $url = add_query_arg(array( | ||
| 110 | 'page' => 'enable-media-replace/enable-media-replace.php', | ||
| 111 | 'action' => 'emr_prepare_remove', | ||
| 112 | 'attachment_id' => $attachment_id, | ||
| 113 | ), $url); | ||
| 114 | ?> | ||
| 115 | |||
| 116 | <p> </p> | ||
| 117 | <?php if ($uiHelper->isBackgroundRemovable($view->attachment)): ?> | ||
| 118 | <div> | ||
| 119 | |||
| 120 | <a href="<?php echo wp_nonce_url( $url , 'emr_prepare_remove' ); ?>"> | ||
| 121 | <?php _e('New! Click here to remove the background of this image!', 'enable-media-replace'); ?></a> | ||
| 122 | <br> | ||
| 123 | <br> | ||
| 124 | <input type="checkbox" id="remove_after_progress" name="remove_after_progress" value="<?php echo $attachment_id;?>"> | ||
| 125 | <label for="remove_after_progress"><?php _e('Remove the background after replacing this image!' ,'enable-media-replace'); ?> </label> | ||
| 126 | </div> | ||
| 127 | <?php endif; ?> | ||
| 128 | </section> | ||
| 129 | |||
| 130 | <div class='option-flex-wrapper'> | ||
| 131 | <section class='replace_type wrapper'> | ||
| 132 | <div class='section-header'> <?php _e('Replacement Options', 'enable-media-replace'); ?></div> | ||
| 133 | |||
| 134 | <?php | ||
| 135 | // these are also used in externals, for checks. | ||
| 136 | do_action( 'emr_before_replace_type_options' ); ?> | ||
| 137 | |||
| 138 | |||
| 139 | <?php $enabled_search = apply_filters( 'emr_display_replace_type_options', true ); | ||
| 140 | $search_disabled = (! $enabled_search) ? 'disabled' : ''; | ||
| 141 | ?> | ||
| 142 | <div class='option replace <?php echo $search_disabled ?>'> | ||
| 143 | <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"); ?> | ||
| 144 | </label> | ||
| 145 | |||
| 146 | <p class="howto"> | ||
| 147 | <?php printf( esc_html__("Note: This option requires you to upload a file of the same type (%s) as the file you want to replace. The attachment name will remain the same (%s) regardless of what the file you upload is called. If a CDN is used, remember to clear the cache for this image!", "enable-media-replace"), $sourceFile->getExtension(), $sourceFile->getFileName() ); ?> | ||
| 148 | </p> | ||
| 149 | |||
| 150 | <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'); ?> | ||
| 151 | </p> | ||
| 152 | |||
| 153 | <?php do_action('emr_after_search_type_options'); ?> | ||
| 154 | </div> | ||
| 155 | |||
| 156 | <?php $enabled_replacesearch = apply_filters( 'emr_enable_replace_and_search', true ); | ||
| 157 | $searchreplace_disabled = (! $enabled_replacesearch) ? 'disabled' : ''; | ||
| 158 | ?> | ||
| 159 | |||
| 160 | <div class="option searchreplace <?php echo $searchreplace_disabled ?>"> | ||
| 161 | <label for="replace_type_2"><input id="replace_type_2" <?php checked('replace_and_search', $settings['replace_type']) ?> type="radio" name="replace_type" value="replace_and_search" <?php echo $searchreplace_disabled ?> > <?php echo __("Replace the file, use the new file name, and update all links", "enable-media-replace"); ?> | ||
| 162 | </label> | ||
| 163 | |||
| 164 | <p class="howto"><?php printf( esc_html__("Note: If you enable this option, the name and type of the file you are uploading will replace the old file. All links pointing to the current file (%s) will be updated to point to the new file name. (If other websites link directly to the file, those links will no longer work. Be careful!)", "enable-media-replace"), $sourceFile->getFileName() ); ?></p> | ||
| 165 | |||
| 166 | <!-- <p class="howto"><?php echo esc_html__("Please note that if you upload a new image, only the embeds/links of the original size image will be replaced in your posts.", "enable-media-replace"); ?></p> --> | ||
| 167 | |||
| 168 | <?php do_action('emr_after_replace_type_options'); ?> | ||
| 169 | </div> | ||
| 170 | |||
| 171 | </section> | ||
| 172 | <section class='options wrapper'> | ||
| 173 | <div class='section-header'> <?php _e('Options', 'enable-media-replace'); ?></div> | ||
| 174 | <div class='option timestamp'> | ||
| 175 | <?php | ||
| 176 | $attachment_current_date = date_i18n('d/M/Y H:i', strtotime($view->attachment->post_date) ); | ||
| 177 | $attachment_now_date = date_i18n('d/M/Y H:i' ); | ||
| 178 | |||
| 179 | $time = current_time('mysql'); | ||
| 180 | $date = $nowDate = new \dateTime($time); // default to now. | ||
| 181 | $attachmentDate = new \dateTime($view->attachment->post_date); | ||
| 182 | |||
| 183 | |||
| 184 | if ($settings['timestamp_replace'] == ReplaceController::TIME_CUSTOM) | ||
| 185 | { | ||
| 186 | $date = new \dateTime($settings['custom_date']); | ||
| 187 | } | ||
| 188 | ?> | ||
| 189 | <p><?php _e('When replacing the media, do you want to:', 'enable-media-replace'); ?></p> | ||
| 190 | <ul> | ||
| 191 | <li><label><input type='radio' <?php checked('1', $settings['timestamp_replace']) ?> name='timestamp_replace' value='1' /><?php printf(__('Replace the date with the current date %s(%s)%s', 'enable-media-replace'), "<span class='small'>", $attachment_now_date, "</span>") ; ?></label></li> | ||
| 192 | <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> | ||
| 193 | <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> | ||
| 194 | </ul> | ||
| 195 | <div class='custom_date'> | ||
| 196 | |||
| 197 | <span class='field-title dashicons dashicons-calendar'><?php _e('Custom Date', 'enable-media-replace'); ?></span> | ||
| 198 | <input type='text' name="custom_date" value="<?php echo $date->format(get_option('date_format')); ?>" id='emr_datepicker' | ||
| 199 | class='emr_datepicker' /> | ||
| 200 | |||
| 201 | @ <input type='text' name="custom_hour" class='emr_hour' id='emr_hour' value="<?php echo $date->format('H') ?>" /> | ||
| 202 | <input type="text" name="custom_minute" class='emr_minute' id='emr_minute' value="<?php echo $date->format('i'); ?>" /> | ||
| 203 | <input type="hidden" name="custom_date_formatted" value="<?php echo $date->format('Y-m-d'); ?>" /> | ||
| 204 | |||
| 205 | <span class="replace_custom_date_wrapper"> | ||
| 206 | <?php | ||
| 207 | 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')); | ||
| 208 | echo " "; | ||
| 209 | 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')); | ||
| 210 | ?> | ||
| 211 | </span> | ||
| 212 | </div> | ||
| 213 | <?php if ($subdir = $uiHelper->getRelPathNow()): | ||
| 214 | |||
| 215 | if ($settings['new_location'] !== false) | ||
| 216 | $subdir = $settings['new_location_dir']; | ||
| 217 | ?> | ||
| 218 | |||
| 219 | <!-- | ||
| 220 | <div class='title_option'> | ||
| 221 | <input type="text" name="new_title" value=""> | ||
| 222 | </div> | ||
| 223 | --> | ||
| 224 | <div class='location_option'> | ||
| 225 | <?php | ||
| 226 | if (true === $view->is_movable): ?> | ||
| 227 | <label><input type="checkbox" name="new_location" value="1" <?php checked($settings['new_location'], 1); ?> /> <?php _e('Place the newly uploaded file in this folder: ', 'enable-media-replace'); ?></label> | ||
| 228 | <br> | ||
| 229 | <?php echo $view->custom_basedir ?> <input type="text" name="location_dir" value="<?php echo $subdir ?>" /> | ||
| 230 | <?php | ||
| 231 | else: | ||
| 232 | echo __('File is offloaded and can\'t be moved to other directory', 'enable-media-replace'); | ||
| 233 | endif; | ||
| 234 | ?> | ||
| 235 | </div> | ||
| 236 | <?php endif; ?> | ||
| 237 | |||
| 238 | </div> | ||
| 239 | |||
| 240 | </section> | ||
| 241 | </div> | ||
| 242 | <section class='form_controls wrapper'> | ||
| 243 | <input id="submit" type="submit" class="button button-primary" disabled="disabled" value="<?php echo esc_attr__("Upload", "enable-media-replace"); ?>" /> | ||
| 244 | <a href="#" class="button" onclick="history.back();"><?php echo esc_html__("Cancel", "enable-media-replace"); ?></a> | ||
| 245 | </section> | ||
| 246 | </div> | ||
| 247 | |||
| 248 | <?php include_once('upsell.php'); ?> | ||
| 249 | |||
| 250 | |||
| 251 | |||
| 252 | </form> | ||
| 253 | </div> |
| 1 | <?php | ||
| 2 | namespace EnableMediaReplace; | ||
| 3 | |||
| 4 | if (! defined('ABSPATH')) { | ||
| 5 | exit; // Exit if accessed directly. | ||
| 6 | } | ||
| 7 | |||
| 8 | //use \EnableMediaReplace\UIHelper; | ||
| 9 | use EnableMediaReplace\ShortPixelLogger\ShortPixelLogger as Log; | ||
| 10 | |||
| 11 | |||
| 12 | ?> | ||
| 13 | |||
| 14 | <div class='enable-media-replace emr-screen success-screen'> | ||
| 15 | <h3 class='title'><?php _e('Enable Media Replace', 'enable-media-replace'); ?></h3> | ||
| 16 | <div class='content'> | ||
| 17 | <h1><?php _e('Your image has been replaced!', 'enable-media-replace'); ?></h1> | ||
| 18 | |||
| 19 | <p><?php _e('Your image has been successfully replaced!', 'enable-media-replace'); ?></p> | ||
| 20 | |||
| 21 | <p><?php _e('Did you know that you can also optimize the images on your website to make them load faster?', 'enable-media-replace'); ?></p> | ||
| 22 | |||
| 23 | <p><?php printf(esc_html__('Try the %sShortPixel Image Optimizer%s plugin!', 'enable-media-replace'), '<a href="https://wordpress.org/plugins/shortpixel-image-optimiser/" target="_blank">', '</a>'); ?></p> | ||
| 24 | |||
| 25 | <p><?php _e('You will be redirect to the image screen in a few seconds.', 'enable-media-replace'); | ||
| 26 | printf(esc_html__('( %s ) or %s click here to continue %s', 'enable-media-replace'), '<span id="redirect_counter"></span>', | ||
| 27 | '<a id="redirect_url" href="' . esc_url( $view->postUrl ) . '">', '</a>'); | ||
| 28 | ?> | ||
| 29 | |||
| 30 | </p> | ||
| 31 | |||
| 32 | </div> | ||
| 33 | |||
| 34 | </div> | ||
| 35 | |||
| 36 | <?php | ||
| 37 | require_once ABSPATH . 'wp-admin/admin-footer.php'; |
| 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 esc_url(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 AI --> | ||
| 100 | |||
| 101 | <!--- Shortpixel THEME --> | ||
| 102 | <div class='shortpixel-offer theme-offer'> | ||
| 103 | <p><a href="https://wordpress.org/themes/superb-pixels/" target="_blank"><img src="<?php echo esc_url(emr()->getPluginURL('img/sp-banner-theme.jpg')); ?>" alt='ShortPixel Theme' ></a></p> | ||
| 104 | |||
| 105 | </div> | ||
| 106 | <!--- // Shortpixel THEME --> | ||
| 107 | |||
| 108 | <!--- WPSO --> | ||
| 109 | <?php /* | ||
| 110 | <div class='shortpixel-offer site-speed'> | ||
| 111 | <p class='img-wrapper'><img width="40" height="40" src="<?php echo emr()->getPluginURL('img/sp-logo-wink.svg'); ?>" alt='ShortPixel'></p> | ||
| 112 | <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> | ||
| 113 | |||
| 114 | <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> | ||
| 115 | </div> | ||
| 116 | */ ?> | ||
| 117 | <!--- // WPSO --> | ||
| 118 | |||
| 119 | |||
| 120 | |||
| 121 | <!--- ENVIRA temprary deactivated | ||
| 122 | <?php if (! $envira_pro_active): ?> | ||
| 123 | <div class='envira-shortpixel-install shortpixel-offer'> | ||
| 124 | |||
| 125 | <p class='img-wrapper'><img src="<?php echo emr()->getPluginURL('img/envira-logo.png'); ?>" alt='Envira Gallery'></p> | ||
| 126 | <p><?php esc_html_e('Create beautiful, fast-loading photo & video galleries for your site in minutes.', 'enable-media-replace' ); ?></p> | ||
| 127 | |||
| 128 | <?php | ||
| 129 | $install_class = (! $envira_installed) ? '' : 'hidden'; | ||
| 130 | $activate_class = ($envira_installed && ! $envira_active) ? '' : 'hidden'; | ||
| 131 | ?> | ||
| 132 | <?php if (! $envira_active) { ?> | ||
| 133 | <p class='button-wrapper envira-emr-button-wrap'> | ||
| 134 | |||
| 135 | <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> | ||
| 136 | |||
| 137 | <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> | ||
| 138 | |||
| 139 | <h4 class='emr-activate-done hidden' data-plugin='envira'><?php _e('Envira Gallery activated!', 'enable-media-replace'); ?></h4> | ||
| 140 | |||
| 141 | </p> | ||
| 142 | |||
| 143 | <?php } else { | ||
| 144 | if ( is_plugin_active( 'envira-gallery-lite/envira-gallery-lite.php' ) ) { | ||
| 145 | ?> | ||
| 146 | <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> | ||
| 147 | |||
| 148 | <?php } else { ?> | ||
| 149 | |||
| 150 | <?php } | ||
| 151 | } ?> | ||
| 152 | </div> | ||
| 153 | <style> | ||
| 154 | .envira-emr-button-wrap { | ||
| 155 | text-align: center; | ||
| 156 | } | ||
| 157 | .button-envira-emr { | ||
| 158 | background-color: #7cc048 !important; | ||
| 159 | border: none !important; | ||
| 160 | color: rgb(255,255,255) !important; | ||
| 161 | font-size: 21px !important; | ||
| 162 | } | ||
| 163 | .button-envira-emr:hover { | ||
| 164 | background-color: #95dc5e !important; | ||
| 165 | } | ||
| 166 | </style> | ||
| 167 | <?php endif; // envira ?> | ||
| 168 | --> | ||
| 169 | |||
| 170 | </section> |
-
Please register or sign in to post a comment