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

Version Description

(2020-06-12) = * [Removed] Ability to skip converting existing images when Regenerate All * [Fixed] Creating /uploads-webpc directory webpc after re-activation plugin * [Fixed] Error message about not supporting old PHP version * [Fixed] Ignoring case sensitivity when verifying image extensions * [Changed] Error messages when converting images * [Changed] New argument for filter webpc_htaccess_mod_rewrite and support for multiple .htaccess files * [Added] Converting all images from /uploads directory (also other than from Media Library). * [Added] Converting images from /plugins directory * [Added] Converting images from /themes directory * [Added] Information about used filters in Server configuration tab * [Added] Option to force all images to be converted again when Regenerate All

Download this release

Release Info

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

Code changes from version 1.2.7 to 1.3.0

app/Action/Convert.php CHANGED
@@ -11,6 +11,7 @@
11
  {
12
  add_action('webpc_convert_paths', [$this, 'convertFilesByPaths']);
13
  add_action('webpc_convert_attachment', [$this, 'convertFilesByAttachment']);
 
14
  }
15
 
16
  /* ---
@@ -26,7 +27,8 @@
26
  if (!isset($convert)) return false;
27
 
28
  foreach ($paths as $path) {
29
- if (!in_array(pathinfo($path, PATHINFO_EXTENSION), $settings['extensions'])) continue;
 
30
 
31
  $response = $convert->convertImage($path, $settings['quality']);
32
  if (!$response['success']) $this->addErrorToLog($response['message']);
@@ -39,10 +41,16 @@
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
  }
11
  {
12
  add_action('webpc_convert_paths', [$this, 'convertFilesByPaths']);
13
  add_action('webpc_convert_attachment', [$this, 'convertFilesByAttachment']);
14
+ add_action('webpc_convert_dir', [$this, 'convertFilesByDirectory'], 10, 2);
15
  }
16
 
17
  /* ---
27
  if (!isset($convert)) return false;
28
 
29
  foreach ($paths as $path) {
30
+ $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
31
+ if (!in_array($extension, $settings['extensions'])) continue;
32
 
33
  $response = $convert->convertImage($path, $settings['quality']);
34
  if (!$response['success']) $this->addErrorToLog($response['message']);
41
  do_action('webpc_convert_paths', $paths);
42
  }
43
 
44
+ public function convertFilesByDirectory($dirPath, $skipExists = true)
45
+ {
46
+ $paths = apply_filters('webpc_dir_files', [], $dirPath, $skipExists);
47
+ do_action('webpc_convert_paths', $paths);
48
+ }
49
+
50
  private function addErrorToLog($message)
51
  {
52
  error_log(sprintf(
53
+ 'WebP Converter for Media (Error): %s',
54
  $message
55
  ));
56
  }
app/Action/Dir.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Action;
4
+
5
+ class Dir
6
+ {
7
+ public function __construct()
8
+ {
9
+ add_filter('webpc_dir_files', [$this, 'getFilesByDirectory'], 10, 3);
10
+ }
11
+
12
+ /* ---
13
+ Functions
14
+ --- */
15
+
16
+ public function getFilesByDirectory($value, $dirPath, $skipExists = false)
17
+ {
18
+ if (!file_exists($dirPath)) return $value;
19
+
20
+ $settings = apply_filters('webpc_get_values', []);
21
+ $excluded = apply_filters('webpc_dir_excluded', []);
22
+
23
+ $paths = $this->findFilesInDirectory($dirPath, $settings['extensions'], $excluded);
24
+ return apply_filters('webpc_attachment_paths', $paths, $skipExists);
25
+ }
26
+
27
+ private function findFilesInDirectory($dirPath, $allowedExts, $excludedDirs)
28
+ {
29
+ $paths = scandir($dirPath);
30
+ $list = [];
31
+ foreach ($paths as $path) {
32
+ if (in_array($path, $excludedDirs)) continue;
33
+
34
+ $currentPath = $dirPath . '/' . $path;
35
+ if (is_dir($currentPath)) {
36
+ $list = array_merge($list, $this->findFilesInDirectory($currentPath, $allowedExts, $excludedDirs));
37
+ } else if (in_array(strtolower(pathinfo($currentPath, PATHINFO_EXTENSION)), $allowedExts)) {
38
+ $list[] = $currentPath;
39
+ }
40
+ }
41
+ return $list;
42
+ }
43
+ }
app/Action/Regenerate.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Action;
4
+
5
+ use WebpConverter\Regenerate\Paths;
6
+
7
+ class Regenerate
8
+ {
9
+ public function __construct()
10
+ {
11
+ add_action('webpc_regenerate_all', [$this, 'runRegenerationAllImages']);
12
+ }
13
+
14
+ /* ---
15
+ Functions
16
+ --- */
17
+
18
+ public function runRegenerationAllImages()
19
+ {
20
+ $paths = (new Paths())->getPaths(true);
21
+ do_action('webpc_convert_paths', $paths);
22
+ }
23
+ }
app/Action/_Core.php CHANGED
@@ -8,5 +8,7 @@
8
  {
9
  new Convert();
10
  new Delete();
 
 
11
  }
12
  }
8
  {
9
  new Convert();
10
  new Delete();
11
+ new Dir();
12
+ new Regenerate();
13
  }
14
  }
app/Admin/Activation.php CHANGED
@@ -4,6 +4,8 @@
4
 
5
  class Activation
