Version Description
- (released 27 dec 2018) *
- Optionally make .htaccess redirect directly to existing webp (improves performance)
- Optionally do not send filename from .htaccess to the PHP in Querystring, but use other means (improves security and reduces risks of problems due to firewall rules)
- Fixed some bugs
For more info, see the closed issues on the 0.9.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.9.0
Download this release
Release Info
Developer | rosell.dk |
Plugin | WebP Express |
Version | 0.9.0 |
Comparing to | |
See all releases |
Code changes from version 0.8.1 to 0.9.0
- README.md +38 -10
- README.txt +34 -19
- changelog.txt +8 -0
- lib/classes/Config.php +178 -0
- lib/classes/HTAccess.php +158 -40
- lib/classes/Paths.php +30 -8
- lib/classes/TestRun.php +25 -6
- lib/migrate/migrate1.php +1 -1
- lib/options/css/webp-express-options-page.css +31 -0
- lib/options/enqueue_scripts.php +27 -12
- lib/options/js/converters.js +16 -4
- lib/options/js/page.js +11 -0
- lib/options/js/whitelist.js +4 -0
- lib/options/options-hooks.php +13 -7
- lib/options/options/cache-control.inc +25 -0
- lib/options/{converter-options → options/converter-options}/cwebp.php +0 -0
- lib/options/{converter-options → options/converter-options}/ewww.php +0 -0
- lib/options/{converter-options → options/converter-options}/gd.php +0 -0
- lib/options/{converter-options → options/converter-options}/imagick.php +0 -0
- lib/options/{converter-options → options/converter-options}/imagickbinary.php +0 -0
- lib/options/{converter-options → options/converter-options}/wpc.php +0 -0
- lib/options/options/converters.inc +76 -0
- lib/options/options/do-not-pass-source-path-in-query-string.inc +6 -0
- lib/options/options/image-types.inc +22 -0
- lib/options/options/metadata.inc +16 -0
- lib/options/options/quality.inc +52 -0
- lib/options/options/redirect-to-existing.inc +8 -0
- lib/options/options/response-on-failure.inc +17 -0
- lib/options/options/web-service.inc +58 -0
- lib/options/page.php +70 -534
- lib/options/submit.php +3 -1
- web-service/.htaccess +9 -0
- webp-express.php +1 -1
- wod/.htaccess +9 -0
- wod/webp-on-demand.php +104 -30
README.md
CHANGED
@@ -117,36 +117,64 @@ It is possible to make WebP Express work on NGINX, but it requieres manually ins
|
|
117 |
|
118 |
*Note that the rules stated here previously had a bug*: It had ” rather than ". The slightly slanted quotation mark does not work. Also, it used $request_uri, which contains the querystring, which resulted in errors when querystrings were supplied (ie ?debug)
|
119 |
|
|
|
120 |
```
|
121 |
if ($http_accept ~* "webp"){
|
122 |
rewrite ^/(.*).(jpe?g|png)$ /wp-content/plugins/webp-express/wod/webp-on-demand.php?xsource=x$request_filename&wp-content=wp-content break;
|
123 |
}
|
124 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
The `wp-content` argument must point to the wp-content folder (relative to document root). In most installations, it is 'wp-content'.
|
127 |
|
128 |
-
Discussion on this topic here
|
129 |
|
130 |
### I am on a WAMP stack
|
131 |
It has been reported that WebP Express *almost* works on WAMP stack (Windows, Apache, MySQL, PHP). I'd love to debug this, but do not own a Windows server or access to one... Can you help?
|
132 |
|
133 |
### Why do I not see the option to set WebP quality to auto?
|
134 |
-
The option will only display, if your system is able to detect jpeg qualities. To make your server capable to do that, install *Imagick* or *Gmagick
|
|
|
|
|
|
|
|
|
135 |
|
136 |
### How do I make this work with a CDN?
|
137 |
Chances are that the default setting of your CDN is not to forward any headers to your origin server. But the plugin needs the "Accept" header, because this is where the information is whether the browser accepts webp images or not. You will therefore have to make sure to configure your CDN to forward the "Accept" header.
|
138 |
|
139 |
The plugin takes care of setting the "Vary" HTTP header to "Accept" when routing WebP images. When the CDN sees this, it knows that the response varies, depending on the "Accept" header. The CDN is thus instructed not to cache the response on URL only, but also on the "Accept" header. This means that it will store an image for every accept header it meets. Luckily, there are (not that many variants for images)[https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values#Values_for_an_image], so it is not an issue.
|
140 |
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
-
|
145 |
-
|
146 |
-
|
147 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
|
149 |
-
For more info, see the closed issues on the 0.
|
150 |
|
151 |
## Supporting WebP Express
|
152 |
Bread on the table don't come for free, even though this plugin does, and always will. I enjoy developing this, and supporting you guys, but I kind of need the bread too. Please make it possible for me to continue putting effort into this plugin:
|
117 |
|
118 |
*Note that the rules stated here previously had a bug*: It had ” rather than ". The slightly slanted quotation mark does not work. Also, it used $request_uri, which contains the querystring, which resulted in errors when querystrings were supplied (ie ?debug)
|
119 |
|
120 |
+
For 0.8.0:
|
121 |
```
|
122 |
if ($http_accept ~* "webp"){
|
123 |
rewrite ^/(.*).(jpe?g|png)$ /wp-content/plugins/webp-express/wod/webp-on-demand.php?xsource=x$request_filename&wp-content=wp-content break;
|
124 |
}
|
125 |
```
|
126 |
+
*Beware:* If you copy the code above, you might get an html-encoded ampersand before "wp-content"
|
127 |
+
|
128 |
+
For 0.7.0:
|
129 |
+
```
|
130 |
+
if ($http_accept ~* "webp"){
|
131 |
+
rewrite ^/(.*).(jpe?g|png)$ /wp-content/plugins/webp-express/wod/webp-on-demand.php?source=$request_filename&wp-content=wp-content break;
|
132 |
+
}
|
133 |
+
```
|
134 |
+
*Beware:* If you copy the code above, you might get an html-encoded ampersand before "wp-content"
|
135 |
|
136 |
The `wp-content` argument must point to the wp-content folder (relative to document root). In most installations, it is 'wp-content'.
|
137 |
|
138 |
+
Discussion on this topic [here](https://wordpress.org/support/topic/nginx-rewrite-rules-4/)
|
139 |
|
140 |
### I am on a WAMP stack
|
141 |
It has been reported that WebP Express *almost* works on WAMP stack (Windows, Apache, MySQL, PHP). I'd love to debug this, but do not own a Windows server or access to one... Can you help?
|
142 |
|
143 |
### Why do I not see the option to set WebP quality to auto?
|
144 |
+
The option will only display, if your system is able to detect jpeg qualities. To make your server capable to do that, install *Imagick extension* (PECL >= 2.2.2) or enable exec() calls and install either *Imagick* or *Gmagick*.
|
145 |
+
|
146 |
+
If you have the *Imagick*, the *Imagick binary* or the *Remote WebP Express* conversion method working, but don't have the global "auto" option, you will have the auto option available in options of the individual converter.
|
147 |
+
|
148 |
+
Note: If you experience that the general auto option doesn't show, even though the above-mentioned requirements should be in order, check out [this support-thread](https://wordpress.org/support/topic/still-no-auto-option/).
|
149 |
|
150 |
### How do I make this work with a CDN?
|
151 |
Chances are that the default setting of your CDN is not to forward any headers to your origin server. But the plugin needs the "Accept" header, because this is where the information is whether the browser accepts webp images or not. You will therefore have to make sure to configure your CDN to forward the "Accept" header.
|
152 |
|
153 |
The plugin takes care of setting the "Vary" HTTP header to "Accept" when routing WebP images. When the CDN sees this, it knows that the response varies, depending on the "Accept" header. The CDN is thus instructed not to cache the response on URL only, but also on the "Accept" header. This means that it will store an image for every accept header it meets. Luckily, there are (not that many variants for images)[https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values#Values_for_an_image], so it is not an issue.
|
154 |
|
155 |
+
### Does it work with lazy loaded images?
|
156 |
+
No plugins/frameworks has yet been discovered, which does not work with *WebP Express*.
|
157 |
+
|
158 |
+
The most common way of lazy-loading is by setting a *data-src* attribute on the image and let javascript use that value for setten the *src* attribute. That method works, as the image request, seen from the server side, is indistinguishable from any other image request. It could however be that some obscure lazy load implementation would load the image with an XHR request. In that case, the *Accept* header will not contain 'image/webp', but '*/*', and a jpeg will be served, even though the browser supports webp.
|
159 |
+
|
160 |
+
The following lazy load plugins/frameworks has been tested and works with *WebP Express*:
|
161 |
+
- [BJ Lazy Load](https://da.wordpress.org/plugins/bj-lazy-load/)
|
162 |
+
- [Owl Carousel 2](https://owlcarousel2.github.io/OwlCarousel2/)
|
163 |
+
|
164 |
+
### When is feature X coming? / Roadmap
|
165 |
+
No schedule. I move forward as time allows. I currently spend a lot of time answering questions in the support forum. If someone would be nice and help out answering questions here, it would allow me to spend that time developing. Also, donations would allow me to turn down some of the more boring requests from my customers, and speed things up here.
|
166 |
+
|
167 |
+
Here are my loose plans ahead: The 0.10 release will probably add a some diagnose tool – this should release some time spend in the forum. I might also throw in configurable destination. 0.11 could be focused on PNG. 0.12 might be displaying rules for NGINX. 0.13 might be supporting Save-Data header (send extra compressed images to clients who wants to use as little bandwidth as possible). 0.14 might be multisite support. 0.15 might be a file manager-like interface for inspecting generated webp files. 0.16 might be WAMP support. This is all guessing. I’m only planning one milestone at the time. You can follow the issue queue here: https://github.com/rosell-dk/webp-express/issues
|
168 |
+
|
169 |
+
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
170 |
+
|
171 |
+
|
172 |
+
## Changes in 0.9.0
|
173 |
+
- Optionally make .htaccess redirect directly to existing webp (improves performance)
|
174 |
+
- Optionally do not send filename from .htaccess to the PHP in Querystring, but use other means (improves security and reduces risks of problems due to firewall rules)
|
175 |
+
- Fixed some bugs
|
176 |
|
177 |
+
For more info, see the closed issues on the 0.9.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.9.0
|
178 |
|
179 |
## Supporting WebP Express
|
180 |
Bread on the table don't come for free, even though this plugin does, and always will. I enjoy developing this, and supporting you guys, but I kind of need the bread too. Please make it possible for me to continue putting effort into this plugin:
|
README.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://ko-fi.com/rosell
|
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.0
|
7 |
-
Stable tag: 0.
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
@@ -124,29 +124,19 @@ Easy enough. Browsers looks at the *content type* header rather than the URL to
|
|
124 |
I am btw considering making an option to have the plugin redirect to the webp instead of serving immediately. That would remove the apparent mismatch between file extension and content type header. However, the cost of doing that will be an extra request for each image, which means extra time and worse performance. I believe you'd be ill advised to use that option, so I guess I will not implement it. But perhaps you have good reasons to use it? If you do, please let me know!
|
125 |
|
126 |
= I am on NGINX / OpenResty =
|
127 |
-
It is possible to make WebP Express work on NGINX, but it requieres manually inserting redirection rules in the NGINX configuration file (nginx.conf). For standard wordpress installations, the following rules should work:
|
128 |
|
129 |
-
|
130 |
-
|
131 |
-
For 0.8.0:
|
132 |
-
`
|
133 |
if ($http_accept ~* "webp"){
|
134 |
rewrite ^/(.*).(jpe?g|png)$ /wp-content/plugins/webp-express/wod/webp-on-demand.php?xsource=x$request_filename&wp-content=wp-content break;
|
135 |
}
|
136 |
-
|
137 |
-
*Beware:* If you copy the code above, you might get an html-encoded ampersand before "wp-content"
|
138 |
-
|
139 |
-
For 0.7.0:
|
140 |
-
`
|
141 |
-
if ($http_accept ~* "webp"){
|
142 |
-
rewrite ^/(.*).(jpe?g|png)$ /wp-content/plugins/webp-express/wod/webp-on-demand.php?source=$request_filename&wp-content=wp-content break;
|
143 |
-
}
|
144 |
-
`
|
145 |
*Beware:* If you copy the code above, you might get an html-encoded ampersand before "wp-content"
|
146 |
|
147 |
-
|
148 |
The `wp-content` argument must point to the wp-content folder (relative to document root). In most installations, it is 'wp-content'.
|
149 |
|
|
|
|
|
150 |
Discussion on this topic [here](https://wordpress.org/support/topic/nginx-rewrite-rules-4/)
|
151 |
|
152 |
|
@@ -167,6 +157,21 @@ The plugin takes care of setting the "Vary" HTTP header to "Accept" when routing
|
|
167 |
https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values#Values_for_an_image
|
168 |
- so it is not an issue.
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
= Does it work with lazy loaded images? =
|
171 |
No plugins/frameworks has yet been discovered, which does not work with *WebP Express*.
|
172 |
|
@@ -179,13 +184,12 @@ The following lazy load plugins/frameworks has been tested and works with *WebP
|
|
179 |
= When is feature X coming? =
|
180 |
No schedule. I move forward as time allows. I currently spend a lot of time answering questions in the support forum. If someone would be nice and help out answering questions here, it would allow me to spend that time developing. Also, donations would allow me to turn down some of the more boring requests from my customers, and speed things up here.
|
181 |
|
182 |
-
Here are my loose plans ahead: The 0.
|
183 |
|
184 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
185 |
|
186 |
-
|
187 |
= How do I buy you a cup of coffee? =
|
188 |
-
Easy enough! - [Go here!](https://ko-fi.com/rosell)
|
189 |
|
190 |
== Screenshots ==
|
191 |
|
@@ -193,6 +197,14 @@ Easy enough! - [Go here!](https://ko-fi.com/rosell)
|
|
193 |
|
194 |
== Changelog ==
|
195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
= 0.8.1 =
|
197 |
* Fixed javascript bug
|
198 |
|
@@ -261,5 +273,8 @@ For older releases, check out changelog.txt
|
|
261 |
|
262 |
== Upgrade Notice ==
|
263 |
|
|
|
|
|
|
|
264 |
= 0.8.0 =
|
265 |
New converter and miscellaneous improvements
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.0
|
7 |
+
Stable tag: 0.9.0
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
124 |
I am btw considering making an option to have the plugin redirect to the webp instead of serving immediately. That would remove the apparent mismatch between file extension and content type header. However, the cost of doing that will be an extra request for each image, which means extra time and worse performance. I believe you'd be ill advised to use that option, so I guess I will not implement it. But perhaps you have good reasons to use it? If you do, please let me know!
|
125 |
|
126 |
= I am on NGINX / OpenResty =
|
127 |
+
It is possible to make WebP Express work on NGINX, but it requieres manually inserting redirection rules in the NGINX configuration file (nginx.conf or the configuration file for the site, found in `/etc/nginx/sites-available`). For standard wordpress installations, the following rules should work:
|
128 |
|
129 |
+
```
|
|
|
|
|
|
|
130 |
if ($http_accept ~* "webp"){
|
131 |
rewrite ^/(.*).(jpe?g|png)$ /wp-content/plugins/webp-express/wod/webp-on-demand.php?xsource=x$request_filename&wp-content=wp-content break;
|
132 |
}
|
133 |
+
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
*Beware:* If you copy the code above, you might get an html-encoded ampersand before "wp-content"
|
135 |
|
|
|
136 |
The `wp-content` argument must point to the wp-content folder (relative to document root). In most installations, it is 'wp-content'.
|
137 |
|
138 |
+
Note that the rules above redirects every image request to the PHP script. To get better performance, you can add a rule that redirects jpeg/png requests directly to existing webp images. There are some rules for that [here](https://www.keycdn.com/blog/convert-to-webp-the-successor-of-jpeg#rewriterules-for-nginx-nginx-conf), but they need to be modified because WebP Express stores the webp files in a different location (`wp-content/webp-express/webp-images/doc-root`).
|
139 |
+
|
140 |
Discussion on this topic [here](https://wordpress.org/support/topic/nginx-rewrite-rules-4/)
|
141 |
|
142 |
|
157 |
https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation/List_of_default_Accept_values#Values_for_an_image
|
158 |
- so it is not an issue.
|
159 |
|
160 |
+
In the 0.10.0 release, you will have another (and better) option, as [described here](https://github.com/rosell-dk/webp-express/issues/133)
|
161 |
+
|
162 |
+
= I am on Cloudflare =
|
163 |
+
Without configuration, Cloudflare will not maintain separate caches for jpegs and webp; all browsers will get jpeg. To make Cloudflare cache not only by URL, but also by header, you need to use the [Custom Cache Key](https://support.cloudflare.com/hc/en-us/articles/115004290387) page rule, and add *Header content* to make separate caches depending on the *Accept* request header.
|
164 |
+
|
165 |
+
However, the *Custom Cache Key* rule currently requires an *Enterprise* account. And if you already have that, you may as well go with the *Polish* feature, which starts at the “Pro” level plan. With the *Polish* feature, you will not need WebP Express.
|
166 |
+
|
167 |
+
To make *WebP Express* work on a free Cloudflare account, you have the following choices:
|
168 |
+
|
169 |
+
1. You can configure the CDN not to cache jpeg images by adding the following page rule: If rule matches: `example.com/*.jpg`, set: *Cache level* to: *Bypass*
|
170 |
+
|
171 |
+
2. You can set up another CDN (on another provider), which you just use for handling the images. You need to configure that CDN to forward the *Accept header*. You also need to install a Wordpress plugin that points images to that CDN.
|
172 |
+
|
173 |
+
In the 0.10.0 release, you will have another (and better) option, as [described here](https://github.com/rosell-dk/webp-express/issues/133)
|
174 |
+
|
175 |
= Does it work with lazy loaded images? =
|
176 |
No plugins/frameworks has yet been discovered, which does not work with *WebP Express*.
|
177 |
|
184 |
= When is feature X coming? =
|
185 |
No schedule. I move forward as time allows. I currently spend a lot of time answering questions in the support forum. If someone would be nice and help out answering questions here, it would allow me to spend that time developing. Also, donations would allow me to turn down some of the more boring requests from my customers, and speed things up here.
|
186 |
|
187 |
+
Here are my loose plans ahead: The 0.10 release adds possibility to configure where the generated webp files are located. This together with a few other new options allows WebP Express to work together with the [Cache Enabler](https://wordpress.org/plugins/cache-enabler/) plugin. This is a great combination, which eliminates the need to redirect jpeg to webp. Read more about it [here](https://github.com/rosell-dk/webp-express/issues/133). The 0.11 release will probably add a some diagnose tool – this should release some time spend in the forum. 0.12 could be focused on PNG. 0.13 might be displaying rules for NGINX. 0.14 might be supporting Save-Data header (send extra compressed images to clients who wants to use as little bandwidth as possible). 0.15 might be multisite support. 0.16 might be a file manager-like interface for inspecting generated webp files. 0.17 might be WAMP support. This is all guessing. I’m only planning one milestone at the time. You can follow the issue queue here: https://github.com/rosell-dk/webp-express/issues
|
188 |
|
189 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
190 |
|
|
|
191 |
= How do I buy you a cup of coffee? =
|
192 |
+
Easy enough! - [Go here!](https://ko-fi.com/rosell). Or [here](https://buymeacoff.ee/rosell).
|
193 |
|
194 |
== Screenshots ==
|
195 |
|
197 |
|
198 |
== Changelog ==
|
199 |
|
200 |
+
= 0.9.0 =
|
201 |
+
* (released 27 dec 2018) *
|
202 |
+
* Optionally make .htaccess redirect directly to existing webp (improves performance)
|
203 |
+
* Optionally do not send filename from .htaccess to the PHP in Querystring, but use other means (improves security and reduces risks of problems due to firewall rules)
|
204 |
+
* Fixed some bugs
|
205 |
+
|
206 |
+
For more info, see the closed issues on the 0.9.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.9.0
|
207 |
+
|
208 |
= 0.8.1 =
|
209 |
* Fixed javascript bug
|
210 |
|
273 |
|
274 |
== Upgrade Notice ==
|
275 |
|
276 |
+
= 0.9.0 =
|
277 |
+
Option to redirect to existing webp images directly in .htaccess (improves performance)
|
278 |
+
|
279 |
= 0.8.0 =
|
280 |
New converter and miscellaneous improvements
|
changelog.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 0.8.1 =
|
2 |
* (released 11 dec 2018) *
|
3 |
* Fixed javascript bug
|
1 |
+
= 0.9.0 =
|
2 |
+
* (released 27 dec 2018) *
|
3 |
+
* Optionally make .htaccess redirect directly to existing webp (improves performance)
|
4 |
+
* Optionally do not send filename from .htaccess to the PHP in Querystring, but use other means (improves security and reduces risks of problems due to firewall rules)
|
5 |
+
* Fixed some bugs
|
6 |
+
|
7 |
+
For more info, see the closed issues on the 0.9.0 milestone on the github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.9.0
|
8 |
+
|
9 |
= 0.8.1 =
|
10 |
* (released 11 dec 2018) *
|
11 |
* Fixed javascript bug
|
lib/classes/Config.php
CHANGED
@@ -2,6 +2,9 @@
|
|
2 |
|
3 |
namespace WebPExpress;
|
4 |
|
|
|
|
|
|
|
5 |
include_once "FileHelper.php";
|
6 |
use \WebPExpress\FileHelper;
|
7 |
|
@@ -17,6 +20,9 @@ use \WebPExpress\Paths;
|
|
17 |
include_once "State.php";
|
18 |
use \WebPExpress\State;
|
19 |
|
|
|
|
|
|
|
20 |
class Config
|
21 |
{
|
22 |
|
@@ -52,6 +58,174 @@ class Config
|
|
52 |
return self::loadJSONOptions(Paths::getConfigFileName());
|
53 |
}
|
54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
public static function isConfigFileThere()
|
56 |
{
|
57 |
return (FileHelper::fileExists(Paths::getConfigFileName()));
|
@@ -106,6 +280,7 @@ class Config
|
|
106 |
unset ($c['id']);
|
107 |
unset($c['working']);
|
108 |
unset($c['error']);
|
|
|
109 |
if (isset($c['options']['quality']) && ($c['options']['quality'] == 'inherit')) {
|
110 |
unset ($c['options']['quality']);
|
111 |
}
|
@@ -148,6 +323,9 @@ class Config
|
|
148 |
unset($options['image-types']);
|
149 |
unset($options['cache-control']);
|
150 |
unset($options['cache-control-custom']);
|
|
|
|
|
|
|
151 |
|
152 |
return $options;
|
153 |
}
|
2 |
|
3 |
namespace WebPExpress;
|
4 |
|
5 |
+
include_once "ConvertersHelper.php";
|
6 |
+
use \WebPExpress\ConvertersHelper;
|
7 |
+
|
8 |
include_once "FileHelper.php";
|
9 |
use \WebPExpress\FileHelper;
|
10 |
|
20 |
include_once "State.php";
|
21 |
use \WebPExpress\State;
|
22 |
|
23 |
+
include_once "TestRun.php";
|
24 |
+
use \WebPExpress\TestRun;
|
25 |
+
|
26 |
class Config
|
27 |
{
|
28 |
|
58 |
return self::loadJSONOptions(Paths::getConfigFileName());
|
59 |
}
|
60 |
|
61 |
+
public static $configForOptionsPage = null; // cache the result (called twice, - also in enqueue_scripts)
|
62 |
+
public static function getConfigForOptionsPage()
|
63 |
+
{
|
64 |
+
if (isset(self::$configForOptionsPage)) {
|
65 |
+
return self::$configForOptionsPage;
|
66 |
+
}
|
67 |
+
// Test converters
|
68 |
+
$testResult = TestRun::getConverterStatus();
|
69 |
+
$workingConverters = [];
|
70 |
+
if ($testResult) {
|
71 |
+
$workingConverters = $testResult['workingConverters'];
|
72 |
+
//print_r($testResult);
|
73 |
+
}
|
74 |
+
|
75 |
+
$canDetectQuality = TestRun::isLocalQualityDetectionWorking();
|
76 |
+
$defaultConfig = [
|
77 |
+
'cache-control' => 'no-header',
|
78 |
+
'cache-control-custom' => 'public, max-age:3600',
|
79 |
+
'converters' => [],
|
80 |
+
'fail' => 'original',
|
81 |
+
'forward-query-string' => true,
|
82 |
+
'image-types' => 1,
|
83 |
+
'quality-auto' => $canDetectQuality,
|
84 |
+
'max-quality' => 80,
|
85 |
+
'quality-specific' => 70,
|
86 |
+
'metadata' => 'none',
|
87 |
+
'do-not-pass-source-in-query-string' => false,
|
88 |
+
'redirect-to-existing-in-htaccess' => false,
|
89 |
+
'web-service' => [
|
90 |
+
'enabled' => false,
|
91 |
+
'whitelist' => [
|
92 |
+
/*[
|
93 |
+
'uid' => '', // for internal purposes
|
94 |
+
'label' => '', // ie website name. It is just for display
|
95 |
+
'ip' => '', // restrict to these ips. * pattern is allowed.
|
96 |
+
'api-key' => '', // Api key for the entry. Not neccessarily unique for the entry
|
97 |
+
//'quota' => 60
|
98 |
+
]
|
99 |
+
*/
|
100 |
+
]
|
101 |
+
|
102 |
+
]
|
103 |
+
];
|
104 |
+
|
105 |
+
$defaultConverters = ConvertersHelper::$defaultConverters;
|
106 |
+
|
107 |
+
$config = self::loadConfig();
|
108 |
+
//echo '<pre>' . print_r($config, true) . '</pre>';
|
109 |
+
if (!$config) {
|
110 |
+
$config = [];
|
111 |
+
}
|
112 |
+
//$config = [];
|
113 |
+
|
114 |
+
$config = array_merge($defaultConfig, $config);
|
115 |
+
if ($config['converters'] == null) {
|
116 |
+
$config['converters'] = [];
|
117 |
+
}
|
118 |
+
if (!isset($config['web-service'])) {
|
119 |
+
$config['web-service'] = [];
|
120 |
+
}
|
121 |
+
if (!isset($config['web-service']['whitelist'])) {
|
122 |
+
$config['web-service']['whitelist'] = [];
|
123 |
+
}
|
124 |
+
|
125 |
+
// Remove keys in whitelist (so they cannot easily be picked up by examining the html)
|
126 |
+
foreach ($config['web-service']['whitelist'] as &$whitelistEntry) {
|
127 |
+
unset($whitelistEntry['api-key']);
|
128 |
+
}
|
129 |
+
|
130 |
+
// Remove keys from WPC converters
|
131 |
+
foreach ($config['converters'] as &$converter) {
|
132 |
+
if (isset($converter['converter']) && ($converter['converter'] == 'wpc')) {
|
133 |
+
if (isset($converter['options']['api-key'])) {
|
134 |
+
if ($converter['options']['api-key'] != '') {
|
135 |
+
$converter['options']['_api-key-non-empty'] = true;
|
136 |
+
}
|
137 |
+
unset($converter['options']['api-key']);
|
138 |
+
}
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
if (count($config['converters']) == 0) {
|
143 |
+
// This is first time visit!
|
144 |
+
|
145 |
+
if (count($workingConverters) == 0) {
|
146 |
+
// No converters are working
|
147 |
+
// Send ewww converter to top
|
148 |
+
$resultPart1 = [];
|
149 |
+
$resultPart2 = [];
|
150 |
+
foreach ($defaultConverters as $converter) {
|
151 |
+
$converterId = $converter['converter'];
|
152 |
+
if ($converterId == 'ewww') {
|
153 |
+
$resultPart1[] = $converter;
|
154 |
+
} else {
|
155 |
+
$resultPart2[] = $converter;
|
156 |
+
}
|
157 |
+
}
|
158 |
+
$config['converters'] = array_merge($resultPart1, $resultPart2);
|
159 |
+
} else {
|
160 |
+
// Send converters not working to the bottom
|
161 |
+
// - and also deactivate them..
|
162 |
+
$resultPart1 = [];
|
163 |
+
$resultPart2 = [];
|
164 |
+
foreach ($defaultConverters as $converter) {
|
165 |
+
$converterId = $converter['converter'];
|
166 |
+
if (in_array($converterId, $workingConverters)) {
|
167 |
+
$resultPart1[] = $converter;
|
168 |
+
} else {
|
169 |
+
$converter['deactivated'] = true;
|
170 |
+
$resultPart2[] = $converter;
|
171 |
+
}
|
172 |
+
}
|
173 |
+
$config['converters'] = array_merge($resultPart1, $resultPart2);
|
174 |
+
}
|
175 |
+
|
176 |
+
// $workingConverters
|
177 |
+
//echo '<pre>' . print_r($converters, true) . '</pre>';
|
178 |
+
} else {
|
179 |
+
// not first time visit...
|
180 |
+
// merge missing converters in
|
181 |
+
$config['converters'] = ConvertersHelper::mergeConverters($config['converters'], ConvertersHelper::$defaultConverters);
|
182 |
+
}
|
183 |
+
|
184 |
+
|
185 |
+
// Set "working" and "error" properties
|
186 |
+
if ($testResult) {
|
187 |
+
foreach ($config['converters'] as &$converter) {
|
188 |
+
$converterId = $converter['converter'];
|
189 |
+
$hasError = isset($testResult['errors'][$converterId]);
|
190 |
+
$working = !$hasError;
|
191 |
+
if (isset($converter['working']) && ($converter['working'] != $working)) {
|
192 |
+
if ($working) {
|
193 |
+
Messenger::printMessage(
|
194 |
+
'info',
|
195 |
+
'Hurray! - The <i>' . webpexpress_converterName($converterId) . '</i> conversion method is working now!'
|
196 |
+
);
|
197 |
+
} else {
|
198 |
+
Messenger::printMessage(
|
199 |
+
'warning',
|
200 |
+
'Sad news. The <i>' . webpexpress_converterName($converterId) . '</i> conversion method is not working anymore. What happened?'
|
201 |
+
);
|
202 |
+
}
|
203 |
+
}
|
204 |
+
$converter['working'] = $working;
|
205 |
+
if ($hasError) {
|
206 |
+
$error = $testResult['errors'][$converterId];
|
207 |
+
if ($converterId == 'wpc') {
|
208 |
+
if (preg_match('/Missing URL/', $error)) {
|
209 |
+
$error = 'Not configured';
|
210 |
+
}
|
211 |
+
if ($error == 'No remote host has been set up') {
|
212 |
+
$error = 'Not configured';
|
213 |
+
}
|
214 |
+
|
215 |
+
if (preg_match('/cloud service is not enabled/', $error)) {
|
216 |
+
$error = 'The server is not enabled. Click the "Enable web service" on WebP Express settings on the site you are trying to connect to.';
|
217 |
+
}
|
218 |
+
}
|
219 |
+
$converter['error'] = $error;
|
220 |
+
} else {
|
221 |
+
unset($converter['error']);
|
222 |
+
}
|
223 |
+
}
|
224 |
+
}
|
225 |
+
self::$configForOptionsPage = $config; // cache the result
|
226 |
+
return $config;
|
227 |
+
}
|
228 |
+
|
229 |
public static function isConfigFileThere()
|
230 |
{
|
231 |
return (FileHelper::fileExists(Paths::getConfigFileName()));
|
280 |
unset ($c['id']);
|
281 |
unset($c['working']);
|
282 |
unset($c['error']);
|
283 |
+
|
284 |
if (isset($c['options']['quality']) && ($c['options']['quality'] == 'inherit')) {
|
285 |
unset ($c['options']['quality']);
|
286 |
}
|
323 |
unset($options['image-types']);
|
324 |
unset($options['cache-control']);
|
325 |
unset($options['cache-control-custom']);
|
326 |
+
//unset($options['forward-query-string']); // It is used in webp-on-demand.php, so do not unset!
|
327 |
+
unset($options['do-not-pass-source-in-query-string']);
|
328 |
+
unset($options['redirect-to-existing-in-htaccess']);
|
329 |
|
330 |
return $options;
|
331 |
}
|
lib/classes/HTAccess.php
CHANGED
@@ -16,10 +16,9 @@ use \WebPExpress\State;
|
|
16 |
|
17 |
class HTAccess
|
18 |
{
|
19 |
-
|
20 |
-
public static function generateHTAccessRulesFromConfigObj($config)
|
21 |
{
|
22 |
-
|
23 |
/* Calculate $fileExt */
|
24 |
$imageTypes = $config['image-types'];
|
25 |
$fileExtensions = [];
|
@@ -34,6 +33,7 @@ class HTAccess
|
|
34 |
if ($imageTypes == 0) {
|
35 |
return '# WebP Express disabled (no image types have been choosen to be converted)';
|
36 |
}
|
|
|
37 |
/* Build rules */
|
38 |
$rules = '';
|
39 |
|
@@ -45,41 +45,126 @@ class HTAccess
|
|
45 |
$rules .= "<IfModule mod_rewrite.c>\n" .
|
46 |
" RewriteEngine On\n\n";
|
47 |
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
$rules .= " RewriteCond %{HTTP_ACCEPT} image/webp\n";
|
|
|
56 |
$rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $pathToExisting . "/$1.$2.webp -f\n";
|
57 |
-
$rules .= " RewriteRule ^\/?(.*)\.(" . $fileExt . ")$ /" . $pathToExisting . "/$1.$2.webp [NC,T=image/webp,QSD,L]\n\n";
|
58 |
-
}
|
59 |
-
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
$rules .= " # Redirect images to webp-on-demand.php (if browser supports webp)\n";
|
62 |
$rules .= " RewriteCond %{HTTP_ACCEPT} image/webp\n";
|
63 |
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
64 |
if ($config['forward-query-string']) {
|
65 |
$rules .= " RewriteCond %{QUERY_STRING} (.*)\n";
|
66 |
}
|
|
|
|
|
|
|
|
|
|
|
67 |
$rules .= " RewriteRule ^(.*)\.(" . $fileExt . ")$ " .
|
68 |
"/" . Paths::getWodUrlPath() .
|
69 |
-
"?xsource=x%{SCRIPT_FILENAME}" .
|
70 |
-
"
|
71 |
($config['forward-query-string'] ? '&%1' : '') .
|
72 |
-
" [NC,L]\n";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
-
$rules .="
|
75 |
-
"AddType image/webp .webp\n";
|
76 |
|
77 |
return $rules;
|
78 |
}
|
79 |
|
80 |
-
|
|
|
81 |
if (Config::isConfigFileThereAndOk()) {
|
82 |
-
return self::generateHTAccessRulesFromConfigObj(Config::loadConfig());
|
83 |
} else {
|
84 |
return false;
|
85 |
}
|
@@ -122,10 +207,42 @@ class HTAccess
|
|
122 |
return true;
|
123 |
}
|
124 |
|
125 |
-
$propsToCompare = [
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
|
128 |
foreach ($propsToCompare as $prop) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
if ($newConfig[$prop] != $oldConfig[$prop]) {
|
130 |
return true;
|
131 |
}
|
@@ -285,6 +402,7 @@ class HTAccess
|
|
285 |
return $success;
|
286 |
}
|
287 |
|
|
|
288 |
public static function saveHTAccessRulesToFirstWritableHTAccessDir($dirs, $rules)
|
289 |
{
|
290 |
foreach ($dirs as $dir) {
|
@@ -372,35 +490,33 @@ class HTAccess
|
|
372 |
/**
|
373 |
* Try to save the rules.
|
374 |
* Returns many details
|
|
|
375 |
*/
|
376 |
public static function saveRules($config) {
|
377 |
|
378 |
-
$rules = HTAccess::generateHTAccessRulesFromConfigObj($config);
|
379 |
|
380 |
list($minRequired, $pluginToo, $uploadToo) = self::getHTAccessDirRequirements();
|
381 |
|
382 |
-
$
|
383 |
$wpContentDir = Paths::getWPContentDirAbs();
|
384 |
-
|
385 |
-
$acceptableDirs = [
|
386 |
-
$wpContentDir
|
387 |
-
];
|
388 |
-
if ($minRequired == 'index') {
|
389 |
-
$acceptableDirs[] = $indexDir;
|
390 |
-
}
|
391 |
|
392 |
$overidingRulesInWpContentWarning = false;
|
393 |
-
|
394 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
$mainResult = 'wp-content';
|
396 |
-
|
397 |
-
HTAccess::saveHTAccessRulesToFile($indexDir . '/.htaccess', '# WebP Express has placed its rules in your wp-content dir. Go there.', false);
|
398 |
-
//}
|
399 |
-
} elseif ($result == $indexDir) {
|
400 |
-
$mainResult = 'index';
|
401 |
-
$overidingRulesInWpContentWarning = self::haveWeRulesInThisHTAccessBestGuess($wpContentDir . '/.htaccess');
|
402 |
-
} elseif ($result === false) {
|
403 |
-
$mainResult = 'failed';
|
404 |
}
|
405 |
|
406 |
/* plugin */
|
@@ -416,6 +532,7 @@ class HTAccess
|
|
416 |
$pluginFailed = false;
|
417 |
$pluginFailedBadly = true;
|
418 |
if ($pluginToo == 'yes') {
|
|
|
419 |
$pluginDir = Paths::getPluginDirAbs();
|
420 |
$pluginFailed = !(HTAccess::saveHTAccessRulesToFile($pluginDir . '/.htaccess', $rules, true));
|
421 |
if ($pluginFailed) {
|
@@ -437,6 +554,7 @@ class HTAccess
|
|
437 |
$uploadFailedBadly = true;
|
438 |
if ($uploadToo == 'yes') {
|
439 |
$uploadDir = Paths::getUploadDirAbs();
|
|
|
440 |
$uploadFailed = !(HTAccess::saveHTAccessRulesToFile($uploadDir . '/.htaccess', $rules, true));
|
441 |
if ($uploadFailed) {
|
442 |
$uploadFailedBadly = self::haveWeRulesInThisHTAccessBestGuess($uploadDir . '/.htaccess');
|
16 |
|
17 |
class HTAccess
|
18 |
{
|
19 |
+
// (called from this file only)
|
20 |
+
public static function generateHTAccessRulesFromConfigObj($config, $htaccessDir = 'index')
|
21 |
{
|
|
|
22 |
/* Calculate $fileExt */
|
23 |
$imageTypes = $config['image-types'];
|
24 |
$fileExtensions = [];
|
33 |
if ($imageTypes == 0) {
|
34 |
return '# WebP Express disabled (no image types have been choosen to be converted)';
|
35 |
}
|
36 |
+
|
37 |
/* Build rules */
|
38 |
$rules = '';
|
39 |
|
45 |
$rules .= "<IfModule mod_rewrite.c>\n" .
|
46 |
" RewriteEngine On\n\n";
|
47 |
|
48 |
+
//$pathToExisting = Paths::getPathToExisting();
|
49 |
+
//$pathToExisting = Paths::getCacheDirRel() . '/doc-root/' . Paths::getHomeDirRel();
|
50 |
+
//$pathToExisting = Paths::getCacheDirRel() . '/doc-root/' . Paths::getPluginDirRel();
|
51 |
+
//$pathToExisting = Paths::getCacheDirRel() . '/doc-root/' . Paths::getPluginDirRel();
|
52 |
+
$pathToExisting = Paths::getCacheDirRel() . '/doc-root/';
|
53 |
+
switch ($htaccessDir) {
|
54 |
+
case 'index':
|
55 |
+
$pathToExisting .= Paths::getIndexDirRel();
|
56 |
+
break;
|
57 |
+
case 'home':
|
58 |
+
$pathToExisting .= Paths::getHomeDirRel();
|
59 |
+
break;
|
60 |
+
case 'plugin':
|
61 |
+
$pathToExisting .= Paths::getPluginDirRel();
|
62 |
+
break;
|
63 |
+
case 'uploads':
|
64 |
+
$pathToExisting .= Paths::getUploadDirRel();
|
65 |
+
break;
|
66 |
+
case 'wp-content':
|
67 |
+
$pathToExisting .= Paths::getWPContentDirRel();
|
68 |
+
break;
|
69 |
+
}
|
70 |
+
|
71 |
+
$doNotpassSourceInQS = (isset($config['do-not-pass-source-in-query-string']) && ($config['do-not-pass-source-in-query-string']));
|
72 |
+
$passSourceInQS = !$doNotpassSourceInQS;
|
73 |
+
|
74 |
+
$redirectToExisting = (isset($config['redirect-to-existing-in-htaccess']) && ($config['redirect-to-existing-in-htaccess']));
|
75 |
+
|
76 |
+
// TODO: Is it possible to handle when wp-content is outside document root?
|
77 |
+
|
78 |
+
// TODO: It seems $pathToExisting needs to be adjusted, depending on where the .htaccess is located
|
79 |
+
// Ie, if plugin folder has been moved out of ABSPATH, we should ie set
|
80 |
+
// $pathToExisting to 'doc-root/plugins-moved/'
|
81 |
+
// to get: RewriteRule ^\/?(.*)\.(jpe?g)$ /wp-content-moved/webp-express/webp-images/doc-root/plugins-moved/$1.$2.webp [NC,T=image/webp,QSD,E=WEBPACCEPT:1,E=EXISTING:1,L]
|
82 |
+
|
83 |
+
// https://stackoverflow.com/questions/34124819/mod-rewrite-set-custom-header-through-htaccess
|
84 |
+
if ($redirectToExisting) {
|
85 |
+
$rules .= " # Redirect to existing converted image in cache-dir (if browser supports webp)\n";
|
86 |
$rules .= " RewriteCond %{HTTP_ACCEPT} image/webp\n";
|
87 |
+
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
88 |
$rules .= " RewriteCond %{DOCUMENT_ROOT}/" . $pathToExisting . "/$1.$2.webp -f\n";
|
89 |
+
$rules .= " RewriteRule ^\/?(.*)\.(" . $fileExt . ")$ /" . $pathToExisting . "/$1.$2.webp [NC,T=image/webp,QSD,E=EXISTING:1,L]\n\n";
|
90 |
+
}
|
|
|
91 |
|
92 |
+
if (!$passSourceInQS) {
|
93 |
+
$rules .= " # Pass REQUEST_FILENAME to PHP by setting request header\n" .
|
94 |
+
" RewriteCond %{HTTP_ACCEPT} image/webp\n" .
|
95 |
+
" RewriteCond %{REQUEST_FILENAME} -f\n" .
|
96 |
+
" RewriteRule ^(.*)\.(jpe?g)$ - [E=REQFN:%{REQUEST_FILENAME}]\n" .
|
97 |
+
" <IfModule mod_headers.c>\n" .
|
98 |
+
" RequestHeader set REQFN \"%{REQFN}e\" env=REQFN\n" .
|
99 |
+
" </IfModule>\n\n";
|
100 |
+
}
|
101 |
$rules .= " # Redirect images to webp-on-demand.php (if browser supports webp)\n";
|
102 |
$rules .= " RewriteCond %{HTTP_ACCEPT} image/webp\n";
|
103 |
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
104 |
if ($config['forward-query-string']) {
|
105 |
$rules .= " RewriteCond %{QUERY_STRING} (.*)\n";
|
106 |
}
|
107 |
+
|
108 |
+
// TODO:
|
109 |
+
// Add "NE" flag?
|
110 |
+
// https://github.com/rosell-dk/webp-convert/issues/95
|
111 |
+
// (and try testing spaces in directory paths)
|
112 |
$rules .= " RewriteRule ^(.*)\.(" . $fileExt . ")$ " .
|
113 |
"/" . Paths::getWodUrlPath() .
|
114 |
+
($passSourceInQS ? "?xsource=x%{SCRIPT_FILENAME}&" : "?") .
|
115 |
+
"wp-content=" . Paths::getWPContentDirRel() .
|
116 |
($config['forward-query-string'] ? '&%1' : '') .
|
117 |
+
" [NC,L]\n"; // E=WOD:1
|
118 |
+
|
119 |
+
|
120 |
+
// Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
|
121 |
+
$rules .="\n <IfModule mod_headers.c>\n" .
|
122 |
+
" # Set Vary:Accept header for the image types handled by WebP Express.\n" .
|
123 |
+
" # The purpose is to make CDN cache both original images and converted images.\n" .
|
124 |
+
" SetEnvIf Request_URI \"\.(" . $fileExt . ")\" ADDVARY\n" .
|
125 |
+
" Header append \"Vary\" \"Accept\" env=ADDVARY\n\n" .
|
126 |
+
" # Set X-WebP-Express header for diagnose purposes\n" .
|
127 |
+
" # Apache appends \"REDIRECT_\" in front of the environment variables defined in mod_rewrite, but LiteSpeed does not.\n" .
|
128 |
+
" # So, the next line is for Apache, in order to set environment variables without \"REDIRECT_\"\n" .
|
129 |
+
" SetEnvIf REDIRECT_EXISTING 1 EXISTING=1\n" .
|
130 |
+
//" SetEnvIf REDIRECT_WOD 1 WOD=1\n\n" .
|
131 |
+
//" # Set the debug header\n" .
|
132 |
+
" Header set \"X-WebP-Express\" \"Redirected directly to existing webp\" env=EXISTING\n" .
|
133 |
+
//" Header set \"X-WebP-Express\" \"Redirected to image converter\" env=WOD\n" .
|
134 |
+
" </IfModule>\n\n";
|
135 |
+
|
136 |
+
$rules .="</IfModule>\n";
|
137 |
+
|
138 |
+
|
139 |
+
|
140 |
+
|
141 |
+
|
142 |
+
/*if ($redirectToExisting) {
|
143 |
+
$rules .=
|
144 |
+
"<IfModule mod_headers.c>\n" .
|
145 |
+
" # Append Vary Accept header, when the rules above are redirecting to existing webp\n" .
|
146 |
+
" # or existing jpg" .
|
147 |
+
|
148 |
+
" # Apache appends \"REDIRECT_\" in front of the environment variables, but LiteSpeed does not.\n" .
|
149 |
+
" # These next line is for Apache, in order to set environment variables without \"REDIRECT_\"\n" .
|
150 |
+
" SetEnvIf REDIRECT_WEBPACCEPT 1 WEBPACCEPT=1\n\n" .
|
151 |
+
|
152 |
+
" # Make CDN caching possible.\n" .
|
153 |
+
" # The effect is that the CDN will cache both the webp image and the jpeg/png image and return the proper\n" .
|
154 |
+
" # image to the proper clients (for this to work, make sure to set up CDN to forward the \"Accept\" header)\n" .
|
155 |
+
" Header append Vary Accept env=WEBPACCEPT\n" .
|
156 |
+
"</IfModule>\n\n";
|
157 |
+
}*/
|
158 |
|
159 |
+
$rules .= "AddType image/webp .webp\n";
|
|
|
160 |
|
161 |
return $rules;
|
162 |
}
|
163 |
|
164 |
+
/* only called from page-messages.inc, but commented out there... */
|
165 |
+
public static function generateHTAccessRulesFromConfigFile($htaccessDir = '') {
|
166 |
if (Config::isConfigFileThereAndOk()) {
|
167 |
+
return self::generateHTAccessRulesFromConfigObj(Config::loadConfig(), $htaccessDir);
|
168 |
} else {
|
169 |
return false;
|
170 |
}
|
207 |
return true;
|
208 |
}
|
209 |
|
210 |
+
$propsToCompare = [
|
211 |
+
'forward-query-string',
|
212 |
+
'image-types',
|
213 |
+
'do-not-pass-source-in-query-string',
|
214 |
+
'redirect-to-existing-in-htaccess',
|
215 |
+
];
|
216 |
|
217 |
|
218 |
foreach ($propsToCompare as $prop) {
|
219 |
+
if (!isset($newConfig[$prop])) {
|
220 |
+
continue;
|
221 |
+
}
|
222 |
+
if (!isset($oldConfig[$prop])) {
|
223 |
+
if ($prop == 'do-not-pass-source-in-query-string') {
|
224 |
+
|
225 |
+
// Do not trigger .htaccess update if the new value results
|
226 |
+
// in same old behaviour (before this option was introduced)
|
227 |
+
if ($newConfig[$prop] == false) {
|
228 |
+
continue;
|
229 |
+
} else {
|
230 |
+
// Otherwise DO trigger .htaccess update
|
231 |
+
return true;
|
232 |
+
}
|
233 |
+
}
|
234 |
+
if ($prop == 'redirect-to-existing-in-htaccess') {
|
235 |
+
if ($newConfig[$prop] == false) {
|
236 |
+
continue;
|
237 |
+
} else {
|
238 |
+
return true;
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
// The option was not set in the old configuration,
|
243 |
+
// - so lets say that .htaccess needs updating
|
244 |
+
return true;
|
245 |
+
}
|
246 |
if ($newConfig[$prop] != $oldConfig[$prop]) {
|
247 |
return true;
|
248 |
}
|
402 |
return $success;
|
403 |
}
|
404 |
|
405 |
+
/* only called in this file */
|
406 |
public static function saveHTAccessRulesToFirstWritableHTAccessDir($dirs, $rules)
|
407 |
{
|
408 |
foreach ($dirs as $dir) {
|
490 |
/**
|
491 |
* Try to save the rules.
|
492 |
* Returns many details
|
493 |
+
* (called from migrate1.php, reactivate.php, Config.php and this file)
|
494 |
*/
|
495 |
public static function saveRules($config) {
|
496 |
|
|
|
497 |
|
498 |
list($minRequired, $pluginToo, $uploadToo) = self::getHTAccessDirRequirements();
|
499 |
|
500 |
+
$rules = HTAccess::generateHTAccessRulesFromConfigObj($config, 'wp-content');
|
501 |
$wpContentDir = Paths::getWPContentDirAbs();
|
502 |
+
$wpContentFailed = !(HTAccess::saveHTAccessRulesToFile($wpContentDir . '/.htaccess', $rules, true));
|
|
|
|
|
|
|
|
|
|
|
|
|
503 |
|
504 |
$overidingRulesInWpContentWarning = false;
|
505 |
+
if ($wpContentFailed) {
|
506 |
+
if ($minRequired == 'index') {
|
507 |
+
$rules = HTAccess::generateHTAccessRulesFromConfigObj($config, 'index');
|
508 |
+
$indexFailed = !(HTAccess::saveHTAccessRulesToFile(Paths::getIndexDirAbs() . '/.htaccess', $rules, true));
|
509 |
+
|
510 |
+
if ($indexFailed) {
|
511 |
+
$mainResult = 'failed';
|
512 |
+
} else {
|
513 |
+
$mainResult = 'index';
|
514 |
+
$overidingRulesInWpContentWarning = self::haveWeRulesInThisHTAccessBestGuess($wpContentDir . '/.htaccess');
|
515 |
+
}
|
516 |
+
}
|
517 |
+
} else {
|
518 |
$mainResult = 'wp-content';
|
519 |
+
HTAccess::saveHTAccessRulesToFile(Paths::getIndexDirAbs() . '/.htaccess', '# WebP Express has placed its rules in your wp-content dir. Go there.', false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
520 |
}
|
521 |
|
522 |
/* plugin */
|
532 |
$pluginFailed = false;
|
533 |
$pluginFailedBadly = true;
|
534 |
if ($pluginToo == 'yes') {
|
535 |
+
$rules = HTAccess::generateHTAccessRulesFromConfigObj($config, 'plugin');
|
536 |
$pluginDir = Paths::getPluginDirAbs();
|
537 |
$pluginFailed = !(HTAccess::saveHTAccessRulesToFile($pluginDir . '/.htaccess', $rules, true));
|
538 |
if ($pluginFailed) {
|
554 |
$uploadFailedBadly = true;
|
555 |
if ($uploadToo == 'yes') {
|
556 |
$uploadDir = Paths::getUploadDirAbs();
|
557 |
+
$rules = HTAccess::generateHTAccessRulesFromConfigObj($config, 'uploads');
|
558 |
$uploadFailed = !(HTAccess::saveHTAccessRulesToFile($uploadDir . '/.htaccess', $rules, true));
|
559 |
if ($uploadFailed) {
|
560 |
$uploadFailedBadly = self::haveWeRulesInThisHTAccessBestGuess($uploadDir . '/.htaccess');
|
lib/classes/Paths.php
CHANGED
@@ -20,14 +20,22 @@ class Paths
|
|
20 |
}
|
21 |
|
22 |
/**
|
23 |
-
|
24 |
-
|
25 |
public static function isDirInsideDir($dir1, $dir2)
|
26 |
{
|
27 |
$rel = PathHelper::getRelDir($dir2, $dir1);
|
28 |
return (substr($rel, 0, 3) != '../');
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
// ------------ Home Dir -------------
|
32 |
|
33 |
public static function getHomeDirAbs()
|
@@ -40,7 +48,7 @@ class Paths
|
|
40 |
|
41 |
public static function getHomeDirRel()
|
42 |
{
|
43 |
-
return
|
44 |
}
|
45 |
|
46 |
// ------------ Index Dir -------------
|
@@ -51,6 +59,11 @@ class Paths
|
|
51 |
return rtrim(ABSPATH, '/');
|
52 |
}
|
53 |
|
|
|
|
|
|
|
|
|
|
|
54 |
|
55 |
// ------------ .htaccess dir -------------
|
56 |
// (directory containing the relevant .htaccess)
|
@@ -79,7 +92,7 @@ class Paths
|
|
79 |
}
|
80 |
public static function getWPContentDirRel()
|
81 |
{
|
82 |
-
return
|
83 |
}
|
84 |
|
85 |
public static function isWPContentDirMoved()
|
@@ -106,7 +119,7 @@ class Paths
|
|
106 |
|
107 |
public static function getContentDirRel()
|
108 |
{
|
109 |
-
return
|
110 |
}
|
111 |
|
112 |
public static function createContentDirIfMissing()
|
@@ -120,6 +133,10 @@ class Paths
|
|
120 |
$upload_dir = wp_upload_dir(null, false);
|
121 |
return $upload_dir['basedir'];
|
122 |
}
|
|
|
|
|
|
|
|
|
123 |
|
124 |
/*
|
125 |
public static function getUploadDirAbs()
|
@@ -150,7 +167,7 @@ class Paths
|
|
150 |
|
151 |
public static function getConfigDirRel()
|
152 |
{
|
153 |
-
return
|
154 |
}
|
155 |
|
156 |
public static function createConfigDirIfMissing()
|
@@ -196,7 +213,7 @@ APACHE
|
|
196 |
|
197 |
public static function getCacheDirRel()
|
198 |
{
|
199 |
-
return
|
200 |
}
|
201 |
|
202 |
public static function createCacheDirIfMissing()
|
@@ -211,6 +228,11 @@ APACHE
|
|
211 |
return untrailingslashit(WP_PLUGIN_DIR);
|
212 |
}
|
213 |
|
|
|
|
|
|
|
|
|
|
|
214 |
public static function isPluginDirMovedOutOfAbsPath()
|
215 |
{
|
216 |
return !(self::isDirInsideDir(self::getPluginDirAbs(), ABSPATH));
|
@@ -305,7 +327,7 @@ APACHE
|
|
305 |
*/
|
306 |
public static function getPathToExisting()
|
307 |
{
|
308 |
-
return self::getCacheDirRel() . '/' . self::getHomeDirRel();
|
309 |
}
|
310 |
|
311 |
public static function getUrlsAndPathsForTheJavascript()
|
20 |
}
|
21 |
|
22 |
/**
|
23 |
+
* Find out if $dir1 is inside - or equal to - $dir2
|
24 |
+
*/
|
25 |
public static function isDirInsideDir($dir1, $dir2)
|
26 |
{
|
27 |
$rel = PathHelper::getRelDir($dir2, $dir1);
|
28 |
return (substr($rel, 0, 3) != '../');
|
29 |
}
|
30 |
|
31 |
+
/**
|
32 |
+
* Return relative dir - relative to realpath(document root)
|
33 |
+
*/
|
34 |
+
public static function getRelDir($dir)
|
35 |
+
{
|
36 |
+
return PathHelper::getRelDir(realpath($_SERVER['DOCUMENT_ROOT']), $dir);
|
37 |
+
}
|
38 |
+
|
39 |
// ------------ Home Dir -------------
|
40 |
|
41 |
public static function getHomeDirAbs()
|
48 |
|
49 |
public static function getHomeDirRel()
|
50 |
{
|
51 |
+
return self::getRelDir(self::getHomeDirAbs());
|
52 |
}
|
53 |
|
54 |
// ------------ Index Dir -------------
|
59 |
return rtrim(ABSPATH, '/');
|
60 |
}
|
61 |
|
62 |
+
public static function getIndexDirRel()
|
63 |
+
{
|
64 |
+
return self::getRelDir(self::getIndexDirAbs());
|
65 |
+
}
|
66 |
+
|
67 |
|
68 |
// ------------ .htaccess dir -------------
|
69 |
// (directory containing the relevant .htaccess)
|
92 |
}
|
93 |
public static function getWPContentDirRel()
|
94 |
{
|
95 |
+
return self::getRelDir(self::getWPContentDirAbs());
|
96 |
}
|
97 |
|
98 |
public static function isWPContentDirMoved()
|
119 |
|
120 |
public static function getContentDirRel()
|
121 |
{
|
122 |
+
return self::getRelDir(self::getContentDirAbs());
|
123 |
}
|
124 |
|
125 |
public static function createContentDirIfMissing()
|
133 |
$upload_dir = wp_upload_dir(null, false);
|
134 |
return $upload_dir['basedir'];
|
135 |
}
|
136 |
+
public static function getUploadDirRel()
|
137 |
+
{
|
138 |
+
return self::getRelDir(self::getUploadDirAbs());
|
139 |
+
}
|
140 |
|
141 |
/*
|
142 |
public static function getUploadDirAbs()
|
167 |
|
168 |
public static function getConfigDirRel()
|
169 |
{
|
170 |
+
return self::getRelDir(self::getConfigDirAbs());
|
171 |
}
|
172 |
|
173 |
public static function createConfigDirIfMissing()
|
213 |
|
214 |
public static function getCacheDirRel()
|
215 |
{
|
216 |
+
return self::getRelDir(self::getCacheDirAbs());
|
217 |
}
|
218 |
|
219 |
public static function createCacheDirIfMissing()
|
228 |
return untrailingslashit(WP_PLUGIN_DIR);
|
229 |
}
|
230 |
|
231 |
+
public static function getPluginDirRel()
|
232 |
+
{
|
233 |
+
return self::getRelDir(self::getPluginDirAbs());
|
234 |
+
}
|
235 |
+
|
236 |
public static function isPluginDirMovedOutOfAbsPath()
|
237 |
{
|
238 |
return !(self::isDirInsideDir(self::getPluginDirAbs(), ABSPATH));
|
327 |
*/
|
328 |
public static function getPathToExisting()
|
329 |
{
|
330 |
+
return self::getCacheDirRel() . '/doc-root/' . self::getHomeDirRel();
|
331 |
}
|
332 |
|
333 |
public static function getUrlsAndPathsForTheJavascript()
|
lib/classes/TestRun.php
CHANGED
@@ -25,16 +25,24 @@ class TestRun
|
|
25 |
{
|
26 |
|
27 |
|
|
|
|
|
28 |
/**
|
29 |
* Get an array of working converters OR false, if tests cannot be made
|
30 |
*/
|
31 |
public static function getConverterStatus() {
|
|
|
|
|
|
|
|
|
|
|
32 |
$source = Paths::getWebPExpressPluginDirAbs() . '/test/small-q61.jpg';
|
33 |
$destination = Paths::getUploadDirAbs() . '/webp-express-test-conversion.webp';
|
34 |
if (!FileHelper::canCreateFile($destination)) {
|
35 |
$destination = Paths::getWPContentDirAbs() . '/webp-express-test-conversion.webp';
|
36 |
}
|
37 |
-
if (!FileHelper::canCreateFile($destination)) {
|
|
|
38 |
return false;
|
39 |
}
|
40 |
$workingConverters = [];
|
@@ -79,16 +87,27 @@ class TestRun
|
|
79 |
}
|
80 |
}
|
81 |
//print_r($errors);
|
82 |
-
|
|
|
|
|
83 |
'workingConverters' => $workingConverters,
|
84 |
'errors' => $errors
|
85 |
];
|
|
|
86 |
}
|
87 |
|
|
|
|
|
|
|
88 |
public static function isLocalQualityDetectionWorking() {
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
93 |
}
|
94 |
}
|
25 |
{
|
26 |
|
27 |
|
28 |
+
public static $converterStatus = null; // to cache the result
|
29 |
+
|
30 |
/**
|
31 |
* Get an array of working converters OR false, if tests cannot be made
|
32 |
*/
|
33 |
public static function getConverterStatus() {
|
34 |
+
|
35 |
+
// Is result cached?
|
36 |
+
if (isset(self::$converterStatus)) {
|
37 |
+
return self::$converterStatus;
|
38 |
+
}
|
39 |
$source = Paths::getWebPExpressPluginDirAbs() . '/test/small-q61.jpg';
|
40 |
$destination = Paths::getUploadDirAbs() . '/webp-express-test-conversion.webp';
|
41 |
if (!FileHelper::canCreateFile($destination)) {
|
42 |
$destination = Paths::getWPContentDirAbs() . '/webp-express-test-conversion.webp';
|
43 |
}
|
44 |
+
if (!FileHelper::canCreateFile($destination)) {
|
45 |
+
self::$converterStatus = false; // // cache the result
|
46 |
return false;
|
47 |
}
|
48 |
$workingConverters = [];
|
87 |
}
|
88 |
}
|
89 |
//print_r($errors);
|
90 |
+
|
91 |
+
// cache the result
|
92 |
+
self::$converterStatus = [
|
93 |
'workingConverters' => $workingConverters,
|
94 |
'errors' => $errors
|
95 |
];
|
96 |
+
return self::$converterStatus;
|
97 |
}
|
98 |
|
99 |
+
|
100 |
+
public static $localQualityDetectionWorking = null; // to cache the result
|
101 |
+
|
102 |
public static function isLocalQualityDetectionWorking() {
|
103 |
+
if (isset(self::$localQualityDetectionWorking)) {
|
104 |
+
return self::$localQualityDetectionWorking;
|
105 |
+
} else {
|
106 |
+
$q = ConverterHelper::detectQualityOfJpg(
|
107 |
+
Paths::getWebPExpressPluginDirAbs() . '/test/small-q61.jpg'
|
108 |
+
);
|
109 |
+
self::$localQualityDetectionWorking = ($q === 61);
|
110 |
+
return self::$localQualityDetectionWorking;
|
111 |
+
}
|
112 |
}
|
113 |
}
|
lib/migrate/migrate1.php
CHANGED
@@ -88,7 +88,7 @@ function webpexpress_migrate1_migrateOptions()
|
|
88 |
$config = $options;
|
89 |
|
90 |
//$htaccessExists = Config::doesHTAccessExists();
|
91 |
-
|
92 |
|
93 |
if (Config::saveConfigurationFile($config)) {
|
94 |
$options = Config::generateWodOptionsFromConfigObj($config);
|
88 |
$config = $options;
|
89 |
|
90 |
//$htaccessExists = Config::doesHTAccessExists();
|
91 |
+
//$rules = HTAccess::generateHTAccessRulesFromConfigObj($config);
|
92 |
|
93 |
if (Config::saveConfigurationFile($config)) {
|
94 |
$options = Config::generateWodOptionsFromConfigObj($config);
|
lib/options/css/webp-express-options-page.css
CHANGED
@@ -345,3 +345,34 @@
|
|
345 |
display: inline-block;
|
346 |
}
|
347 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
display: inline-block;
|
346 |
}
|
347 |
*/
|
348 |
+
|
349 |
+
#webpexpress_settings .block {
|
350 |
+
position: relative;
|
351 |
+
margin: 0 auto 0.5rem;
|
352 |
+
padding: 0 1rem;
|
353 |
+
box-sizing: border-box;
|
354 |
+
background-color: #fff;
|
355 |
+
box-shadow: 0 0 0 1px rgba(200,215,225,0.25), 0 1px 2px #e9eff3;
|
356 |
+
}
|
357 |
+
|
358 |
+
#webpexpress_settings .block.buttons {
|
359 |
+
padding: 10px;
|
360 |
+
position: sticky;
|
361 |
+
top: 30px;
|
362 |
+
z-index: 1;
|
363 |
+
}
|
364 |
+
|
365 |
+
@media (min-width: 768px) {
|
366 |
+
#webpexpress_settings .block {
|
367 |
+
padding: 10px 1.5rem 20px;
|
368 |
+
}
|
369 |
+
}
|
370 |
+
|
371 |
+
#webpexpress_settings .block.buttons p.submit {
|
372 |
+
margin: 0;
|
373 |
+
padding: 0;
|
374 |
+
}
|
375 |
+
|
376 |
+
#webpexpress_settings .block.buttons table {
|
377 |
+
float: right;
|
378 |
+
}
|
lib/options/enqueue_scripts.php
CHANGED
@@ -3,36 +3,51 @@
|
|
3 |
include_once __DIR__ . '/../classes/Paths.php';
|
4 |
use \WebPExpress\Paths;
|
5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
wp_register_script('sortable', plugins_url('js/sortable.min.js', __FILE__), [], '1.9.0');
|
7 |
wp_enqueue_script('sortable');
|
8 |
|
9 |
-
wp_register_script('daspopup', plugins_url('js/das-popup.js', __FILE__), [],
|
10 |
wp_enqueue_script('daspopup');
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
13 |
wp_enqueue_script('converters');
|
14 |
|
15 |
-
|
|
|
|
|
|
|
16 |
wp_enqueue_script('whitelist');
|
17 |
|
18 |
//wp_register_script('api_keys', plugins_url('js/api-keys.js', __FILE__), ['daspopup'], '0.7.0-dev8');
|
19 |
//wp_enqueue_script('api_keys');
|
20 |
|
21 |
-
wp_register_script( 'page', plugins_url('js/page.js', __FILE__), [],
|
22 |
wp_enqueue_script('page');
|
23 |
|
24 |
-
if (function_exists('wp_add_inline_script')) {
|
25 |
-
// wp_add_inline_script is available from Wordpress 4.5
|
26 |
-
wp_add_inline_script('converters', 'window.webpExpressPaths = ' . json_encode(Paths::getUrlsAndPathsForTheJavascript()) . ';');
|
27 |
-
} else {
|
28 |
-
echo '<script>window.webpExpressPaths = ' . json_encode(Paths::getUrlsAndPathsForTheJavascript()) . ';</script>';
|
29 |
-
}
|
30 |
|
31 |
// Register styles
|
32 |
-
wp_register_style('webp-express-options-page-css', plugins_url('css/webp-express-options-page.css', __FILE__), null,
|
33 |
wp_enqueue_style('webp-express-options-page-css');
|
34 |
|
35 |
-
wp_register_style('das-popup-css', plugins_url('css/das-popup.css', __FILE__), null,
|
36 |
wp_enqueue_style('das-popup-css');
|
37 |
|
38 |
add_thickbox();
|
3 |
include_once __DIR__ . '/../classes/Paths.php';
|
4 |
use \WebPExpress\Paths;
|
5 |
|
6 |
+
include_once __DIR__ . '/../classes/Config.php';
|
7 |
+
use \WebPExpress\Config;
|
8 |
+
|
9 |
+
$version = '0.9.0';
|
10 |
+
|
11 |
+
function webp_express_add_inline_script($id, $script, $position) {
|
12 |
+
if (function_exists('wp_add_inline_script')) {
|
13 |
+
// wp_add_inline_script is available from Wordpress 4.5
|
14 |
+
wp_add_inline_script($id, $script, $position);
|
15 |
+
} else {
|
16 |
+
echo '<script>' . $script . '</script>';
|
17 |
+
}
|
18 |
+
}
|
19 |
wp_register_script('sortable', plugins_url('js/sortable.min.js', __FILE__), [], '1.9.0');
|
20 |
wp_enqueue_script('sortable');
|
21 |
|
22 |
+
wp_register_script('daspopup', plugins_url('js/das-popup.js', __FILE__), [], $version);
|
23 |
wp_enqueue_script('daspopup');
|
24 |
|
25 |
+
$config = Config::getConfigForOptionsPage();
|
26 |
+
|
27 |
+
// Converters
|
28 |
+
wp_register_script('converters', plugins_url('js/converters.js', __FILE__), ['sortable','daspopup'], $version);
|
29 |
+
webp_express_add_inline_script('converters', 'window.webpExpressPaths = ' . json_encode(Paths::getUrlsAndPathsForTheJavascript()) . ';', 'before');
|
30 |
+
webp_express_add_inline_script('converters', 'window.converters = ' . json_encode($config['converters']) . ';', 'before');
|
31 |
wp_enqueue_script('converters');
|
32 |
|
33 |
+
|
34 |
+
// Whitelist
|
35 |
+
wp_register_script('whitelist', plugins_url('js/whitelist.js', __FILE__), ['daspopup'], $version);
|
36 |
+
webp_express_add_inline_script('whitelist', 'window.whitelist = ' . json_encode($config['web-service']['whitelist']) . ';', 'before');
|
37 |
wp_enqueue_script('whitelist');
|
38 |
|
39 |
//wp_register_script('api_keys', plugins_url('js/api-keys.js', __FILE__), ['daspopup'], '0.7.0-dev8');
|
40 |
//wp_enqueue_script('api_keys');
|
41 |
|
42 |
+
wp_register_script( 'page', plugins_url('js/page.js', __FILE__), [], $version);
|
43 |
wp_enqueue_script('page');
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
// Register styles
|
47 |
+
wp_register_style('webp-express-options-page-css', plugins_url('css/webp-express-options-page.css', __FILE__), null, $version);
|
48 |
wp_enqueue_style('webp-express-options-page-css');
|
49 |
|
50 |
+
wp_register_style('das-popup-css', plugins_url('css/das-popup.css', __FILE__), null, $version);
|
51 |
wp_enqueue_style('das-popup-css');
|
52 |
|
53 |
add_thickbox();
|
lib/options/js/converters.js
CHANGED
@@ -13,6 +13,7 @@ function addMissingConvertersAndOptions() {
|
|
13 |
// check if all available converters are in the array.
|
14 |
// if not - add!
|
15 |
// the double loop could be avoided with map. But arrays are so small, so not worth it
|
|
|
16 |
for (var i=0; i<window.defaultConverters.length; i++) {
|
17 |
var checkMe = window.defaultConverters[i];
|
18 |
var found = false;
|
@@ -42,9 +43,10 @@ function addMissingConvertersAndOptions() {
|
|
42 |
if (!found) {
|
43 |
window.converters.push(window.defaultConverters[i]);
|
44 |
}
|
45 |
-
|
46 |
-
|
47 |
-
console.log(window.
|
|
|
48 |
}
|
49 |
|
50 |
function getConversionMethodDescription(converterId) {
|
@@ -118,8 +120,12 @@ function generateConverterHTML(converter) {
|
|
118 |
|
119 |
/* Set ids on global converters object */
|
120 |
function setTemporaryIdsOnConverters() {
|
|
|
|
|
|
|
|
|
121 |
var numConverterInstances = [];
|
122 |
-
for (var i=0; i<converters.length; i++) {
|
123 |
var converter = converters[i]['converter'];
|
124 |
if (numConverterInstances[converter]) {
|
125 |
numConverterInstances[converter]++;
|
@@ -162,10 +168,16 @@ function updateInputValue() {
|
|
162 |
|
163 |
function setConvertersHTML() {
|
164 |
|
|
|
165 |
var html = '';
|
166 |
|
167 |
setTemporaryIdsOnConverters();
|
168 |
|
|
|
|
|
|
|
|
|
|
|
169 |
for (var i=0; i<window.converters.length; i++) {
|
170 |
var converter = converters[i];
|
171 |
html += generateConverterHTML(converter);
|
13 |
// check if all available converters are in the array.
|
14 |
// if not - add!
|
15 |
// the double loop could be avoided with map. But arrays are so small, so not worth it
|
16 |
+
/*
|
17 |
for (var i=0; i<window.defaultConverters.length; i++) {
|
18 |
var checkMe = window.defaultConverters[i];
|
19 |
var found = false;
|
43 |
if (!found) {
|
44 |
window.converters.push(window.defaultConverters[i]);
|
45 |
}
|
46 |
+
|
47 |
+
}*/
|
48 |
+
//console.log(window.converters);
|
49 |
+
//console.log(window.defaultConverters);
|
50 |
}
|
51 |
|
52 |
function getConversionMethodDescription(converterId) {
|
120 |
|
121 |
/* Set ids on global converters object */
|
122 |
function setTemporaryIdsOnConverters() {
|
123 |
+
if (window.converters == undefined) {
|
124 |
+
alert('window.converters is undefined. Strange. Please report!');
|
125 |
+
return;
|
126 |
+
}
|
127 |
var numConverterInstances = [];
|
128 |
+
for (var i=0; i<window.converters.length; i++) {
|
129 |
var converter = converters[i]['converter'];
|
130 |
if (numConverterInstances[converter]) {
|
131 |
numConverterInstances[converter]++;
|
168 |
|
169 |
function setConvertersHTML() {
|
170 |
|
171 |
+
|
172 |
var html = '';
|
173 |
|
174 |
setTemporaryIdsOnConverters();
|
175 |
|
176 |
+
if (document.getElementById('converters') == null) {
|
177 |
+
alert('document.getElementById("converters") returns null. Strange! Please report.');
|
178 |
+
return;
|
179 |
+
}
|
180 |
+
|
181 |
for (var i=0; i<window.converters.length; i++) {
|
182 |
var converter = converters[i];
|
183 |
html += generateConverterHTML(converter);
|
lib/options/js/page.js
CHANGED
@@ -1,5 +1,16 @@
|
|
1 |
|
2 |
function updateCacheControlCustomVisibility() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
var cacheControlValue = document.getElementById('cache_control_select').value;
|
4 |
var customEl = document.getElementById('cache_control_custom');
|
5 |
if (cacheControlValue == 'custom') {
|
1 |
|
2 |
function updateCacheControlCustomVisibility() {
|
3 |
+
|
4 |
+
if (document.getElementById('cache_control_select') == null) {
|
5 |
+
// this ought not to happen,
|
6 |
+
// but it does? https://wordpress.org/support/topic/console-errors-9/#post-11018243
|
7 |
+
alert('document.getElementById("cache_control_select") returns null. Strange! Please report.');
|
8 |
+
return;
|
9 |
+
}
|
10 |
+
if (document.getElementById('cache_control_custom') == null) {
|
11 |
+
alert('document.getElementById("cache_control_custom") returns null. Strange! Please report.');
|
12 |
+
return;
|
13 |
+
}
|
14 |
var cacheControlValue = document.getElementById('cache_control_select').value;
|
15 |
var customEl = document.getElementById('cache_control_custom');
|
16 |
if (cacheControlValue == 'custom') {
|
lib/options/js/whitelist.js
CHANGED
@@ -1,4 +1,8 @@
|
|
1 |
function updateWhitelistInputValue() {
|
|
|
|
|
|
|
|
|
2 |
document.getElementById('whitelist').value = JSON.stringify(window.whitelist);
|
3 |
}
|
4 |
|
1 |
function updateWhitelistInputValue() {
|
2 |
+
if (document.getElementById('whitelist') == null) {
|
3 |
+
alert('document.getElementById("whitelist") returns null. Strange! Please report.');
|
4 |
+
return;
|
5 |
+
}
|
6 |
document.getElementById('whitelist').value = JSON.stringify(window.whitelist);
|
7 |
}
|
8 |
|
lib/options/options-hooks.php
CHANGED
@@ -16,14 +16,20 @@ add_action('admin_post_webpexpress_settings_submit', function() {
|
|
16 |
include __DIR__ . '/submit.php';
|
17 |
});
|
18 |
|
19 |
-
global $pagenow;
|
20 |
-
if (($pagenow == 'options-general.php') && (isset($_GET['page'])) && ($_GET['page'] == 'webp_express_settings_page')) {
|
21 |
-
add_action('admin_enqueue_scripts', function () {
|
22 |
-
include __DIR__ . '/enqueue_scripts.php';
|
23 |
-
});
|
24 |
-
}
|
25 |
-
|
26 |
function webp_express_settings_page_content()
|
27 |
{
|
|
|
28 |
include __DIR__ . '/page.php';
|
29 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
include __DIR__ . '/submit.php';
|
17 |
});
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
function webp_express_settings_page_content()
|
20 |
{
|
21 |
+
//include __DIR__ . '/enqueue_scripts.php'; // we don't do that, because our inline scripts would not be written in head on wordpress 4.4 and below
|
22 |
include __DIR__ . '/page.php';
|
23 |
}
|
24 |
+
|
25 |
+
function webp_express_admin_init() {
|
26 |
+
|
27 |
+
global $pagenow;
|
28 |
+
if ( ( 'options-general.php' === $pagenow ) && ( isset( $_GET['page'] ) ) && ( 'webp_express_settings_page' === $_GET['page'] ) ) {
|
29 |
+
add_action( 'admin_enqueue_scripts', function () {
|
30 |
+
include __DIR__ . '/enqueue_scripts.php';
|
31 |
+
} );
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
add_action( 'admin_init', 'webp_express_admin_init');
|
lib/options/options/cache-control.inc
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
//$maxQuality = get_option('webp_express_max_quality');
|
4 |
+
$cacheControl = $config['cache-control'];
|
5 |
+
$cacheControlCustom = $config['cache-control-custom'];
|
6 |
+
|
7 |
+
echo '<tr><th scope="row">Caching';
|
8 |
+
echo helpIcon(
|
9 |
+
'Controls the cache-control header for the converted image. ' .
|
10 |
+
'This header is only sent when a converted image can be successfully delivered (either existing, or new ' .
|
11 |
+
'conversion). In case of failure, headers will be sent to prevent caching.');
|
12 |
+
echo '</th><td>';
|
13 |
+
echo '<select id="cache_control_select" name="cache-control">';
|
14 |
+
echo '<option value="no-header"' . ($cacheControl == 'no-header' ? ' selected' : '') . '>Do not set Cache-Control header</option>';
|
15 |
+
echo '<option value="one-second"' . ($cacheControl == 'one-second' ? ' selected' : '') . '>One second</option>';
|
16 |
+
echo '<option value="one-minute"' . ($cacheControl == 'one-minute' ? ' selected' : '') . '>One minute</option>';
|
17 |
+
echo '<option value="one-hour"' . ($cacheControl == 'one-hour' ? ' selected' : '') . '>One hour</option>';
|
18 |
+
echo '<option value="one-day"' . ($cacheControl == 'one-day' ? ' selected' : '') . '>One day</option>';
|
19 |
+
echo '<option value="one-week"' . ($cacheControl == 'one-week' ? ' selected' : '') . '>One week</option>';
|
20 |
+
echo '<option value="one-month"' . ($cacheControl == 'one-month' ? ' selected' : '') . '>One month</option>';
|
21 |
+
echo '<option value="one-year"' . ($cacheControl == 'one-year' ? ' selected' : '') . '>One year</option>';
|
22 |
+
echo '<option value="custom"' . ($cacheControl == 'custom' ? ' selected' : '') . '>Custom Cache-Control header</option>';
|
23 |
+
echo '</select><br>';
|
24 |
+
echo '<input type="text" id="cache_control_custom" name="cache-control-custom" value="' . $cacheControlCustom . '">';
|
25 |
+
echo '</td></tr>';
|
lib/options/{converter-options → options/converter-options}/cwebp.php
RENAMED
File without changes
|
lib/options/{converter-options → options/converter-options}/ewww.php
RENAMED
File without changes
|
lib/options/{converter-options → options/converter-options}/gd.php
RENAMED
File without changes
|
lib/options/{converter-options → options/converter-options}/imagick.php
RENAMED
File without changes
|
lib/options/{converter-options → options/converter-options}/imagickbinary.php
RENAMED
File without changes
|
lib/options/{converter-options → options/converter-options}/wpc.php
RENAMED
File without changes
|
lib/options/options/converters.inc
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Converters
|
3 |
+
// --------------------
|
4 |
+
|
5 |
+
echo '<tr><th scope="row">Conversion method';
|
6 |
+
echo helpIcon('Drag to reorder. The conversion method on top will first be tried. ' .
|
7 |
+
'Should it fail, the next will be used, etc. To learn more about the conversion methods, <a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a>');
|
8 |
+
|
9 |
+
echo '</th><td>';
|
10 |
+
|
11 |
+
//$converters = $config['converters'];
|
12 |
+
//echo '<script>window.converters = ' . json_encode($converters) . '</script>';
|
13 |
+
//echo '<script>window.defaultConverters = ' . json_encode($defaultConverters) . '</script>';
|
14 |
+
|
15 |
+
echo "<input type='text' name='converters' value='' style='visibility:hidden; height:0' />";
|
16 |
+
|
17 |
+
// https://premium.wpmudev.org/blog/handling-form-submissions/
|
18 |
+
|
19 |
+
|
20 |
+
?>
|
21 |
+
<?php
|
22 |
+
/*
|
23 |
+
$localConverters = ['cwebp', 'imagick', 'gd'];
|
24 |
+
$testResult = WebPExpressHelpers::testConverters($localConverters);
|
25 |
+
//print_r($testResult);
|
26 |
+
|
27 |
+
if ($testResult['numOperationalConverters'] == 0) {
|
28 |
+
echo 'Unfortunately, your server is currently not able to convert to webp files by itself. You will need to set up a cloud converter.<br><br>';
|
29 |
+
foreach ($testResult['results'] as $result) {
|
30 |
+
echo $result['converter'] . ':' . $result['message'] . '<br>';
|
31 |
+
}
|
32 |
+
} else {
|
33 |
+
//echo 'Your server is able to convert webp files by itself.';
|
34 |
+
}
|
35 |
+
if ($testResult['numOperationalConverters'] == 1) {
|
36 |
+
//
|
37 |
+
}
|
38 |
+
*/
|
39 |
+
|
40 |
+
|
41 |
+
/*
|
42 |
+
http://php.net/manual/en/function.set-include-path.php
|
43 |
+
|
44 |
+
//exec('/usr/sbin/getsebool -a', $output6, $returnCode5); // ok
|
45 |
+
//echo 'All se bools: ' . print_r($output6, true) . '. Return code:' . $returnCode5;
|
46 |
+
*/
|
47 |
+
|
48 |
+
//echo '<h2>Conversion methods to try</h2>';
|
49 |
+
$dragIcon = '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="17px" height="17px" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#444444" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
|
50 |
+
|
51 |
+
/*echo '<p><i>Drag to reorder. The conversion method on top will first be tried. ';
|
52 |
+
echo 'Should it fail, the next will be used, etc.<br>';
|
53 |
+
echo 'To learn more about the conversion methods, ';
|
54 |
+
echo '<a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a></i></p>';
|
55 |
+
*/
|
56 |
+
// https://github.com/RubaXa/Sortable
|
57 |
+
|
58 |
+
// Empty list of converters. The list will be populated by the javascript
|
59 |
+
|
60 |
+
function webp_express_printUpdateButtons() {
|
61 |
+
?>
|
62 |
+
<button onclick="updateConverterOptionsAndSave()" class="button button-primary" type="button">Update and save settings</button>
|
63 |
+
<button onclick="updateConverterOptions()" class="button button-secondary" type="button">Update, but do not save yet</button>
|
64 |
+
<?php
|
65 |
+
//echo '<a href="javascript: tb_remove();">close</a>';
|
66 |
+
}
|
67 |
+
echo '<ul id="converters" style="margin-top: -13px"></ul>';
|
68 |
+
|
69 |
+
include 'converter-options/cwebp.php';
|
70 |
+
include 'converter-options/gd.php';
|
71 |
+
include 'converter-options/imagick.php';
|
72 |
+
include 'converter-options/ewww.php';
|
73 |
+
include 'converter-options/wpc.php';
|
74 |
+
include 'converter-options/imagickbinary.php';
|
75 |
+
?>
|
76 |
+
</td></tr>
|
lib/options/options/do-not-pass-source-path-in-query-string.inc
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
echo '<tr><th scope="row"><span style="color:darkorange">Beta:</span> Do not pass source in Query String';
|
3 |
+
echo helpIcon('In v0.8 and below, the .htaccess always passed the filename of the image to the script through the query string. It however seems that the PHP can determine the original file name in a server variable, and therefore does not need it in the query string. Removing it has the benefit of reducing risk of firewalls blocking the request. This option will probably go away in the next release, when it is confirmed that the feature is stable. So you better test if it works now, thanks!');
|
4 |
+
echo '</th><td>';
|
5 |
+
echo '<input type="checkbox" id="do_not_pass_source_in_query_string" name="do-not-pass-source-in-query-string" value="true" ' . ($config['do-not-pass-source-in-query-string'] ? 'checked="checked"' : '') . '">';
|
6 |
+
echo '</td></tr>';
|
lib/options/options/image-types.inc
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Image types
|
3 |
+
// ------------
|
4 |
+
echo '<tr><th scope="row">Image types to send to the converter';
|
5 |
+
echo helpIcon('Beware that the Gd conversion method cannot handle transparency for PNGs. PNG conversions havent been tested much yet. Please report any problems with PNG images <a target="_blank" href="https://github.com/rosell-dk/webp-convert/issues/42">here</a>');
|
6 |
+
echo '</th><td>';
|
7 |
+
|
8 |
+
// bitmask
|
9 |
+
// 1: JPEGs
|
10 |
+
// 2: PNG's
|
11 |
+
// Converting only jpegs is thus "1"
|
12 |
+
// Converting both jpegs and pngs is (1+2) = 3
|
13 |
+
//$imageTypes = get_option('webp_express_image_types_to_convert');
|
14 |
+
$imageTypes = $config['image-types'];
|
15 |
+
|
16 |
+
echo '<select name="image-types">';
|
17 |
+
echo '<option value="0"' . ($imageTypes == 0 ? ' selected' : '') . '>Do not convert any images!</option>';
|
18 |
+
echo '<option value="1"' . ($imageTypes == 1 ? ' selected' : '') . '>Only convert jpegs</option>';
|
19 |
+
echo '<option value="3"' . ($imageTypes == 3 ? ' selected' : '') . '>Convert both jpegs and pngs</option>';
|
20 |
+
echo '</select>';
|
21 |
+
|
22 |
+
echo '</td></tr>';
|
lib/options/options/metadata.inc
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Metadata
|
3 |
+
// --------------------
|
4 |
+
//$maxQuality = get_option('webp_express_max_quality');
|
5 |
+
$metadata = $config['metadata'];
|
6 |
+
|
7 |
+
echo '<tr><th scope="row">Metadata';
|
8 |
+
echo helpIcon('Decide what to do with image metadata, such as Exif. Note that this setting is not supported by the "Gd" conversion method, as it is not possible to copy the metadata with the Gd extension. Imagickbinary also currently lacks support');
|
9 |
+
echo '</th><td>';
|
10 |
+
|
11 |
+
echo '<select name="metadata">';
|
12 |
+
echo '<option value="none"' . ($metadata == 'none' ? ' selected' : '') . '>No metadata in webp</option>';
|
13 |
+
echo '<option value="all"' . ($metadata == 'all' ? ' selected' : '') . '>Copy all metadata to webp</option>';
|
14 |
+
echo '</select>';
|
15 |
+
echo '</td></tr>';
|
16 |
+
// echo '<tr><td colspan=2><p>Converted jpeg images will get same quality as original, but not more than this setting. Something between 70-85 is recommended for most websites.</p></td></tr>';
|
lib/options/options/quality.inc
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Quality
|
3 |
+
// --------------------
|
4 |
+
|
5 |
+
if ($canDetectQuality) {
|
6 |
+
echo '<tr><th scope="row">Quality';
|
7 |
+
echo helpIcon('If "Auto" is selected, the converted image will get same quality as source. Auto is recommended!');
|
8 |
+
echo '</th><td>';
|
9 |
+
$qualityAuto = $config['quality-auto'];;
|
10 |
+
echo '<select id="quality_auto_select" name="quality-auto">';
|
11 |
+
echo '<option value="auto_on"' . ($qualityAuto ? ' selected' : '') . '>Auto</option>';
|
12 |
+
echo '<option value="auto_off"' . (!$qualityAuto ? ' selected' : '') . '>Specific value</option>';
|
13 |
+
echo '</select>';
|
14 |
+
|
15 |
+
echo '</td></tr>';
|
16 |
+
|
17 |
+
|
18 |
+
// Max quality
|
19 |
+
// --------------------
|
20 |
+
$maxQuality = $config['max-quality'];
|
21 |
+
|
22 |
+
echo '<tr id="max_quality_row"><th scope="row">Max quality (0-100)';
|
23 |
+
echo helpIcon('Quality is expensive byte-wise. For most websites, more than 80 is a waste of bytes. ' .
|
24 |
+
'This option allows you to limit the quality to whatever is lowest: ' .
|
25 |
+
'the quality of the source or max quality. Recommended value: Somewhere between 50-85');
|
26 |
+
echo '</th><td>';
|
27 |
+
|
28 |
+
echo '<input type="text" size=3 id="max_quality" name="max-quality" value="' . $maxQuality . '">';
|
29 |
+
echo '</td></tr>';
|
30 |
+
} else {
|
31 |
+
|
32 |
+
}
|
33 |
+
|
34 |
+
// Quality - specific
|
35 |
+
// --------------------
|
36 |
+
$qualitySpecific = $config['quality-specific'];
|
37 |
+
|
38 |
+
echo '<tr id="quality_specific_row"><th scope="row">Quality (0-100)';
|
39 |
+
if ($canDetectQuality) {
|
40 |
+
echo helpIcon('All converted images will be encoded with this quality');
|
41 |
+
} else {
|
42 |
+
echo helpIcon('All converted images will be encoded with this quality. ' .
|
43 |
+
'For Remote WebP Express and Imagick, you however have the option to use override this, and use ' .
|
44 |
+
'"auto". With some setup, you can get quality detection working and you will then be able to set ' .
|
45 |
+
'quality to "auto" generally. For that you either need to get the imagick extension running ' .
|
46 |
+
'(PECL >= 2.2.2) or exec() rights and either imagick or gmagick installed.'
|
47 |
+
);
|
48 |
+
}
|
49 |
+
echo '</th><td>';
|
50 |
+
|
51 |
+
echo '<input type="text" size=3 id="quality_specific" name="quality-specific" value="' . $qualitySpecific . '">';
|
52 |
+
echo '</td></tr>';
|
lib/options/options/redirect-to-existing.inc
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Redirect to existing with .htaccess
|
3 |
+
// --------------------------------
|
4 |
+
echo '<tr><th scope="row"><span style="color:darkorange">Beta:</span> Redirect directly to converted image when available';
|
5 |
+
echo helpIcon('This will add rules in the .htaccess that redirects directly to existing converted files. If you do not activate this setting, it will be the PHP script that handles the redirection to existing webp files. Best performance is achieved by redirecting in .htaccess, however the feature is new and has not been tested widely. Please try it out, and report any problems in the forum, thanks :)<br>Beware that there is currently no hooks for regenerating converted images when source image is edited.');
|
6 |
+
echo '</th><td>';
|
7 |
+
echo '<input type="checkbox" id="redirect_to_existing_in_htaccess" name="redirect-to-existing-in-htaccess" value="true" ' . ($config['redirect-to-existing-in-htaccess'] ? 'checked="checked"' : '') . '">';
|
8 |
+
echo '</td></tr>';
|
lib/options/options/response-on-failure.inc
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// Response on failure
|
3 |
+
// --------------------
|
4 |
+
echo '<tr><th scope="row">Response on failure';
|
5 |
+
echo helpIcon('Determines what to serve in case the image conversion should fail.');
|
6 |
+
echo '</th><td>';
|
7 |
+
|
8 |
+
//$fail = get_option('webp_express_failure_response');
|
9 |
+
$fail = $config['fail'];
|
10 |
+
echo '<select name="fail">';
|
11 |
+
echo '<option value="original"' . ($fail == 'original' ? ' selected' : '') . '>Original image</option>';
|
12 |
+
echo '<option value="404"' . ($fail == '404' ? ' selected' : '') . '>404</option>';
|
13 |
+
echo '<option value="report"' . ($fail == 'report' ? ' selected' : '') . '>Error report (in plain text)</option>';
|
14 |
+
echo '<option value="report-as-image"' . ($fail == 'report-as-image' ? ' selected' : '') . '>Error report as image</option>';
|
15 |
+
echo '</select>';
|
16 |
+
echo '</td></tr>';
|
17 |
+
// echo '<tr><td colspan=2>Determines what the converter should serve, in case the image conversion should fail. For production servers, recommended value is "Original image". For development servers, choose anything you like, but that</td></tr>';
|
lib/options/options/web-service.inc
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
include_once __DIR__ . '/../../classes/Paths.php';
|
3 |
+
use \WebPExpress\Paths;
|
4 |
+
|
5 |
+
//$whitelist = $config['web-service']['whitelist'];
|
6 |
+
//echo '<script>window.whitelist = ' . json_encode($whitelist) . '</script>';
|
7 |
+
?>
|
8 |
+
<tr id="share">
|
9 |
+
<th scope="row">Enable web service?<?php echo helpIcon('Enabling the web service will allow selected sites to convert webp-images through this site (more options will appear, if you enable)'); ?></th>
|
10 |
+
<td>
|
11 |
+
<input type="checkbox" id="web_service_enabled" name="web-service-enabled" value="true" <?php echo ($config['web-service']['enabled'] ? 'checked="checked"' : '') ?>>
|
12 |
+
<input type='text' name='whitelist' id='whitelist' value='' style='visibility:hidden; height:0' />
|
13 |
+
<div id="whitelist_div"></div>
|
14 |
+
<div id="whitelist_properties_popup" class="das-popup">
|
15 |
+
<h3 class="hide-in-edit">Authorize website</h3>
|
16 |
+
<h3 class="hide-in-add">Edit authorized website</h3>
|
17 |
+
<input type="hidden" id="whitelist_uid">
|
18 |
+
<input type="hidden" id="whitelist_i">
|
19 |
+
<div>
|
20 |
+
<label for="whitelist_label">
|
21 |
+
Label
|
22 |
+
<?php echo helpIcon('The label is purely for your own reference'); ?>
|
23 |
+
</label>
|
24 |
+
<input id="whitelist_label" type="text">
|
25 |
+
</div>
|
26 |
+
<div>
|
27 |
+
<label for="whitelist_ip">
|
28 |
+
IP
|
29 |
+
<?php echo helpIcon('IP to allow access to service. You can use *, ie "212.91.*", or even "*"'); ?>
|
30 |
+
</label>
|
31 |
+
<input id="whitelist_ip" type="text">
|
32 |
+
</div>
|
33 |
+
<div>
|
34 |
+
<label for="whitelist_api_key">
|
35 |
+
Api key
|
36 |
+
<?php echo helpIcon('Who says api keys must be dull-looking meaningless sequences of random ' .
|
37 |
+
'characters? Here you get to shape your key to your liking. Enter any phrase you want'); ?>
|
38 |
+
</label>
|
39 |
+
<input id="whitelist_api_key" type="password" class="hide-in-edit">
|
40 |
+
<a href="javascript:whitelistChangeApiKey()" class="hide-in-add" style="line-height:34px">Change api key</a>
|
41 |
+
</div>
|
42 |
+
<div>
|
43 |
+
<label for="whitelist_require_api_key_to_be_crypted_in_transfer">
|
44 |
+
Require api-key to be crypted in transfer?
|
45 |
+
<?php echo helpIcon('If checked, the web service will only accept crypted api keys. Crypting the api-key protects it from being stolen during transfer. On a few older server setups, clients do not have the capability to crypt'); ?>
|
46 |
+
</label>
|
47 |
+
<input id="whitelist_require_api_key_to_be_crypted_in_transfer" type="checkbox">
|
48 |
+
</div>
|
49 |
+
<p style="margin-top: 15px">Psst: The endpoint of the web service is: <b><?php echo Paths::getWebServiceUrl() ?></b></p>
|
50 |
+
<button id="whitelist_properties_add_button" onclick="whitelistAddWhitelistEntry()" class="hide-in-edit button button-primary" type="button" style="position:absolute; bottom:20px">
|
51 |
+
Add
|
52 |
+
</button>
|
53 |
+
<button id="whitelist_properties_update_button" onclick="whitelistUpdateWhitelistEntry()" class="hide-in-add button button-primary" type="button" style="position:absolute; bottom:20px">
|
54 |
+
Update
|
55 |
+
</button>
|
56 |
+
</div>
|
57 |
+
</td>
|
58 |
+
</tr>
|
lib/options/page.php
CHANGED
@@ -43,8 +43,6 @@ function webpexpress_converterName($converterId) {
|
|
43 |
return $converterId;
|
44 |
}
|
45 |
|
46 |
-
$canDetectQuality = TestRun::isLocalQualityDetectionWorking();
|
47 |
-
|
48 |
function printAutoQualityOptionForConverter($converterId) {
|
49 |
?>
|
50 |
<div>
|
@@ -68,18 +66,16 @@ function printAutoQualityOptionForConverter($converterId) {
|
|
68 |
}
|
69 |
//update_option('webp-express-migration-version', '1');
|
70 |
|
71 |
-
|
72 |
$testResult = TestRun::getConverterStatus();
|
73 |
-
$
|
74 |
-
|
75 |
-
|
76 |
-
//print_r($testResult);
|
77 |
-
} else {
|
78 |
Messenger::printMessage(
|
79 |
'error',
|
80 |
'WebP Express cannot save a test conversion, because it does not have write ' .
|
81 |
'access to your upload folder, nor your wp-content folder. Please provide!'
|
82 |
-
);
|
83 |
}
|
84 |
|
85 |
|
@@ -92,165 +88,20 @@ foreach (Paths::getHTAccessDirs() as $dir) {
|
|
92 |
}*/
|
93 |
|
94 |
|
95 |
-
$defaultConfig = [
|
96 |
-
'cache-control' => 'no-header',
|
97 |
-
'cache-control-custom' => 'public, max-age:3600',
|
98 |
-
'converters' => [],
|
99 |
-
'fail' => 'original',
|
100 |
-
'forward-query-string' => true,
|
101 |
-
'image-types' => 1,
|
102 |
-
'quality-auto' => $canDetectQuality,
|
103 |
-
'max-quality' => 80,
|
104 |
-
'quality-specific' => 70,
|
105 |
-
'metadata' => 'none',
|
106 |
-
'web-service' => [
|
107 |
-
'enabled' => false,
|
108 |
-
'whitelist' => [
|
109 |
-
/*[
|
110 |
-
'uid' => '', // for internal purposes
|
111 |
-
'label' => '', // ie website name. It is just for display
|
112 |
-
'ip' => '', // restrict to these ips. * pattern is allowed.
|
113 |
-
'api-key' => '', // Api key for the entry. Not neccessarily unique for the entry
|
114 |
-
//'quota' => 60
|
115 |
-
]
|
116 |
-
*/
|
117 |
-
]
|
118 |
-
|
119 |
-
]
|
120 |
-
];
|
121 |
-
|
122 |
-
$defaultConverters = ConvertersHelper::$defaultConverters;
|
123 |
-
|
124 |
-
|
125 |
-
$config = Config::loadConfig();
|
126 |
-
//echo '<pre>' . print_r($config, true) . '</pre>';
|
127 |
-
if (!$config) {
|
128 |
-
$config = [];
|
129 |
-
}
|
130 |
-
//$config = [];
|
131 |
-
|
132 |
-
$config = array_merge($defaultConfig, $config);
|
133 |
-
if ($config['converters'] == null) {
|
134 |
-
$config['converters'] = [];
|
135 |
-
}
|
136 |
-
if (!isset($config['web-service'])) {
|
137 |
-
$config['web-service'] = [];
|
138 |
-
}
|
139 |
-
if (!isset($config['web-service']['whitelist'])) {
|
140 |
-
$config['web-service']['whitelist'] = [];
|
141 |
-
}
|
142 |
-
|
143 |
-
// Remove keys in whitelist (so they cannot easily be picked up by examining the html)
|
144 |
-
foreach ($config['web-service']['whitelist'] as &$whitelistEntry) {
|
145 |
-
unset($whitelistEntry['api-key']);
|
146 |
-
}
|
147 |
-
|
148 |
-
// Remove keys from WPC converters
|
149 |
-
foreach ($config['converters'] as &$converter) {
|
150 |
-
if (isset($converter['converter']) && ($converter['converter'] == 'wpc')) {
|
151 |
-
if (isset($converter['options']['api-key'])) {
|
152 |
-
if ($converter['options']['api-key'] != '') {
|
153 |
-
$converter['options']['_api-key-non-empty'] = true;
|
154 |
-
}
|
155 |
-
unset($converter['options']['api-key']);
|
156 |
-
}
|
157 |
-
}
|
158 |
-
}
|
159 |
-
|
160 |
-
|
161 |
-
if (count($config['converters']) == 0) {
|
162 |
-
// This is first time visit!
|
163 |
-
|
164 |
-
if (count($workingConverters) == 0) {
|
165 |
-
// No converters are working
|
166 |
-
// Send ewww converter to top
|
167 |
-
$resultPart1 = [];
|
168 |
-
$resultPart2 = [];
|
169 |
-
foreach ($defaultConverters as $converter) {
|
170 |
-
$converterId = $converter['converter'];
|
171 |
-
if ($converterId == 'ewww') {
|
172 |
-
$resultPart1[] = $converter;
|
173 |
-
} else {
|
174 |
-
$resultPart2[] = $converter;
|
175 |
-
}
|
176 |
-
}
|
177 |
-
$config['converters'] = array_merge($resultPart1, $resultPart2);
|
178 |
-
} else {
|
179 |
-
// Send converters not working to the bottom
|
180 |
-
// - and also deactivate them..
|
181 |
-
$resultPart1 = [];
|
182 |
-
$resultPart2 = [];
|
183 |
-
foreach ($defaultConverters as $converter) {
|
184 |
-
$converterId = $converter['converter'];
|
185 |
-
if (in_array($converterId, $workingConverters)) {
|
186 |
-
$resultPart1[] = $converter;
|
187 |
-
} else {
|
188 |
-
$converter['deactivated'] = true;
|
189 |
-
$resultPart2[] = $converter;
|
190 |
-
}
|
191 |
-
}
|
192 |
-
$config['converters'] = array_merge($resultPart1, $resultPart2);
|
193 |
-
}
|
194 |
-
|
195 |
-
// $workingConverters
|
196 |
-
//echo '<pre>' . print_r($converters, true) . '</pre>';
|
197 |
-
} else {
|
198 |
-
// not first time visit...
|
199 |
-
// merge missing converters in
|
200 |
-
$config['converters'] = ConvertersHelper::mergeConverters($config['converters'], ConvertersHelper::$defaultConverters);
|
201 |
-
}
|
202 |
-
|
203 |
-
|
204 |
-
// Set "working" and "error" properties
|
205 |
-
if ($testResult) {
|
206 |
-
foreach ($config['converters'] as &$converter) {
|
207 |
-
$converterId = $converter['converter'];
|
208 |
-
$hasError = isset($testResult['errors'][$converterId]);
|
209 |
-
$working = !$hasError;
|
210 |
-
if (isset($converter['working']) && ($converter['working'] != $working)) {
|
211 |
-
if ($working) {
|
212 |
-
Messenger::printMessage(
|
213 |
-
'info',
|
214 |
-
'Hurray! - The <i>' . webpexpress_converterName($converterId) . '</i> conversion method is working now!'
|
215 |
-
);
|
216 |
-
} else {
|
217 |
-
Messenger::printMessage(
|
218 |
-
'warning',
|
219 |
-
'Sad news. The <i>' . webpexpress_converterName($converterId) . '</i> conversion method is not working anymore. What happened?'
|
220 |
-
);
|
221 |
-
}
|
222 |
-
}
|
223 |
-
$converter['working'] = $working;
|
224 |
-
if ($hasError) {
|
225 |
-
$error = $testResult['errors'][$converterId];
|
226 |
-
if ($converterId == 'wpc') {
|
227 |
-
if (preg_match('/Missing URL/', $error)) {
|
228 |
-
$error = 'Not configured';
|
229 |
-
}
|
230 |
-
if ($error == 'No remote host has been set up') {
|
231 |
-
$error = 'Not configured';
|
232 |
-
}
|
233 |
-
|
234 |
-
if (preg_match('/cloud service is not enabled/', $error)) {
|
235 |
-
$error = 'The server is not enabled. Click the "Enable web service" on WebP Express settings on the site you are trying to connect to.';
|
236 |
-
}
|
237 |
-
}
|
238 |
-
$converter['error'] = $error;
|
239 |
-
} else {
|
240 |
-
unset($converter['error']);
|
241 |
-
}
|
242 |
-
}
|
243 |
-
}
|
244 |
//echo '<pre>' . print_r($config['converters'], true) . '</pre>';
|
245 |
|
246 |
//echo 'Working converters:' . print_r($workingConverters, true) . '<br>';
|
247 |
// Generate a custom nonce value.
|
248 |
$webpexpress_settings_nonce = wp_create_nonce('webpexpress_settings_nonce');
|
249 |
?>
|
250 |
-
<p>
|
251 |
-
<i>WebP Express takes care of serving autogenerated WebP images instead of jpeg/png to browsers that supports WebP
|
252 |
-
|
253 |
-
</
|
|
|
|
|
|
|
|
|
254 |
|
255 |
<?php
|
256 |
|
@@ -261,388 +112,73 @@ echo '<form id="webpexpress_settings" action="' . esc_url( admin_url( 'admin-pos
|
|
261 |
<input type="hidden" name="action" value="webpexpress_settings_submit">
|
262 |
<input type="hidden" name="webpexpress_settings_nonce" value="<?php echo $webpexpress_settings_nonce ?>" />
|
263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
<?php
|
265 |
|
266 |
function helpIcon($text) {
|
267 |
return '<div class="help">?<div class="popup">' . $text . '</div></div>';
|
268 |
}
|
269 |
-
echo '<table class="form-table"><tbody>';
|
270 |
-
|
271 |
-
// Image types
|
272 |
-
// ------------
|
273 |
-
echo '<tr><th scope="row">Image types to convert';
|
274 |
-
echo helpIcon('Beware that the Gd conversion method cannot handle transparency for PNGs. PNG conversions havent been tested much yet. Please report any problems with PNG images <a target="_blank" href="https://github.com/rosell-dk/webp-convert/issues/42">here</a>');
|
275 |
-
echo '</th><td>';
|
276 |
-
|
277 |
-
// bitmask
|
278 |
-
// 1: JPEGs
|
279 |
-
// 2: PNG's
|
280 |
-
// Converting only jpegs is thus "1"
|
281 |
-
// Converting both jpegs and pngs is (1+2) = 3
|
282 |
-
//$imageTypes = get_option('webp_express_image_types_to_convert');
|
283 |
-
$imageTypes = $config['image-types'];
|
284 |
-
|
285 |
-
echo '<select name="image-types">';
|
286 |
-
echo '<option value="0"' . ($imageTypes == 0 ? ' selected' : '') . '>Do not convert any images!</option>';
|
287 |
-
echo '<option value="1"' . ($imageTypes == 1 ? ' selected' : '') . '>Only convert jpegs</option>';
|
288 |
-
echo '<option value="3"' . ($imageTypes == 3 ? ' selected' : '') . '>Convert both jpegs and pngs</option>';
|
289 |
-
echo '</select>';
|
290 |
-
|
291 |
-
echo '</td></tr>';
|
292 |
-
|
293 |
-
// Quality
|
294 |
-
// --------------------
|
295 |
-
|
296 |
-
if ($canDetectQuality) {
|
297 |
-
echo '<tr><th scope="row">Quality';
|
298 |
-
echo helpIcon('If "Auto" is selected, the converted image will get same quality as source. Auto is recommended!');
|
299 |
-
echo '</th><td>';
|
300 |
-
$qualityAuto = $config['quality-auto'];;
|
301 |
-
echo '<select id="quality_auto_select" name="quality-auto">';
|
302 |
-
echo '<option value="auto_on"' . ($qualityAuto ? ' selected' : '') . '>Auto</option>';
|
303 |
-
echo '<option value="auto_off"' . (!$qualityAuto ? ' selected' : '') . '>Specific value</option>';
|
304 |
-
echo '</select>';
|
305 |
-
|
306 |
-
echo '</td></tr>';
|
307 |
-
|
308 |
-
|
309 |
-
// Max quality
|
310 |
-
// --------------------
|
311 |
-
$maxQuality = $config['max-quality'];
|
312 |
-
|
313 |
-
echo '<tr id="max_quality_row"><th scope="row">Max quality (0-100)';
|
314 |
-
echo helpIcon('Quality is expensive byte-wise. For most websites, more than 80 is a waste of bytes. ' .
|
315 |
-
'This option allows you to limit the quality to whatever is lowest: ' .
|
316 |
-
'the quality of the source or max quality. Recommended value: Somewhere between 50-85');
|
317 |
-
echo '</th><td>';
|
318 |
-
|
319 |
-
echo '<input type="text" size=3 id="max_quality" name="max-quality" value="' . $maxQuality . '">';
|
320 |
-
echo '</td></tr>';
|
321 |
-
} else {
|
322 |
-
|
323 |
-
}
|
324 |
-
|
325 |
-
// Quality - specific
|
326 |
-
// --------------------
|
327 |
-
$qualitySpecific = $config['quality-specific'];
|
328 |
-
|
329 |
-
echo '<tr id="quality_specific_row"><th scope="row">Quality (0-100)';
|
330 |
-
if ($canDetectQuality) {
|
331 |
-
echo helpIcon('All converted images will be encoded with this quality');
|
332 |
-
} else {
|
333 |
-
echo helpIcon('All converted images will be encoded with this quality. ' .
|
334 |
-
'For Remote WebP Express and Imagick, you however have the option to use override this, and use ' .
|
335 |
-
'"auto". With some setup, you can get quality detection working and you will then be able to set ' .
|
336 |
-
'quality to "auto" generally. For that you either need to get the imagick extension running ' .
|
337 |
-
'(PECL >= 2.2.2) or exec() rights and either imagick or gmagick installed.'
|
338 |
-
);
|
339 |
-
}
|
340 |
-
echo '</th><td>';
|
341 |
-
|
342 |
-
echo '<input type="text" size=3 id="quality_specific" name="quality-specific" value="' . $qualitySpecific . '">';
|
343 |
-
echo '</td></tr>';
|
344 |
-
|
345 |
-
// Converters
|
346 |
-
// --------------------
|
347 |
-
|
348 |
-
echo '<tr><th scope="row">Conversion method';
|
349 |
-
echo helpIcon('Drag to reorder. The conversion method on top will first be tried. ' .
|
350 |
-
'Should it fail, the next will be used, etc. To learn more about the conversion methods, <a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a>');
|
351 |
-
|
352 |
-
echo '</th><td>';
|
353 |
-
|
354 |
-
$converters = $config['converters'];
|
355 |
-
echo '<script>window.converters = ' . json_encode($converters) . '</script>';
|
356 |
-
echo '<script>window.defaultConverters = ' . json_encode($defaultConverters) . '</script>';
|
357 |
-
|
358 |
-
echo "<input type='text' name='converters' value='' style='visibility:hidden; height:0' />";
|
359 |
-
|
360 |
-
// https://premium.wpmudev.org/blog/handling-form-submissions/
|
361 |
-
|
362 |
-
|
363 |
-
?>
|
364 |
-
<?php
|
365 |
-
/*
|
366 |
-
$localConverters = ['cwebp', 'imagick', 'gd'];
|
367 |
-
$testResult = WebPExpressHelpers::testConverters($localConverters);
|
368 |
-
//print_r($testResult);
|
369 |
-
|
370 |
-
if ($testResult['numOperationalConverters'] == 0) {
|
371 |
-
echo 'Unfortunately, your server is currently not able to convert to webp files by itself. You will need to set up a cloud converter.<br><br>';
|
372 |
-
foreach ($testResult['results'] as $result) {
|
373 |
-
echo $result['converter'] . ':' . $result['message'] . '<br>';
|
374 |
-
}
|
375 |
-
} else {
|
376 |
-
//echo 'Your server is able to convert webp files by itself.';
|
377 |
-
}
|
378 |
-
if ($testResult['numOperationalConverters'] == 1) {
|
379 |
-
//
|
380 |
-
}
|
381 |
-
*/
|
382 |
-
|
383 |
-
|
384 |
-
/*
|
385 |
-
http://php.net/manual/en/function.set-include-path.php
|
386 |
-
|
387 |
-
//exec('/usr/sbin/getsebool -a', $output6, $returnCode5); // ok
|
388 |
-
//echo 'All se bools: ' . print_r($output6, true) . '. Return code:' . $returnCode5;
|
389 |
-
*/
|
390 |
-
|
391 |
-
//echo '<h2>Conversion methods to try</h2>';
|
392 |
-
$dragIcon = '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="17px" height="17px" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#444444" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
|
393 |
-
|
394 |
-
/*echo '<p><i>Drag to reorder. The conversion method on top will first be tried. ';
|
395 |
-
echo 'Should it fail, the next will be used, etc.<br>';
|
396 |
-
echo 'To learn more about the conversion methods, ';
|
397 |
-
echo '<a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a></i></p>';
|
398 |
-
*/
|
399 |
-
// https://github.com/RubaXa/Sortable
|
400 |
-
|
401 |
-
// Empty list of converters. The list will be populated by the javascript
|
402 |
-
|
403 |
-
function webp_express_printUpdateButtons() {
|
404 |
-
?>
|
405 |
-
<button onclick="updateConverterOptionsAndSave()" class="button button-primary" type="button">Update and save settings</button>
|
406 |
-
<button onclick="updateConverterOptions()" class="button button-secondary" type="button">Update, but do not save yet</button>
|
407 |
-
<?php
|
408 |
-
//echo '<a href="javascript: tb_remove();">close</a>';
|
409 |
-
}
|
410 |
-
echo '<ul id="converters" style="margin-top: -13px"></ul>';
|
411 |
-
|
412 |
-
include 'converter-options/cwebp.php';
|
413 |
-
include 'converter-options/gd.php';
|
414 |
-
include 'converter-options/imagick.php';
|
415 |
-
include 'converter-options/ewww.php';
|
416 |
-
include 'converter-options/wpc.php';
|
417 |
-
include 'converter-options/imagickbinary.php';
|
418 |
?>
|
419 |
-
</td></tr>
|
420 |
-
<?php
|
421 |
-
|
422 |
-
// echo '<tr><td colspan=2><p>Converted jpeg images will get same quality as original, but not more than this setting. Something between 70-85 is recommended for most websites.</p></td></tr>';
|
423 |
-
|
424 |
-
// method
|
425 |
-
//echo '<p>When higher values are used, the encoder will spend more time inspecting additional encoding possibilities and decide on the quality gain. Supported by cwebp, wpc and imagick</p>';
|
426 |
-
|
427 |
-
// Cache-Control
|
428 |
-
// --------------------
|
429 |
-
//$maxQuality = get_option('webp_express_max_quality');
|
430 |
-
$cacheControl = $config['cache-control'];
|
431 |
-
$cacheControlCustom = $config['cache-control-custom'];
|
432 |
-
|
433 |
-
echo '<tr><th scope="row">Caching';
|
434 |
-
echo helpIcon(
|
435 |
-
'Controls the cache-control header for the converted image. ' .
|
436 |
-
'This header is only sent when a converted image is successfully delivered (either existing, or new ' .
|
437 |
-
'conversion). In case of failure, headers will be sent to prevent caching.');
|
438 |
-
echo '</th><td>';
|
439 |
-
echo '<select id="cache_control_select" name="cache-control">';
|
440 |
-
echo '<option value="no-header"' . ($cacheControl == 'no-header' ? ' selected' : '') . '>Do not set Cache-Control header</option>';
|
441 |
-
echo '<option value="one-second"' . ($cacheControl == 'one-second' ? ' selected' : '') . '>One second</option>';
|
442 |
-
echo '<option value="one-minute"' . ($cacheControl == 'one-minute' ? ' selected' : '') . '>One minute</option>';
|
443 |
-
echo '<option value="one-hour"' . ($cacheControl == 'one-hour' ? ' selected' : '') . '>One hour</option>';
|
444 |
-
echo '<option value="one-day"' . ($cacheControl == 'one-day' ? ' selected' : '') . '>One day</option>';
|
445 |
-
echo '<option value="one-week"' . ($cacheControl == 'one-week' ? ' selected' : '') . '>One week</option>';
|
446 |
-
echo '<option value="one-month"' . ($cacheControl == 'one-month' ? ' selected' : '') . '>One month</option>';
|
447 |
-
echo '<option value="one-year"' . ($cacheControl == 'one-year' ? ' selected' : '') . '>One year</option>';
|
448 |
-
echo '<option value="custom"' . ($cacheControl == 'custom' ? ' selected' : '') . '>Custom Cache-Control header</option>';
|
449 |
-
echo '</select><br>';
|
450 |
-
echo '<input type="text" id="cache_control_custom" name="cache-control-custom" value="' . $cacheControlCustom . '">';
|
451 |
-
echo '</td></tr>';
|
452 |
-
|
453 |
-
|
454 |
-
// Metadata
|
455 |
-
// --------------------
|
456 |
-
//$maxQuality = get_option('webp_express_max_quality');
|
457 |
-
$metadata = $config['metadata'];
|
458 |
-
|
459 |
-
echo '<tr><th scope="row">Metadata';
|
460 |
-
echo helpIcon('Decide what to do with image metadata, such as Exif. Note that this setting is not supported by the "Gd" conversion method, as it is not possible to copy the metadata with the Gd extension');
|
461 |
-
echo '</th><td>';
|
462 |
-
|
463 |
-
echo '<select name="metadata">';
|
464 |
-
echo '<option value="none"' . ($metadata == 'none' ? ' selected' : '') . '>No metadata in webp</option>';
|
465 |
-
echo '<option value="all"' . ($metadata == 'all' ? ' selected' : '') . '>Copy all metadata to webp</option>';
|
466 |
-
echo '</select>';
|
467 |
-
echo '</td></tr>';
|
468 |
-
// echo '<tr><td colspan=2><p>Converted jpeg images will get same quality as original, but not more than this setting. Something between 70-85 is recommended for most websites.</p></td></tr>';
|
469 |
-
|
470 |
-
// method
|
471 |
-
//echo '<p>When higher values are used, the encoder will spend more time inspecting additional encoding possibilities and decide on the quality gain. Supported by cwebp, wpc and imagick</p>';
|
472 |
-
|
473 |
-
// Response on failure
|
474 |
-
// --------------------
|
475 |
-
echo '<tr><th scope="row">Response on failure';
|
476 |
-
echo helpIcon('Determines what to serve in case the image conversion should fail.');
|
477 |
-
echo '</th><td>';
|
478 |
-
|
479 |
-
//$fail = get_option('webp_express_failure_response');
|
480 |
-
$fail = $config['fail'];
|
481 |
-
echo '<select name="fail">';
|
482 |
-
echo '<option value="original"' . ($fail == 'original' ? ' selected' : '') . '>Original image</option>';
|
483 |
-
echo '<option value="404"' . ($fail == '404' ? ' selected' : '') . '>404</option>';
|
484 |
-
echo '<option value="report"' . ($fail == 'report' ? ' selected' : '') . '>Error report (in plain text)</option>';
|
485 |
-
echo '<option value="report-as-image"' . ($fail == 'report-as-image' ? ' selected' : '') . '>Error report as image</option>';
|
486 |
-
echo '</select>';
|
487 |
-
echo '</td></tr>';
|
488 |
-
// echo '<tr><td colspan=2>Determines what the converter should serve, in case the image conversion should fail. For production servers, recommended value is "Original image". For development servers, choose anything you like, but that</td></tr>';
|
489 |
-
|
490 |
-
//echo '</tbody></table>';
|
491 |
-
|
492 |
-
|
493 |
-
// Web Service
|
494 |
-
// --------------------
|
495 |
-
|
496 |
-
$whitelist = $config['web-service']['whitelist'];
|
497 |
-
echo '<script>window.whitelist = ' . json_encode($whitelist) . '</script>';
|
498 |
-
echo '<tr id="share"><th scope="row">Enable web service?';
|
499 |
-
echo helpIcon('Enabling the web service will allow selected sites to convert webp-images through this site (more options will appear, if you enable)');
|
500 |
-
echo '</th><td>';
|
501 |
-
|
502 |
-
echo '<input type="checkbox" id="web_service_enabled" name="web-service-enabled" value="true" ' . ($config['web-service']['enabled'] ? 'checked="checked"' : '') . '">';
|
503 |
-
echo "<input type='text' name='whitelist' id='whitelist' value='' style='visibility:hidden; height:0' />";
|
504 |
|
505 |
-
|
506 |
-
<div id="whitelist_div"></div>
|
507 |
-
<!--
|
508 |
-
<div id="whitelist_listen_popup" class="das-popup">
|
509 |
-
<h3>Listening for a request<span class="animated-dots">...</span></h3>
|
510 |
-
<div style="font-size:90%">
|
511 |
-
Send the instructions below to the one that controls the website that you want to grant access.
|
512 |
-
If you control that website, simply open up a new tab and perform the following:
|
513 |
-
<ol>
|
514 |
-
<li>Log in to the website you want to use the web service</li>
|
515 |
-
<li>In WebP Express settings, find the <i>Remote WebP Express</i> conversion method and click <i>configure</i></li>
|
516 |
-
<li>Click "Make request"</li>
|
517 |
-
<li>Enter this url: <b><?php echo Paths::getWebServiceUrl(); ?></b></li>
|
518 |
-
</ol>
|
519 |
-
This popup will close once the above is completed<br><br>
|
520 |
-
</div>
|
521 |
-
<div style="display: inline-block;vertical-align:middle; line-height:27px;">
|
522 |
-
<button onclick="whitelistCancelListening()" class="button button-secondary" type="button">
|
523 |
-
Give up
|
524 |
-
</button>
|
525 |
-
or
|
526 |
-
<button onclick="whitelistAddManually()" class="button button-secondary" type="button">
|
527 |
-
Add manually
|
528 |
-
</button>
|
529 |
-
</div>
|
530 |
-
</div>
|
531 |
-
-->
|
532 |
-
<div id="whitelist_properties_popup" class="das-popup">
|
533 |
-
<h3 class="hide-in-edit">Authorize website</h3>
|
534 |
-
<h3 class="hide-in-add">Edit authorized website</h3>
|
535 |
-
<input type="hidden" id="whitelist_uid">
|
536 |
-
<input type="hidden" id="whitelist_i">
|
537 |
-
<div>
|
538 |
-
<label for="whitelist_label">
|
539 |
-
Label
|
540 |
-
<?php echo helpIcon('The label is purely for your own reference'); ?>
|
541 |
-
</label>
|
542 |
-
<input id="whitelist_label" type="text">
|
543 |
-
</div>
|
544 |
-
<div>
|
545 |
-
<label for="whitelist_ip">
|
546 |
-
IP
|
547 |
-
<?php echo helpIcon('IP to allow access to service. You can use *, ie "212.91.*", or even "*"'); ?>
|
548 |
-
</label>
|
549 |
-
<input id="whitelist_ip" type="text">
|
550 |
-
</div>
|
551 |
-
<div>
|
552 |
-
<label for="whitelist_api_key">
|
553 |
-
Api key
|
554 |
-
<?php echo helpIcon('Who says api keys must be dull-looking meaningless sequences of random ' .
|
555 |
-
'characters? Here you get to shape your key to your liking. Enter any phrase you want'); ?>
|
556 |
-
</label>
|
557 |
-
<input id="whitelist_api_key" type="password" class="hide-in-edit">
|
558 |
-
<a href="javascript:whitelistChangeApiKey()" class="hide-in-add" style="line-height:34px">Change api key</a>
|
559 |
-
</div>
|
560 |
-
<div>
|
561 |
-
<label for="whitelist_require_api_key_to_be_crypted_in_transfer">
|
562 |
-
Require api-key to be crypted in transfer?
|
563 |
-
<?php echo helpIcon('If checked, the web service will only accept crypted api keys. Crypting the api-key protects it from being stolen during transfer. On a few older server setups, clients do not have the capability to crypt'); ?>
|
564 |
-
</label>
|
565 |
-
<input id="whitelist_require_api_key_to_be_crypted_in_transfer" type="checkbox">
|
566 |
-
</div>
|
567 |
-
<p style="margin-top: 15px">Psst: The endpoint of the web service is: <b><?php echo Paths::getWebServiceUrl() ?></b></p>
|
568 |
-
|
569 |
-
<button id="whitelist_properties_add_button" onclick="whitelistAddWhitelistEntry()" class="hide-in-edit button button-primary" type="button" style="position:absolute; bottom:20px">
|
570 |
-
Add
|
571 |
-
</button>
|
572 |
-
<button id="whitelist_properties_update_button" onclick="whitelistUpdateWhitelistEntry()" class="hide-in-add button button-primary" type="button" style="position:absolute; bottom:20px">
|
573 |
-
Update
|
574 |
-
</button>
|
575 |
-
</div>
|
576 |
-
<!--
|
577 |
-
<div id="whitelist_accept_request" class="das-popup">
|
578 |
-
<h3>Incoming request!</h3>
|
579 |
-
<div id="request_details"></div>
|
580 |
-
<button onclick="whitelistAcceptRequest()" class="button button-primary" type="button" style="position:absolute; bottom:20px">Grant access</button>
|
581 |
-
<button onclick="whitelistDenyRequest()" class="button button-secondary" type="button" style="position:absolute; bottom:20px;right:20px">Deny</button>
|
582 |
-
</div>-->
|
583 |
-
|
584 |
-
<?php
|
585 |
-
echo '</td></tr>';
|
586 |
|
587 |
|
588 |
-
// WPC - whitelist
|
589 |
-
// --------------------
|
590 |
-
/*
|
591 |
-
echo '<tr id="whitelist_row"><th scope="row">Whitelist';
|
592 |
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
618 |
|
619 |
-
</div>
|
620 |
-
</div>
|
621 |
-
-->
|
622 |
-
<?php
|
623 |
-
/*
|
624 |
-
echo '<div id="whitelist_div"></div>';
|
625 |
-
echo "<input type='text' name='whitelist' value='' style='visibility:hidden; height:0' />"; //
|
626 |
-
//echo gethostbyaddr('212.97.134.33');
|
627 |
-
//echo gethostbyname('www.rosell.dk');
|
628 |
-
echo '<div id="password_helptext">' . helpIcon('You may have to leave blank, if the site in question doesnt have the md5() function available.<br><br>' .
|
629 |
-
'md5 is needed because the password is not transmitted directly, but used to create a ' .
|
630 |
-
'unique hash for the image being converted. So if someone intercepts, they will only get the hash, not the password. And that ' .
|
631 |
-
'hash will only work for that specific image.') . '</div>';visibility:
|
632 |
-
echo '<div id="whitelist_site_helptext">' . helpIcon('Enter IP or domain (ie www.example.com). You may use * as a wildcard.') . '</div>';
|
633 |
-
//echo '<div id="whitelist_quota_helptext">' . helpIcon('Maximum conversions per hour for this site') . '</div>';
|
634 |
-
|
635 |
-
echo '</td></tr>';
|
636 |
-
*/
|
637 |
-
|
638 |
-
?>
|
639 |
-
</tbody></table>
|
640 |
-
|
641 |
-
<table>
|
642 |
-
<tr>
|
643 |
-
<td style="padding-right:20px"><?php submit_button('Save settings', 'primary', 'mysubmit'); ?></td>
|
644 |
-
<td><?php submit_button('Save settings and force new .htaccess rules', 'secondary', 'force'); ?></td>
|
645 |
-
</tr>
|
646 |
-
</table>
|
647 |
</form>
|
648 |
</div>
|
43 |
return $converterId;
|
44 |
}
|
45 |
|
|
|
|
|
46 |
function printAutoQualityOptionForConverter($converterId) {
|
47 |
?>
|
48 |
<div>
|
66 |
}
|
67 |
//update_option('webp-express-migration-version', '1');
|
68 |
|
69 |
+
$canDetectQuality = TestRun::isLocalQualityDetectionWorking();
|
70 |
$testResult = TestRun::getConverterStatus();
|
71 |
+
$config = Config::getConfigForOptionsPage();
|
72 |
+
|
73 |
+
if (!$testResult) {
|
|
|
|
|
74 |
Messenger::printMessage(
|
75 |
'error',
|
76 |
'WebP Express cannot save a test conversion, because it does not have write ' .
|
77 |
'access to your upload folder, nor your wp-content folder. Please provide!'
|
78 |
+
);
|
79 |
}
|
80 |
|
81 |
|
88 |
}*/
|
89 |
|
90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
//echo '<pre>' . print_r($config['converters'], true) . '</pre>';
|
92 |
|
93 |
//echo 'Working converters:' . print_r($workingConverters, true) . '<br>';
|
94 |
// Generate a custom nonce value.
|
95 |
$webpexpress_settings_nonce = wp_create_nonce('webpexpress_settings_nonce');
|
96 |
?>
|
97 |
+
<p><div>
|
98 |
+
<i>WebP Express takes care of serving autogenerated WebP images instead of jpeg/png to browsers that supports WebP.</i>
|
99 |
+
<div class="help">?<div class="popup"><ol>
|
100 |
+
<li>Some redirect rules set up in <i>.htaccess</i> redirects (unconverted) jpeg/png images to a PHP script for handling.</li>
|
101 |
+
<li>The PHP script reads the options and passes them to the <i><a target="_blank" href="https://github.com/rosell-dk/webp-convert/">WebP Convert</a></i> library for converting <i>and</i> serving.</li>
|
102 |
+
<li>If WebP Convert finds that the image already is converted, it will be served immediately (unless it is bigger than the original, or the original has been modified). Otherwise it will be converted and then served</li>
|
103 |
+
</ol></div></div>
|
104 |
+
</div></p>
|
105 |
|
106 |
<?php
|
107 |
|
112 |
<input type="hidden" name="action" value="webpexpress_settings_submit">
|
113 |
<input type="hidden" name="webpexpress_settings_nonce" value="<?php echo $webpexpress_settings_nonce ?>" />
|
114 |
|
115 |
+
<fieldset class="block buttons">
|
116 |
+
<table>
|
117 |
+
<tr>
|
118 |
+
<td style="padding-right:20px"><?php submit_button('Save settings', 'primary', 'mysubmit'); ?></td>
|
119 |
+
<td><?php submit_button('Save settings and force new .htaccess rules', 'secondary', 'force'); ?></td>
|
120 |
+
</tr>
|
121 |
+
</table>
|
122 |
+
</fieldset>
|
123 |
<?php
|
124 |
|
125 |
function helpIcon($text) {
|
126 |
return '<div class="help">?<div class="popup">' . $text . '</div></div>';
|
127 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
|
130 |
+
<p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
|
132 |
|
|
|
|
|
|
|
|
|
133 |
|
134 |
+
<fieldset class="block">
|
135 |
+
<h3>Redirection rules</h3>
|
136 |
+
<p><i>The options here affects the rules created in the .htaccess.</i></p>
|
137 |
+
<table class="form-table">
|
138 |
+
<tbody>
|
139 |
+
<?php
|
140 |
+
include_once 'options/image-types.inc';
|
141 |
+
include_once 'options/redirect-to-existing.inc';
|
142 |
+
include_once 'options/do-not-pass-source-path-in-query-string.inc';
|
143 |
+
?>
|
144 |
+
</tbody>
|
145 |
+
</table>
|
146 |
+
</fieldset>
|
147 |
+
<fieldset class="block">
|
148 |
+
<h3>Conversion options</h3>
|
149 |
+
<p><i>The options here affects the conversion process</i></p>
|
150 |
+
<table class="form-table">
|
151 |
+
<tbody>
|
152 |
+
<?php
|
153 |
+
include_once 'options/quality.inc';
|
154 |
+
include_once 'options/metadata.inc';
|
155 |
+
include_once 'options/converters.inc';
|
156 |
+
?>
|
157 |
+
</tbody>
|
158 |
+
</table>
|
159 |
+
</fieldset>
|
160 |
+
<fieldset class="block">
|
161 |
+
<h3>Serve options</h3>
|
162 |
+
<p><i>The options here affects how the image is served after a successful / unsuccessful conversion</i></p>
|
163 |
+
<table class="form-table">
|
164 |
+
<tbody>
|
165 |
+
<?php
|
166 |
+
include_once 'options/cache-control.inc';
|
167 |
+
include_once 'options/response-on-failure.inc';
|
168 |
+
?>
|
169 |
+
</tbody>
|
170 |
+
</table>
|
171 |
+
</fieldset>
|
172 |
+
<fieldset class="block">
|
173 |
+
<h3>Web service</h3>
|
174 |
+
<table class="form-table">
|
175 |
+
<tbody>
|
176 |
+
<?php
|
177 |
+
include_once 'options/web-service.inc';
|
178 |
+
?>
|
179 |
+
</tbody>
|
180 |
+
</table>
|
181 |
+
</fieldset>
|
182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
</form>
|
184 |
</div>
|
lib/options/submit.php
CHANGED
@@ -104,9 +104,11 @@ $config = [
|
|
104 |
'cache-control-custom' => sanitize_text_field($_POST['cache-control-custom']),
|
105 |
'converters' => json_decode(wp_unslash($_POST['converters']), true), // holy moly! - https://stackoverflow.com/questions/2496455/why-are-post-variables-getting-escaped-in-php
|
106 |
'fail' => sanitize_text_field($_POST['fail']),
|
107 |
-
'forward-query-string' => true,
|
108 |
'image-types' => sanitize_text_field($_POST['image-types']),
|
109 |
'metadata' => sanitize_text_field($_POST['metadata']),
|
|
|
|
|
|
|
110 |
'web-service' => [
|
111 |
'enabled' => isset($_POST['web-service-enabled']),
|
112 |
'whitelist' => json_decode(wp_unslash($_POST['whitelist']), true)
|
104 |
'cache-control-custom' => sanitize_text_field($_POST['cache-control-custom']),
|
105 |
'converters' => json_decode(wp_unslash($_POST['converters']), true), // holy moly! - https://stackoverflow.com/questions/2496455/why-are-post-variables-getting-escaped-in-php
|
106 |
'fail' => sanitize_text_field($_POST['fail']),
|
|
|
107 |
'image-types' => sanitize_text_field($_POST['image-types']),
|
108 |
'metadata' => sanitize_text_field($_POST['metadata']),
|
109 |
+
'forward-query-string' => true,
|
110 |
+
'do-not-pass-source-in-query-string' => isset($_POST['do-not-pass-source-in-query-string']),
|
111 |
+
'redirect-to-existing-in-htaccess' => isset($_POST['redirect-to-existing-in-htaccess']),
|
112 |
'web-service' => [
|
113 |
'enabled' => isset($_POST['web-service-enabled']),
|
114 |
'whitelist' => json_decode(wp_unslash($_POST['whitelist']), true)
|
web-service/.htaccess
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<FilesMatch "wpc\.php$">
|
2 |
+
<IfModule !mod_authz_core.c>
|
3 |
+
Order deny,allow
|
4 |
+
Allow from all
|
5 |
+
</IfModule>
|
6 |
+
<IfModule mod_authz_core.c>
|
7 |
+
Require all granted
|
8 |
+
</IfModule>
|
9 |
+
</FilesMatch>
|
webp-express.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
-
* Version: 0.
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
+
* Version: 0.9.0
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|
wod/.htaccess
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<FilesMatch "webp-on-demand\.php$">
|
2 |
+
<IfModule !mod_authz_core.c>
|
3 |
+
Order deny,allow
|
4 |
+
Allow from all
|
5 |
+
</IfModule>
|
6 |
+
<IfModule mod_authz_core.c>
|
7 |
+
Require all granted
|
8 |
+
</IfModule>
|
9 |
+
</FilesMatch>
|
wod/webp-on-demand.php
CHANGED
@@ -1,4 +1,8 @@
|
|
1 |
<?php
|
|
|
|
|
|
|
|
|
2 |
|
3 |
//echo 'display errors:' . ini_get('display_errors');
|
4 |
//exit;
|
@@ -7,52 +11,93 @@
|
|
7 |
require '../vendor/rosell-dk/webp-convert/build/webp-on-demand-1.inc';
|
8 |
//require '../vendor/autoload.php';
|
9 |
|
|
|
|
|
10 |
use \WebPConvert\WebPConvert;
|
11 |
|
12 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
-
|
15 |
-
$
|
16 |
-
$
|
17 |
-
|
18 |
-
|
|
|
19 |
|
20 |
-
|
21 |
-
//echo '<pre>' . print_r($
|
22 |
-
//exit;
|
23 |
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
$converterId = $converter;
|
32 |
}
|
33 |
-
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
35 |
}
|
36 |
-
}
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
|
|
41 |
}
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
44 |
}
|
|
|
|
|
|
|
|
|
45 |
}
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
|
|
|
|
|
|
|
53 |
// Calculate destination
|
54 |
-
$
|
55 |
-
$imageRoot = $contentDirAbs . '/webp-images';
|
56 |
|
57 |
// Check if source is residing inside document root.
|
58 |
// (it is, if path starts with document root + '/')
|
@@ -75,5 +120,34 @@ if (substr($source, 0, strlen($docRoot) + 1) === $docRoot . '/') {
|
|
75 |
// If we wanted webp images to be located in same folder, with ".webp" extension:
|
76 |
// $destination = preg_replace('/\.(jpg|jpeg|png)$/', '.webp', $source);
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
|
|
79 |
WebPConvert::convertAndServe($source, $destination, $options);
|
1 |
<?php
|
2 |
+
// https://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial/#Decoding_Mod_Rewrite_Variables
|
3 |
+
|
4 |
+
ini_set('display_errors', 1);
|
5 |
+
error_reporting(E_ALL);
|
6 |
|
7 |
//echo 'display errors:' . ini_get('display_errors');
|
8 |
//exit;
|
11 |
require '../vendor/rosell-dk/webp-convert/build/webp-on-demand-1.inc';
|
12 |
//require '../vendor/autoload.php';
|
13 |
|
14 |
+
//print_r($_GET); exit;
|
15 |
+
|
16 |
use \WebPConvert\WebPConvert;
|
17 |
|
18 |
+
function loadConfig($configFilename) {
|
19 |
+
if (!file_exists($configFilename)) {
|
20 |
+
header('X-WebP-Express-Error: Configuration file not found!', true);
|
21 |
+
echo 'Configuration file not found!';
|
22 |
+
//WebPConvert::convertAndServe($source, $destination, []);
|
23 |
+
exit;
|
24 |
+
}
|
25 |
|
26 |
+
// TODO: Handle read error / json error
|
27 |
+
$handle = @fopen($configFilename, "r");
|
28 |
+
$json = fread($handle, filesize($configFilename));
|
29 |
+
fclose($handle);
|
30 |
+
return json_decode($json, true);
|
31 |
+
}
|
32 |
|
33 |
+
function getSource($allowInQS, $allowInHeader) {
|
34 |
+
//echo '<pre>' . print_r($_SERVER, true) . '</pre>'; exit;
|
|
|
35 |
|
36 |
+
// First check if it is in an environment variable - thats the safest way
|
37 |
+
foreach ($_SERVER as $key => $item) {
|
38 |
+
if (substr($key, -14) == 'REDIRECT_REQFN') {
|
39 |
+
return $item;
|
40 |
+
}
|
41 |
+
}
|
42 |
|
43 |
+
if ($allowInHeader) {
|
44 |
+
if (isset($_SERVER['HTTP_REQFN'])) {
|
45 |
+
return $_SERVER['HTTP_REQFN'];
|
46 |
+
}
|
|
|
47 |
}
|
48 |
+
|
49 |
+
if ($allowInQS) {
|
50 |
+
if (isset($_GET['source'])) {
|
51 |
+
return $_GET['source']; // No url decoding needed as $_GET is already decoded
|
52 |
+
} elseif (isset($_GET['xsource'])) {
|
53 |
+
return substr($_GET['xsource'], 1);
|
54 |
+
}
|
55 |
}
|
|
|
56 |
|
57 |
+
// Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
|
58 |
+
// correct result in all setups (ie "folder method 1")
|
59 |
+
$requestUriNoQS = explode('?', $_SERVER['REQUEST_URI'])[0];
|
60 |
+
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
61 |
+
$source = $docRoot . urldecode($requestUriNoQS);
|
62 |
+
if (file_exists($source)) {
|
63 |
+
return $source;
|
64 |
}
|
65 |
+
|
66 |
+
header('X-WebP-Express-Error: None of the available methods for locating source file works', true);
|
67 |
+
echo 'None of the available methods for locating source file works!';
|
68 |
+
if (!$allowInHeader) {
|
69 |
+
echo '<br>Have you tried allowing source to be passed as a request header?';
|
70 |
}
|
71 |
+
if (!$allowInQS) {
|
72 |
+
echo '<br>Have you tried allowing source to be passed in querystring?';
|
73 |
+
}
|
74 |
+
exit;
|
75 |
}
|
76 |
|
77 |
+
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
78 |
+
$wpContentDirRel = (isset($_GET['wp-content']) ? $_GET['wp-content'] : 'wp-content');
|
79 |
+
$webExpressContentDirRel = $wpContentDirRel . '/webp-express';
|
80 |
+
$webExpressContentDirAbs = $docRoot . '/' . $webExpressContentDirRel;
|
81 |
+
$configFilename = $webExpressContentDirAbs . '/config/wod-options.json';
|
82 |
+
|
83 |
+
$options = loadConfig($configFilename);
|
84 |
+
|
85 |
+
$allowInQS = !(isset($options['do-not-pass-source-in-query-string']) && $options['do-not-pass-source-in-query-string']);
|
86 |
+
$allowInHeader = true; // todo: implement setting
|
87 |
+
$source = getSource($allowInQS, $allowInHeader);
|
88 |
+
//$source = getSource(false, false);
|
89 |
+
|
90 |
+
if (!file_exists($source)) {
|
91 |
+
header('X-WebP-Express-Error: Source file not found!', true);
|
92 |
+
echo 'Source file not found!';
|
93 |
+
exit;
|
94 |
}
|
95 |
|
96 |
+
//echo $source; exit;
|
97 |
+
|
98 |
+
|
99 |
// Calculate destination
|
100 |
+
$imageRoot = $webExpressContentDirAbs . '/webp-images';
|
|
|
101 |
|
102 |
// Check if source is residing inside document root.
|
103 |
// (it is, if path starts with document root + '/')
|
120 |
// If we wanted webp images to be located in same folder, with ".webp" extension:
|
121 |
// $destination = preg_replace('/\.(jpg|jpeg|png)$/', '.webp', $source);
|
122 |
|
123 |
+
//echo $destination; exit;
|
124 |
+
|
125 |
+
|
126 |
+
//echo '<pre>' . print_r($options, true) . '</pre>';
|
127 |
+
//exit;
|
128 |
+
|
129 |
+
$options['require-for-conversion'] = 'webp-on-demand-2.inc';
|
130 |
+
//$options['require-for-conversion'] = '../../../autoload.php';
|
131 |
+
|
132 |
+
foreach ($options['converters'] as &$converter) {
|
133 |
+
if (isset($converter['converter'])) {
|
134 |
+
$converterId = $converter['converter'];
|
135 |
+
} else {
|
136 |
+
$converterId = $converter;
|
137 |
+
}
|
138 |
+
if ($converterId == 'cwebp') {
|
139 |
+
$converter['options']['rel-path-to-precompiled-binaries'] = '../src/Converters/Binaries';
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
if ($options['forward-query-string']) {
|
144 |
+
if (isset($_GET['debug'])) {
|
145 |
+
$options['show-report'] = true;
|
146 |
+
}
|
147 |
+
if (isset($_GET['reconvert'])) {
|
148 |
+
$options['reconvert'] = true;
|
149 |
+
}
|
150 |
+
}
|
151 |
|
152 |
+
//echo "<pre>source: $source \ndestination: $destination \n\noptions:" . print_r($options, true) . '</pre>'; exit;
|
153 |
WebPConvert::convertAndServe($source, $destination, $options);
|