Converter for Media – Optimize images | Convert WebP & AVIF - Version 1.0.1

Version Description

(2019-06-23) = * Securing access to REST API * Error handler for undefined gd extension

Download this release

Release Info

Developer mateuszgbiorczyk
Plugin Icon 128x128 Converter for Media – Optimize images | Convert WebP & AVIF
Version 1.0.1
Comparing to
See all releases

Code changes from version 1.0.0 to 1.0.1

app/Convert/Gd.php CHANGED
@@ -105,10 +105,9 @@
105
  $output = $directory->getPath($path, true);
106
  if (!$output) {
107
  throw new \Exception(sprintf('An error occurred creating destination directory for "%s" file.', $path));
108
- }
109
-
110
- $success = imagewebp($image, $output, $quality);
111
- if (!$success) {
112
  throw new \Exception('Error occurred while converting image.');
113
  }
114
 
105
  $output = $directory->getPath($path, true);
106
  if (!$output) {
107
  throw new \Exception(sprintf('An error occurred creating destination directory for "%s" file.', $path));
108
+ } else if (!function_exists('imagewebp')) {
109
+ throw new \Exception(sprintf('"%s" function is not available.', 'imagewebp'));
110
+ } else if (!$success = imagewebp($image, $output, $quality)) {
 
111
  throw new \Exception('Error occurred while converting image.');
112
  }
113
 
app/Media/Upload.php CHANGED
@@ -46,6 +46,7 @@
46
 
47
  if ($settings['method'] === 'gd') $convert = new Convert\Gd();
48
  else if ($settings['method'] === 'imagick') $convert = new Convert\Imagick();
 
49
 
