WebP Express - Version 0.6.0

Version Description

This version added option for setting caching header, fixed a serious issue with Imagick, added a new converter, Gmagick, added a great deal of options to Cwebp and generally improved the interface.

  • Added option for caching
  • Fixed long standing and serious issue with Imagick converter. It no longer generates webp images in poor quality
  • Added gmagick as a new conversion method
  • WebPExpress now runs on newly released WebP-Convert 1.2.0
  • Added many new options for cwebp
  • You can now quickly see converter status by hovering over a converter
  • You can now choose between having quality auto-detected or not (if the server supports detecting quality).
  • If the server does not support detecting quality, the WPC converter will display a quality "auto" option
  • Added special intro message for those who has no working conversion methods
  • Added help texts for options
  • Settings are now saved, when changing converter options. Too many times, I found myself forgetting to save...

For more info, see the closed issues on the 0.6.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.6.0

=

Download this release

Release Info

Developer rosell.dk
Plugin Icon 128x128 WebP Express
Version 0.6.0
Comparing to
See all releases

Code changes from version 0.5.0 to 0.6.0

.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ composer.lock
2
+ composer.phar
3
+ /vendor
README.md CHANGED
@@ -2,16 +2,18 @@
2
3
Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library, galleries, theme images etc).
4
5
## Description
6
7
This plugin let's you take advantage of the WebP image format with only a little effort. Install, configure, test, forget - and enjoy the increased performance of your website.
8
9
The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
10
11
- The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) and some of the ecosystem around it: [WebPConvertAndServe](https://github.com/rosell-dk/webp-convert-and-serve) and [WebPOnDemand](https://github.com/rosell-dk/webp-on-demand)
12
13
#### Benefits
14
- - Much faster load time on images in Chrome browsers. The converted images are typically less than half the size (for jpeg), while maintaining the same quality. Bear in mind that images typically are responsible for most of the bandwidth usage.
15
- Better user experience (whether performance goes from terrible to bad, or from good to impressive, it is a benefit)
16
- Better ranking in Google searches (performance is taken into account by Google)
17
- Less bandwidth consumption - makes a difference when abroad and in the parts of the world with slow and expensive internet connections.
@@ -47,20 +49,20 @@ Note that the plugin does not change any HTML. In the HTML the image src is stil
47
- Reload the page
48
- Find a jpeg or png image in the list. In the "type" column, it should say "webp"
49
50
- In order to test that the image is not being reconverted every time, look at the Response headers of the image. There should be a "X-WebP-On-Demand" header. It should say "Converting image (handed over to WebPConvertAndServe)" the first time, but "Serving existing converted image" on subsequent requests (WebP-Express is based upon [WebP On Demand](https://github.com/rosell-dk/webp-on-demand)). When routed to image converter, there should also be some headers beginning with "X-WebP-Convert-And-Serve", which reveals information about the conversion.
51
52
- You can also append `?debug` after any image url, in order to run a conversion, and see the conversion report. Btw: If you append `?reconvert` after an image url, you will force a reconversion of the image.
53
54
### Notes
55
56
*Note:*
57
- The redirect rules created in *.htaccess* are pointing to the WebP on demand script. If you happen to change the url path of your plugins, the rules will have to be updated. The *.htaccess* also passes the path to wp-content (relative to document root) to the script, so the script knows where to find its configuration and where to store converted images. So again, if you move the wp-content folder, or perhaps moves Wordpress to a subfolder, the rules will have to be updated. As moving these things around is is a rare situation, WebP Express are not using any resources monitoring this. However, it will do the check when you visit the settings page.
58
59
*Note:*
60
Do not simply remove the plugin without deactivating it first. Deactivation takes care of removing the rules in the *.htaccess* file. With the rules there, but converter gone, your Google Chrome visitors will not see any jpeg images.
61
62
*Note:*
63
- The plugin has not been tested in multisite configurations. It's on the roadmap!
64
65
66
## Limitations
@@ -71,8 +73,8 @@ The plugin has not been tested in multisite configurations. It's on the roadmap!
71
72
## Frequently Asked Questions
73
74
- ### How do I set the WebP quality?
75
- You don't. The plugin will try to detect the quality of the source file, and use same quality as that. You do however have an option to select a maximum quality - usefull, because there is seldom any need for a quality above 85 on ordinary web content. In case quality of the source file cannot be determined (that feature requires that Imagick or GraphicsMagick is installed), it will be set to 80.
76
77
### How do I make this work with a CDN?
78
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.
@@ -82,28 +84,22 @@ The plugin takes care of setting the "Vary" HTTP header to "Accept" when routing
82
### How do I donate?
83
Putting this question in the "frequently" asked questions section is of course some mixture of humour, sarcasm and wishful thinking. In case there really is someone out there wanting to donate, you can simply write to me, and we can arrange. My contact information is available here https://www.bitwise-it.dk/contact. I have paypal and of course an ordinary bank account.
84
85
- ## Changes in 0.5.0
86
- This version works on many more setups than the previous. Also uses less resources and handles when images are changed.
87
-
88
- * Configuration is now stored in a separate configuration file instead of storing directly in the *.htaccess* file and passing it on via query string. When updating, these settings are migrated automatically.
89
- * Handles setups where Wordpress has been given its own directory (both methods mentioned [here](https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory))
90
- * Handles setups where *wp-content* has been moved, even out of Wordpress root.
91
- * Handles setups where Uploads folder has been moved, even out of *wp-content*.
92
- * Handles setups where Plugins folder has been moved, even out of *wp-content* or out of Wordpress root
93
- * Is not as likely to be subject to firewalls blocking requests (in 0.4.0, we passed all options in a querystring, and that could trigger firewalls under some circumstances)
94
- * Is not as likely to be subject to rewrite rules from other plugins interfering. WebP Express now stores the .htaccess in the wp-content folder (if you allow it). As this is deeper than the root folder, the rules in here takes precedence over rules in the main *.htaccess*
95
- * The *.htaccess* now passes the complete absulute path to the source file instead of a relative path. This is a less error-prone method.
96
- * Reconverts the webp, if source image has changed
97
- * Now runs on version 1.0.0 of [WebP On Demand](https://github.com/rosell-dk/webp-on-demand). Previously ran on 0.3.0
98
- * Now takes care of only loading the PHP classes when needed in order not to slow down your Wordpress. The frontend will only need to process four lines of code. The backend footprint is also quite small now (80 lines of code of hooks)
99
- * Now works in Wordpress 4.0 - 4.6.
100
- * Added cache-breaking tokens to image test links
101
- * Denies deactivation if rewrite rules could not be removed
102
- * Refactored thoroughly
103
- * More helpful texts.
104
- * Extensive testing. Tested on Wordpress 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8 and 4.9. Tested with PHP 5.6, PHP 7.0 and PHP 7.1. Tested on Apache and LiteSpeed. Tested when missing various write permissions. Tested migration. Tested when installed in root, in subfolder, when Wordpress has its own directory (both methods), when wp-content is moved out of Wordpress directory, when plugins is moved out of Wordpress directory, when both of them are moved and when uploads have been moved.
105
-
106
- For more info, see the closed issues on the 0.5.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/milestone/2?closed=1
107
108
# Roadmap
109
2
3
Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library, galleries, theme images etc).
4
5
+ The plugin is available on the Wordpress codex ([here](https://wordpress.org/plugins/webp-express/)), and developed on github ([here](https://github.com/rosell-dk/webp-express/)).
6
+
7
## Description
8
9
This plugin let's you take advantage of the WebP image format with only a little effort. Install, configure, test, forget - and enjoy the increased performance of your website.
10
11
The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
12
13
+ The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) and its "WebP On Demand" solution described [here](https://github.com/rosell-dk/webp-convert/blob/master/docs/webp-on-demand/webp-on-demand.md)
14
15
#### Benefits
16
+ - Much faster load time for images in blink based browsers such as Chrome and Opera (accounting for ~73% of all traffic, according to [caniuse.com](https://caniuse.com/webp)). The converted images are typically *less than half the size* (for jpeg), while maintaining the same quality. Bear in mind that for most web sites, images are responsible for the largest part of the waiting time.
17
- Better user experience (whether performance goes from terrible to bad, or from good to impressive, it is a benefit)
18
- Better ranking in Google searches (performance is taken into account by Google)
19
- Less bandwidth consumption - makes a difference when abroad and in the parts of the world with slow and expensive internet connections.
49
- Reload the page
50
- Find a jpeg or png image in the list. In the "type" column, it should say "webp"
51
52
+ In order to test that the image is not being reconverted every time, look at the Response headers of the image. There should be a "X-WebP-Convert-Status" header. It should say "Serving existing converted image" the first time, but "Serving existing converted image" on subsequent requests (WebP-Express is based upon [WebP Convert](https://github.com/rosell-dk/webp-convert)).
53
54
+ You can also append `?debug` after any image url, in order to run a conversion, and see the conversion report. Also, if you append `?reconvert` after an image url, you will force a reconversion of the image.
55
56
### Notes
57
58
*Note:*
59
+ The redirect rules created in *.htaccess* are pointing to a PHP script. If you happen to change the url path of your plugins, the rules will have to be updated. The *.htaccess* also passes the path to wp-content (relative to document root) to the script, so the script knows where to find its configuration and where to store converted images. So again, if you move the wp-content folder, or perhaps moves Wordpress to a subfolder, the rules will have to be updated. As moving these things around is is a rare situation, WebP Express are not using any resources monitoring this. However, it will do the check when you visit the settings page.
60
61
*Note:*
62
Do not simply remove the plugin without deactivating it first. Deactivation takes care of removing the rules in the *.htaccess* file. With the rules there, but converter gone, your Google Chrome visitors will not see any jpeg images.
63
64
*Note:*
65
+ The plugin has not been tested in multisite configurations. It's on the roadmap...
66
67
68
## Limitations
73
74
## Frequently Asked Questions
75
76
+ ### Why do I not see the option to set WebP quality to auto?
77
+ 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*
78
79
### How do I make this work with a CDN?
80
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.
84
### How do I donate?
85
Putting this question in the "frequently" asked questions section is of course some mixture of humour, sarcasm and wishful thinking. In case there really is someone out there wanting to donate, you can simply write to me, and we can arrange. My contact information is available here https://www.bitwise-it.dk/contact. I have paypal and of course an ordinary bank account.
86
87
+ ## Changes in 0.6.0
88
+ This version added option for setting caching header, fixed a serious issue with *Imagick*, added a new converter, *Gmagick*, added a great deal of options to *Cwebp* and generally improved the interface.
89
+
90
+ * Added option for caching
91
+ * Fixed long standing and serious issue with Imagick converter. It no longer generates webp images in poor quality
92
+ * Added gmagick as a new conversion method
93
+ * WebPExpress now runs on newly released WebP-Convert 1.2.0
94
+ * Added many new options for *cwebp*
95
+ * You can now quickly see converter status by hovering over a converter
96
+ * You can now choose between having quality auto-detected or not (if the server supports detecting quality).
97
+ * If the server does not support detecting quality, the WPC converter will display a quality "auto" option
98
+ * Added special intro message for those who has no working conversion methods
99
+ * Added help texts for options
100
+ * Settings are now saved, when changing converter options. Too many times, I found myself forgetting to save...
101
+
102
+ For more info, see the closed issues on the 0.6.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.6.0
103
104
# Roadmap
105
README.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.bitwise-it.dk/contact
4
Tags: webp, images, performance
5
Requires at least: 4.0
6
Tested up to: 4.9
7
- Stable tag: 0.5.0
8
Requires PHP: 5.6
9
License: GPLv3
10
License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -17,10 +17,10 @@ This plugin let's you take advantage of the WebP image format with only a little
17
18
The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
19
20
- The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) and some of the ecosystem around it: [WebPConvertAndServe](https://github.com/rosell-dk/webp-convert-and-serve) and [WebPOnDemand](https://github.com/rosell-dk/webp-on-demand)
21
22
#### Benefits
23
- - Much faster load time on images in Chrome browsers. The converted images are typically less than half the size (for jpeg), while maintaining the same quality. Bear in mind that images typically are responsible for most of the bandwidth usage.
24
- Better user experience (whether performance goes from terrible to bad, or from good to impressive, it is a benefit)
25
- Better ranking in Google searches (performance is taken into account by Google)
26
- Less bandwidth consumption - makes a difference when abroad and in the parts of the world with slow and expensive internet connections.
@@ -57,21 +57,21 @@ Note that the plugin does not change any HTML. In the HTML the image src is stil
57
- Reload the page
58
- Find a jpeg or png image in the list. In the "type" column, it should say "webp"
59
60
- In order to test that the image is not being reconverted every time, look at the Response headers of the image. There should be a "X-WebP-On-Demand" header. It should say "Converting image (handed over to WebPConvertAndServe)" the first time, but "Serving existing converted image" on subsequent requests (WebP-Express is based upon [WebP On Demand](https://github.com/rosell-dk/webp-on-demand)). When routed to image converter, there should also be some headers beginning with "X-WebP-Convert-And-Serve", which reveals information about the conversion.
61
62
You can also append ?debug after any image url, in order to run a conversion, and see the conversion report.
63
- Btw: If you append ?reconvert after an image url, you will force a reconversion of the image.
64
65
### Notes
66
67
*Note:*
68
- The redirect rules created in *.htaccess* are pointing to the WebP on demand script. If you happen to change the url path of your plugins, the rules will have to be updated. The *.htaccess* also passes the path to wp-content (relative to document root) to the script, so the script knows where to find its configuration and where to store converted images. So again, if you move the wp-content folder, or perhaps moves Wordpress to a subfolder, the rules will have to be updated. As moving these things around is is a rare situation, WebP Express are not using any resources monitoring this. However, it will do the check when you visit the settings page.
69
70
*Note:*
71
Do not simply remove the plugin without deactivating it first. Deactivation takes care of removing the rules in the *.htaccess* file. With the rules there, but converter gone, your Google Chrome visitors will not see any jpeg images.
72
73
*Note:*
74
- The plugin has not been tested in multisite configurations. It's on the roadmap!
75
76
== Limitations ==
77
@@ -81,8 +81,8 @@ The plugin has not been tested in multisite configurations. It's on the roadmap!
81
82
== Frequently Asked Questions ==
83
84
- = How do I set the WebP quality? =
85
- You don't. The plugin will try to detect the quality of the source file, and use same quality as that. You do however have an option to select a maximum quality - usefull, because there is seldom any need for a quality above 85 on ordinary web content. In case quality of the source file cannot be determined (that feature requires that Imagick or GraphicsMagick is installed), it will be set to 80.
86
87
= How do I make this work with a CDN? =
88
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.
@@ -100,33 +100,27 @@ Putting this question in the "frequently" asked questions section is of course s
100
101
== Changelog ==
102
103
- = 0.5.0 =
104
- This version works on many more setups than the previous. Also uses less resources and handles when images are changed.
105
-
106
- * Configuration is now stored in a separate configuration file instead of storing directly in the *.htaccess* file and passing it on via query string. When updating, these settings are migrated automatically.
107
- * Handles setups where Wordpress has been given its own directory (both methods mentioned [here](https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory))
108
- * Handles setups where *wp-content* has been moved, even out of Wordpress root.
109
- * Handles setups where Uploads folder has been moved, even out of *wp-content*.
110
- * Handles setups where Plugins folder has been moved, even out of *wp-content* or out of Wordpress root
111
- * Is not as likely to be subject to firewalls blocking requests (in 0.4.0, we passed all options in a querystring, and that could trigger firewalls under some circumstances)
112
- * Is not as likely to be subject to rewrite rules from other plugins interfering. WebP Express now stores the .htaccess in the wp-content folder (if you allow it). As this is deeper than the root folder, the rules in here takes precedence over rules in the main *.htaccess*
113
- * The *.htaccess* now passes the complete absulute path to the source file instead of a relative path. This is a less error-prone method.
114
- * Reconverts the webp, if source image has changed
115
- * Now runs on version 1.0.0 of [WebP On Demand](https://github.com/rosell-dk/webp-on-demand). Previously ran on 0.3.0
116
- * Now takes care of only loading the PHP classes when needed in order not to slow down your Wordpress. The frontend will only need to process four lines of code. The backend footprint is also quite small now (80 lines of code of hooks)
117
- * Now works in Wordpress 4.0 - 4.6.
118
- * Added cache-breaking tokens to image test links
119
- * Denies deactivation if rewrite rules could not be removed
120
- * Refactored thoroughly
121
- * More helpful texts.
122
- * Extensive testing. Tested on Wordpress 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8 and 4.9. Tested with PHP 5.6, PHP 7.0 and PHP 7.1. Tested on Apache and LiteSpeed. Tested when missing various write permissions. Tested migration. Tested when installed in root, in subfolder, when Wordpress has its own directory (both methods), when wp-content is moved out of Wordpress directory, when plugins is moved out of Wordpress directory, when both of them are moved and when uploads have been moved.
123
-
124
- For more info, see the closed issues on the 0.5.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/milestone/2?closed=1
125
126
== Upgrade Notice ==
127
128
- = 0.5.0 =
129
- This version is a leap forward regarding stability. Also uses less resources and handles when images are changed.
130
131
== Roadmap ==
132
4
Tags: webp, images, performance
5
Requires at least: 4.0
6
Tested up to: 4.9
7
+ Stable tag: 0.6.0
8
Requires PHP: 5.6
9
License: GPLv3
10
License URI: https://www.gnu.org/licenses/gpl-3.0.html
17
18
The plugin basically routes jpeg/png images to an image converter, or - if the image converter has already converted the image - directly to a converted image. The approach has the benefit that is works regardless of how an image found its way into your server - be it Media Library, Galleries, or even theme images referenced with CSS.
19
20
+ The plugin builds on [WebPConvert](https://github.com/rosell-dk/webp-convert) and its "WebP On Demand" solution described [here](https://github.com/rosell-dk/webp-convert/blob/master/docs/webp-on-demand/webp-on-demand.md)
21
22
#### Benefits
23
+ - Much faster load time for images in blink based browsers such as Chrome and Opera (accounting for ~73% of all traffic, according to [caniuse.com](https://caniuse.com/webp)). The converted images are typically *less than half the size* (for jpeg), while maintaining the same quality. Bear in mind that for most web sites, images are responsible for the largest part of the waiting time.
24
- Better user experience (whether performance goes from terrible to bad, or from good to impressive, it is a benefit)
25
- Better ranking in Google searches (performance is taken into account by Google)
26
- Less bandwidth consumption - makes a difference when abroad and in the parts of the world with slow and expensive internet connections.
57
- Reload the page
58
- Find a jpeg or png image in the list. In the "type" column, it should say "webp"
59
60
+ In order to test that the image is not being reconverted every time, look at the Response headers of the image. There should be a "X-WebP-Convert-Status" header. It should say "Serving existing converted image" the first time, but "Serving existing converted image" on subsequent requests (WebP-Express is based upon [WebP Convert](https://github.com/rosell-dk/webp-convert)).
61
62
You can also append ?debug after any image url, in order to run a conversion, and see the conversion report.
63
+ Also, you append ?reconvert after an image url, you will force a reconversion of the image.
64
65
### Notes
66
67
*Note:*
68
+ The redirect rules created in *.htaccess* are pointing to a PHP script. If you happen to change the url path of your plugins, the rules will have to be updated. The *.htaccess* also passes the path to wp-content (relative to document root) to the script, so the script knows where to find its configuration and where to store converted images. So again, if you move the wp-content folder, or perhaps moves Wordpress to a subfolder, the rules will have to be updated. As moving these things around is is a rare situation, WebP Express are not using any resources monitoring this. However, it will do the check when you visit the settings page.
69
70
*Note:*
71
Do not simply remove the plugin without deactivating it first. Deactivation takes care of removing the rules in the *.htaccess* file. With the rules there, but converter gone, your Google Chrome visitors will not see any jpeg images.
72
73
*Note:*
74
+ The plugin has not been tested in multisite configurations. It's on the roadmap...
75
76
== Limitations ==
77
81
82
== Frequently Asked Questions ==
83
84
+ = Why do I not see the option to set WebP quality to auto? =
85
+ 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*
86
87
= How do I make this work with a CDN? =
88
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.
100
101
== Changelog ==
102
103
+ = 0.6.0 =
104
+ This version added option for setting caching header, fixed a serious issue with *Imagick*, added a new converter, *Gmagick*, added a great deal of options to *Cwebp* and generally improved the interface.
105
+
106
+ * Added option for caching
107
+ * Fixed long standing and serious issue with Imagick converter. It no longer generates webp images in poor quality
108
+ * Added gmagick as a new conversion method
109
+ * WebPExpress now runs on newly released WebP-Convert 1.2.0
110
+ * Added many new options for *cwebp*
111
+ * You can now quickly see converter status by hovering over a converter
112
+ * You can now choose between having quality auto-detected or not (if the server supports detecting quality).
113
+ * If the server does not support detecting quality, the WPC converter will display a quality "auto" option
114
+ * Added special intro message for those who has no working conversion methods
115
+ * Added help texts for options
116
+ * Settings are now saved, when changing converter options. Too many times, I found myself forgetting to save...
117
+
118
+ For more info, see the closed issues on the 0.6.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/issues?q=is%3Aclosed+milestone%3A0.6.0
119
120
== Upgrade Notice ==
121
122
+ = 0.6.0 =
123
+ Adding caching option, fixed imagick converter, added gmagick converter and more!
124
125
== Roadmap ==
126
changelog.txt CHANGED
@@ -1,3 +1,26 @@
1
= 0.4.0 =
2
This version fixes some misbehaviours and provides new http headers with info about the conversion process.
3
@@ -7,6 +30,7 @@ This version fixes some misbehaviours and provides new http headers with info ab
7
* WebPExpress options are now removed when plugin is uninstalled.
8
* No longer generates .htaccess rules on install. The user now has to actively go to Web Express setting and save first
9
* Added a "first time" message on options page and a reactivation message
10
For more info, see the closed issues on the github repository: https://github.com/rosell-dk/webp-express/milestone/1?closed=1
11
12
= 0.3.1 =
1
+ = 0.5.0 =
2
+ This version works on many more setups than the previous. Also uses less resources and handles when images are changed.
3
+
4
+ * Configuration is now stored in a separate configuration file instead of storing directly in the *.htaccess* file and passing it on via query string. When updating, these settings are migrated automatically.
5
+ * Handles setups where Wordpress has been given its own directory (both methods mentioned [here](https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory))
6
+ * Handles setups where *wp-content* has been moved, even out of Wordpress root.
7
+ * Handles setups where Uploads folder has been moved, even out of *wp-content*.
8
+ * Handles setups where Plugins folder has been moved, even out of *wp-content* or out of Wordpress root
9
+ * Is not as likely to be subject to firewalls blocking requests (in 0.4.0, we passed all options in a querystring, and that could trigger firewalls under some circumstances)
10
+ * Is not as likely to be subject to rewrite rules from other plugins interfering. WebP Express now stores the .htaccess in the wp-content folder (if you allow it). As this is deeper than the root folder, the rules in here takes precedence over rules in the main *.htaccess*
11
+ * The *.htaccess* now passes the complete absulute path to the source file instead of a relative path. This is a less error-prone method.
12
+ * Reconverts the webp, if source image has changed
13
+ * Now runs on version 1.0.0 of [WebP On Demand](https://github.com/rosell-dk/webp-on-demand). Previously ran on 0.3.0
14
+ * Now takes care of only loading the PHP classes when needed in order not to slow down your Wordpress. The frontend will only need to process four lines of code. The backend footprint is also quite small now (80 lines of code of hooks)
15
+ * Now works in Wordpress 4.0 - 4.6.
16
+ * Added cache-breaking tokens to image test links
17
+ * Denies deactivation if rewrite rules could not be removed
18
+ * Refactored thoroughly
19
+ * More helpful texts.
20
+ * Extensive testing. Tested on Wordpress 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8 and 4.9. Tested with PHP 5.6, PHP 7.0 and PHP 7.1. Tested on Apache and LiteSpeed. Tested when missing various write permissions. Tested migration. Tested when installed in root, in subfolder, when Wordpress has its own directory (both methods), when wp-content is moved out of Wordpress directory, when plugins is moved out of Wordpress directory, when both of them are moved and when uploads have been moved.
21
+
22
+ For more info, see the closed issues on the 0.5.0 milestone on our github repository: https://github.com/rosell-dk/webp-express/milestone/2?closed=1
23
+
24
= 0.4.0 =
25
This version fixes some misbehaviours and provides new http headers with info about the conversion process.
26
30
* WebPExpress options are now removed when plugin is uninstalled.
31
* No longer generates .htaccess rules on install. The user now has to actively go to Web Express setting and save first
32
* Added a "first time" message on options page and a reactivation message
33
+
34
For more info, see the closed issues on the github repository: https://github.com/rosell-dk/webp-express/milestone/1?closed=1
35
36
= 0.3.1 =
composer.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "minimum-stability": "dev",
3
+ "repositories": [
4
+ {
5
+ "type": "vcs",
6
+ "url": "https://github.com/rosell-dk/webp-convert"
7
+ }
8
+ ],
9
+ "require": {
10
+ "rosell-dk/webp-convert": "dev-master"
11
+ }
12
+ }
lib/activate-first-time.php CHANGED
@@ -9,6 +9,9 @@ use \WebPExpress\Config;
9
include_once __DIR__ . '/classes/Messenger.php';
10
use \WebPExpress\Messenger;
11
12
include_once __DIR__ . '/classes/PlatformInfo.php';
13
use \WebPExpress\PlatformInfo;
14
@@ -61,5 +64,5 @@ if (PlatformInfo::isApache() || PlatformInfo::isLiteSpeed()) {
61
Messenger::addMessage(
62
'info',
63
'WebP Express was installed successfully. To start using it, you must ' .
64
- '<a href="options-general.php?page=webp_express_settings_page">configure it here</a>.'
65
);
9
include_once __DIR__ . '/classes/Messenger.php';
10
use \WebPExpress\Messenger;
11
12
+ include_once __DIR__ . '/classes/Paths.php';
13
+ use \WebPExpress\Paths;
14
+
15
include_once __DIR__ . '/classes/PlatformInfo.php';
16
use \WebPExpress\PlatformInfo;
17
64
Messenger::addMessage(
65
'info',
66
'WebP Express was installed successfully. To start using it, you must ' .
67
+ '<a href="' . Paths::getSettingsUrl() . '">configure it here</a>.'
68
);
lib/admin.php CHANGED
@@ -1,7 +1,7 @@
1
<?php
2
3
// When an update requires a migration, the number should be increased
4
- define('WEBPEXPRESS_MIGRATION_VERSION', '1');
5
6
if (WEBPEXPRESS_MIGRATION_VERSION != get_option('webp-express-migration-version', 0)) {
7
// run migration logic
1
<?php
2
3
// When an update requires a migration, the number should be increased
4
+ define('WEBPEXPRESS_MIGRATION_VERSION', '2');
5
6
if (WEBPEXPRESS_MIGRATION_VERSION != get_option('webp-express-migration-version', 0)) {
7
// run migration logic
lib/classes/Config.php CHANGED
@@ -90,18 +90,62 @@ class Config
90
$options = $config;
91
$options['converters'] = [];
92
foreach ($config['converters'] as $converter) {
93
- if (isset($converter['deactivated'])) continue;
94
95
$options['converters'][] = $converter;
96
}
97
foreach ($options['converters'] as &$c) {
98
unset ($c['id']);
99
if (!isset($c['options'])) {
100
$c = $c['converter'];
101
}
102
}
103
104
unset($options['image-types']);
105
return $options;
106
}
107
90
$options = $config;
91
$options['converters'] = [];
92
foreach ($config['converters'] as $converter) {
93
+ if (isset($converter['deactivated']) && ($converter['deactivated'])) continue;
94
95
$options['converters'][] = $converter;
96
}
97
foreach ($options['converters'] as &$c) {
98
+ if ($c['converter'] == 'cwebp') {
99
+ if (isset($c['options']['set-size']) && $c['options']['set-size']) {
100
+ unset($c['options']['set-size']);
101
+ } else {
102
+ unset($c['options']['set-size']);
103
+ unset($c['options']['size-in-percentage']);
104
+ }
105
+ }
106
unset ($c['id']);
107
+ unset($c['working']);
108
+ unset($c['error']);
109
if (!isset($c['options'])) {
110
$c = $c['converter'];
111
}
112
}
113
114
+ if (isset($options['cache-control'])) {
115
+ $cacheControl = $options['cache-control'];
116
+ $cacheControlOptions = [
117
+ 'no-header' => '',
118
+ 'one-second' => 'public, max-age=1',
119
+ 'one-minute' => 'public, max-age=60',
120
+ 'one-hour' => 'public, max-age=3600',
121
+ 'one-day' => 'public, max-age=86400',
122
+ 'one-week' => 'public, max-age=604800',
123
+ 'one-month' => 'public, max-age=2592000',
124
+ 'one-year' => 'public, max-age=31536000',
125
+ ];
126
+
127
+ if (isset($cacheControlOptions[$cacheControl])) {
128
+ $options['cache-control-header'] = $cacheControlOptions[$cacheControl];
129
+ } else {
130
+ $options['cache-control-header'] = $options['cache-control-custom'];
131
+ }
132
+ }
133
+
134
+ $auto = (isset($options['quality-auto']) && $options['quality-auto']);
135
+ $qualitySpecific = (isset($options['quality-specific']) ? $options['quality-specific'] : 70);
136
+ if ($auto) {
137
+ $options['quality'] = 'auto';
138
+ } else {
139
+ $options['quality'] = $qualitySpecific;
140
+ unset ($options['max-quality']);
141
+ }
142
+ unset($options['quality-auto']);
143
+ unset($options['quality-specific']);
144
+
145
unset($options['image-types']);
146
+ unset($options['cache-control']);
147
+ unset($options['cache-control-custom']);
148
+
149
return $options;
150
}
151
lib/classes/ConvertersHelper.php ADDED
@@ -0,0 +1,63 @@
1
+ <?php
2
+
3
+ namespace WebPExpress;
4
+
5
+ class ConvertersHelper
6
+ {
7
+ public static $defaultConverters = [
8
+ ['converter' => 'gd', 'options' => ['skip-pngs' => true]],
9
+ ['converter' => 'cwebp', 'options' => [
10
+ 'use-nice' => false,
11
+ 'try-common-system-paths' => true,
12
+ 'try-supplied-binary-for-os' => true,
13
+ 'method' => 6,
14
+ 'size-in-percentage' => 45,
15
+ 'low-memory' => false,
16
+ 'command-line-options' => '-low_memory',
17
+ ]],
18
+ ['converter' => 'imagick'],
19
+ ['converter' => 'gmagick'],
20
+ ['converter' => 'wpc', 'options' => ['quality' => 'auto']],
21
+ ['converter' => 'ewww'],
22
+ ];
23
+
24
+ public static function getDefaultConverterNames()
25
+ {
26
+ return array_column(self::$defaultConverters, 'converter');
27
+ }
28
+
29
+ public static function getConverterNames($converters)
30
+ {
31
+ return array_column(self::normalize($converters), 'converter');
32
+ }
33
+
34
+ public static function normalize($converters)
35
+ {
36
+ foreach ($converters as &$converter) {
37
+ if (!isset($converter['converter'])) {
38
+ $converter = ['converter' => $converter];
39
+ }
40
+ if (!isset($converter['options'])) {
41
+ $converter['options'] = [];
42
+ }
43
+ }
44
+ return $converters;
45
+ }
46
+
47
+ /**
48
+ * Those converters in second, but not in first will be appended to first
49
+ */
50
+ public static function mergeConverters($first, $second)
51
+ {
52
+ $namesInFirst = self::getConverterNames($first);
53
+ $second = self::normalize($second);
54
+
55
+ foreach ($second as $converter) {
56
+ if (!in_array($converter['converter'], $namesInFirst)) {
57
+ $first[] = $converter;
58
+ }
59
+ }
60
+ return $first;
61
+ }
62
+
63
+ }
lib/classes/Paths.php CHANGED
@@ -308,4 +308,18 @@ APACHE
308
];
309
}
310
311
}
308
];
309
}
310
311
+ /* Get complete url to admin (no trailing slash) */
312
+ public static function getAdminUrl()
313
+ {
314
+ if (!function_exists('get_admin_url')) {
315
+ require_once ABSPATH . 'wp-includes/link-template.php';
316
+ }
317
+ return untrailingslashit(get_admin_url());
318
+ }
319
+
320
+ public static function getSettingsUrl()
321
+ {
322
+ return self::getAdminUrl() . '/' . 'options-general.php?page=webp_express_settings_page';
323
+ }
324
+
325
}
lib/classes/TestRun.php ADDED
@@ -0,0 +1,94 @@
1
+ <?php
2
+
3
+ namespace WebPExpress;
4
+
5
+ include_once "Config.php";
6
+ use \WebPExpress\Config;
7
+
8
+ include_once __DIR__ . '/../classes/ConvertersHelper.php';
9
+ use \WebPExpress\ConvertersHelper;
10
+
11
+ include_once "Paths.php";
12
+ use \WebPExpress\Paths;
13
+
14
+ include_once "FileHelper.php";
15
+ use \WebPExpress\FileHelper;
16
+
17
+ include_once __DIR__ . '/../../vendor/autoload.php';
18
+ use \WebPConvert\Converters\ConverterHelper;
19
+
20
+ /**
21
+ *
22
+ */
23
+
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 = [];
41
+ $errors = [];
42
+
43
+ // We need wod options.
44
+ // But we cannot simply use loadWodOptions - because that would leave out the deactivated
45
+ // converters. And we need to test all converters - even the deactivated ones.
46
+ // So we load config, set "deactivated" to false, and generate Wod options from the config
47
+ $config = Config::loadConfig();
48
+ if ((!$config) || (!isset($config['converters'])) || (count($config['converters']) == 0)) {
49
+ $config = [
50
+ 'converters' => ConvertersHelper::$defaultConverters
51
+ ];
52
+ } else {
53
+ // set deactivated to false on all converters
54
+ foreach($config['converters'] as &$converter) {
55
+ $converter['deactivated'] = false;
56
+ }
57
+
58
+ // merge missing converters in
59
+ $config['converters'] = ConvertersHelper::mergeConverters($config['converters'], ConvertersHelper::$defaultConverters);
60
+ // echo '<pre>' . print_r($config, true) . '</pre>';
61
+
62
+ }
63
+
64
+ $options = Config::generateWodOptionsFromConfigObj($config);
65
+ $options['converters'] = ConvertersHelper::normalize($options['converters']);
66
+
67
+ //echo '<pre>' . print_r($options, true) . '</pre>';
68
+ foreach ($options['converters'] as $converter) {
69
+ $converterId = $converter['converter'];
70
+ try {
71
+ $converterOptions = array_merge($options, $converter['options']);
72
+ unset($converterOptions['converters']);
73
+
74
+ ConverterHelper::runConverter($converterId, $source, $destination, $converterOptions);
75
+ $workingConverters[] = $converterId;
76
+ } catch (\Exception $e) {
77
+ //echo $e->getMessage() . '<br>';
78
+ $errors[$converterId] = $e->getMessage();
79
+ }
80
+ }
81
+ //print_r($errors);
82
+ return [
83
+ 'workingConverters' => $workingConverters,
84
+ 'errors' => $errors
85
+ ];
86
+ }
87
+
88
+ public static function isLocalQualityDetectionWorking() {
89
+ $q = ConverterHelper::detectQualityOfJpg(
90
+ Paths::getWebPExpressPluginDirAbs() . '/test/small-q61.jpg'
91
+ );
92
+ return ($q === 61);
93
+ }
94
+ }
lib/migrate/migrate.php CHANGED
@@ -36,12 +36,9 @@ if (!(State::getState('configured', false))) {
36
include __DIR__ . '/migrate1.php';
37
}
38
39
- // When a new version needs a new migration, uncomment this:
40
- // (make sure to grab the option again - it might have been changed in the migration above)
41
- /*
42
if (intval(get_option('webp-express-migration-version', 0)) == 1) {
43
// run migration 2
44
include __DIR__ . '/migrate2.php';
45
}
46
- */
47
}
36
include __DIR__ . '/migrate1.php';
37
}
38
39
+ // We make sure to grab the option again - it might have been changed in the migration above
40
if (intval(get_option('webp-express-migration-version', 0)) == 1) {
41
// run migration 2
42
include __DIR__ . '/migrate2.php';
43
}
44
}
lib/migrate/migrate1.php CHANGED
@@ -111,7 +111,7 @@ function webpexpress_migrate1_migrateOptions()
111
if ($mainResult != 'failed') {
112
Messenger::addMessage(
113
'success',
114
- 'WebP Express has successfully migrated its configuration and updated the rewrite rules'
115
);
116
} else {
117
Messenger::addMessage(
@@ -119,7 +119,7 @@ function webpexpress_migrate1_migrateOptions()
119
'WebP Express has successfully migrated its configuration.' .
120
'However, WebP Express could not update the rewrite rules<br>' .
121
'You need to change some permissions. Head to the ' .
122
- '<a href="options-general.php?page=webp_express_settings_page">settings page</a> ' .
123
'and try to save the settings there (it will provide more information about the problem)'
124
);
125
}
111
if ($mainResult != 'failed') {
112
Messenger::addMessage(
113
'success',
114
+ 'WebP Express has successfully migrated its configuration and updated the rewrite rules to 0.5.0'
115
);
116
} else {
117
Messenger::addMessage(
119
'WebP Express has successfully migrated its configuration.' .
120
'However, WebP Express could not update the rewrite rules<br>' .
121
'You need to change some permissions. Head to the ' .
122
+ '<a href="' . Paths::getSettingsUrl() . '">settings page</a> ' .
123
'and try to save the settings there (it will provide more information about the problem)'
124
);
125
}
lib/migrate/migrate2.php ADDED
@@ -0,0 +1,71 @@
1
+ <?php
2
+
3
+ namespace WebPExpress;
4
+
5
+ include_once __DIR__ . '/../classes/Paths.php';
6
+ use \WebPExpress\Paths;
7
+
8
+ include_once __DIR__ . '/../classes/Messenger.php';
9
+ use \WebPExpress\Messenger;
10
+
11
+ include_once __DIR__ . '/../classes/TestRun.php';
12
+ use \WebPExpress\TestRun;
13
+
14
+ /* helper. Remove dir recursively. No warnings - fails silently
15
+ Set $removeTheDirItself to false if you want to empty the dir
16
+ */
17
+ function webpexpress_migrate2_rrmdir($dir, $removeTheDirItself = true) {
18
+ if (@is_dir($dir)) {
19
+ $objects = @scandir($dir);
20
+ foreach ($objects as $object) {
21
+ if ($object != "." && $object != "..") {
22
+ $file = $dir . "/" . $object;
23
+ if (@is_dir($file)) {
24
+ webpexpress_migrate2_rrmdir($file);
25
+ } else {
26
+ @unlink($file);
27
+ }
28
+ }
29
+ }
30
+ if ($removeTheDirItself) {
31
+ @rmdir($dir);
32
+ }
33
+ }
34
+ }
35
+
36
+ $testResult = TestRun::getConverterStatus();
37
+ if ($testResult) {
38
+ $workingConverters = $testResult['workingConverters'];
39
+ if (in_array('imagick', $workingConverters)) {
40
+ webpexpress_migrate2_rrmdir(Paths::getCacheDirAbs(), false);
41
+ Messenger::addMessage(
42
+ 'info',
43
+ 'WebP Express has emptied the image cache. In previous versions, the imagick converter ' .
44
+ 'was generating images in poor quality. This has been fixed. As your system meets the ' .
45
+ 'requirements of the imagick converter, it might be that you have been using that. So ' .
46
+ 'to be absolutely sure you do not have inferior conversions in the cache dir, it has been emptied.'
47
+ );
48
+ }
49
+ if (in_array('gmagick', $workingConverters)) {
50
+ Messenger::addMessage(
51
+ 'info',
52
+ 'Good news! WebP Express is now able to use the gmagick extension for conversion - ' .
53
+ 'and your server meets the requirements!'
54
+ );
55
+ }
56
+ if (in_array('cwebp', $workingConverters)) {
57
+ Messenger::addMessage(
58
+ 'info',
59
+ 'WebP Express added several options for the cwebp conversion method. ' .
60
+ '<a href="' . Paths::getSettingsUrl() . '">Go to the settings page to check it out</a>.'
61
+ );
62
+ }
63
+ }
64
+ Messenger::addMessage(
65
+ 'info',
66
+ 'WebP Express can now be configured to cache the webp images. You might want to ' .
67
+ '<a href="' . Paths::getSettingsUrl() . '">do that</a>.'
68
+ );
69
+
70
+
71
+ update_option('webp-express-migration-version', '2');
lib/options/css/webp-express-options-page.css CHANGED
@@ -19,45 +19,74 @@
19
padding: 0;
20
}*/
21
22
23
#converters li {
24
cursor: move;
25
- border: 1px solid #e5e5e5;
26
box-shadow: 0 1px 1px rgba(0,0,0,.04);
27
line-height: 1.4em;
28
- background-color: #fafafa;
29
- padding: 10px;
30
- max-width: 400px;
31
}
32
#converters li:hover {
33
border-color: #999;
34
- box-shadow: 0 1px 2px rgba(0,0,0,.1);
35
}
36
#converters li.deactivated,
37
#converters li.deactivated a.configure-converter,
38
- #converters li.deactivated a.test-converter {
39
- color: #aaa;
40
}
41
#converters li a {
42
cursor: pointer;
43
}
44
-
45
-
46
-
47
-
48
49
#converters li > * {
50
vertical-align: middle;
51
52
}
53
- #converters li > span {
54
display: inline-block;
55
line-height: 1;
56
}
57
- #converters li > span.text {
58
- font-size: 15px;
59
padding-left: 10px;
60
- width: 165px;
61
}
62
63
#converters li > a.btn {
@@ -75,8 +104,61 @@
75
background-color: #eee;*/
76
}
77
#converters li > a.configure-converter {
78
79
80
}
81
82
/*
@@ -90,9 +172,35 @@
90
display: inline-block;
91
}
92
93
.converter-options .info {
94
margin-bottom: 20px;
95
}
96
.converter-options button {
97
margin-top: 15px;
98
}
19
padding: 0;
20
}*/
21
22
+ @media (min-width: 782px) {
23
+ #webpexpress_settings .form-table th {
24
+ padding-top: 5px;
25
+ padding-bottom: 5px;
26
+ width: 180px;
27
+ }
28
+ #webpexpress_settings .form-table td {
29
+ padding-top: 1px;
30
+ padding-bottom: 5px;
31
+ }
32
+
33
+ }
34
35
#converters li {
36
cursor: move;
37
+ border: 1px solid grey;
38
box-shadow: 0 1px 1px rgba(0,0,0,.04);
39
line-height: 1.4em;
40
+ background-color: #fff;
41
+ padding: 10px 10px 0;
42
+ max-width: 465px;
43
+ min-height: 30px;
44
+ position: relative;
45
+ font-size: 12px;
46
}
47
#converters li:hover {
48
+ border-color: #000;
49
+ box-shadow: 0 1px 2px rgba(0,0,0,.2);
50
+ }
51
+ #converters li.deactivated {
52
+ border-color: #ccc;
53
+ background-color: #f0f0f0;
54
+ }
55
+ #converters li.deactivated:hover {
56
border-color: #999;
57
}
58
#converters li.deactivated,
59
#converters li.deactivated a.configure-converter,
60
+ #converters li.deactivated a.test-converter,
61
+ #converters li.deactivated a.activate-converter {
62
+ color: #888;
63
+ }
64
+ #converters li.not-operational {
65
+ border-style: dotted;
66
+ border-color: #666;
67
+ }
68
+ #converters li.not-operational:hover {
69
+ border-style: solid;
70
}
71
#converters li a {
72
cursor: pointer;
73
}
74
+ #converters li[data-id='gmagick'] a.configure-converter,
75
+ #converters li[data-id='imagick'] a.configure-converter {
76
+ visibility: hidden;
77
+ }
78
79
#converters li > * {
80
vertical-align: middle;
81
82
}
83
+ #converters li > div {
84
display: inline-block;
85
line-height: 1;
86
}
87
+ #converters li > .text {
88
padding-left: 10px;
89
+ width: 205px;
90
}
91
92
#converters li > a.btn {
104
background-color: #eee;*/
105
}
106
#converters li > a.configure-converter {
107
+ }
108
+ #converters li .status {
109
+ font-size: 10px;
110
+ position: absolute;
111
+ right: 14px;
112
+ bottom: 2px;
113
+ }
114
115
+ #converters li .status svg {
116
+ padding: 5px;
117
+ }
118
+ #converters li svg#status_ok {
119
+ color: #008000;
120
+ }
121
+ #converters li.deactivated svg#status_ok {
122
+ color: #99cc99;
123
+ }
124
+ #converters li svg#status_not_ok {
125
+ color: #b11010; /* 444444 */
126
+ }
127
+ #converters li.deactivated svg#status_not_ok {
128
+ color: #999999;
129
+ }
130
+
131
+
132
+ #converters li .popup,
133
+ .help .popup {
134
+ display: none;
135
+ position: absolute;
136
+ border: 1px solid #666;
137
+ z-index:2;
138
+ background-color: #ffffaa;
139
+ padding: 8px 10px;
140
+ /*left: 22px;
141
+ top: 20px;*/
142
+ margin-top: -5px;
143
+ font-size: 12px;
144
+ /*white-space: nowrap;*/
145
+ color: #000;
146
+ min-width: 150px;
147
+ font-weight: normal;
148
+ text-align: left;
149
+ max-width: 450px;
150
+ }
151
+ #converters li.operational .popup {
152
+ background-color: #80ff80;
153
+ }
154
+ /* #converters li .status:hover .popup */
155
+ #converters li:hover .status .popup,
156
+ .help:hover .popup {
157
+ display: block;
158
+ }
159
160
+ .help .popup {
161
+ min-width: 250px;
162
}
163
164
/*
172
display: inline-block;
173
}
174
175
+ .converter-options.wpc label {
176
+ min-width: 100px;
177
+ }
178
+
179
.converter-options .info {
180
margin-bottom: 20px;
181
}
182
.converter-options button {
183
margin-top: 15px;
184
}
185
+ .converter-options div {
186
+ margin-bottom: 15px;
187
+ }
188
+
189
+ .help {
190
+ text-align: center;
191
+ display: inline-block;
192
+ border-radius: 50%;
193
+ background-color: #00a0ee;
194
+ width: 16px;
195
+ height: 16px;
196
+ border: 0px solid #00a0ee;
197
+ color: white;
198
+ font-weight: bolder;
199
+ margin-left: 7px;
200
+ cursor: pointer;
201
+ font-size: 12px;
202
+ line-height: 16px;
203
+ vertical-align: top;
204
+ font-family: sans-serif;
205
+ position: relative;
206
+ }
lib/options/enqueue_scripts.php CHANGED
@@ -10,7 +10,7 @@ wp_register_script(
10
'webp-express-options-page',
11
plugins_url('js/webp-express-options-page.js', __FILE__),
12
['sortable'],
13
- '0.5.1'
14
);
15
wp_enqueue_script('webp-express-options-page');
16
@@ -25,7 +25,7 @@ wp_register_style(
25
'webp-express-options-page-css',
26
plugins_url('css/webp-express-options-page.css', __FILE__),
27
null,
28
- '0.5.1'
29
);
30
wp_enqueue_style('webp-express-options-page-css');
31
10
'webp-express-options-page',
11
plugins_url('js/webp-express-options-page.js', __FILE__),
12
['sortable'],
13
+ '0.6.0dev9'
14
);
15
wp_enqueue_script('webp-express-options-page');
16
25
'webp-express-options-page-css',
26
plugins_url('css/webp-express-options-page.css', __FILE__),
27
null,
28
+ '0.6.0dev7'
29
);
30
wp_enqueue_style('webp-express-options-page-css');
31
lib/options/js/webp-express-options-page.js CHANGED
@@ -5,59 +5,79 @@ window.convertersMap = {};
5
6
window.currentlyEditing = '';
7
8
- window.defaultConverters = [
9
- {
10
- 'converter': 'cwebp',
11
- 'options': {
12
- 'use-nice': false
13
- },
14
- },
15
- {
16
- 'converter': 'wpc',
17
- },
18
- {
19
- 'converter': 'gd',
20
- 'options': {
21
- 'skip-pngs': true
22
- },
23
- },
24
- {
25
- 'converter': 'ewww',
26
- },
27
- {
28
- 'converter': 'imagick',
29
- },
30
- ]
31
-
32
function resetToDefaultConverters() {
33
window.converters = window.defaultConverters;
34
}
35
36
- function addMissingConverters() {
37
// check if all available converters are in the array.
38
// if not - add!
39
// the double loop could be avoided with map. But arrays are so small, so not worth it
40
for (var i=0; i<window.defaultConverters.length; i++) {
41
- var checkMe = window.defaultConverters[i]['converter'];
42
var found = false;
43
for (var j=0; j<window.converters.length; j++) {
44
- if (window.converters[j]['converter'] == checkMe) {
45
found = true;
46
}
47
}
48
if (!found) {
49
window.converters.push(window.defaultConverters[i]);
50
}
51
52
}
53
}
54
function generateConverterHTML(converter) {
55
- html = '<li data-id="' + converter['id'] + '" class="' + (converter.deactivated ? 'deactivated' : '') + '">';
56
//html += '<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>';
57
// html += '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"/></svg>';
58
// html += '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#888888" 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>';
59
- html += '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><path d="M2 13.5h14V12H2v1.5zm0-4h14V8H2v1.5zM2 4v1.5h14V4H2z"/></svg>';
60
- html += '<span class="text">' + converter['id'] + '</span>';
61
html += '<a class="configure-converter btn" onclick="configureConverter(\'' + converter['id'] + '\')">configure</a>';
62
html += '<a class="test-converter btn" onclick="testConverter(\'' + converter['id'] + '\')">test</a>';
63
@@ -68,6 +88,26 @@ html += '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox=
68
html += '<a class="deactivate-converter btn" onclick=deactivateConverter(\'' + converter['id'] + '\')>deactivate</a>';
69
}
70
71
html += '</li>';
72
return html;
73
}
@@ -148,11 +188,51 @@ function setConvertersHTML() {
148
updateInputValue();
149
}
150
151
document.addEventListener('DOMContentLoaded', function() {
152
//resetToDefaultConverters();
153
- addMissingConverters();
154
setConvertersHTML();
155
156
157
//alert(sortable.toArray());
158
});
@@ -175,6 +255,10 @@ function setConverterOption(converter, optionName, value) {
175
converter['options'][optionName] = value;
176
}
177
178
function configureConverter(id) {
179
var converter = window.convertersMap[id];
180
window.currentlyEditing = id;
@@ -189,12 +273,25 @@ function configureConverter(id) {
189
document.getElementById('wpc_secret').value = getConverterOption(converter, 'secret', '');
190
document.getElementById('wpc_url_2').value = getConverterOption(converter, 'url-2', '');
191
document.getElementById('wpc_secret_2').value = getConverterOption(converter, 'secret-2', '');
192
break;
193
case 'gd':
194
document.getElementById('gd_skip_pngs').checked = getConverterOption(converter, 'skip-pngs', '');
195
break;
196
case 'cwebp':
197
document.getElementById('cwebp_use_nice').checked = getConverterOption(converter, 'use-nice', '');
198
break;
199
200
}
@@ -214,16 +311,37 @@ function updateConverterOptions() {
214
setConverterOption(converter, 'secret', document.getElementById('wpc_secret').value);
215
setConverterOption(converter, 'url-2', document.getElementById('wpc_url_2').value);
216
setConverterOption(converter, 'secret-2', document.getElementById('wpc_secret_2').value);
217
break;
218
case 'gd':
219
setConverterOption(converter, 'skip-pngs', document.getElementById('gd_skip_pngs').checked);
220
break;
221
case 'cwebp':
222
setConverterOption(converter, 'use-nice', document.getElementById('cwebp_use_nice').checked);
223
break;
224
}
225
updateInputValue();
226
tb_remove();
227
}
228
229
function testConverter(id) {
5
6
window.currentlyEditing = '';
7
8
function resetToDefaultConverters() {
9
window.converters = window.defaultConverters;
10
}
11
12
+ 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;
19
for (var j=0; j<window.converters.length; j++) {
20
+ var checkMe2 = window.converters[j]
21
+ if (checkMe2['converter'] == checkMe['converter']) {
22
found = true;
23
+
24
+ if (checkMe['options']) {
25
+ for (var optionName in checkMe['options']) {
26
+ if (checkMe['options'].hasOwnProperty(optionName)) {
27
+ if (!checkMe2['options']) {
28
+ checkMe2['options'] = [];
29
+ }
30
+ if (!checkMe2['options'].hasOwnProperty(optionName)) {
31
+ checkMe2['options'][optionName] = checkMe['options'][optionName];
32
+ }
33
+ }
34
+ }
35
+ }
36
}
37
}
38
if (!found) {
39
window.converters.push(window.defaultConverters[i]);
40
}
41
+ }
42
+ }
43
+
44
+ function addMissingOptions() {
45
+
46
+ }
47
48
+ function getConversionMethodDescription(converterId) {
49
+ var descriptions = {
50
+ 'cwebp': '<i>cwebp</i> binary',
51
+ 'wpc': 'wpc cloud converter',
52
+ 'ewww': 'ewww cloud converter',
53
+ 'gd': 'Gd extension',
54
+ 'imagick': 'Imagick extension',
55
+ 'gmagick': 'Gmagick extension',
56
+ };
57
+ if (descriptions[converterId]) {
58
+ return descriptions[converterId];
59
}
60
+ return converterId;
61
}
62
+
63
+ function htmlEscape(str) {
64
+ return str
65
+ .replace(/&/g, '&amp;')
66
+ .replace(/"/g, '&quot;')
67
+ .replace(/'/g, '&#39;')
68
+ .replace(/</g, '&lt;')
69
+ .replace(/>/g, '&gt;');
70
+ }
71
+
72
function generateConverterHTML(converter) {
73
+ html = '<li data-id="' + converter['id'] + '" class="' + (converter.deactivated ? 'deactivated' : '') + ' ' + (converter.working ? 'operational' : 'not-operational') + '">';
74
//html += '<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>';
75
// html += '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"/></svg>';
76
// html += '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#888888" 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>';
77
+ html += '<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18"><path d="M2 13.5h14V12H2v1.5zm0-4h14V8H2v1.5zM2 4v1.5h14V4H2z"/></svg>';
78
+ html += '<div class="text">';
79
+ html += getConversionMethodDescription(converter['id']);
80
+ html += '</div>';
81
html += '<a class="configure-converter btn" onclick="configureConverter(\'' + converter['id'] + '\')">configure</a>';
82
html += '<a class="test-converter btn" onclick="testConverter(\'' + converter['id'] + '\')">test</a>';
83
88
html += '<a class="deactivate-converter btn" onclick=deactivateConverter(\'' + converter['id'] + '\')>deactivate</a>';
89
}
90
91
+ html += '<div class="status">';
92
+ if (converter.working) {
93
+ html += '<svg id="status_ok" width="21" height="21" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.000000 256.000000" preserveAspectRatio="xMidYMid meet">';
94
+ html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"><path d="M1064 2545 c-406 -72 -744 -324 -927 -690 -96 -193 -127 -333 -127 -575 0 -243 33 -387 133 -585 177 -351 518 -606 907 -676 118 -22 393 -17 511 8 110 24 252 78 356 136 327 183 569 525 628 887 19 122 19 338 0 460 -81 498 -483 914 -990 1025 -101 22 -389 28 -491 10z m814 -745 c39 -27 73 -59 77 -70 9 -27 10 -25 -372 -590 -345 -510 -357 -524 -420 -512 -19 4 -98 74 -250 225 -123 121 -225 228 -228 238 -3 10 1 31 9 47 20 40 125 132 149 132 11 0 79 -59 162 -140 79 -77 146 -140 149 -140 3 0 38 48 78 108 95 143 465 678 496 720 35 46 64 42 150 -18z"/></g></svg>';
95
+ html += '<div class="popup">' + converter['id'] + ' is operational</div>';
96
+ } else {
97
+ // + converter['id'] + ' is not operational<br>';
98
+ //html += 'not operational. ';
99
+ if (converter['error']) {
100
+ html += '<svg id="status_not_ok" width="21" height="21" title="not operational" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500.000000 500.000000" preserveAspectRatio="xMidYMid meet">';
101
+ html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M2315 4800 c-479 -35 -928 -217 -1303 -527 -352 -293 -615 -702 -738 -1151 -104 -380 -104 -824 0 -1204 107 -389 302 -724 591 -1013 354 -354 785 -572 1279 -646 196 -30 476 -30 672 0 494 74 925 292 1279 646 354 354 571 784 646 1279 30 197 30 475 0 672 -75 495 -292 925 -646 1279 -289 289 -624 484 -1013 591 -228 62 -528 91 -767 74z m353 -511 c458 -50 874 -272 1170 -624 417 -497 536 -1174 308 -1763 -56 -145 -176 -367 -235 -434 -4 -4 -566 552 -1250 1236 l-1243 1243 94 60 c354 229 754 327 1156 282z m864 -3200 c-67 -59 -289 -179 -434 -235 -946 -366 -2024 172 -2322 1158 -47 155 -66 276 -73 453 -13 362 84 704 290 1023 l60 94 1243 -1243 c684 -684 1240 -1246 1236 -1250z"/></g></svg>';
102
+ html += '<div class="popup">';
103
+
104
+ html += htmlEscape(converter['error']);
105
+
106
+ html += '</div>';
107
+ }
108
+ }
109
+ html += '</div>';
110
+
111
html += '</li>';
112
return html;
113
}
188
updateInputValue();
189
}
190
191
+ function updateCacheControlCustomVisibility() {
192
+ var cacheControlValue = document.getElementById('cache_control_select').value;
193
+ var customEl = document.getElementById('cache_control_custom');
194
+ if (cacheControlValue == 'custom') {
195
+ customEl.setAttribute('type', 'text');
196
+ } else {
197
+ customEl.setAttribute('type', 'hidden');
198
+ }
199
+ }
200
+
201
+ function updateQualityVisibility() {
202
+ var qualityAutoEl = document.getElementById('quality_auto_select');
203
+ if (!qualityAutoEl) {
204
+ return;
205
+ }
206
+ var qualityAutoValue = qualityAutoEl.value;
207
+ var maxQualityRowEl = document.getElementById('max_quality_row');
208
+ var qualitySpecificRowEl = document.getElementById('quality_specific_row');
209
+
210
+ //alert(qualityAutoValue);
211
+ if (qualityAutoValue == 'auto_on') {
212
+ maxQualityRowEl.style['display'] = 'table-row';
213
+ qualitySpecificRowEl.style['display'] = 'none';
214
+ } else {
215
+ maxQualityRowEl.style['display'] = 'none';
216
+ qualitySpecificRowEl.style['display'] = 'table-row';
217
+ }
218
+
219
+ }
220
+
221
document.addEventListener('DOMContentLoaded', function() {
222
//resetToDefaultConverters();
223
+ addMissingConvertersAndOptions();
224
+ addMissingOptions();
225
setConvertersHTML();
226
+ updateCacheControlCustomVisibility();
227
+ updateQualityVisibility();
228
229
+ document.getElementById('cache_control_select').addEventListener('change', function() {
230
+ updateCacheControlCustomVisibility();
231
+ });
232
+
233
+ document.getElementById('quality_auto_select').addEventListener('change', function() {
234
+ updateQualityVisibility();
235
+ });
236
237
//alert(sortable.toArray());
238
});
255
converter['options'][optionName] = value;
256
}
257
258
+ function wpcQualityChanged() {
259
+ var q = document.getElementById('wpc_quality').value;
260
+ document.getElementById('wpc_max_quality_div').style['display'] = (q == 'auto' ? 'block' : 'none');
261
+ }
262
function configureConverter(id) {
263
var converter = window.convertersMap[id];
264
window.currentlyEditing = id;
273
document.getElementById('wpc_secret').value = getConverterOption(converter, 'secret', '');
274
document.getElementById('wpc_url_2').value = getConverterOption(converter, 'url-2', '');
275
document.getElementById('wpc_secret_2').value = getConverterOption(converter, 'secret-2', '');
276
+ var q = getConverterOption(converter, 'quality', 'not_set');
277
+ if (document.getElementById('wpc_quality')) {
278
+ document.getElementById('wpc_quality').value = q;
279
+ document.getElementById('wpc_max_quality_div').style['display'] = (q == 'auto' ? 'block' : 'none');
280
+ document.getElementById('wpc_max_quality').value = getConverterOption(converter, 'max-quality', 85);
281
+ }
282
+
283
break;
284
case 'gd':
285
document.getElementById('gd_skip_pngs').checked = getConverterOption(converter, 'skip-pngs', '');
286
break;
287
case 'cwebp':
288
document.getElementById('cwebp_use_nice').checked = getConverterOption(converter, 'use-nice', '');
289
+ document.getElementById('cwebp_method').value = getConverterOption(converter, 'method', '');
290
+ document.getElementById('cwebp_try_common_system_paths').checked = getConverterOption(converter, 'try-common-system-paths', '');
291
+ document.getElementById('cwebp_try_supplied_binary').checked = getConverterOption(converter, 'try-supplied-binary-for-os', '');
292
+ document.getElementById('cwebp_set_size').checked = getConverterOption(converter, 'set-size', '');
293
+ document.getElementById('cwebp_size_in_percentage').value = getConverterOption(converter, 'size-in-percentage', '');
294
+ document.getElementById('cwebp_command_line_options').value = getConverterOption(converter, 'command-line-options', '');
295
break;
296
297
}
311
setConverterOption(converter, 'secret', document.getElementById('wpc_secret').value);
312
setConverterOption(converter, 'url-2', document.getElementById('wpc_url_2').value);
313
setConverterOption(converter, 'secret-2', document.getElementById('wpc_secret_2').value);
314
+
315
+ if (document.getElementById('wpc_quality')) {
316
+ var q = document.getElementById('wpc_quality').value;
317
+ if (q == 'auto') {
318
+ setConverterOption(converter, 'quality', 'auto');
319
+ setConverterOption(converter, 'max-quality', document.getElementById('wpc_max_quality').value);
320
+ } else {
321
+ delete converter['options']['quality'];
322
+ delete converter['options']['max-quality'];
323
+ }
324
+ } else {
325
+ delete converter['options']['quality'];
326
+ delete converter['options']['max-quality'];
327
+ }
328
break;
329
case 'gd':
330
setConverterOption(converter, 'skip-pngs', document.getElementById('gd_skip_pngs').checked);
331
break;
332
case 'cwebp':
333
setConverterOption(converter, 'use-nice', document.getElementById('cwebp_use_nice').checked);
334
+ setConverterOption(converter, 'method', document.getElementById('cwebp_method').value);
335
+ setConverterOption(converter, 'try-common-system-paths', document.getElementById('cwebp_try_common_system_paths').checked);
336
+ setConverterOption(converter, 'try-supplied-binary-for-os', document.getElementById('cwebp_try_supplied_binary').checked);
337
+ setConverterOption(converter, 'set-size', document.getElementById('cwebp_set_size').checked);
338
+ setConverterOption(converter, 'size-in-percentage', document.getElementById('cwebp_size_in_percentage').value);
339
+ setConverterOption(converter, 'command-line-options', document.getElementById('cwebp_command_line_options').value);
340
break;
341
}
342
updateInputValue();
343
tb_remove();
344
+ document.getElementById('webpexpress_settings').submit();
345
}
346
347
function testConverter(id) {
lib/options/options-hooks.php CHANGED
@@ -17,7 +17,7 @@ add_action('admin_post_webpexpress_settings_submit', function() {
17
});
18
19
global $pagenow;
20
- if (($pagenow == 'options-general.php') && ($_GET['page'] == 'webp_express_settings_page')) {
21
add_action('admin_enqueue_scripts', function () {
22
include __DIR__ . '/enqueue_scripts.php';
23
});
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
});
lib/options/page-messages.php CHANGED
@@ -8,6 +8,8 @@ use \WebPExpress\Messenger;
8
use \WebPExpress\PlatformInfo;
9
use \WebPExpress\FileHelper;
10
11
if ((!State::getState('configured', false))) {
12
include __DIR__ . "/page-welcome.php";
13
}
8
use \WebPExpress\PlatformInfo;
9
use \WebPExpress\FileHelper;
10
11
+ //include __DIR__ . "/page-welcome.php";
12
+
13
if ((!State::getState('configured', false))) {
14
include __DIR__ . "/page-welcome.php";
15
}
lib/options/page-welcome.php CHANGED
@@ -5,7 +5,7 @@ use \WebPExpress\Config;
5
use \WebPExpress\State;
6
use \WebPExpress\Messenger;
7
use \WebPExpress\PlatformInfo;
8
- use \WebPExpress\FileHelper;
9
10
$indexDir = Paths::getIndexDirAbs();
11
$homeDir = Paths::getHomeDirAbs();
@@ -13,12 +13,38 @@ $wpContentDir = Paths::getWPContentDirAbs();
13
$pluginDir = Paths::getPluginDirAbs();
14
$uploadDir = Paths::getUploadDirAbs();
15
16
- echo '<div style="background-color: #cfc; padding: 20px; border: 1px solid #ccc; color: black">';
17
echo '<h3>Welcome!</h3>';
18
- echo '<p>The rewrite rules are not active yet. They will be activated the first time you click the "Save settings" button.</p>';
19
- echo '<p>Before you do that, I suggest you find out which converters that works. Start from the top. Click "test" next to a converter to test it. Try also clicking the "configure" buttons</p>';
20
21
22
if (Paths::isWPContentDirMovedOutOfAbsPath()) {
23
if (!Paths::canWriteHTAccessRulesHere($wpContentDir)) {
24
echo '<p><b>Oh, one more thing</b>. Unless you are going to put the rewrite rules into your configuration manually, ';
@@ -104,7 +130,7 @@ if (Paths::isWPContentDirMovedOutOfAbsPath()) {
104
}
105
}
106
}
107
-
108
/*
109
if(Paths::canWriteHTAccessRulesHere($wpContentDir)) {
110
5
use \WebPExpress\State;
6
use \WebPExpress\Messenger;
7
use \WebPExpress\PlatformInfo;
8
+
9
10
$indexDir = Paths::getIndexDirAbs();
11
$homeDir = Paths::getHomeDirAbs();
13
$pluginDir = Paths::getPluginDirAbs();
14
$uploadDir = Paths::getUploadDirAbs();
15
16
+ $weKnowThereAreNoWorkingConverters = false;
17
+ if ($testResult !== false) {
18
+ $workingConverters = $testResult['workingConverters'];
19
+ $weKnowThereAreNoWorkingConverters = (count($workingConverters) == 0);
20
+ }
21
+ $bgColor = ($weKnowThereAreNoWorkingConverters ? '#fff' : '#cfc');
22
+ echo '<div style="background-color: ' . $bgColor . '; padding: 10px 20px; border: 1px solid #ccc; color: black; margin-top:15px">';
23
echo '<h3>Welcome!</h3>';
24
25
+ //if ($localQualityDetectionWorking) {
26
+ //echo 'Local quality detection working :)';
27
+ //}
28
+
29
+ if ($weKnowThereAreNoWorkingConverters) {
30
+ echo '<p>Unfortunately none of the local conversion methods are available on your server. ' .
31
+ 'but do not despear! - You have options!' .
32
+ '<ol style="list-style-position:outside">' .
33
+ '<li>You can purchase a key for the <a target="_blank" href="https://ewww.io/plans/">ewww cloud converter</a>. They do not charge credits for webp conversions, so all you ever have to pay is the one dollar start-up fee :)</li>' .
34
+ '<li>You can set up a <a target="_blank" href="https://github.com/rosell-dk/webp-convert-cloud-service">webp-convert-cloud-service</a> on another server and connect to that. Its open source.</li>' .
35
+ '<li>You can try to meet the server requirements of cwebp, gd, imagick or gmagick. Check out <a target="_blank" href="https://github.com/rosell-dk/webp-convert/wiki/Meeting-the-requirements-of-the-converters">this wiki page</a> on how to do that</li>' .
36
+ '</ol></p>' .
37
+ "<p>Btw, don't worry, your images still works. The rewrite rules will not be saved until you click the " .
38
+ '"Save settings" button (and you also have "Response on failure" set to "Original image", so they will work even if you click save)</p>';
39
+ } else {
40
+ echo '<p>The rewrite rules are not active yet. They will be activated the first time you click the "Save settings" button.</p>';
41
+ }
42
+ //echo 'working converters:';
43
+ //print_r($workingConverters);
44
+
45
+ //echo '<p>Before you do that, I suggest you find out which converters that works. Start from the top. Click "test" next to a converter to test it. Try also clicking the "configure" buttons</p>';
46
47
+ /*
48
if (Paths::isWPContentDirMovedOutOfAbsPath()) {
49
if (!Paths::canWriteHTAccessRulesHere($wpContentDir)) {
50
echo '<p><b>Oh, one more thing</b>. Unless you are going to put the rewrite rules into your configuration manually, ';
130
}
131
}
132
}
133
+ */
134
/*
135
if(Paths::canWriteHTAccessRulesHere($wpContentDir)) {
136
lib/options/page.php CHANGED
@@ -3,6 +3,9 @@
3
include_once __DIR__ . '/../classes/Config.php';
4
use \WebPExpress\Config;
5
6
include_once __DIR__ . '/../classes/FileHelper.php';
7
use \WebPExpress\FileHelper;
8
@@ -21,6 +24,8 @@ use \WebPExpress\PlatformInfo;
21
include_once __DIR__ . '/../classes/State.php';
22
use \WebPExpress\State;
23
24
25
if (!current_user_can('manage_options')) {
26
wp_die('You do not have sufficient permissions to access this page.');
@@ -30,6 +35,25 @@ if (!current_user_can('manage_options')) {
30
<h2>WebP Express Settings</h2>
31
32
<?php
33
include __DIR__ . "/page-messages.php";
34
35
/*
@@ -40,38 +64,132 @@ foreach (Paths::getHTAccessDirs() as $dir) {
40
41
42
$defaultConfig = [
43
- 'image-types' => 1,
44
'fail' => 'original',
45
'max-quality' => 80,
46
- 'converters' => [],
47
- 'forward-query-string' => true
48
];
49
50
$config = Config::loadConfig();
51
if (!$config) {
52
$config = [];
53
}
54
55
$config = array_merge($defaultConfig, $config);
56
if ($config['converters'] == null) {
57
$config['converters'] = [];
58
}
59
60
// Generate a custom nonce value.
61
$webpexpress_settings_nonce = wp_create_nonce('webpexpress_settings_nonce');
62
63
- echo '<form action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" method="post" id="webpexpress_settings" >';
64
?>
65
<input type="hidden" name="action" value="webpexpress_settings_submit">
66
<input type="hidden" name="webpexpress_settings_nonce" value="<?php echo $webpexpress_settings_nonce ?>" />
67
68
<?php
69
70
echo '<table class="form-table"><tbody>';
71
72
// Image types
73
// ------------
74
- echo '<tr><th scope="row">Image types to convert</th><td>';
75
76
// bitmask
77
// 1: JPEGs
@@ -89,9 +207,115 @@ echo '</select>';
89
90
echo '</td></tr>';
91
92
// Response on failure
93
// --------------------
94
- echo '<tr><th scope="row">Response on failure</th><td>';
95
96
//$fail = get_option('webp_express_failure_response');
97
$fail = $config['fail'];
@@ -104,18 +328,6 @@ echo '</select>';
104
echo '</td></tr>';
105
// 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>';
106
107
- // Max quality
108
- // --------------------
109
- //$maxQuality = get_option('webp_express_max_quality');
110
- $maxQuality = $config['max-quality'];
111
-
112
- echo '<tr><th scope="row">Max quality (0-100)</th><td>';
113
- echo '<input type="text" name="max-quality" value="' . $maxQuality . '">';
114
- echo '</td></tr>';
115
- // 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>';
116
-
117
- // method
118
- //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>';
119
120
echo '</tbody></table>';
121
@@ -124,6 +336,8 @@ echo '</tbody></table>';
124
125
$converters = $config['converters'];
126
echo '<script>window.converters = ' . json_encode($converters) . '</script>';
127
echo "<input type='text' name='converters' value='' style='visibility:hidden' />";
128
129
// https://premium.wpmudev.org/blog/handling-form-submissions/
@@ -157,10 +371,13 @@ http://php.net/manual/en/function.set-include-path.php
157
//echo 'All se bools: ' . print_r($output6, true) . '. Return code:' . $returnCode5;
158
*/
159
160
- echo '<h2>Converters</h2>';
161
$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>';
162
163
- echo '<p><i>Drag to reorder. The converter on top will be used. Should it fail, the next will be used, etc</i></p>';
164
// https://github.com/RubaXa/Sortable
165
166
// Empty list of converters. The list will be populated by the javascript
@@ -168,60 +385,86 @@ echo '<ul id="converters"></ul>';
168
?>
169
<div id="cwebp" style="display:none;">
170
<div class="cwebp converter-options">
171
- <h3>cwebp</h3>
172
- <div class="info">
173
- cwebp works by executing the cwebp binary from Google. This should normally be your first choice.
174
- Its best in terms of quality, speed and options.
175
- The only catch is that it requires the exec function to be enabled, and that the webserver user is
176
- allowed to execute the cwebp binary (either at known system locations, or one of the precompiled binaries,
177
- that comes with this library).
178
- If you are on a shared host that doesn't allow that, the second best choice would probably be the wpc cloud converter.
179
- </div>
180
<h3>cweb options</h3>
181
<div>
182
<label for="cwebp_use_nice">Use nice</label>
183
<input type="checkbox" id="cwebp_use_nice">
184
- <br>Enabling "use nice" saves system resources at the cost of slightly slower conversion
185
-
186
</div>
187
<br>
188
- <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update</button>
189
<!-- <a href="javascript: tb_remove();">close</a> -->
190
</div>
191
</div>
192
<div id="gd" style="display:none;">
193
- <div class="ewww converter-options">
194
- <h3>Gd</h3>
195
- <p>
196
- The gd converter uses the Gd extension to do the conversion. It is per default placed below the cloud converters for two reasons.
197
- Firstly, it does not seem to produce quite as good quality as cwebp.
198
- Secondly, it provides no conversion options, besides quality.
199
- The Gd extension is pretty common, so the main feature of this converter is that it <i>may</i> work out of the box.
200
- This is in contrast to the cloud converters, which requires that the user does some setup.
201
- </p>
202
<h3>Gd options</h3>
203
- <div class="info">
204
- Gd neither supports copying metadata nor exposes any WebP options. Lacking the option to set lossless encoding results in poor encoding of PNGs - the filesize is generally much larger than the original. For this reason, the converter defaults to skip PNG's.
205
- </div>
206
<div>
207
<label for="gd_skip_pngs">Skip PNGs</label>
208
<input type="checkbox" id="gd_skip_pngs">
209
</div>
210
<br>
211
- <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update</button>
212
<!-- <a href="javascript: tb_remove();">close</a> -->
213
</div>
214
</div>
215
<div id="imagick" style="display:none;">
216
<div class="imagick converter-options">
217
- <h3>Imagick</h3>
218
- <p>
219
- imagick would be your last choice. For some reason it produces conversions that are only marginally better than the originals.
220
- See <a href="https://github.com/rosell-dk/webp-convert/issues/43" target="_blank">this issue</a>. But it is fast.
221
- </p>
222
<h3>Imagick options</h3>
223
<div class="info">
224
- imagick has no extra options.
225
</div>
226
<br>
227
<!--
@@ -234,14 +477,11 @@ echo '<ul id="converters"></ul>';
234
<div class="ewww converter-options">
235
<h3>Ewww</h3>
236
<p>
237
- <a href="https://ewww.io/" target="_blank">ewww</a> is a cloud service.
238
- It is a decent alternative for those who don't have the technical know-how to install wpc.
239
- ewww is using cwebp to do the conversion, so quality is great.
240
- ewww however only provides one conversion option (quality), and it does not support "auto"
241
- quality (yet - I have requested the feature and the maintainer are considering it).
242
- Also, it is not free. But very cheap. Like in almost free.
243
</p>
244
- <h3>Ewww options</h3>
245
<div>
246
<label for="ewww_key">Key</label>
247
<input type="text" id="ewww_key" placeholder="Your API key here">
@@ -253,24 +493,18 @@ echo '<ul id="converters"></ul>';
253
<input type="text" id="ewww_key_2" placeholder="In case the first one expires...">
254
</div>
255
<br>
256
- <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update</button>
257
<!-- <a href="javascript: tb_remove();">close</a> -->
258
</div>
259
</div>
260
<div id="wpc" style="display:none;">
261
<div class="wpc converter-options">
262
- <h3>WebPConvert Cloud Service</h3>
263
- wpc is an open source cloud converter based on <a href="https://github.com/rosell-dk/webp-convert" target="_blank">WebPConvert</a>
264
- (this plugin also happens to be based on WebPConvert).
265
- Conversions will of course be slower than cwebp, as images need to go back and forth to the cloud converter.
266
- As images usually just needs to be converted once, the slower conversion
267
- speed is probably acceptable. The conversion quality and options of wpc matches cwebp.
268
- The only catch is that you will need to install the WPC library on a server (or have someone do it for you).
269
<a href="https://github.com/rosell-dk/webp-convert-cloud-service" target="blank">Visit WPC on github</a>.
270
- If this is a problem, we suggest you turn to ewww.
271
- (PS: A Wordpress plugin is planned, making it easier to set up a WPC instance. Or perhaps the functionality will even be part of this plugin)
272
-
273
- <h3>Options for WebPConvert Cloud Service</h3>
274
<div>
275
<label for="wpc_url">URL</label>
276
<input type="text" id="wpc_url" placeholder="Url to your WPC instance">
@@ -280,7 +514,30 @@ echo '<ul id="converters"></ul>';
280
<label for="wpc_secret">Secret</label>
281
<input type="text" id="wpc_secret" placeholder="Secret (must match secret on server side)">
282
</div>
283
- <br>
284
<h4>Fallback (optional)</h4>
285
<p>In case the first is down, the fallback will be used.</p>
286
<div>
@@ -292,13 +549,13 @@ echo '<ul id="converters"></ul>';
292
<input type="text" id="wpc_secret_2" placeholder="Secret (must match secret on server side)">
293
</div>
294
<br>
295
- <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update</button>
296
</div>
297
</div>
298
299
<table>
300
<tr>
301
- <td style="padding-right:20px"><?php submit_button('Save settings'); ?></td>
302
<td><?php submit_button('Save settings and force new .htaccess rules', 'secondary', 'force'); ?></td>
303
</tr>
304
</table>
3
include_once __DIR__ . '/../classes/Config.php';
4
use \WebPExpress\Config;
5
6
+ include_once __DIR__ . '/../classes/ConvertersHelper.php';
7
+ use \WebPExpress\ConvertersHelper;
8
+
9
include_once __DIR__ . '/../classes/FileHelper.php';
10
use \WebPExpress\FileHelper;
11
24
include_once __DIR__ . '/../classes/State.php';
25
use \WebPExpress\State;
26
27
+ include_once __DIR__ . '/../classes/TestRun.php';
28
+ use \WebPExpress\TestRun;
29
30
if (!current_user_can('manage_options')) {
31
wp_die('You do not have sufficient permissions to access this page.');
35
<h2>WebP Express Settings</h2>
36
37
<?php
38
+
39
+ //update_option('webp-express-migration-version', '1');
40
+
41
+ // Test converters
42
+ $testResult = TestRun::getConverterStatus();
43
+ $workingConverters = [];
44
+ if ($testResult) {
45
+ $workingConverters = $testResult['workingConverters'];
46
+ //print_r($testResult);
47
+ } else {
48
+ Messenger::printMessage(
49
+ 'error',
50
+ 'WebP Express cannot save a test conversion, because it does not have write ' .
51
+ 'access to your upload folder, nor your wp-content folder. Please provide!'
52
+ );
53
+ }
54
+
55
+ $canDetectQuality = TestRun::isLocalQualityDetectionWorking();
56
+
57
include __DIR__ . "/page-messages.php";
58
59
/*
64
65
66
$defaultConfig = [
67
+ 'cache-control' => 'no-header',
68
+ 'cache-control-custom' => 'public, max-age:3600',
69
+ 'converters' => [],
70
'fail' => 'original',
71
+ 'forward-query-string' => true,
72
+ 'image-types' => 1,
73
+ 'quality-auto' => $canDetectQuality,
74
'max-quality' => 80,
75
+ 'quality-specific' => 70,
76
+ 'metadata' => 'none',
77
];
78
79
+ $defaultConverters = ConvertersHelper::$defaultConverters;
80
+
81
+
82
$config = Config::loadConfig();
83
+ //echo '<pre>' . print_r($config, true) . '</pre>';
84
if (!$config) {
85
$config = [];
86
}
87
+ //$config = [];
88
89
$config = array_merge($defaultConfig, $config);
90
if ($config['converters'] == null) {
91
$config['converters'] = [];
92
}
93
94
+ if (count($config['converters']) == 0) {
95
+ // This is first time visit!
96
+
97
+ if (count($workingConverters) == 0) {
98
+ // No converters are working
99
+ // Send ewww converter to top
100
+ $resultPart1 = [];
101
+ $resultPart2 = [];
102
+ foreach ($defaultConverters as $converter) {
103
+ $converterId = $converter['converter'];
104
+ if ($converterId == 'ewww') {
105
+ $resultPart1[] = $converter;
106
+ } else {
107
+ $resultPart2[] = $converter;
108
+ }
109
+ }
110
+ $config['converters'] = array_merge($resultPart1, $resultPart2);
111
+ } else {
112
+ // Send converters not working to the bottom
113
+ // - and also deactivate them..
114
+ $resultPart1 = [];
115
+ $resultPart2 = [];
116
+ foreach ($defaultConverters as $converter) {
117
+ $converterId = $converter['converter'];
118
+ if (in_array($converterId, $workingConverters)) {
119
+ $resultPart1[] = $converter;
120
+ } else {
121
+ $converter['deactivated'] = true;
122
+ $resultPart2[] = $converter;
123
+ }
124
+ }
125
+ $config['converters'] = array_merge($resultPart1, $resultPart2);
126
+ }
127
+
128
+ // $workingConverters
129
+ //echo '<pre>' . print_r($converters, true) . '</pre>';
130
+ } else {
131
+ // not first time visit...
132
+ // merge missing converters in
133
+ $config['converters'] = ConvertersHelper::mergeConverters($config['converters'], ConvertersHelper::$defaultConverters);
134
+ }
135
+
136
+
137
+ // Set "working" and "error" properties
138
+ if ($testResult) {
139
+ foreach ($config['converters'] as &$converter) {
140
+ $converterId = $converter['converter'];
141
+ $hasError = isset($testResult['errors'][$converterId]);
142
+ $working = !$hasError;
143
+ if (isset($converter['working']) && ($converter['working'] != $working)) {
144
+ if ($working) {
145
+ Messenger::printMessage(
146
+ 'info',
147
+ 'Hurray! - The <i>' . $converterId . '</i> conversion method is working now!'
148
+ );
149
+ } else {
150
+ Messenger::printMessage(
151
+ 'warning',
152
+ 'Sad news. The <i>' . $converterId . '</i> conversion method is not working anymore. What happened?'
153
+ );
154
+ }
155
+ }
156
+ $converter['working'] = $working;
157
+ if ($hasError) {
158
+ $converter['error'] = $testResult['errors'][$converterId];
159
+ } else {
160
+ unset($converter['error']);
161
+ }
162
+ }
163
+ }
164
+ //echo '<pre>' . print_r($config['converters'], true) . '</pre>';
165
+
166
+ //echo 'Working converters:' . print_r($workingConverters, true) . '<br>';
167
// Generate a custom nonce value.
168
$webpexpress_settings_nonce = wp_create_nonce('webpexpress_settings_nonce');
169
+ ?>
170
+ <p>
171
+ <i>WebP Express takes care of serving autogenerated WebP images instead of jpeg/png to browsers that supports WebP.<br>
172
+ The settings below does not affect your original images - only the converted webp images, and the redirection rules.</i>
173
+ </p>
174
175
+ <?php
176
+ echo '<form id="webpexpress_settings" action="' . esc_url( admin_url( 'admin-post.php' ) ) . '" method="post" >';
177
?>
178
<input type="hidden" name="action" value="webpexpress_settings_submit">
179
<input type="hidden" name="webpexpress_settings_nonce" value="<?php echo $webpexpress_settings_nonce ?>" />
180
181
<?php
182
183
+ function helpIcon($text) {
184
+ return '<div class="help">?<div class="popup">' . $text . '</div></div>';
185
+ }
186
echo '<table class="form-table"><tbody>';
187
188
// Image types
189
// ------------
190
+ echo '<tr><th scope="row">Image types to convert';
191
+ 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>');
192
+ echo '</th><td>';
193
194
// bitmask
195
// 1: JPEGs
207
208
echo '</td></tr>';
209
210
+ // Quality
211
+ // --------------------
212
+
213
+ if ($canDetectQuality) {
214
+ echo '<tr><th scope="row">Quality';
215
+ echo helpIcon('If "Auto" is selected, the converted image will get same quality as source. Auto is recommended!');
216
+ echo '</th><td>';
217
+ $qualityAuto = $config['quality-auto'];;
218
+ echo '<select id="quality_auto_select" name="quality-auto">';
219
+ echo '<option value="auto_on"' . ($qualityAuto ? ' selected' : '') . '>Auto</option>';
220
+ echo '<option value="auto_off"' . (!$qualityAuto ? ' selected' : '') . '>Specific value</option>';
221
+ echo '</select>';
222
+
223
+ echo '</td></tr>';
224
+
225
+
226
+ // Max quality
227
+ // --------------------
228
+ $maxQuality = $config['max-quality'];
229
+
230
+ echo '<tr id="max_quality_row"><th scope="row">Max quality (0-100)';
231
+ echo helpIcon('Quality is expensive byte-wise. For most websites, more than 80 is a waste of bytes. ' .
232
+ 'This option allows you to limit the quality to whatever is lowest: ' .
233
+ 'the quality of the source or max quality. Recommended value: Somewhere between 50-85');
234
+ echo '</th><td>';
235
+
236
+ echo '<input type="text" size=3 name="max-quality" value="' . $maxQuality . '">';
237
+ echo '</td></tr>';
238
+ } else {
239
+
240
+ }
241
+
242
+ // Quality - specific
243
+ // --------------------
244
+ $qualitySpecific = $config['quality-specific'];
245
+
246
+ echo '<tr id="quality_specific_row"><th scope="row">Quality (0-100)';
247
+ if ($canDetectQuality) {
248
+ echo helpIcon('All converted images will be encoded with this quality');
249
+ } else {
250
+ echo helpIcon('All converted images will be encoded with this quality. ' .
251
+ 'For the wpc converter, you will however have the option to use override this, and use ' .
252
+ '"auto". If you install imagick or gmagick, quality can have "auto" for all convertion methods. '
253
+ );
254
+ }
255
+ echo '</th><td>';
256
+
257
+ echo '<input type="text" size=3 name="quality-specific" value="' . $qualitySpecific . '">';
258
+ echo '</td></tr>';
259
+
260
+
261
+
262
+
263
+ // 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>';
264
+
265
+ // method
266
+ //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>';
267
+
268
+ // Cache-Control
269
+ // --------------------
270
+ //$maxQuality = get_option('webp_express_max_quality');
271
+ $cacheControl = $config['cache-control'];
272
+ $cacheControlCustom = $config['cache-control-custom'];
273
+
274
+ echo '<tr><th scope="row">Caching';
275
+ echo helpIcon(
276
+ 'Controls the cache-control header for the converted image. ' .
277
+ 'This header is only sent when a converted image is successfully delivered (either existing, or new ' .
278
+ 'conversion). In case of failure, headers will be sent to prevent caching.');
279
+ echo '</th><td>';
280
+ echo '<select id="cache_control_select" name="cache-control">';
281
+ echo '<option value="no-header"' . ($cacheControl == 'no-header' ? ' selected' : '') . '>Do not set Cache-Control header</option>';
282
+ echo '<option value="one-second"' . ($cacheControl == 'one-second' ? ' selected' : '') . '>One second</option>';
283
+ echo '<option value="one-minute"' . ($cacheControl == 'one-minute' ? ' selected' : '') . '>One minute</option>';
284
+ echo '<option value="one-hour"' . ($cacheControl == 'one-hour' ? ' selected' : '') . '>One hour</option>';
285
+ echo '<option value="one-day"' . ($cacheControl == 'one-day' ? ' selected' : '') . '>One day</option>';
286
+ echo '<option value="one-week"' . ($cacheControl == 'one-week' ? ' selected' : '') . '>One week</option>';
287
+ echo '<option value="one-month"' . ($cacheControl == 'one-month' ? ' selected' : '') . '>One month</option>';
288
+ echo '<option value="one-year"' . ($cacheControl == 'one-year' ? ' selected' : '') . '>One year</option>';
289
+ echo '<option value="custom"' . ($cacheControl == 'custom' ? ' selected' : '') . '>Custom Cache-Control header</option>';
290
+ echo '</select><br>';
291
+ echo '<input type="text" id="cache_control_custom" name="cache-control-custom" value="' . $cacheControlCustom . '">';
292
+ echo '</td></tr>';
293
+
294
+
295
+ // Metadata
296
+ // --------------------
297
+ //$maxQuality = get_option('webp_express_max_quality');
298
+ $metadata = $config['metadata'];
299
+
300
+ echo '<tr><th scope="row">Metadata';
301
+ 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');
302
+ echo '</th><td>';
303
+
304
+ echo '<select name="metadata">';
305
+ echo '<option value="none"' . ($metadata == 'none' ? ' selected' : '') . '>No metadata in webp</option>';
306
+ echo '<option value="all"' . ($metadata == 'all' ? ' selected' : '') . '>Copy all metadata to webp</option>';
307
+ echo '</select>';
308
+ echo '</td></tr>';
309
+ // 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>';
310
+
311
+ // method
312
+ //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>';
313
+
314
// Response on failure
315
// --------------------
316
+ echo '<tr><th scope="row">Response on failure';
317
+ echo helpIcon('Determines what to serve in case the image conversion should fail.');
318
+ echo '</th><td>';
319
320
//$fail = get_option('webp_express_failure_response');
321
$fail = $config['fail'];
328
echo '</td></tr>';
329
// 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>';
330
331
332
echo '</tbody></table>';
333
336
337
$converters = $config['converters'];
338
echo '<script>window.converters = ' . json_encode($converters) . '</script>';
339
+ echo '<script>window.defaultConverters = ' . json_encode($defaultConverters) . '</script>';
340
+
341
echo "<input type='text' name='converters' value='' style='visibility:hidden' />";
342
343
// https://premium.wpmudev.org/blog/handling-form-submissions/
371
//echo 'All se bools: ' . print_r($output6, true) . '. Return code:' . $returnCode5;
372
*/
373
374
+ echo '<h2>Conversion methods to try</h2>';
375
$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>';
376
377
+ echo '<p><i>Drag to reorder. The conversion method on top will first be tried. ';
378
+ echo 'Should it fail, the next will be used, etc.<br>';
379
+ echo 'To learn more about the conversion methods, ';
380
+ echo '<a target="_blank" href="https://github.com/rosell-dk/webp-convert/blob/master/docs/converters.md">Go here</a></i></p>';
381
// https://github.com/RubaXa/Sortable
382
383
// Empty list of converters. The list will be populated by the javascript
385
?>
386
<div id="cwebp" style="display:none;">
387
<div class="cwebp converter-options">
388
<h3>cweb options</h3>
389
<div>
390
<label for="cwebp_use_nice">Use nice</label>
391
<input type="checkbox" id="cwebp_use_nice">
392
+ <br>Enabling this option saves system resources at the cost of slightly slower conversion
393
+ </div>
394
+ <div>
395
+ <label for="cwebp_try_common_system_paths">Try to execute cweb binary at common locations</label>
396
+ <input type="checkbox" id="cwebp_try_common_system_paths">
397
+ <br>If checked, we will look for binaries in common locations, such as <i>/usr/bin/cwebp</i>
398
+ </div>
399
+ <div>
400
+ <label for="cwebp_try_common_system_paths">Try precompiled cwebp</label>
401
+ <input type="checkbox" id="cwebp_try_supplied_binary">
402
+ <br>This plugin ships with precompiled cweb binaries for different platforms. If checked, and we have a precompiled binary for your OS, we will try to exectute it
403
+ </div>
404
+ <div>
405
+ <label for="cwebp_method">Method (0-6)</label>
406
+ <input type="text" size="2" id="cwebp_method">
407
+ <br>This parameter controls the trade off between encoding speed and the compressed file size and quality.
408
+ Possible values range from 0 to 6. 0 is fastest. 6 results in best quality.
409
+ </div>
410
+ <div>
411
+ <label for="cwebp_set_size">Set size option (and ignore quality option)</label>
412
+ <input type="checkbox" id="cwebp_set_size">
413
+ <br>This option activates the size option below.
414
+ <?php
415
+ if ($canDetectQuality) {
416
+ echo 'As you have quality detection working on your server, it is probably best to use that, rather ';
417
+ echo 'than the "size" option. Using the size option takes more ressources (it takes about 2.5 times ';
418
+ echo 'longer for cwebp to do a a conversion with the size option than the quality option). Long ';
419
+ echo 'story short, you should probably <i>not</i> activate the size option.';
420
+ } else {
421
+ echo 'As you do not have quality detection working on your server, it is probably a good ';
422
+ echo 'idea to use the size option to avoid making conversions with a higher quality setting ';
423
+ echo 'than the source image. ';
424
+ echo 'Beware, though, that cwebp takes about 2.5 times longer to do a a conversion with the size option set.';
425
+ }
426
+ ?>
427
+ </div>
428
+ <div>
429
+ <label for="cwebp_size_in_percentage">Size (in percentage of source)</label>
430
+ <input type="text" size="2" id="cwebp_size_in_percentage">
431
+ <br>Set the cwebp should aim for, in percentage of the original.
432
+ Usually cwebp can reduce to ~45% of original without loosing quality.
433
+ </div>
434
+ <div>
435
+ <label for="cwebp_command_line_options">Extra command line options</label><br>
436
+ <input type="text" size="40" id="cwebp_command_line_options" style="width:100%">
437
+ <br>This allows you to set any parameter available for cwebp in the same way as
438
+ you would do when executing <i>cwebp</i>. As a syntax example, you could ie. set it to
439
+ "-low_memory -af -f 50 -sharpness 0 -mt -crop 10 10 40 40" (do not include the quotes).
440
+ Read more about all the available parameters in
441
+ <a target="_blank" href="https://developers.google.com/speed/webp/docs/cwebp">the docs</a>
442
</div>
443
<br>
444
+ <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update and save settings</button>
445
<!-- <a href="javascript: tb_remove();">close</a> -->
446
</div>
447
</div>
448
<div id="gd" style="display:none;">
449
+ <div class="gd converter-options">
450
<h3>Gd options</h3>
451
<div>
452
<label for="gd_skip_pngs">Skip PNGs</label>
453
<input type="checkbox" id="gd_skip_pngs">
454
+ <br>Gd is not suited for converting PNGs into webp. &ndash;
455
+ The filesize is generally much larger than the original.
456
+ For this reason, the converter defaults to skip PNG's.
457
</div>
458
<br>
459
+ <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update and save settings</button>
460
<!-- <a href="javascript: tb_remove();">close</a> -->
461
</div>
462
</div>
463
<div id="imagick" style="display:none;">
464
<div class="imagick converter-options">
465
<h3>Imagick options</h3>
466
<div class="info">
467
+ imagick has no special options.
468
</div>
469
<br>
470
<!--
477
<div class="ewww converter-options">
478
<h3>Ewww</h3>
479
<p>
480
+ ewww is a cloud service for converting images.
481
+ To use it, you need to purchase a key <a target="_blank" href="https://ewww.io/plans/">here</a>.
482
+ They do not charge credits for webp conversions, so all you ever have to pay is the one dollar start-up fee :)
483
</p>
484
+ <h3>Options</h3>
485
<div>
486
<label for="ewww_key">Key</label>
487
<input type="text" id="ewww_key" placeholder="Your API key here">
493
<input type="text" id="ewww_key_2" placeholder="In case the first one expires...">
494
</div>
495
<br>
496
+ <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update and save settings</button>
497
<!-- <a href="javascript: tb_remove();">close</a> -->
498
</div>
499
</div>
500
<div id="wpc" style="display:none;">
501
<div class="wpc converter-options">
502
+ <h3>WebPConvert Cloud Service (WPC)</h3>
503
+ wpc is an open source cloud converter based on <a href="https://github.com/rosell-dk/webp-convert" target="_blank">WebPConvert</a>.
504
+ You will need to install the WPC library on a server (or have someone do it for you).
505
<a href="https://github.com/rosell-dk/webp-convert-cloud-service" target="blank">Visit WPC on github</a>.
506
+ (PS: It is planned to integrate wpc into <i>WebP Express</i>, making it very easy to share the capability to convert with your other sites)
507
+ <h3>Options</h3>
508
<div>
509
<label for="wpc_url">URL</label>
510
<input type="text" id="wpc_url" placeholder="Url to your WPC instance">
514
<label for="wpc_secret">Secret</label>
515
<input type="text" id="wpc_secret" placeholder="Secret (must match secret on server side)">
516
</div>
517
+ <?php
518
+ if ($canDetectQuality) { ?>
519
+ <div>
520
+ <label for="wpc_quality">
521
+ Quality
522
+ <?php echo helpIcon('If "Auto" is selected, the converted image will get same quality as source. Auto is recommended!'); ?>
523
+ </label>
524
+ <!--
525
+ Your server cannot detect quality of jpeg files. But you can have the cloud server do it for you
526
+ (provided that <i>it</i> can) -->
527
+ <select id="wpc_quality" onchange="wpcQualityChanged()">
528
+ <option value="not_set">Use global settings</option>
529
+ <option value="auto">Auto</option>
530
+ </select>
531
+ </div>
532
+ <div id="wpc_max_quality_div">
533
+ <label>
534
+ Max quality
535
+ <?php echo helpIcon('Enter number (0-100). Converted images will be encoded with same quality as the source image, but not more than this setting'); ?>
536
+ </label>
537
+ <input type="text" size=3 id="wpc_max_quality">
538
+ </div>
539
+ <?php } ?>
540
+ <br>
541
<h4>Fallback (optional)</h4>
542
<p>In case the first is down, the fallback will be used.</p>
543
<div>
549
<input type="text" id="wpc_secret_2" placeholder="Secret (must match secret on server side)">
550
</div>
551
<br>
552
+ <button onclick="updateConverterOptions()" class="button button-primary" type="button">Update and save settings</button>
553
</div>
554
</div>
555
556
<table>
557
<tr>
558
+ <td style="padding-right:20px"><?php submit_button('Save settings', 'primary', 'mysubmit'); ?></td>
559
<td><?php submit_button('Save settings and force new .htaccess rules', 'secondary', 'force'); ?></td>
560
</tr>
561
</table>
lib/options/submit.php CHANGED
@@ -17,14 +17,34 @@ use \WebPExpress\Paths;
17
// https://premium.wpmudev.org/blog/handling-form-submissions/
18
// checkout https://codex.wordpress.org/Function_Reference/sanitize_meta
19
20
$config = [
21
'fail' => sanitize_text_field($_POST['fail']),
22
- 'max-quality' => sanitize_text_field($_POST['max-quality']),
23
'image-types' => sanitize_text_field($_POST['image-types']),
24
- 'converters' => json_decode(wp_unslash($_POST['converters']), true), // holy moly! - https://stackoverflow.com/questions/2496455/why-are-post-variables-getting-escaped-in-php
25
- 'forward-query-string' => true
26
];
27
28
// remove id's
29
foreach ($config['converters'] as &$converter) {
30
unset ($converter['id']);
@@ -40,6 +60,11 @@ Messenger::addMessage(
40
);*/
41
42
/*
43
Messenger::addMessage(
44
'info',
45
'<pre>' . htmlentities(print_r($result, true)) . '</pre>'
17
// https://premium.wpmudev.org/blog/handling-form-submissions/
18
// checkout https://codex.wordpress.org/Function_Reference/sanitize_meta
19
20
+ /* We want an integer value between 0-100. We round "77.5" to 78. */
21
+ function webp_express_sanitize_quality_field($text) {
22
+ $text = str_replace(',', '.', $text);
23
+ $q = floatval(sanitize_text_field($text));
24
+ $q = round($q);
25
+ return max(0, min($q, 100));
26
+ }
27
$config = [
28
+ 'cache-control' => sanitize_text_field($_POST['cache-control']),
29
+ 'cache-control-custom' => sanitize_text_field($_POST['cache-control-custom']),
30
+ 'converters' => json_decode(wp_unslash($_POST['converters']), true), // holy moly! - https://stackoverflow.com/questions/2496455/why-are-post-variables-getting-escaped-in-php
31
'fail' => sanitize_text_field($_POST['fail']),
32
+ 'forward-query-string' => true,
33
'image-types' => sanitize_text_field($_POST['image-types']),
34
+ 'metadata' => sanitize_text_field($_POST['metadata']),
35
];
36
37
+ $auto = (isset($_POST['quality-auto']) && $_POST['quality-auto'] == 'auto_on');
38
+ $config['quality-auto'] = $auto;
39
+
40
+ if ($auto) {
41
+ $config['max-quality'] = webp_express_sanitize_quality_field($_POST['max-quality']);
42
+ $config['quality-specific'] = 70;
43
+ } else {
44
+ $config['max-quality'] = 80;
45
+ $config['quality-specific'] = webp_express_sanitize_quality_field($_POST['quality-specific']);
46
+ }
47
+
48
// remove id's
49
foreach ($config['converters'] as &$converter) {
50
unset ($converter['id']);
60
);*/
61
62
/*
63
+ Messenger::addMessage(
64
+ 'info',
65
+ '<pre>' . htmlentities(print_r($config, true)) . '</pre>'
66
+ );
67
+
68
Messenger::addMessage(
69
'info',
70
'<pre>' . htmlentities(print_r($result, true)) . '</pre>'
lib/reactivate.php CHANGED
@@ -12,6 +12,9 @@ use \WebPExpress\Messenger;
12
include_once __DIR__ . '/classes/Actions.php';
13
use \WebPExpress\Actions;
14
15
include_once __DIR__ . '/classes/PlatformInfo.php';
16
use \WebPExpress\PlatformInfo;
17
@@ -30,7 +33,8 @@ $config = Config::loadConfig();
30
if ($config === false) {
31
Messenger::addMessage(
32
'error',
33
- 'The config file seems to have gone missing. You will need to reconfigure WebP Express <a href="options-general.php?page=webp_express_settings_page">(here)</a>.'
34
);
35
} else {
36
$rulesResult = HTAccess::saveRules($config);
@@ -52,14 +56,15 @@ if ($config === false) {
52
'WebP Express re-activated successfully.<br>' .
53
'The image redirections are in effect again.<br><br>' .
54
'Just a quick reminder: If you at some point change the upload directory or move Wordpress, the <i>.htaccess</i> will need to be regenerated.<br>' .
55
- 'You do that by re-saving the settings <a href="options-general.php?page=webp_express_settings_page">(here)</a>'
56
);
57
} else {
58
Messenger::addMessage(
59
'warning',
60
'WebP Express could not regenerate the rewrite rules<br>' .
61
'You need to change some permissions. Head to the ' .
62
- '<a href="options-general.php?page=webp_express_settings_page">settings page</a> ' .
63
'and try to save the settings there (it will provide more information about the problem)'
64
);