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

Version Description

(2020-04-07) = * [Removed] Filter webpc_option_disabled * [Fixed] Converting images multiple times when uploading to media library * [Added] Action webpc_convert_paths to convert images by paths * [Added] Action webpc_convert_attachment to convert images by Post ID

Download this release

Release Info

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

Code changes from version 1.2.0 to 1.2.1

app/Media/Attachment.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Media;
4
+
5
+ class Attachment
6
+ {
7
+ private $settings, $uploadDir, $imageSizes;
8
+
9
+ public function __construct()
10
+ {
11
+ $this->settings = apply_filters('webpc_get_values', []);
12
+ $this->uploadDir = wp_upload_dir();
13
+ $this->imageSizes = get_intermediate_image_sizes();
14
+ }
15
+
16
+ /* ---
17
+ Functions
18
+ --- */
19
+
20
+ public function getAttachmentPaths($attachmentId)
21
+ {
22
+ $paths = $this->getPathsByAttachment($attachmentId);
23
+ return $paths;
24
+ }
25
+
26
+ private function getPathsByAttachment($postId)
27
+ {
28
+ $list = [];
29
+ $metadata = wp_get_attachment_metadata($postId);
30
+ if (!$metadata) return $list;
31
+
32
+ $extension = pathinfo($metadata['file'], PATHINFO_EXTENSION);
33
+ if (!isset($metadata['file'])
34
+ || !in_array($extension, $this->settings['extensions'])) return $list;
35
+
36
+ $paths = $this->getPathsBySizes($postId, $metadata['file']);
37
+ $paths = apply_filters('webpc_attachment_paths', $paths, $postId);
38
+ return $paths;
39
+ }
40
+
41
+ private function getPathsBySizes($postId, $path)
42
+ {
43
+ $list = [];
44
+ $list[] = str_replace('\\', '/', implode('/', [$this->uploadDir['basedir'], $path]));
45
+
46
+ foreach ($this->imageSizes as $size) {
47
+ $src = wp_get_attachment_image_src($postId, $size);
48
+ $url = str_replace($this->uploadDir['baseurl'], $this->uploadDir['basedir'], $src[0]);
49
+ $url = str_replace('\\', '/', $url);
50
+ $list[] = $url;
51
+ }
52
+ return array_values(array_unique($list));
53
+ }
54
+ }
app/Media/Convert.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Media;
4
+
5
+ use WebpConverter\Convert as ConvertMethod;
6
+
7
+ class Convert
8
+ {
9
+ public function __construct()
10
+ {
11
+ add_action('webpc_convert_paths', [$this, 'convertFilesByPaths']);
12
+ add_action('webpc_convert_attachment', [$this, 'convertFilesByAttachment']);
13
+ }
14
+
15
+ /* ---
16
+ Functions
17
+ --- */
18
+
19
+ public function convertFilesByPaths($paths)
20
+ {
21
+ $settings = apply_filters('webpc_get_values', []);
22
+
23
+ if ($settings['method'] === 'gd') $convert = new ConvertMethod\Gd();
24
+ else if ($settings['method'] === 'imagick') $convert = new ConvertMethod\Imagick();
25
+ if (!isset($convert)) return false;
26
+
27
+ foreach ($paths as $path) {
28
+ if (!in_array(pathinfo($path, PATHINFO_EXTENSION), $settings['extensions'])) continue;
29
+
30
+ $response = $convert->convertImage($path, $settings['quality']);
31
+ if (!$response['success']) $this->addErrorToLog($response['message']);
32
+ }
33
+ }
34
+
35
+ public function convertFilesByAttachment($postId)
36
+ {
37
+ $attachment = new Attachment();
38
+ $paths = $attachment->getAttachmentPaths($postId);
39
+ do_action('webpc_convert_paths', $paths);
40
+ }
41
+
42
+ private function addErrorToLog($message)
43
+ {
44
+ error_log(sprintf(
45
+ 'WebP Converter: %s',
46
+ $message
47
+ ));
48
+ }
49
+ }
app/Media/Upload.php CHANGED
@@ -2,10 +2,10 @@
2
 
3
  namespace WebpConverter\Media;
4
 
5
- use WebpConverter\Convert as Convert;
6
-
7
  class Upload