50
  foreach ($paths as $path) {
51
  if (!in_array(pathinfo($path, PATHINFO_EXTENSION), $settings['extensions'])) continue;
46
 
47
  if ($settings['method'] === 'gd') $convert = new Convert\Gd();
48
  else if ($settings['method'] === 'imagick') $convert = new Convert\Imagick();
49
+ if (!isset($convert)) return false;
50
 
51
  foreach ($paths as $path) {
52
  if (!in_array(pathinfo($path, PATHINFO_EXTENSION), $settings['extensions'])) continue;
app/Regenerate/Endpoints.php CHANGED
@@ -25,6 +25,10 @@
25
  'paths',
26
  [
27
  'methods' => \WP_REST_Server::ALLMETHODS,
 
 
 
 
28
  'callback' => [$this, 'getPaths'],
29
  'args' => [],
30
  ]
@@ -35,6 +39,10 @@
35
  'regenerate',
36
  [
37
  'methods' => \WP_REST_Server::ALLMETHODS,
 
 
 
 
38
  'callback' => [$this, 'convertImages'],
39
  'args' => [
40
  'paths' => [
@@ -54,7 +62,8 @@
54
  {
55
  $api = new Paths();
56
  $data = $api->getPaths();
57
- return new \WP_REST_Response($data, 200);
 
58
  }
59
 
60
  public function convertImages($request)
@@ -62,18 +71,21 @@
62
  $params = $request->get_params();
63
  $api = new Regenerate();
64
  $data = $api->convertImages($params['paths']);
65
- return new \WP_REST_Response($data, 200);
 
66
  }
67
 
68
  public function showApiPathsUrl()
69
  {
70
- $url = get_rest_url(null, $this->namespace . '/paths');
 
71
  return $url;
72
  }
73
 
74
  public function showApiRegenerateUrl()
75
  {
76
- $url = get_rest_url(null, $this->namespace . '/regenerate');
 
77
  return $url;
78
  }
79
  }
25
  'paths',
26
  [
27
  'methods' => \WP_REST_Server::ALLMETHODS,
28
+ 'permission_callback' => function() {
29
+ return (isset($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wp_rest')
30
+ && current_user_can('manage_options'));
31
+ },
32
  'callback' => [$this, 'getPaths'],
33
  'args' => [],
34
  ]
39
  'regenerate',
40
  [
41
  'methods' => \WP_REST_Server::ALLMETHODS,
42
+ 'permission_callback' => function() {
43
+ return (isset($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'wp_rest')
44
+ && current_user_can('manage_options'));
45
+ },
46
  'callback' => [$this, 'convertImages'],
47
  'args' => [
48
  'paths' => [
62
  {
63
  $api = new Paths();
64
  $data = $api->getPaths();
65
+ if ($data !== false) return new \WP_REST_Response($data, 200);
66
+ else return new \WP_Error('webpc_rest_api_error', null, ['status' => 405]);
67
  }
68
 
69
  public function convertImages($request)
71
  $params = $request->get_params();
72
  $api = new Regenerate();
73
  $data = $api->convertImages($params['paths']);
74
+ if ($data !== false) return new \WP_REST_Response($data, 200);
75
+ else return new \WP_Error('webpc_rest_api_error', null, ['status' => 405]);
76
  }
77
 
78
  public function showApiPathsUrl()
79
  {
80
+ $nonce = wp_create_nonce('wp_rest');
81
+ $url = get_rest_url(null, $this->namespace . '/paths?_wpnonce=' . $nonce);
82
  return $url;
83
  }
84
 
85
  public function showApiRegenerateUrl()
86
  {
87
+ $nonce = wp_create_nonce('wp_rest');
88
+ $url = get_rest_url(null, $this->namespace . '/regenerate?_wpnonce=' . $nonce);
89
  return $url;
90
  }
91
  }
app/Regenerate/Regenerate.php CHANGED
@@ -18,6 +18,7 @@
18
 
19
  if ($settings['method'] === 'gd') $convert = new Convert\Gd();
20
  else if ($settings['method'] === 'imagick') $convert = new Convert\Imagick();
 
21
 
22
  foreach ($paths as $path) {
23
  $response = $convert->convertImage($path, $settings['quality']);
18
 
19
  if ($settings['method'] === 'gd') $convert = new Convert\Gd();
20
  else if ($settings['method'] === 'imagick') $convert = new Convert\Imagick();
21
+ if (!isset($convert)) return false;
22
 
23
  foreach ($paths as $path) {
24
  $response = $convert->convertImage($path, $settings['quality']);
app/Settings/Options.php CHANGED
@@ -74,6 +74,7 @@
74
  switch ($name) {
75
  case 'method':
76
  if (!extension_loaded('imagick')) $list[] = 'imagick';
 
77
  break;
78
  }
79
  return $list;
74
  switch ($name) {
75
  case 'method':
76
  if (!extension_loaded('imagick')) $list[] = 'imagick';
77
+ if (!extension_loaded('gd')) $list[] = 'gd';
78
  break;
79
  }
80
  return $list;
app/Settings/Values.php CHANGED
@@ -21,7 +21,7 @@
21
 
22
  $value = get_option('webpc_settings', [
23
  'extensions' => ['jpg', 'jpeg', 'png'],
24
- 'method' => 'gd',
25
  'features' => ['mod_expires'],
26
  'quality' => 85,
27
  ]);
21
 
22
  $value = get_option('webpc_settings', [
23
  'extensions' => ['jpg', 'jpeg', 'png'],
24
+ 'method' => extension_loaded('gd') ? 'gd' : (extension_loaded('imagick') ? 'imagick' : ''),
25
  'features' => ['mod_expires'],
26
  'quality' => 85,
27
  ]);
public/build/js/scripts.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function r(s){if(t[s])return t[s].exports;var n=t[s]={i:s,l:!1,exports:{}};return e[s].call(n.exports,n,n.exports,r),n.l=!0,n.exports}r.m=e,r.c=t,r.d=function(e,t,s){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:s})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var s=Object.create(null);if(r.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(s,n,function(t){return e[t]}.bind(null,n));return s},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="/",r(r.s=0)}([function(e,t,r){r(1),e.exports=r(2)},function(e,t,r){"use strict";function s(e,t){for(var r=0;r<t.length;r++){var s=t[r];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(e,s.key,s)}}r.r(t);var n=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.setVars()&&this.setEvents()}var t,r,n;return t=e,(r=[{key:"setVars",value:function(){if(this.notice=document.querySelector(".notice[data-notice=webp-converter]"),this.notice)return this.settings={isHidden:!1,ajaxUrl:this.notice.getAttribute("data-url")},!0}},{key:"setEvents",value:function(){window.addEventListener("load",this.getButtons.bind(this))}},{key:"getButtons",value:function(){this.buttonClose=this.notice.querySelector(".notice-dismiss"),this.buttonPermanently=this.notice.querySelector("[data-permanently]"),this.setButtonsEvents()}},{key:"setButtonsEvents",value:function(){var e=this;this.buttonClose.addEventListener("click",function(){e.hideNotice(!1)}),this.buttonPermanently.addEventListener("click",function(t){t.preventDefault(),e.hideNotice(!0)})}},{key:"hideNotice",value:function(e){this.settings.isHidden||(this.settings.isHidden=!0,jQuery.ajax(this.settings.ajaxUrl,{type:"POST",data:{is_permanently:e?1:0}}),this.buttonClose.click())}}])&&s(t.prototype,r),n&&s(t,n),e}();function i(e,t){for(var r=0;r<t.length;r++){var s=t[r];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(e,s.key,s)}}var a=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.setVars()&&this.setEvents()}var t,r,s;return t=e,(r=[{key:"setVars",value:function(){if(this.section=document.querySelector(".webpLoader"),this.section)return this.wrapper=this.section.querySelector(".webpLoader__status"),this.progress=this.wrapper.querySelector(".webpLoader__barProgress"),this.progressSize=this.section.querySelector(".webpLoader__sizeProgress"),this.errors=this.section.querySelector(".webpLoader__errors"),this.errorsInner=this.errors.querySelector(".webpLoader__errorsContentList"),this.errorsMessage=this.errors.querySelector(".webpLoader__errorsContentMessage"),this.success=this.section.querySelector(".webpLoader__success"),this.button=this.section.querySelector(".webpLoader__button"),this.data={count:0,max:0,items:[],size:{before:0,after:0},errors:[]},this.settings={isDisabled:!1,ajax:{urlPaths:this.section.getAttribute("data-api-paths"),urlRegenerate:this.section.getAttribute("data-api-regenerate")},units:["kB","MB","GB"]},this.atts={progress:"data-percent"},this.classes={progressError:"webpLoader__barProgress--error",buttonDisabled:"webpLoader__button--disabled"},!0}},{key:"setEvents",value:function(){this.button.addEventListener("click",this.initRegenerate.bind(this))}},{key:"initRegenerate",value:function(e){e.preventDefault(),this.settings.isDisabled||(this.settings.isDisabled=!0,this.button.classList.add(this.classes.buttonDisabled),this.wrapper.removeAttribute("hidden"),this.getImagesList())}},{key:"getImagesList",value:function(){var e=this;jQuery.ajax(this.settings.ajax.urlPaths,{type:"POST",date:{}}).done(function(t){e.data.items=t.data,e.data.max=t.data.length,e.regenerateNextImages()}).fail(function(){e.progress.classList.add(e.classes.progressError),e.errorsMessage.removeAttribute("hidden")})}},{key:"regenerateNextImages",value:function(){if(0===this.data.max&&this.updateProgress(),!(this.data.count>=this.data.max)){var e=this.data.items[this.data.count];this.data.count++,this.sendRequest(e)}}},{key:"sendRequest",value:function(e){var t=this;jQuery.ajax(this.settings.ajax.urlRegenerate,{type:"POST",data:{paths:e}}).done(function(e){t.updateErrors(e),t.updateSize(e),t.updateProgress(),t.regenerateNextImages()}).fail(function(){t.progress.classList.add(t.classes.progressError),t.errorsMessage.removeAttribute("hidden"),t.errors.removeAttribute("hidden")})}},{key:"updateErrors",value:function(e){0!==e.errors.length&&(this.data.errors=this.data.errors.concat(e.errors),this.errorsInner.innerHTML=this.data.errors.join("<br>"),this.errors.removeAttribute("hidden"))}},{key:"updateSize",value:function(e){var t=this.data.size;t.before+=e.size.before,t.after+=e.size.after;var r=t.before-t.after;if(r<0&&(r=0),0!==r){var s=Math.round(100*(1-t.after/t.before));s<0&&(s=0);var n=-1;do{n++,r/=1024}while(r>1024);var i=r.toFixed(2),a=this.settings.units[n],o="".concat(i," ").concat(a," (").concat(s,"%)");this.progressSize.innerHTML=o}}},{key:"updateProgress",value:function(){var e=this.data.max>0?Math.floor(this.data.count/this.data.max*100):100;e>100&&(e=100),100===e&&this.success.removeAttribute("hidden"),this.progress.setAttribute(this.atts.progress,e)}}])&&i(t.prototype,r),s&&i(t,s),e}();new function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),new n,new a}},function(e,t){}]);
1
+ !function(e){var t={};function r(s){if(t[s])return t[s].exports;var n=t[s]={i:s,l:!1,exports:{}};return e[s].call(n.exports,n,n.exports,r),n.l=!0,n.exports}r.m=e,r.c=t,r.d=function(e,t,s){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:s})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var s=Object.create(null);if(r.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(s,n,function(t){return e[t]}.bind(null,n));return s},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="/",r(r.s=0)}([function(e,t,r){r(1),e.exports=r(2)},function(e,t,r){"use strict";function s(e,t){for(var r=0;r<t.length;r++){var s=t[r];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(e,s.key,s)}}r.r(t);var n=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.setVars()&&this.setEvents()}var t,r,n;return t=e,(r=[{key:"setVars",value:function(){if(this.notice=document.querySelector(".notice[data-notice=webp-converter]"),this.notice)return this.settings={isHidden:!1,ajaxUrl:this.notice.getAttribute("data-url")},!0}},{key:"setEvents",value:function(){window.addEventListener("load",this.getButtons.bind(this))}},{key:"getButtons",value:function(){this.buttonClose=this.notice.querySelector(".notice-dismiss"),this.buttonPermanently=this.notice.querySelector("[data-permanently]"),this.setButtonsEvents()}},{key:"setButtonsEvents",value:function(){var e=this;this.buttonClose.addEventListener("click",function(){e.hideNotice(!1)}),this.buttonPermanently.addEventListener("click",function(t){t.preventDefault(),e.hideNotice(!0)})}},{key:"hideNotice",value:function(e){this.settings.isHidden||(this.settings.isHidden=!0,jQuery.ajax(this.settings.ajaxUrl,{type:"POST",data:{is_permanently:e?1:0}}),this.buttonClose.click())}}])&&s(t.prototype,r),n&&s(t,n),e}();function i(e,t){for(var r=0;r<t.length;r++){var s=t[r];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(e,s.key,s)}}var a=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.setVars()&&this.setEvents()}var t,r,s;return t=e,(r=[{key:"setVars",value:function(){if(this.section=document.querySelector(".webpLoader"),this.section)return this.wrapper=this.section.querySelector(".webpLoader__status"),this.progress=this.wrapper.querySelector(".webpLoader__barProgress"),this.progressSize=this.section.querySelector(".webpLoader__sizeProgress"),this.errors=this.section.querySelector(".webpLoader__errors"),this.errorsInner=this.errors.querySelector(".webpLoader__errorsContentList"),this.errorsMessage=this.errors.querySelector(".webpLoader__errorsContentMessage"),this.success=this.section.querySelector(".webpLoader__success"),this.button=this.section.querySelector(".webpLoader__button"),this.data={count:0,max:0,items:[],size:{before:0,after:0},errors:[]},this.settings={isDisabled:!1,ajax:{urlPaths:this.section.getAttribute("data-api-paths"),urlRegenerate:this.section.getAttribute("data-api-regenerate")},units:["kB","MB","GB"]},this.atts={progress:"data-percent"},this.classes={progressError:"webpLoader__barProgress--error",buttonDisabled:"webpLoader__button--disabled"},!0}},{key:"setEvents",value:function(){this.button.addEventListener("click",this.initRegenerate.bind(this))}},{key:"initRegenerate",value:function(e){e.preventDefault(),this.settings.isDisabled||(this.settings.isDisabled=!0,this.button.classList.add(this.classes.buttonDisabled),this.wrapper.removeAttribute("hidden"),this.getImagesList())}},{key:"getImagesList",value:function(){var e=this;jQuery.ajax(this.settings.ajax.urlPaths,{type:"POST",date:{}}).done(function(t){e.data.items=t.data,e.data.max=t.data.length,e.regenerateNextImages()}).fail(function(){e.progress.classList.add(e.classes.progressError),e.errorsMessage.removeAttribute("hidden"),e.errors.removeAttribute("hidden")})}},{key:"regenerateNextImages",value:function(){if(0===this.data.max&&this.updateProgress(),!(this.data.count>=this.data.max)){var e=this.data.items[this.data.count];this.data.count++,this.sendRequest(e)}}},{key:"sendRequest",value:function(e){var t=this;jQuery.ajax(this.settings.ajax.urlRegenerate,{type:"POST",data:{paths:e}}).done(function(e){t.updateErrors(e),t.updateSize(e),t.updateProgress(),t.regenerateNextImages()}).fail(function(){t.progress.classList.add(t.classes.progressError),t.errorsMessage.removeAttribute("hidden"),t.errors.removeAttribute("hidden")})}},{key:"updateErrors",value:function(e){0!==e.errors.length&&(this.data.errors=this.data.errors.concat(e.errors),this.errorsInner.innerHTML=this.data.errors.join("<br>"),this.errors.removeAttribute("hidden"))}},{key:"updateSize",value:function(e){var t=this.data.size;t.before+=e.size.before,t.after+=e.size.after;var r=t.before-t.after;if(r<0&&(r=0),0!==r){var s=Math.round(100*(1-t.after/t.before));s<0&&(s=0);var n=-1;do{n++,r/=1024}while(r>1024);var i=r.toFixed(2),a=this.settings.units[n],o="".concat(i," ").concat(a," (").concat(s,"%)");this.progressSize.innerHTML=o}}},{key:"updateProgress",value:function(){var e=this.data.max>0?Math.floor(this.data.count/this.data.max*100):100;e>100&&(e=100),100===e&&this.success.removeAttribute("hidden"),this.progress.setAttribute(this.atts.progress,e)}}])&&i(t.prototype,r),s&&i(t,s),e}();new function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),new n,new a}},function(e,t){}]);
readme.txt CHANGED
@@ -87,7 +87,11 @@ If you are using a CDN server, find one that automatically converts images to We
87
 