6
  {
 
 
7
  public function __construct()
8
  {
9
  register_activation_hook(WEBPC_FILE, [$this, 'disablePluginForOldPhp']);
@@ -18,14 +20,14 @@
18
 
19
  public function disablePluginForOldPhp()
20
  {
21
- if (version_compare(PHP_VERSION, '5.6.12', '>=')) return;
22
 
23
  deactivate_plugins(basename(WEBPC_FILE));
24
  wp_die(sprintf(
25
  __('%sWebP Converter for Media%s plugin requires a minimum PHP %s version. Sorry about that!', 'webp-converter'),
26
  '<strong>',
27
  '</strong>',
28
- $this->version
29
  ));
30
  }
31
 
4
 
5
  class Activation
6
  {
7
+ private $phpVersion = '7.0.0';
8
+
9
  public function __construct()
10
  {
11
  register_activation_hook(WEBPC_FILE, [$this, 'disablePluginForOldPhp']);
20
 
21
  public function disablePluginForOldPhp()
22
  {
23
+ if (version_compare(PHP_VERSION, $this->phpVersion, '>=')) return;
24
 
25
  deactivate_plugins(basename(WEBPC_FILE));
26
  wp_die(sprintf(
27
  __('%sWebP Converter for Media%s plugin requires a minimum PHP %s version. Sorry about that!', 'webp-converter'),
28
  '<strong>',
29
  '</strong>',
30
+ $this->phpVersion
31
  ));
32
  }
33
 
app/Admin/Update.php CHANGED
@@ -35,11 +35,14 @@
35
  {
36
  $settings = apply_filters('webpc_get_values', []);
37
 
38
- if (version_compare($version, '1.1.2', '<=')) {
39
  $settings['features'][] = 'only_smaller';
40
  }
41
 
42
- $settings['features'] = array_unique($settings['features']);
 
 
 
43
  return $settings;
44
  }
45
 
35
  {
36
  $settings = apply_filters('webpc_get_values', []);
37
 
38
+ if (version_compare($version, '1.1.2', '<=') && !in_array('only_smaller', $settings['features'])) {
39
  $settings['features'][] = 'only_smaller';
40
  }
41
 
42
+ if (version_compare($version, '1.2.7', '<=') && !isset($settings['dirs'])) {
43
+ $settings['dirs'] = ['uploads'];
44
+ }
45
+
46
  return $settings;
47
  }
48
 
app/Convert/Gd.php CHANGED
@@ -41,7 +41,7 @@
41
 
42
  private function createImage($path)
43
  {
44
- $extension = pathinfo($path, PATHINFO_EXTENSION);
45
  $methods = apply_filters('webpc_gd_create_methods', [
46
  'imagecreatefromjpeg' => ['jpg', 'jpeg'],
47
  'imagecreatefrompng' => ['png'],
41
 
42
  private function createImage($path)
43
  {
44
+ $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
45
  $methods = apply_filters('webpc_gd_create_methods', [
46
  'imagecreatefromjpeg' => ['jpg', 'jpeg'],
47
  'imagecreatefrompng' => ['png'],
app/Convert/Imagick.php CHANGED
@@ -37,7 +37,7 @@
37
 
38
  private function createImage($path)
39
  {
40
- $extension = pathinfo($path, PATHINFO_EXTENSION);
41
  try {
42
  if (!extension_loaded('imagick') || !class_exists('Imagick')) {
43
  throw new \Exception('Server configuration: Imagick module is not available with this PHP installation.');
37
 
38
  private function createImage($path)
39
  {
40
+ $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
41
  try {
42
  if (!extension_loaded('imagick') || !class_exists('Imagick')) {
43
  throw new \Exception('Server configuration: Imagick module is not available with this PHP installation.');
app/Convert/Size.php CHANGED
@@ -20,6 +20,10 @@
20
  || (!file_exists($webpPath) || !file_exists($originalPath))
21
  || (filesize($webpPath) < filesize($originalPath))) return;
22
 
 
 
 
 
23
  unlink($webpPath);
24
  }
25
  }
20
  || (!file_exists($webpPath) || !file_exists($originalPath))
21
  || (filesize($webpPath) < filesize($originalPath))) return;
22
 
23
+ error_log(sprintf(
24
+ 'WebP Converter for Media (Information): Image `%s` converted to WebP is larger than original and has been deleted.',
25
+ $webpPath
26
+ ));
27
  unlink($webpPath);
28
  }
29
  }
app/Media/Attachment.php CHANGED
@@ -29,7 +29,7 @@
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
 
29
  $metadata = wp_get_attachment_metadata($postId);
30
  if (!$metadata) return $list;
31
 
32
+ $extension = strtolower(pathinfo($metadata['file'], PATHINFO_EXTENSION));
33
  if (!isset($metadata['file'])
34
  || !in_array($extension, $this->settings['extensions'])) return $list;
35
 
app/Media/Htaccess.php CHANGED
@@ -6,6 +6,7 @@
6
  {
7
  public function __construct()
8
  {
 
9
  add_action('webpc_rewrite_htaccess', [$this, 'addRewriteRulesToUploads'], 10, 1);
10
  add_action('webpc_rewrite_htaccess', [$this, 'addRewriteRulesToUploadsWebp'], 10, 1);
11
  }
@@ -14,6 +15,21 @@
14
  Functions
15
  --- */
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  public function addRewriteRulesToUploads($isActive)
18
  {
19
  $path = apply_filters('webpc_uploads_path', '');
@@ -63,7 +79,7 @@
63
  }
64
  $content .= '</IfModule>';
65
 
66
- $content = apply_filters('webpc_htaccess_mod_rewrite', $content);
67
  return $content;
68
  }
69
 
6
  {
7
  public function __construct()
8
  {
9
+ add_action('webpc_rewrite_htaccess', [$this, 'addRewriteRulesToWpContent'], 10, 1);
10
  add_action('webpc_rewrite_htaccess', [$this, 'addRewriteRulesToUploads'], 10, 1);
11
  add_action('webpc_rewrite_htaccess', [$this, 'addRewriteRulesToUploadsWebp'], 10, 1);
12
  }
15
  Functions
16
  --- */
17
 
18
+ public function addRewriteRulesToWpContent($isActive)
19
+ {
20
+ $path = dirname(apply_filters('webpc_uploads_path', ''));
21
+ if (!$isActive) return $this->saveRewritesInHtaccesss($path);
22
+
23
+ $values = apply_filters('webpc_get_values', []);
24
+ $rows = [
25
+ $this->getModRewriteRules($values),
26
+ ];
27
+
28
+ $content = $this->addCommentsToRules($rows);
29
+ $content = apply_filters('webpc_htaccess_rules', $content, $path . '/.htaccess');
30
+ $this->saveRewritesInHtaccesss($path, $content);
31
+ }
32
+
33
  public function addRewriteRulesToUploads($isActive)
34
  {
35
  $path = apply_filters('webpc_uploads_path', '');
79
  }
80
  $content .= '</IfModule>';
81
 
82
+ $content = apply_filters('webpc_htaccess_mod_rewrite', $content, $path);
83
  return $content;
84
  }
85
 
app/Regenerate/Endpoints.php CHANGED
@@ -30,8 +30,8 @@
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) {
@@ -68,10 +68,10 @@
68
 
69
  public function getPaths($request)
70
  {
71
- $params = $request->get_params();
72
- if ($params['skip_converted']) new Skip();
73
 
74
- $data = (new Paths())->getPaths();
75
  if ($data !== false) return new \WP_REST_Response($data, 200);
76
  else return new \WP_Error('webpc_rest_api_error', null, ['status' => 405]);
77
  }
30
  },
31
  'callback' => [$this, 'getPaths'],
32
  'args' => [
33
+ 'regenerate_force' => [
34
+ 'description' => 'Option to force all images to be converted again (set `1` to enable)',
35
  'required' => false,
36
  'default' => false,
37
  'sanitize_callback' => function($value, $request, $param) {
68
 
69
  public function getPaths($request)
70
  {
71
+ $params = $request->get_params();
72
+ $skipExists = (!$params['regenerate_force']) ? true : false;
73
 
74
+ $data = (new Paths())->getPaths($skipExists, 10);
75
  if ($data !== false) return new \WP_REST_Response($data, 200);
76
  else return new \WP_Error('webpc_rest_api_error', null, ['status' => 405]);
77
  }
app/Regenerate/Paths.php CHANGED
@@ -2,38 +2,26 @@
2
 
3
  namespace WebpConverter\Regenerate;
4
 
5
- use WebpConverter\Media\Attachment;
6
-
7
  class Paths
8
  {
9
  /* ---
10
  Functions
11
  --- */
12
 
13
- public function getPaths()
14
  {
15
- $postIds = get_posts([
16
- 'post_type' => 'attachment',
17
- 'post_mime_type' => 'image',
18
- 'post_status' => 'any',
19
- 'posts_per_page' => -1,
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
  }
39
  }
2
 
3
  namespace WebpConverter\Regenerate;
4
 
 
 
5
  class Paths
6
  {
7
  /* ---
8
  Functions
9
  --- */
10
 
11
+ public function getPaths($skipExists = false, $chunkSize = null)
12
  {
13
+ $settings = apply_filters('webpc_get_values', []);
14
+ $dirs = array_filter(array_map(function($dirName) {
15
+ return apply_filters('webpc_dir_path', '', $dirName);
16
+ }, $settings['dirs']));
 
 
 
 
 
 
 
17
 
 
 
18
  $list = [];
19
+ foreach ($dirs as $dirPath) {
20
+ $paths = apply_filters('webpc_dir_files', [], $dirPath, $skipExists);
21
+ $list = array_merge($list, $paths);
 
 
 
22
  }
23
+
24
+ if ($chunkSize === null) return $list;
25
+ return array_chunk($list, $chunkSize);
26
  }
27
  }
app/Regenerate/Skip.php CHANGED
@@ -8,17 +8,18 @@
8
  {
9
  public function __construct()
10
  {
11
- add_filter('webpc_attachment_paths', [$this, 'skipExistsImages']);
12
  }
13
 
14
  /* ---
15
  Functions
16
  --- */
17
 
18
- public function skipExistsImages($paths)
19
  {
20
- $directory = new Directory();
21
 
 
22
  foreach ($paths as $key => $path) {
23
  $output = $directory->getPath($path, false);
24
  if (file_exists($output)) unset($paths[$key]);
8
  {
9
  public function __construct()
10
  {
11
+ add_filter('webpc_attachment_paths', [$this, 'skipExistsImages'], 10, 2);
12
  }
13
 
14
  /* ---
15
  Functions
16
  --- */
17
 
18
+ public function skipExistsImages($paths, $skipExists = false)
19
  {
20
+ if (!$skipExists) return $paths;
21
 
22
+ $directory = new Directory();
23
  foreach ($paths as $key => $path) {
24
  $output = $directory->getPath($path, false);
25
  if (file_exists($output)) unset($paths[$key]);
app/Regenerate/_Core.php CHANGED
@@ -7,5 +7,6 @@
7
  public function __construct()
8
  {
9
  new Endpoints();
 
10
  }
11
  }
7
  public function __construct()
8
  {
9
  new Endpoints();
10
+ new Skip();
11
  }
12
  }
app/Settings/Options.php CHANGED
@@ -29,6 +29,18 @@
29
  ],
30
  'disabled' => $this->getDisabledValues('extensions'),
31
  ],
 
 
 
 
 
 
 
 
 
 
 
 
32
  [
33
  'name' => 'method',
34
  'type' => 'radio',
@@ -77,6 +89,7 @@
77
  $methods = apply_filters('webpc_get_methods', []);
78
  if (!in_array('gd', $methods)) $list[] = 'gd';
79
  if (!in_array('imagick', $methods)) $list[] = 'imagick';
 
80
  }
81
  return $list;
82
  }
29
  ],
30
  'disabled' => $this->getDisabledValues('extensions'),
31
  ],
32
+ [
33
+ 'name' => 'dirs',
34
+ 'type' => 'checkbox',
35
+ 'label' => __('List of supported directories', 'webp-converter'),
36
+ 'info' => __('Files from these directories will be supported in WebP format.', 'webp-converter'),
37
+ 'values' => [
38
+ 'plugins' => '/plugins',
39
+ 'themes' => '/themes',
40
+ 'uploads' => '/uploads',
41
+ ],
42
+ 'disabled' => $this->getDisabledValues('dirs'),
43
+ ],
44
  [
45
  'name' => 'method',
46
  'type' => 'radio',
89
  $methods = apply_filters('webpc_get_methods', []);
90
  if (!in_array('gd', $methods)) $list[] = 'gd';
91
  if (!in_array('imagick', $methods)) $list[] = 'imagick';
92
+ break;
93
  }
94
  return $list;
95
  }
app/Settings/Paths.php CHANGED
@@ -4,17 +4,20 @@
4
 
5
  class Paths
6
  {
7
- private $pathUploads = 'wp-content/uploads';
8
- private $pathOutput = 'wp-content/uploads-webpc';
 
9
 
10
  public function __construct()
11
  {
12
- add_filter('webpc_uploads_path', [$this, 'getUploadsPath'], 0, 2);
13
- add_filter('webpc_uploads_webp', [$this, 'getOutputPath'], 0, 2);
14
- add_filter('webpc_uploads_path', [$this, 'parsePath'], 100, 2);
15
- add_filter('webpc_uploads_webp', [$this, 'parsePath'], 100, 2);
16
- add_filter('webpc_uploads_prefix', [$this, 'getPrefixPath'], 0);
17
- add_filter('webpc_uploads_dir', [$this, 'getUploadsDir'], 0);
 
 
18
  }
19
 
20
  /* ---
@@ -51,13 +54,36 @@
51
 
52
  public function getUploadsDir($value)
53
  {
54
- $uploadsDir = apply_filters('webpc_uploads_path', '');
55
- $parentDir = dirname(apply_filters('webpc_uploads_webp', ''));
56
- if ((!$uploadsDir = realpath($uploadsDir)) || (!$parentDir = realpath($parentDir))) {
 
 
57
  return $value;
58
  }
59
 
60
- $path = str_replace($parentDir, '', $uploadsDir);
61
  return trim($path, '\/');
62
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
4
 
5
  class Paths
6
  {
7
+ private $pathUploads = 'wp-content/uploads';
8
+ private $pathOutput = 'wp-content/uploads-webpc';
9
+ private $dirsExcluded = ['.', '..', '.git', '.svn', 'node_modules'];
10
 
11
  public function __construct()
12
  {
13
+ add_filter('webpc_uploads_path', [$this, 'getUploadsPath'], 0, 2);
14
+ add_filter('webpc_uploads_webp', [$this, 'getOutputPath'], 0, 2);
15
+ add_filter('webpc_uploads_path', [$this, 'parsePath'], 100, 2);
16
+ add_filter('webpc_uploads_webp', [$this, 'parsePath'], 100, 2);
17
+ add_filter('webpc_uploads_prefix', [$this, 'getPrefixPath'], 0);
18
+ add_filter('webpc_uploads_dir', [$this, 'getUploadsDir'], 0);
19
+ add_filter('webpc_dir_path', [$this, 'getPathOfDir'], 0, 2);
20
+ add_filter('webpc_dir_excluded', [$this, 'getExcludedDirs'], 0);
21
  }
22
 
23
  /* ---
54
 
55
  public function getUploadsDir($value)
56
  {
57
+ $uploadsDir = apply_filters('webpc_uploads_path', '');
58
+ $uploadsParent = dirname($uploadsDir);
59
+ $webpParent = dirname(apply_filters('webpc_uploads_webp', ''));
60
+ if ((!$uploadsDir = realpath($uploadsDir)) || (!$uploadsParent = realpath($uploadsParent))
61
+ || ($uploadsParent !== realpath($webpParent))) {
62
  return $value;
63
  }
64
 
65
+ $path = str_replace($uploadsParent, '', $uploadsDir);
66
  return trim($path, '\/');
67
  }
68
+
69
+ public function getPathOfDir($value, $directory)
70
+ {
71
+ switch ($directory) {
72
+ case 'plugins':
73
+ return dirname(WEBPC_PATH);
74
+ break;
75
+ case 'themes':
76
+ return get_theme_root();
77
+ break;
78
+ case 'uploads':
79
+ return apply_filters('webpc_uploads_path', '');
80
+ break;
81
+ }
82
+ return null;
83
+ }
84
+
85
+ public function getExcludedDirs($value)
86
+ {
87
+ return $this->dirsExcluded;
88
+ }
89
  }
app/Settings/Server.php CHANGED
@@ -19,6 +19,7 @@
19
  {
20
  ob_start();
21
 
 
22
  foreach ($this->extensions as $extension) {
23
  $this->getExtensionInfo($extension);
24
  }
@@ -42,4 +43,81 @@
42
  $ext->info();
43
  endif;
44
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
19
  {
20
  ob_start();
21
 
22
+ echo $this->getFiltersInfo();
23
  foreach ($this->extensions as $extension) {
24
  $this->getExtensionInfo($extension);
25
  }
43
  $ext->info();
44
  endif;
45
  }
46
+
47
+ private function getFiltersInfo()
48
+ {
49
+ ob_start();
50
+
51
+ ?>
52
+ <h4>apply_filters</h4>
53
+ <table>
54
+ <tbody>
55
+ <tr>
56
+ <td class="e">webpc_get_values</td>
57
+ <td class="v">
58
+ <?= json_encode(apply_filters('webpc_get_values', [], null)); ?>
59
+ </td>
60
+ </tr>
61
+ <tr>
62
+ <td class="e">webpc_get_methods</td>
63
+ <td class="v">
64
+ <?= implode(' | ', apply_filters('webpc_get_methods', [])); ?>
65
+ </td>
66
+ </tr>
67
+ <tr>
68
+ <td class="e">webpc_uploads_root</td>
69
+ <td class="v">
70
+ <?= apply_filters('webpc_uploads_root', ABSPATH); ?>
71
+ </td>
72
+ </tr>
73
+ <tr>
74
+ <td class="e">webpc_uploads_prefix</td>
75
+ <td class="v">
76
+ <?= apply_filters('webpc_uploads_prefix', '/'); ?>
77
+ </td>
78
+ </tr>
79
+ <tr>
80
+ <td class="e">webpc_uploads_path</td>
81
+ <td class="v">
82
+ <?= apply_filters('webpc_uploads_path', '', false); ?>
83
+ </td>
84
+ </tr>
85
+ <tr>
86
+ <td class="e">webpc_uploads_webp</td>
87
+ <td class="v">
88
+ <?= apply_filters('webpc_uploads_webp', '', false); ?>
89
+ </td>
90
+ </tr>
91
+ <tr>
92
+ <td class="e">webpc_dir_path <em>(plugins)</em></td>
93
+ <td class="v">
94
+ <?= apply_filters('webpc_dir_path', '', 'plugins'); ?>
95
+ </td>
96
+ </tr>
97
+ <tr>
98
+ <td class="e">webpc_dir_path <em>(themes)</em></td>
99
+ <td class="v">
100
+ <?= apply_filters('webpc_dir_path', '', 'themes'); ?>
101
+ </td>
102
+ </tr>
103
+ <tr>
104
+ <td class="e">webpc_dir_path <em>(uploads)</em></td>
105
+ <td class="v">
106
+ <?= apply_filters('webpc_dir_path', '', 'uploads'); ?>
107
+ </td>
108
+ </tr>
109
+ <tr>
110
+ <td class="e">webpc_dir_excluded</td>
111
+ <td class="v">
112
+ <?= implode(' | ', apply_filters('webpc_dir_excluded', [])); ?>
113
+ </td>
114
+ </tr>
115
+ </tbody>
116
+ </table>
117
+ <?php
118
+
119
+ $content = ob_get_contents();
120
+ ob_end_clean();
121
+ return $content;
122
+ }
123
  }
app/Settings/Values.php CHANGED
@@ -22,6 +22,7 @@
22
  $methods = apply_filters('webpc_get_methods', []);
23
  $value = get_option('webpc_settings', [
24
  'extensions' => ['jpg', 'jpeg', 'png'],
 
25
  'method' => ($methods) ? $methods[0] : '',
26
  'features' => ['only_smaller', 'mod_expires'],
27
  'quality' => 85,
22
  $methods = apply_filters('webpc_get_methods', []);
23
  $value = get_option('webpc_settings', [
24
  'extensions' => ['jpg', 'jpeg', 'png'],
25
+ 'dirs' => ['uploads'],
26
  'method' => ($methods) ? $methods[0] : '',
27
  'features' => ['only_smaller', 'mod_expires'],
28
  'quality' => 85,
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_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){}]);
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.inputOptions=this.section.querySelectorAll('input[type="checkbox"]'),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){if(e.preventDefault(),!this.settings.isDisabled){this.settings.isDisabled=!0,this.button.classList.add(this.classes.buttonDisabled);for(var t=this.inputOptions.length,r=0;r<t;r++)this.inputOptions[r].setAttribute("disabled",!0);this.wrapper.removeAttribute("hidden"),this.getImagesList()}}},{key:"getImagesList",value:function(){var e=this;jQuery.ajax(this.settings.ajax.urlPaths,{type:"POST",data:this.getDataForPathsRequest()}).done((function(t){e.data.items=t,e.data.max=t.length,e.regenerateNextImages()})).fail((function(){e.progress.classList.add(e.classes.progressError),e.errorsMessage.removeAttribute("hidden"),e.errors.removeAttribute("hidden")}))}},{key:"getDataForPathsRequest",value:function(){for(var e={},t=this.inputOptions.length,r=0;r<t;r++)e[this.inputOptions[r].getAttribute("name")]=this.inputOptions[r].checked?1:0;return e}},{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
@@ -21,11 +21,15 @@ As of today, nearly 80% of users use browsers that support the WebP format. The
21
 
22
  This will be a profit both for your users who will not have to download so much data, but also for a server that will be less loaded. Remember that a better optimized website also affects your Google ranking.
23
 
 
 
 
 
24
  #### How does this work?
25
 
26
- - By adding images to your media library, they are automatically converted and saved in a separate directory.
27
  - If you have just installed the plugin, you can convert all existing images with one click.
28
- - Converting to WebP format works for all image sizes. As WebP you will see all the images added to the media library.
29
  - Images are converted using PHP `GD` or `Imagick` extension *(you can modify the compression level)*.
30
  - When the browser tries to download an image file, the server verifies if it supports `image/webp` files and if the file exists.
31
  - If everything is OK, instead of the original image, the browser will receive its equivalent in WebP format.
@@ -35,6 +39,10 @@ This will be a profit both for your users who will not have to download so much
35
  - When you try to save the image to disk *(e.g. by clicking Save as...)* the original image will be saved. WebP is only used for browser loading.
36
  - The final result is that your users download less than half of the data, and the website itself loads faster!
37
 
 
 
 
 
38
  #### WebP images are the future!
39
 
40
  Raise your website to a new level now! Install the plugin and enjoy the website that loads faster. Surely you and your users will appreciate it.
@@ -105,15 +113,17 @@ Send a screenshot from console if an error occurred while converting images. Of
105
 
106
  **6.** If in the previous step it turned out that you have files, please do the test, which is described in the FAQ in question `How to check if plugin works?`. Please send a screenshot of Devtools with test results.
107
 
108
- **7.** Content of your `.htaccess` files from directories `/wp-content/uploads` and `/wp-content/uploads-webpc` *(pasting the code using the `CODE` shortcode in the editor)*.
 
 
109
 
110
- **8.** What plugin version are you using? If it is not the latest then update and check everything again.
111
 
112
- **9.** Used Wordpress version.
113
 
114
- **10.** A list of all the plugins you use. Have you tried checking the plugin operation by turning off all others and activating the default theme? If not, please try whenever possible. **This is very important because other plugins or themes can cause problems. Therefore, we recommend disabling all necessary plugins and enabling the default theme.**
115
 
116
- Please remember to include the answers for all 10 questions by adding a thread. It is much easier and accelerate the solution of your problem.
117
 
118
  And if we would help and would like to thank us, you can [provide us a coffee](https://ko-fi.com/gbiorczyk/).
119
 
@@ -137,6 +147,8 @@ If you get an error: `File "%s" is unreadable. Please check file permissions.` m
137
 
138
  If you get an error: `"%s" is not a valid image file.` means that the file is damaged in some way. Download the file to disk, save it again using any graphics program and add again to the page. If the error applies to individual images then you can ignore it - just the original images will load, not WebP.
139
 
 
 
140
  Remember that it happens that other plugins can cause problems with accessing files or the REST API. Please try to disable all other plugins and set the default theme to make sure that it is not one of them that causes these types of problems.
141
 
142
  = What are requirements of plugin? =
@@ -185,7 +197,7 @@ It uses the WordPress REST API by downloading addresses of all images and conver
185
 
186
  This process may take few or more than ten minutes depending on the number of files.
187
 
188
- **It should be done once after installing the plugin.** All images added later will be converted automatically.
189
 
190
  = How to check if plugin works? =
191
 
@@ -204,19 +216,17 @@ Please remember that URLs will remain unchanged. The difference will be only in
204
 
205
  If the file type is `WebP`, then everything is working properly. You can also turn off the plugin for a moment and check the weight of your website, then turn it on and test again. The difference should be visible.
206
 
207
- Only images from the `/uploads` directory are converted. If you use other plugins that also save images in the `/uploads` directory then this may not work because this plugin may not be compatible with WebP Converter for Media. Read question `How to run manually conversion?` in the FAQ to learn more.
208
 
209
  = Why are some images not in WebP? =
210
 
211
- If the converted image in WebP format is larger than the original, the browser will use the original file. This converted file will be deleted. Therefore, you can also see files other than WebP on the list.
212
 
213
  If you want to force the use of WebP files, uncheck the `Automatic removal of WebP files larger than original` option in the plugin settings. Then click on the `Regenerate All` button to convert all images again.
214
 
215
- In addition, images may not be displayed in WebP format if they are files downloaded from the `/themes` directory or from a directory of another plugin that is not compatible.
216
-
217
- Remember that this plugin supports images from the `/uploads` directory, i.e. files downloaded from the media library. Similarly, if your images are downloaded from another domain, i.e. from an external service.
218
 
219
- When checking the operation of the plugin, e.g. in Dev Tools, pay attention to the path from which the files are downloaded.
220
 
221
  = Where are converted images stored? =
222
 
@@ -224,6 +234,8 @@ All WebP images are stored in the `/wp-content/uploads-webpc/` directory. Inside
224
 
225
  In case the location of the original file is as follows: `/wp-content/uploads/2019/06/example.jpg` then its converted version will be in the following location: `/wp-content/uploads-webpc/uploads/2019/06/example.jpg.webp`.
226
 
 
 
227
  Original images are not changed. If you remove plugins, only WebP files will be deleted. Your images are not changed in any way.
228
 
229
  = How to change path to uploads? =
@@ -248,6 +260,8 @@ Directory path with converted WebP files *(relative to the root directory)*:
248
  return 'wp-content/uploads-webpc';
249
  });`
250
 
 
 
251
  Prefix in URL of `/wp-content/` directory or equivalent *(used in .htaccess)*:
252
 
253
  `add_filter('webpc_uploads_prefix', function($prefix) {
@@ -286,19 +300,30 @@ After setting the filters go to `Settings -> WebP Converter` in the admin panel
286
 
287
  = How to run manually conversion? =
288
 
289
- 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.
290
 
291
- Remember that our plugin takes into account images generated by WordPress. There are many plugins that generate, for example, images of a different size or in a different version. Unfortunately, we are not able to integrate with any such plugin.
292
 
293
- If you would like to integrate with your plugin, which generates images by yourself, you can do it. Our plugin provides the possibility of this type of integration. This works for all images in the `/uploads` directory.
294
 
295
  It is a solution for advanced users. If you would like to integrate with another plugin, it's best to contact the author of that plugin and give him information about the actions available in our plugin. This will help you find a solution faster.
296
 
 
 
 
 
 
 
 
 
 
 
 
297
  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)*:
298
 
299
  `do_action('webpc_convert_paths', $paths);`
300
 
301
- 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)*:
302
 
303
  `do_action('webpc_convert_attachment', $postId);`
304
 
@@ -308,7 +333,7 @@ In addition, you can edit the list of files that will be converted. For example,
308
  return $paths;
309
  }, 10, 2);`
310
 
311
- Argument `$paths` is array of absolute server paths and `$attachmentId` is the post ID of attachment, added to the media library.
312
 
313
  To delete manually converted files, use the following action, providing as an argument an array of absolute server paths to the files *(this will delete manually converted files)*:
314
 
@@ -324,9 +349,11 @@ Returning an empty string will delete these rules the next time you save the plu
324
 
325
  Rules for redirects: *(returns rules for `mod_rewrite` module)*:
326
 
327
- `add_filter('webpc_htaccess_mod_rewrite', function($rules) {
328
  return '';
329
- });`
 
 
330
 
331
  Rules for `image/webp` MIME type: *(returns rules for `mod_mime` module)*:
332
 
@@ -340,7 +367,7 @@ Rules for Browser Caching: *(returns rules for `mod_expires` module)*:
340
  return '';
341
  });`
342
 
343
- All rules from the files `/uploads/.htaccess` and `/uploads-webpc/.htaccess`: *(returns rules for modules: `mod_rewrite`, `mod_mime` and `mod_expires`)*:
344
 
345
  `add_filter('webpc_htaccess_rules', function($rules, $path) {
346
  return '';
@@ -360,7 +387,7 @@ Unfortunately not. This is due to the logic of the plugin's operation. Plugins t
360
 
361
  The main problem when changing URLs is cache. When we modify the image URL for WebP supporting browser, then use the browser without WebP support, it will still have the URL address of an image in .webp format, because it will be in the cache.
362
 
363
- While in the case of the `img` tag you can solve this problem, in the case of `background-image` it is possible. We wanted full support so that all images added to the media library would be supported - no matter how they are displayed on the website.
364
 
365
  Therefore in this plugin for browsers supporting the WebP format, only the source of the file is replaced by using the `mod_rewrite` module on the server. The URL for image remains the same. This solves the whole problem, but it is impossible to do when the files are stored on the CDN server.
366
 
@@ -455,6 +482,19 @@ This is all very important to us and allows us to do even better things for you!
455
 
456
  == Changelog ==
457
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
  = 1.2.7 (2020-06-11) =
459
  * `[Changed]` Moving converted WebP files to `/uploads-webpc/uploads` directory from `/uploads-webpc` directory *(**required manual configuration change for Nginx and WordPress Multisite**)*
460
  * `[Changed]` Validation when converting images
@@ -483,7 +523,7 @@ This is all very important to us and allows us to do even better things for you!
483
 
484
  = 1.2.1 (2020-04-07) =
485
  * `[Removed]` Filter `webpc_option_disabled`
486
- * `[Fixed]` Converting images multiple times when uploading to media library
487
  * `[Added]` Action `webpc_convert_paths` to convert images by paths
488
  * `[Added]` Action `webpc_convert_attachment` to convert images by Post ID
489
 
21
 
22
  This will be a profit both for your users who will not have to download so much data, but also for a server that will be less loaded. Remember that a better optimized website also affects your Google ranking.
23
 
24
+ #### New feature
25
+
26
+ Now you can also convert files from the `/uploads` directory into WebP and generated by other plugins! It allows full integration with the WebP format!
27
+
28
  #### How does this work?
29
 
30
+ - By adding images to your Media Library, they are automatically converted and saved in a separate directory.
31
  - If you have just installed the plugin, you can convert all existing images with one click.
32
+ - Converting to WebP format works for all image sizes. As WebP you will see all the images added to the Media Library.
33
  - Images are converted using PHP `GD` or `Imagick` extension *(you can modify the compression level)*.
34
  - When the browser tries to download an image file, the server verifies if it supports `image/webp` files and if the file exists.
35
  - If everything is OK, instead of the original image, the browser will receive its equivalent in WebP format.
39
  - When you try to save the image to disk *(e.g. by clicking Save as...)* the original image will be saved. WebP is only used for browser loading.
40
  - The final result is that your users download less than half of the data, and the website itself loads faster!
41
 
42
+ #### Support for additional directories
43
+
44
+ You can also manually convert images from the `/plugins` and `/themes` directories, as well as other images from the `/uploads` directory that are not in the Media Library *(which are e.g. generated by other plugins)*. It allows full integration with the WebP format and maximum acceleration of your website.
45
+
46
  #### WebP images are the future!
47
 
48
  Raise your website to a new level now! Install the plugin and enjoy the website that loads faster. Surely you and your users will appreciate it.
113
 
114
  **6.** If in the previous step it turned out that you have files, please do the test, which is described in the FAQ in question `How to check if plugin works?`. Please send a screenshot of Devtools with test results.
115
 
116
+ **7.** Content of your `.htaccess` files from directories `/wp-content`, `/wp-content/uploads` and `/wp-content/uploads-webpc` *(pasting the code using the `CODE` shortcode in the editor)*.
117
+
118
+ **8.** Do you use any plugin filters or actions from this FAQ? If so, list them all.
119
 
120
+ **9.** What plugin version are you using? If it is not the latest then update and check everything again.
121
 
122
+ **10.** Used Wordpress version.
123
 
124
+ **11.** A list of all the plugins you use. Have you tried checking the plugin operation by turning off all others and activating the default theme? If not, please try whenever possible. **This is very important because other plugins or themes can cause problems. Therefore, we recommend disabling all necessary plugins and enabling the default theme.**
125
 
126
+ Please remember to include the answers for all 11 questions by adding a thread. It is much easier and accelerate the solution of your problem.
127
 
128
  And if we would help and would like to thank us, you can [provide us a coffee](https://ko-fi.com/gbiorczyk/).
129
 
147
 
148
  If you get an error: `"%s" is not a valid image file.` means that the file is damaged in some way. Download the file to disk, save it again using any graphics program and add again to the page. If the error applies to individual images then you can ignore it - just the original images will load, not WebP.
149
 
150
+ In the case of the above problems, **contacting the support forum will be useless**. Unfortunately, we are unable to help you if your files are damaged. You have to fix it yourself. If you have previously used other tools that changed the original files and damaged them, you will do nothing more.
151
+
152
  Remember that it happens that other plugins can cause problems with accessing files or the REST API. Please try to disable all other plugins and set the default theme to make sure that it is not one of them that causes these types of problems.
153
 
154
  = What are requirements of plugin? =
197
 
198
  This process may take few or more than ten minutes depending on the number of files.
199
 
200
+ **It should be done once after installing the plugin.** New images from the Media Library will be converted automatically. For other images, e.g. from the /themes directory, you must start manual conversion after adding new images.
201
 
202
  = How to check if plugin works? =
203
 
216
 
217
  If the file type is `WebP`, then everything is working properly. You can also turn off the plugin for a moment and check the weight of your website, then turn it on and test again. The difference should be visible.
218
 
219
+ Only images from the `/uploads` directory are automatically converted. If you use other plugins that also save images in the `/uploads` directory then this may not work. Therefore, check the plugin settings and try converting all images again.
220
 
221
  = Why are some images not in WebP? =
222
 
223
+ If the converted image in WebP format is larger than the original, the browser will use the original file. This converted file will be deleted. Therefore, you can also see files other than WebP on the list. When this happens, you will receive information in debug.log.
224
 
225
  If you want to force the use of WebP files, uncheck the `Automatic removal of WebP files larger than original` option in the plugin settings. Then click on the `Regenerate All` button to convert all images again.
226
 
227
+ Remember that this plugin supports images from the `/wp-content` directory, e.g. files downloaded from the Media Library. Redirections will not work if your images are downloaded from another domain, i.e. from an external service.
 
 
228
 
229
+ When checking the operation of the plugin, e.g. in Dev Tools, pay attention to the path from which the files are downloaded and which directories you have enabled in the settings of plugin.
230
 
231
  = Where are converted images stored? =
232
 
234
 
235
  In case the location of the original file is as follows: `/wp-content/uploads/2019/06/example.jpg` then its converted version will be in the following location: `/wp-content/uploads-webpc/uploads/2019/06/example.jpg.webp`.
236
 
237
+ In case the location of the original file is as follows: `/wp-content/themes/my-theme/public/img/example.jpg` then its converted version will be in the following location: `/wp-content/uploads-webpc/themes/my-theme/public/img/example.jpg.webp`.
238
+
239
  Original images are not changed. If you remove plugins, only WebP files will be deleted. Your images are not changed in any way.
240
 
241
  = How to change path to uploads? =
260
  return 'wp-content/uploads-webpc';
261
  });`
262
 
263
+ **Note that the `/uploads-webpc` directory must be at the same nesting level as the `/uploads`, `/plugins` and `/themes` directories.**
264
+
265
  Prefix in URL of `/wp-content/` directory or equivalent *(used in .htaccess)*:
266
 
267
  `add_filter('webpc_uploads_prefix', function($prefix) {
300
 
301
  = How to run manually conversion? =
302
 
303
+ 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.
304
 
305
+ Remember that our plugin takes into account images generated by WordPress. There are many plugins that generate, for example, images of a different size or in a different version.
306
 
307
+ If you would like to integrate with your plugin, which generates images by yourself, you can do it. Our plugin provides the possibility of this type of integration. This works for all images in the `/wp-content` directory.
308
 
309
  It is a solution for advanced users. If you would like to integrate with another plugin, it's best to contact the author of that plugin and give him information about the actions available in our plugin. This will help you find a solution faster.
310
 
311
+ You can automatically run the option to regenerate all new images. This is useful when you use external plugins that generate images themselves. To do this, use the following code:
312
+
313
+ `do_action('webpc_regenerate_all', $paths);`
314
+
315
+ Below is an example of how to use this action to automatically regenerate images after changing the theme:
316
+
317
+ `add_action('init', function()
318
+ {
319
+ do_action('webpc_regenerate_all');
320
+ });`
321
+
322
  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)*:
323
 
324
  `do_action('webpc_convert_paths', $paths);`
325
 
326
+ 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)*:
327
 
328
  `do_action('webpc_convert_attachment', $postId);`
329
 
333
  return $paths;
334
  }, 10, 2);`
335
 
336
+ Argument `$paths` is array of absolute server paths and `$attachmentId` is the post ID of attachment, added to the Media Library.
337
 
338
  To delete manually converted files, use the following action, providing as an argument an array of absolute server paths to the files *(this will delete manually converted files)*:
339
 
349
 
350
  Rules for redirects: *(returns rules for `mod_rewrite` module)*:
351
 
352
+ `add_filter('webpc_htaccess_mod_rewrite', function($rules, $path) {
353
  return '';
354
+ }, 10, 2);`
355
+
356
+ Argument `$path` is absolute server path for `.htaccess` file *(`/wp-content/.htaccess` or `/wp-content/uploads/.htaccess`)*.
357
 
358
  Rules for `image/webp` MIME type: *(returns rules for `mod_mime` module)*:
359
 
367
  return '';
368
  });`
369
 
370
+ All rules from the files `/wp-content/.htaccess`, `/wp-content/uploads/.htaccess` and `/wp-content/uploads-webpc/.htaccess`: *(returns rules for modules: `mod_rewrite`, `mod_mime` and `mod_expires`)*:
371
 
372
  `add_filter('webpc_htaccess_rules', function($rules, $path) {
373
  return '';
387
 
388
  The main problem when changing URLs is cache. When we modify the image URL for WebP supporting browser, then use the browser without WebP support, it will still have the URL address of an image in .webp format, because it will be in the cache.
389
 
390
+ While in the case of the `img` tag you can solve this problem, in the case of `background-image` it is possible. We wanted full support so that all images would be supported - no matter how they are displayed on the website.
391
 
392
  Therefore in this plugin for browsers supporting the WebP format, only the source of the file is replaced by using the `mod_rewrite` module on the server. The URL for image remains the same. This solves the whole problem, but it is impossible to do when the files are stored on the CDN server.
393
 
482
 
483
  == Changelog ==
484
 
485
+ = 1.3.0 (2020-06-12) =
486
+ * `[Removed]` Ability to skip converting existing images when `Regenerate All`
487
+ * `[Fixed]` Creating `/uploads-webpc` directory webpc after re-activation plugin
488
+ * `[Fixed]` Error message about not supporting old PHP version
489
+ * `[Fixed]` Ignoring case sensitivity when verifying image extensions
490
+ * `[Changed]` Error messages when converting images
491
+ * `[Changed]` New argument for filter `webpc_htaccess_mod_rewrite` and support for multiple .htaccess files
492
+ * `[Added]` Converting all images from `/uploads` directory *(also other than from Media Library)*.
493
+ * `[Added]` Converting images from `/plugins` directory
494
+ * `[Added]` Converting images from `/themes` directory
495
+ * `[Added]` Information about used filters in `Server configuration` tab
496
+ * `[Added]` Option to force all images to be converted again when `Regenerate All`
497
+
498
  = 1.2.7 (2020-06-11) =
499
  * `[Changed]` Moving converted WebP files to `/uploads-webpc/uploads` directory from `/uploads-webpc` directory *(**required manual configuration change for Nginx and WordPress Multisite**)*
500
  * `[Changed]` Validation when converting images
523
 
524
  = 1.2.1 (2020-04-07) =
525
  * `[Removed]` Filter `webpc_option_disabled`
526
+ * `[Fixed]` Converting images multiple times when uploading to Media Library
527
  * `[Added]` Action `webpc_convert_paths` to convert images by paths
528
  * `[Added]` Action `webpc_convert_attachment` to convert images by Post ID
529
 
resources/_dev/js/classes/Regenerate.js CHANGED
@@ -19,7 +19,7 @@ export default class Regenerate
19
  this.errorsInner = this.errors.querySelector('.webpLoader__errorsContentList');
20
  this.errorsMessage = this.errors.querySelector('.webpLoader__errorsContentMessage');
21
  this.success = this.section.querySelector('.webpLoader__success');
22
- this.skipOption = this.section.querySelector('input[name="regenerate_skip"]');
23
  this.button = this.section.querySelector('.webpLoader__button');
24
  this.data = {
25
  count: 0,
@@ -63,10 +63,15 @@ export default class Regenerate
63
  {
64
  e.preventDefault();
65
  if (this.settings.isDisabled) return;
 
66
  this.settings.isDisabled = true;
67
- this.skipOption.setAttribute('disabled', true);
68
  this.button.classList.add(this.classes.buttonDisabled);
69
 
 
 
 
 
 
70
  this.wrapper.removeAttribute('hidden');
71
  this.getImagesList();
72
  }
@@ -75,12 +80,10 @@ export default class Regenerate
75
  {
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;
83
- this.data.max = response.data.length;
84
  this.regenerateNextImages();
85
  }).fail(() => {
86
  this.progress.classList.add(this.classes.progressError);
@@ -89,6 +92,17 @@ export default class Regenerate
89
  });
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
92
  /* ---
93
  Regenerate request
94
  --- */
19
  this.errorsInner = this.errors.querySelector('.webpLoader__errorsContentList');
20
  this.errorsMessage = this.errors.querySelector('.webpLoader__errorsContentMessage');
21
  this.success = this.section.querySelector('.webpLoader__success');
22
+ this.inputOptions = this.section.querySelectorAll('input[type="checkbox"]');
23
  this.button = this.section.querySelector('.webpLoader__button');
24
  this.data = {
25
  count: 0,
63
  {
64
  e.preventDefault();
65
  if (this.settings.isDisabled) return;
66
+
67
  this.settings.isDisabled = true;
 
68
  this.button.classList.add(this.classes.buttonDisabled);
69
 
70
+ const { length } = this.inputOptions;
71
+ for (let i = 0; i < length; i++) {
72
+ this.inputOptions[i].setAttribute('disabled', true);
73
+ }
74
+
75
  this.wrapper.removeAttribute('hidden');
76
  this.getImagesList();
77
  }
80
  {
81
  jQuery.ajax(this.settings.ajax.urlPaths, {
82
  type: 'POST',
83
+ data: this.getDataForPathsRequest(),
 
 
84
  }).done((response) => {
85
+ this.data.items = response;
86
+ this.data.max = response.length;
87
  this.regenerateNextImages();
88
  }).fail(() => {
89
  this.progress.classList.add(this.classes.progressError);
92
  });
93
  }
94
 
95
+ getDataForPathsRequest()
96
+ {
97
+ const options = {};
98
+ const { length } = this.inputOptions;
99
+ for (let i = 0; i < length; i++) {
100
+ const name = this.inputOptions[i].getAttribute('name');
101
+ options[name] = (this.inputOptions[i].checked) ? 1 : 0;
102
+ }
103
+ return options;
104
+ }
105
+
106
  /* ---
107
  Regenerate request
108
  --- */
resources/components/widgets/regenerate.php CHANGED
@@ -15,7 +15,7 @@
15
  <?= __('Convert all existing images with just one click! This tool uses the WordPress REST API by downloading addresses of all images and converting all files gradually. This is a process that may take a few or more than ten minutes depending on the number of files. During this process, please do not close your browser window.', 'webp-converter'); ?>
16
  </p>
17
  <p>
18
- <?= __('This operation should be performed only once after installing the plugin. New images will be converted automatically.', 'webp-converter'); ?>
19
  </p>
20
  <div class="webpLoader__status" hidden>
21
  <div class="webpLoader__bar">
@@ -47,13 +47,13 @@
47
  <table class="webpPage__widgetTable">
48
  <tr>
49
  <td>
50
- <input type="checkbox" name="regenerate_skip" value="1"
51
- id="webpc-regenerate-skip" class="webpPage__checkbox">
52
- <label for="webpc-regenerate-skip"></label>
53
  </td>
54
  <td>
55
- <label for="webpc-regenerate-skip" class="webpPage__checkboxLabel">
56
- <?= __('Skip converted images', 'webp-converter'); ?>
57
  </label>
58
  </td>
59
  </tr>
15
  <?= __('Convert all existing images with just one click! This tool uses the WordPress REST API by downloading addresses of all images and converting all files gradually. This is a process that may take a few or more than ten minutes depending on the number of files. During this process, please do not close your browser window.', 'webp-converter'); ?>
16
  </p>
17
  <p>
18
+ <?= __('This operation should be performed only once after installing the plugin. New images from the Media Library will be converted automatically. For other images, e.g. from the /themes or /uploads directory that are not from the Media Library, you must start manual conversion after adding new images.', 'webp-converter'); ?>
19
  </p>
20
  <div class="webpLoader__status" hidden>
21
  <div class="webpLoader__bar">
47
  <table class="webpPage__widgetTable">
48
  <tr>
49
  <td>
50
+ <input type="checkbox" name="regenerate_force" value="1"
51
+ id="webpc-regenerate-force" class="webpPage__checkbox">
52
+ <label for="webpc-regenerate-force"></label>
53
  </td>
54
  <td>
55
+ <label for="webpc-regenerate-force" class="webpPage__checkboxLabel">
56
+ <?= __('Force convert all images again', 'webp-converter'); ?>
57
  </label>
58
  </td>
59
  </tr>
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.7
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter
10
  */
11
 
12
- define('WEBPC_VERSION', '1.2.7');
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.3.0
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter
10
  */
11
 
12
+ define('WEBPC_VERSION', '1.3.0');
13
  define('WEBPC_FILE', __FILE__);
14
  define('WEBPC_NAME', plugin_basename(__FILE__));
15
  define('WEBPC_PATH', plugin_dir_path(__FILE__));