8
  {
 
 
9
  public function __construct()
10
  {
11
  add_filter('wp_update_attachment_metadata', [$this, 'initAttachmentConvert'], 10, 2);
@@ -18,50 +18,35 @@
18
  public function initAttachmentConvert($data, $attachmentId)
19
  {
20
  if (!$data || !isset($data['file']) || !isset($data['sizes'])) return $data;
21
- $path = $this->getAttachmentDirectory($data['file']);
22
- $sizes = [];
23
 
24
- $sizes['_source'] = $path . basename($data['file']);
25
- foreach ($data['sizes'] as $key => $size) {
26
- $url = $path . $size['file'];
27
- if (in_array($url, $sizes)) continue;
28
- $sizes[$key] = $url;
29
- }
30
 
31
- $sizes = apply_filters('webpc_attachment_paths', $sizes, $attachmentId);
32
- $this->convertSizes($sizes);
33
- return $data;
34
- }
35
 
36
- private function getAttachmentDirectory($path)
37
- {
38
- $upload = wp_upload_dir();
39
- $source = rtrim($upload['basedir'], '/\\') . '/' . rtrim(dirname($path), '/\\') . '/';
40
- $source = str_replace('\\', '/', $source);
41
- return $source;
42
  }
43
 
44
- private function convertSizes($paths)
45
  {
46
- $settings = apply_filters('webpc_get_values', []);
47
-
48
- if ($settings['method'] === 'gd') $convert = new Convert\Gd();
49
- else if ($settings['method'] === 'imagick') $convert = new Convert\Imagick();
50
- if (!isset($convert)) return false;
51
 
52
- foreach ($paths as $path) {
53
- if (!in_array(pathinfo($path, PATHINFO_EXTENSION), $settings['extensions'])) continue;
54
-
55
- $response = $convert->convertImage($path, $settings['quality']);
56
- if (!$response['success']) $this->addErrorToLog($response['message']);
57
  }
 
58
  }
59
 
60
- private function addErrorToLog($message)
61
  {
62
- error_log(sprintf(
63
- 'WebP Converter: %s',
64
- $message
65
- ));
66
  }
67
  }
2
 
3
  namespace WebpConverter\Media;
4
 
 
 
5
  class Upload
6
  {
7
+ private $convertedPaths = [];
8
+
9
  public function __construct()
10
  {
11
  add_filter('wp_update_attachment_metadata', [$this, 'initAttachmentConvert'], 10, 2);
18
  public function initAttachmentConvert($data, $attachmentId)
19
  {
20
  if (!$data || !isset($data['file']) || !isset($data['sizes'])) return $data;
 
 
21
 
22
+ $paths = $this->getSizesPaths($data);
23
+ $paths = apply_filters('webpc_attachment_paths', $paths, $attachmentId);
 
 
 
 
24
 
25
+ $paths = array_diff($paths, $this->convertedPaths);
26
+ $this->convertedPaths = array_merge($this->convertedPaths, $paths);
 
 
27
 
28
+ do_action('webpc_convert_paths', $paths);
29
+ return $data;
 
 
 
 
30
  }
31
 
32
+ private function getSizesPaths($data)
33
  {
34
+ $directory = $this->getAttachmentDirectory($data['file']);
35
+ $list = [];
 
 
 
36
 
37
+ $list[] = $directory . basename($data['file']);
38
+ foreach ($data['sizes'] as $key => $size) {
39
+ $path = $directory . $size['file'];
40
+ if (!in_array($path, $list)) $list[] = $path;
 
41
  }
42
+ return array_values(array_unique($list));
43
  }
44
 
45
+ private function getAttachmentDirectory($path)
46
  {
47
+ $upload = wp_upload_dir();
48
+ $source = rtrim($upload['basedir'], '/\\') . '/' . rtrim(dirname($path), '/\\') . '/';
49
+ $source = str_replace('\\', '/', $source);
50
+ return $source;
51
  }
52
  }
app/Media/_Core.php CHANGED
@@ -6,6 +6,7 @@
6
  {
7
  public function __construct()
8
  {
 
9
  new Delete();
10
  new Htaccess();
11
  new Upload();
6
  {
7
  public function __construct()
8
  {
9
+ new Convert();
10
  new Delete();
11
  new Htaccess();
12
  new Upload();
app/Regenerate/Endpoints.php CHANGED
@@ -2,8 +2,6 @@
2
 
3
  namespace WebpConverter\Regenerate;
4
 
5
- use WebpConverter\Convert as Convert;
6
-
7
  class Endpoints
8
  {
9
  public $namespace = 'webp-converter/v1';
@@ -31,7 +29,16 @@
31
  && current_user_can('manage_options'));
32
  },
33
  'callback' => [$this, 'getPaths'],
34
- 'args' => [],
 
 
 
 
 
 
 
 
 
35
  ]
36
  );
37
 
@@ -62,7 +69,7 @@
62
  public function getPaths($request)
63
  {
64
  $params = $request->get_params();
65
- if (isset($params['skip']) && $params['skip']) new Skip();
66
 
67
  $api = new Paths();
68
  $data = $api->getPaths();
2
 
3
  namespace WebpConverter\Regenerate;
4
 
 
 
5
  class Endpoints
6
  {
7
  public $namespace = 'webp-converter/v1';
29
  && current_user_can('manage_options'));
30
  },
31
  'callback' => [$this, 'getPaths'],
32
+ 'args' => [
33
+ 'skip_converted' => [
34
+ 'description' => 'Option to skip converted images (set `1` to enable)',
35
+ 'required' => false,
36
+ 'default' => false,
37
+ 'sanitize_callback' => function($value, $request, $param) {
38
+ return ($value === '1') ? true : false;
39
+ }
40
+ ],
41
+ ],
42
  ]
43
  );
44
 
69
  public function getPaths($request)
70
  {
71
  $params = $request->get_params();
72
+ if ($params['skip_converted']) new Skip();
73
 
74
  $api = new Paths();
75
  $data = $api->getPaths();
app/Regenerate/Paths.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace WebpConverter\Regenerate;
4
 
 
 
5
  class Paths
6
  {
7
  /* ---
@@ -10,8 +12,7 @@
10
 
11
  public function getPaths()
12
  {
13
- $sizes = get_intermediate_image_sizes();
14
- $posts = get_posts([
15
  'post_type' => 'attachment',
16
  'post_mime_type' => 'image',
17
  'post_status' => 'any',
@@ -19,44 +20,19 @@
19
  'fields' => 'ids',
20
  ]);
21
 
22
- $list = $this->parseImages($posts, $sizes);
23
  wp_send_json_success($list);
24
  }
25
 
26
- private function parseImages($posts, $sizes)
27
- {
28
- $settings = apply_filters('webpc_get_values', []);
29
- $upload = wp_upload_dir();
30
- $list = [];
31
- if (!$posts) return $list;
32
-
33
- foreach ($posts as $postId) {
34
- $metadata = wp_get_attachment_metadata($postId);
35
- if (!isset($metadata['file'])
36
- || !in_array(pathinfo($metadata['file'], PATHINFO_EXTENSION), $settings['extensions'])) continue;
37
-
38
- $paths = $this->parseImageSizes($postId, $metadata['file'], $sizes, $upload);
39
- $paths = apply_filters('webpc_attachment_paths', $paths, $postId);
40
-
41
- if (!$paths) continue;
42
- $list[] = $paths;
43
- }
44
-
45
- $list = array_filter($list);
46
- return $list;
47
- }
48
-
49
- private function parseImageSizes($postId, $path, $sizes, $upload)
50
  {
51
  $list = [];
52
- $list['_source'] = str_replace('\\', '/', implode('/', [$upload['basedir'], $path]));
53
- foreach ($sizes as $size) {
54
- $src = wp_get_attachment_image_src($postId, $size);
55
- $url = str_replace($upload['baseurl'], $upload['basedir'], $src[0]);
56
- $url = str_replace('\\', '/', $url);
57
 
58
- if (in_array($url, $list)) continue;
59
- $list[$size] = $url;
 
 
60
  }
61
  return $list;
62
  }
2
 
3
  namespace WebpConverter\Regenerate;
4
 
5
+ use WebpConverter\Media\Attachment as Attachment;
6
+
7
  class Paths
8
  {
9
  /* ---
12
 
13
  public function getPaths()
14
  {
15
+ $postIds = get_posts([
 
16
  'post_type' => 'attachment',
17
  'post_mime_type' => 'image',
18
  'post_status' => 'any',
20
  'fields' => 'ids',
21
  ]);
22
 
23
+ $list = $this->getPathsByAttachments($postIds);
24
  wp_send_json_success($list);
25
  }
26
 
27
+ private function getPathsByAttachments($postIds)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  {
29
  $list = [];
30
+ if (!$postIds) return $list;
 
 
 
 
31
 
32
+ $attachment = new Attachment();
33
+ foreach ($postIds as $postId) {
34
+ $paths = $attachment->getAttachmentPaths($postId);
35
+ if ($paths) $list[] = $paths;
36
  }
37
  return $list;
38
  }
app/Regenerate/Regenerate.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  namespace WebpConverter\Regenerate;
4
 
5
- use WebpConverter\Convert as Convert;
6
 
7
  class Regenerate
8
  {
@@ -17,8 +17,8 @@
17
  $sizeBefore = 0;
18
  $sizeAfter = 0;
19
 
20
- if ($settings['method'] === 'gd') $convert = new Convert\Gd();
21
- else if ($settings['method'] === 'imagick') $convert = new Convert\Imagick();
22
  if (!isset($convert)) return false;
23
 
24
  foreach ($paths as $path) {
2
 
3
  namespace WebpConverter\Regenerate;
4
 
5
+ use WebpConverter\Convert as ConvertMethod;
6
 
7
  class Regenerate
8
  {
17
  $sizeBefore = 0;
18
  $sizeAfter = 0;
19
 
20
+ if ($settings['method'] === 'gd') $convert = new ConvertMethod\Gd();
21
+ else if ($settings['method'] === 'imagick') $convert = new ConvertMethod\Imagick();
22
  if (!isset($convert)) return false;
23
 
24
  foreach ($paths as $path) {
app/Settings/Options.php CHANGED
@@ -6,15 +6,14 @@
6
  {
7
  public function __construct()
8
  {
9
- add_filter('webpc_get_options', [$this, 'getOptions']);
10
- add_filter('webpc_option_disabled', [$this, 'setDisabledValues'], 10, 2);
11
  }
12
 
13
  /* ---
14
  Functions
15
  --- */
16
 
17
- public function getOptions()
18
  {
19
  return [
20
  [
@@ -28,7 +27,7 @@
28
  'png' => '.png',
29
  'gif' => '.gif',
30
  ],
31
- 'disabled' => apply_filters('webpc_option_disabled', [], 'extensions'),
32
  ],
33
  [
34
  'name' => 'method',
@@ -39,7 +38,7 @@
39
  'gd' => sprintf(__('%s (recommended)', 'webp-converter'), 'GD'),
40
  'imagick' => 'Imagick',
41
  ],
42
- 'disabled' => apply_filters('webpc_option_disabled', [], 'method'),
43
  ],
44
  [
45
  'name' => 'features',
@@ -50,7 +49,7 @@
50
  'only_smaller' => __('Automatic removal of WebP files larger than original', 'webp-converter'),
51
  'mod_expires' => __('Browser Caching for WebP files (saving images in browser cache memory)', 'webp-converter'),
52
  ],
53
- 'disabled' => apply_filters('webpc_option_disabled', [], 'features'),
54
  ],
55
  [
56
  'name' => 'quality',
@@ -65,14 +64,15 @@
65
  '95' => '95%',
66
  '100' => '100%',
67
  ],
68
- 'disabled' => apply_filters('webpc_option_disabled', [], 'quality'),
69
  ],
70
  ];