88
  == Changelog ==
89
 
90
- = 1.0.0 =
 
 
 
 
91
  * The first stable release
92
 
93
  == Upgrade Notice ==
87
 
88
  == Changelog ==
89
 
90
+ = 1.0.1 (2019-06-23) =
91
+ * Securing access to REST API
92
+ * Error handler for undefined `gd` extension
93
+
94
+ = 1.0.0 (2019-06-16) =
95
  * The first stable release
96
 
97
  == Upgrade Notice ==
resources/_dev/js/classes/Regenerate.js CHANGED
@@ -80,6 +80,7 @@ export default class Regenerate
80
  }).fail(() => {
81
  this.progress.classList.add(this.classes.progressError);
82
  this.errorsMessage.removeAttribute('hidden');
 
83
  });
84
  }
85
 
80
  }).fail(() => {
81
  this.progress.classList.add(this.classes.progressError);
82
  this.errorsMessage.removeAttribute('hidden');
83
+ this.errors.removeAttribute('hidden');
84
  });
85
  }
86
 
webp-converter-for-media.php CHANGED
@@ -3,13 +3,13 @@
3
  /*
4
  Plugin Name: WebP Converter for Media
5
  Description: Speed up your website by serving WebP images instead of standard formats JPEG, PNG and GIF.
6
- Version: 1.0.0
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter
10
  */
11
 
12
- define('WEBPC_VERSION', '1.0.0');
13
  define('WEBPC_FILE', __FILE__);
14
  define('WEBPC_NAME', plugin_basename(__FILE__));
15
  define('WEBPC_PATH', plugin_dir_path(__FILE__));
3
  /*
4
  Plugin Name: WebP Converter for Media
5
  Description: Speed up your website by serving WebP images instead of standard formats JPEG, PNG and GIF.
6
+ Version: 1.0.1
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter
10
  */
11
 
12
+ define('WEBPC_VERSION', '1.0.1');
13
  define('WEBPC_FILE', __FILE__);
14
  define('WEBPC_NAME', plugin_basename(__FILE__));
15
  define('WEBPC_PATH', plugin_dir_path(__FILE__));