71
  }
72
 
73
- public function setDisabledValues($list, $name)
74
  {
75
- switch ($name) {
 
76
  case 'method':
77
  $methods = apply_filters('webpc_get_methods', []);
78
  if (!in_array('gd', $methods)) $list[] = 'gd';
6
  {
7
  public function __construct()
8
  {
9
+ add_filter('webpc_get_options', [$this, 'getOptions']);
 
10
  }
11
 
12
  /* ---
13
  Functions
14
  --- */
15
 
16
+ public function getOptions($options)
17
  {
18
  return [
19
  [
27
  'png' => '.png',
28
  'gif' => '.gif',
29
  ],
30
+ 'disabled' => $this->getDisabledValues('extensions'),
31
  ],
32
  [
33
  'name' => 'method',
38
  'gd' => sprintf(__('%s (recommended)', 'webp-converter'), 'GD'),
39
  'imagick' => 'Imagick',
40
  ],
41
+ 'disabled' => $this->getDisabledValues('method'),
42
  ],
43
  [
44
  'name' => 'features',
49
  'only_smaller' => __('Automatic removal of WebP files larger than original', 'webp-converter'),
50
  'mod_expires' => __('Browser Caching for WebP files (saving images in browser cache memory)', 'webp-converter'),
51
  ],
52
+ 'disabled' => $this->getDisabledValues('features'),
53
  ],
54
  [
55
  'name' => 'quality',
64
  '95' => '95%',
65
  '100' => '100%',
66
  ],
67
+ 'disabled' => $this->getDisabledValues('quality'),
68
  ],
69
  ];
70
  }
71
 
72
+ private function getDisabledValues($optionName)
73
  {
74
+ $list = [];
75
+ switch ($optionName) {
76
  case 'method':
77
  $methods = apply_filters('webpc_get_methods', []);
78
  if (!in_array('gd', $methods)) $list[] = 'gd';
public/build/js/scripts.js CHANGED
@@ -1 +1 @@
1
- !function(e){var t={};function r(s){if(t[s])return t[s].exports;var i=t[s]={i:s,l:!1,exports:{}};return e[s].call(i.exports,i,i.exports,r),i.l=!0,i.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 i in e)r.d(s,i,function(t){return e[t]}.bind(null,i));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 i=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,i;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),i&&s(t,i),e}();function n(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.skipOption=this.section.querySelector('input[name="regenerate_skip"]'),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"),errorMessage:this.section.getAttribute("data-api-error-message")},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.skipOption.setAttribute("disabled",!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",data:{skip:this.skipOption.checked?1:0}}).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.errors),t.updateSize(e),t.updateProgress(),t.regenerateNextImages()})).fail((function(){var r=JSON.stringify(e),s=t.settings.ajax.errorMessage.replace("%s","<code>".concat(r,"</code>"));t.updateErrors([s]),t.regenerateNextImages()}))}},{key:"updateErrors",value:function(e){0!==e.length&&(this.data.errors=this.data.errors.concat(e),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 i=-1;do{i++,r/=1024}while(r>1024);var n=r.toFixed(2),a=this.settings.units[i],o="".concat(n," ").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)}}])&&n(t.prototype,r),s&&n(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 i,new a}},function(e,t){}]);
1
+ !function(e){var t={};function r(s){if(t[s])return t[s].exports;var i=t[s]={i:s,l:!1,exports:{}};return e[s].call(i.exports,i,i.exports,r),i.l=!0,i.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 i in e)r.d(s,i,function(t){return e[t]}.bind(null,i));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 i=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,i;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),i&&s(t,i),e}();function n(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.skipOption=this.section.querySelector('input[name="regenerate_skip"]'),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"),errorMessage:this.section.getAttribute("data-api-error-message")},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.skipOption.setAttribute("disabled",!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",data:{skip_converted:this.skipOption.checked?1:0}}).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.errors),t.updateSize(e),t.updateProgress(),t.regenerateNextImages()})).fail((function(){var r=JSON.stringify(e),s=t.settings.ajax.errorMessage.replace("%s","<code>".concat(r,"</code>"));t.updateErrors([s]),t.regenerateNextImages()}))}},{key:"updateErrors",value:function(e){0!==e.length&&(this.data.errors=this.data.errors.concat(e),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 i=-1;do{i++,r/=1024}while(r>1024);var n=r.toFixed(2),a=this.settings.units[i],o="".concat(n," ").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)}}])&&n(t.prototype,r),s&&n(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 i,new a}},function(e,t){}]);
readme.txt CHANGED
@@ -233,6 +233,58 @@ add_filter('webpc_uploads_webp', function($path) {
233
 
234
  After setting the filters go to `Settings -> WebP Converter` in the admin panel and click the `Save Changes` button. `.htaccess` file with appropriate rules should be created in the `/uploads` directory.
235
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  = What is Browser Caching? =
237
 
238
  This option allows you to speed up page loading time for returning users because they do not need to re-download files from the server. The plugin allows this by using the module `mod_expires`.
@@ -333,6 +385,12 @@ This is all very important to us and allows us to do even better things for you!
333
 
334
  == Changelog ==
335
 
 
 
 
 
 
 
336
  = 1.2.0 (2020-04-05) =
337
  * `[Changed]` Moving rules from .htaccess file in root directory of WordPress to `/wp-content/uploads` directory
338
  * `[Added]` Ability to disable automatic removal of WebP files larger than original
233
 
234
  After setting the filters go to `Settings -> WebP Converter` in the admin panel and click the `Save Changes` button. `.htaccess` file with appropriate rules should be created in the `/uploads` directory.
235
 
236
+ = How to run manually conversion? =
237
+
238
+ By default, all images are converted when you click on the `Regenerate All` button. In addition, conversion is automatic when you add new files to your media library.
239
+
240
+ To manually start converting selected files, you can use the action to which you will pass an array with a list of paths *(they must be absolute server paths)*:
241
+
242
+ `do_action('webpc_convert_paths', $paths);`
243
+
244
+ An alternative method is to manually start converting the selected attachment by passing the post ID from the media library. Remember to run this action after registering all image sizes *(i.e. after running the `add_image_size` function)*:
245
+
246
+ `do_action('webpc_convert_attachment', $postId);`
247
+
248
+ In addition, you can edit the list of files that will be converted. For example, to add some to the exceptions. To do this, use the following filter, which by default returns a list of all paths:
249
+
250
+ `add_filter('webpc_attachment_paths', function($paths, $attachmentId) {
251
+ return $paths;
252
+ }, 10, 2);`
253
+
254
+ Argument `$paths` is array of absolute server paths and `$attachmentId` is the post ID of attachment, added to the media library.
255
+
256
+ = How to change .htaccess rules? =
257
+
258
+ Manually editing the rules in the .htaccess file is a task only for experienced developers. Remember that the wrong rules can cause your website to stop working.
259
+
260
+ Below is a list of filters that allow you to modify all rules. Remember that it's best to use your own rule set rather than edit parts of exists. This will ensure greater failure-free after plugin update.
261
+
262
+ Returning an empty string will delete these rules the next time you save the plugin settings. You must do this after each filter edit.
263
+
264
+ All rules from the .htaccess file: *(returns rules for modules: `mod_mime`, `mod_rewrite` and `mod_expires`)*:
265
+
266
+ `add_filter('webpc_htaccess_rules', function($rules) {
267
+ return '';
268
+ });`
269
+
270
+ Rules for `image/webp` MIME type: *(returns rules for `mod_mime` module)*:
271
+
272
+ `add_filter('webpc_htaccess_mod_mime', function($rules) {
273
+ return '';
274
+ });`
275
+
276
+ Rules for redirects: *(returns rules for `mod_rewrite` module)*:
277
+
278
+ `add_filter('webpc_htaccess_mod_rewrite', function($rules) {
279
+ return '';
280
+ });`
281
+
282
+ Rules for Browser Caching: *(returns rules for `mod_expires` module)*:
283
+
284
+ `add_filter('webpc_htaccess_mod_expires', function($rules) {
285
+ return '';
286
+ });`
287
+
288
  = What is Browser Caching? =
289
 
290
  This option allows you to speed up page loading time for returning users because they do not need to re-download files from the server. The plugin allows this by using the module `mod_expires`.
385
 
386
  == Changelog ==
387
 
388
+ = 1.2.1 (2020-04-07) =
389
+ * `[Removed]` Filter `webpc_option_disabled`
390
+ * `[Fixed]` Converting images multiple times when uploading to media library
391
+ * `[Added]` Action `webpc_convert_paths` to convert images by paths
392
+ * `[Added]` Action `webpc_convert_attachment` to convert images by Post ID
393
+
394
  = 1.2.0 (2020-04-05) =
395
  * `[Changed]` Moving rules from .htaccess file in root directory of WordPress to `/wp-content/uploads` directory
396
  * `[Added]` Ability to disable automatic removal of WebP files larger than original
resources/_dev/js/classes/Regenerate.js CHANGED
@@ -76,7 +76,7 @@ export default class Regenerate
76
  jQuery.ajax(this.settings.ajax.urlPaths, {
77
  type: 'POST',
78
  data: {
79
- skip: this.skipOption.checked ? 1 : 0,
80
  },
81
  }).done((response) => {
82
  this.data.items = response.data;
76
  jQuery.ajax(this.settings.ajax.urlPaths, {
77
  type: 'POST',
78
  data: {
79
+ skip_converted: this.skipOption.checked ? 1 : 0,
80
  },
81
  }).done((response) => {
82
  this.data.items = response.data;
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.2.0
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter
10
  */
11
 
12
- define('WEBPC_VERSION', '1.2.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.2.1
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter
10
  */
11
 
12
+ define('WEBPC_VERSION', '1.2.1');
13
  define('WEBPC_FILE', __FILE__);
14
  define('WEBPC_NAME', plugin_basename(__FILE__));
15
  define('WEBPC_PATH', plugin_dir_path(__FILE__));