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

Version Description

(2020-12-16) = * [Removed] Filter webpc_uploads_path * [Removed] Filter webpc_uploads_webp * [Removed] Filter webpc_uploads_dir * [Removed] Filter webpc_uploads_root * [Changed] Error messages in administration panel * [Added] Image loading mode: Pass Thru (without rewrites in .htacces files or Nginx configuration) * [Added] Filter webpc_dir_name to change default directory paths * [Added] Filter webpc_site_root to change path for root installation directory of WordPress * [Added] Filter webpc_site_url to change Site URL of WordPress

Download this release

Release Info

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

Code changes from version 1.6.0 to 2.0.0

Files changed (60) hide show
  1. app/Action/Convert.php +6 -5
  2. app/Action/Delete.php +4 -2
  3. app/Convert/Directory.php +7 -7
  4. app/Convert/Paths.php +41 -46
  5. app/Convert/Server.php +2 -2
  6. app/Error/ErrorAbstract.php +24 -0
  7. app/Error/ErrorInterface.php +14 -0
  8. app/Error/LibsError.php +39 -0
  9. app/Error/PassthruError.php +45 -0
  10. app/Error/PathsError.php +58 -0
  11. app/Error/RestapiError.php +31 -0
  12. app/Error/RewritesError.php +102 -0
  13. app/Error/SettingsError.php +35 -0
  14. app/{Media → Loader}/Htaccess.php +37 -20
  15. app/Loader/LoaderAbstract.php +43 -0
  16. app/Loader/LoaderInterface.php +20 -0
  17. app/Loader/Passthru.php +103 -0
  18. app/Loader/_Core.php +12 -0
  19. app/Media/_Core.php +0 -1
  20. app/Method/Gd.php +62 -144
  21. app/Method/Imagick.php +50 -112
  22. app/Method/MethodAbstract.php +89 -0
  23. app/Method/MethodIntegrator.php +40 -0
  24. app/Method/MethodInterface.php +31 -0
  25. app/Plugin/Activation.php +3 -4
  26. app/Plugin/Deactivation.php +2 -3
  27. app/Plugin/Uninstall.php +8 -7
  28. app/Plugin/Update.php +10 -18
  29. app/Regenerate/Regenerate.php +8 -7
  30. app/Settings/Errors.php +25 -165
  31. app/Settings/Methods.php +3 -8
  32. app/Settings/Options.php +28 -4
  33. app/Settings/Save.php +2 -2
  34. app/Settings/Server.php +30 -23
  35. app/Settings/Values.php +6 -5
  36. app/Traits/FileLoaderTrait.php +9 -2
  37. app/WebpConverter.php +1 -0
  38. libs/passthru.php +67 -0
  39. public/build/js/scripts.js +1 -1
  40. public/img/icon-test.png2 +0 -0
  41. public/img/icon-test.webp +0 -0
  42. readme.txt +86 -73
  43. resources/components/errors/bypassing-apache.php +2 -1
  44. resources/components/errors/passthru-execution.php +12 -0
  45. resources/components/errors/passthru-info.php +8 -0
  46. resources/components/errors/path-htaccess-not-writable.php +1 -1
  47. resources/components/errors/path-uploads-unavailable.php +3 -4
  48. resources/components/errors/path-webp-duplicated.php +3 -4
  49. resources/components/errors/path-webp-not-writable.php +3 -4
  50. resources/components/errors/rewrites-cached.php +2 -1
  51. resources/components/errors/rewrites-not-working.php +2 -1
  52. resources/components/widgets/about.php +1 -1
  53. resources/components/widgets/errors.php +2 -1
  54. resources/components/widgets/regenerate.php +1 -0
  55. resources/views/deactivation-modal.php +6 -1
  56. resources/views/settings.php +1 -0
  57. vendor/autoload.php +1 -1
  58. vendor/composer/autoload_real.php +4 -4
  59. vendor/composer/autoload_static.php +3 -3
  60. webp-converter-for-media.php +2 -2
app/Action/Convert.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  namespace WebpConverter\Action;
4
 
5
- use WebpConverter\Method;
6
  use WebpConverter\Media\Attachment;
7
 
8
  class Convert
@@ -22,14 +22,15 @@
22
  {
23
  $settings = apply_filters('webpc_get_values', []);
24
 
25
- if ($settings['method'] === 'gd') $convert = new Method\Gd();
26
- else if ($settings['method'] === 'imagick') $convert = new Method\Imagick();
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
- $convert->convertImage($path, $settings);
33
  }
34
  }
35
 
2
 
3
  namespace WebpConverter\Action;
4
 
5
+ use WebpConverter\Method\MethodIntegrator;
6
  use WebpConverter\Media\Attachment;
7
 
8
  class Convert
22
  {
23
  $settings = apply_filters('webpc_get_values', []);
24
 
25
+ $convertMethod = (new MethodIntegrator())->getMethodUsed($settings['method']);
26
+ if ($convertMethod === null) {
27
+ return false;
28
+ }
29
 
30
  foreach ($paths as $path) {
31
  $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
32
  if (!in_array($extension, $settings['extensions'])) continue;
33
+ $convertMethod->convertImage($path);
34
  }
35
  }
36
 
app/Action/Delete.php CHANGED
@@ -24,7 +24,9 @@
24
 
25
  private function deleteFileByPath($path)
26
  {
27
- $source = (new Directory())->getPath($path);
28
- if (is_writable($source) && (pathinfo($source, PATHINFO_EXTENSION) === 'webp')) unlink($source);
 
 
29
  }
30
  }
24
 
25
  private function deleteFileByPath($path)
26
  {
27
+ $source = Directory::getPath($path);
28
+ if (is_writable($source) && (pathinfo($source, PATHINFO_EXTENSION) === 'webp')) {
29
+ unlink($source);
30
+ }
31
  }
32
  }
app/Convert/Directory.php CHANGED
@@ -8,9 +8,9 @@
8
  Functions
9
  --- */
10
 
11
- public function getPath($path, $createDirectory = false)
12
  {
13
- $webpRoot = apply_filters('webpc_uploads_webp', '');
14
  $uploadsRoot = dirname($webpRoot);
15
  $outputPath = str_replace(realpath($uploadsRoot), '', realpath($path));
16
  $outputPath = trim($outputPath, '\/');
@@ -18,12 +18,12 @@
18
  $newPath = sprintf('%s/%s.webp', $webpRoot, $outputPath);
19
  if (!$createDirectory) return $newPath;
20
 
21
- if (!$paths = $this->checkDirectories($newPath)) return $newPath;
22
- else if (!$this->makeDirectories($paths)) return null;
23
  else return $newPath;
24
  }
25
 
26
- private function checkDirectories($path)
27
  {
28
  $current = dirname($path);
29
  $paths = [];
@@ -34,11 +34,11 @@
34
  return $paths;
35
  }
36
 
37
- private function makeDirectories($paths)
38
  {
39
  $paths = array_reverse($paths);
40
  foreach ($paths as $path) {
41
- if (!is_writable(dirname($path))) return;
42
  mkdir($path);
43
  }
44
  return true;
8
  Functions
9
  --- */
10
 
11
+ public static function getPath($path, $createDirectory = false)
12
  {
13
+ $webpRoot = apply_filters('webpc_dir_path', '', 'webp');
14
  $uploadsRoot = dirname($webpRoot);
15
  $outputPath = str_replace(realpath($uploadsRoot), '', realpath($path));
16
  $outputPath = trim($outputPath, '\/');
18
  $newPath = sprintf('%s/%s.webp', $webpRoot, $outputPath);
19
  if (!$createDirectory) return $newPath;
20
 
21
+ if (!$paths = self::checkDirectories($newPath)) return $newPath;
22
+ else if (!self::makeDirectories($paths)) return null;
23
  else return $newPath;
24
  }
25
 
26
+ private static function checkDirectories($path)
27
  {
28
  $current = dirname($path);
29
  $paths = [];
34
  return $paths;
35
  }
36
 
37
+ private static function makeDirectories($paths)
38
  {
39
  $paths = array_reverse($paths);
40
  foreach ($paths as $path) {
41
+ if (!is_writable(dirname($path))) return false;
42
  mkdir($path);
43
  }
44
  return true;
app/Convert/Paths.php CHANGED
@@ -4,19 +4,18 @@
4
 
5
  class Paths
6
  {
 
 
7
  const PATH_UPLOADS = 'wp-content/uploads';
8
  const PATH_OUTPUT = 'wp-content/uploads-webpc';
9
  const DIRS_EXCLUDED = ['.', '..', '.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
 
@@ -24,64 +23,60 @@
24
  Functions
25
  --- */
26
 
27
- public function getUploadsPath($value, $skipRoot = false)
28
  {
29
- return self::PATH_UPLOADS;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
- public function getOutputPath($value, $skipRoot = false)
33
  {
34
- return self::PATH_OUTPUT;
 
 
 
 
 
 
 
 
35
  }
36
 
37
- public function parsePath($value, $skipRoot = false)
38
  {
39
- if ($skipRoot) return trim($value, '\/');
40
-
41
- $path = apply_filters('webpc_uploads_root', ABSPATH);
42
- return $path . '/' . trim($value, '\/');
 
 
 
 
43
  }
44
 
45
  public function getPrefixPath($value)
46
  {
47
  $docDir = realpath($_SERVER['DOCUMENT_ROOT']);
48
- $wpDir = realpath(ABSPATH);
49
  $diffDir = trim(str_replace($docDir, '', $wpDir), '\/');
50
  $diffPath = sprintf('/%s/', $diffDir);
51
 
52
  return str_replace('//', '/', $diffPath);
53
  }
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 self::DIRS_EXCLUDED;
4
 
5
  class Paths
6
  {
7
+ const PATH_PLUGINS = 'wp-content/plugins';
8
+ const PATH_THEMES = 'wp-content/themes';
9
  const PATH_UPLOADS = 'wp-content/uploads';
10
  const PATH_OUTPUT = 'wp-content/uploads-webpc';
11
  const DIRS_EXCLUDED = ['.', '..', '.git', '.svn', 'node_modules'];
12
 
13
  public function __construct()
14
  {
15
+ add_filter('webpc_dir_name', [$this, 'getDirAsName'], 0, 2);
16
+ add_filter('webpc_dir_path', [$this, 'getDirAsPath'], 0, 2);
17
+ add_filter('webpc_dir_url', [$this, 'getDirAsUrl'], 0, 2);
 
18
  add_filter('webpc_uploads_prefix', [$this, 'getPrefixPath'], 0);
 
 
19
  add_filter('webpc_dir_excluded', [$this, 'getExcludedDirs'], 0);
20
  }
21
 
23
  Functions
24
  --- */
25
 
26
+ public function getDirAsName($value, $directory)
27
  {
28
+ switch ($directory) {
29
+ case 'plugins':
30
+ return self::PATH_PLUGINS;
31
+ break;
32
+ case 'themes':
33
+ return self::PATH_THEMES;
34
+ break;
35
+ case 'uploads':
36
+ return self::PATH_UPLOADS;
37
+ break;
38
+ case 'webp':
39
+ return self::PATH_OUTPUT;
40
+ break;
41
+ }
42
+ return null;
43
  }
44
 
45
+ public function getDirAsPath($value, $directory)
46
  {
47
+ $sourcePath = apply_filters('webpc_site_root', realpath(ABSPATH));
48
+ switch ($directory) {
49
+ default:
50
+ if ($path = apply_filters('webpc_dir_name', null, $directory)) {
51
+ return $sourcePath . '/' . $path;
52
+ }
53
+ break;
54
+ }
55
+ return null;
56
  }
57
 
58
+ public function getDirAsUrl($value, $directory)
59
  {
60
+ $sourceUrl = apply_filters('webpc_site_url', get_site_url());
61
+ switch ($directory) {
62
+ default:
63
+ if ($path = apply_filters('webpc_dir_name', null, $directory)) {
64
+ return $sourceUrl . '/' . $path;
65
+ }
66
+ break;
67
+ }
68
  }
69
 
70
  public function getPrefixPath($value)
71
  {
72
  $docDir = realpath($_SERVER['DOCUMENT_ROOT']);
73
+ $wpDir = apply_filters('webpc_site_root', realpath(ABSPATH));
74
  $diffDir = trim(str_replace($docDir, '', $wpDir), '\/');
75
  $diffPath = sprintf('/%s/', $diffDir);
76
 
77
  return str_replace('//', '/', $diffPath);
78
  }
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  public function getExcludedDirs($value)
81
  {
82
  return self::DIRS_EXCLUDED;
app/Convert/Server.php CHANGED
@@ -8,7 +8,7 @@
8
  Functions
9
  --- */
10
 
11
- public function setSettings()
12
  {
13
  ini_set('memory_limit', '1G');
14
 
@@ -17,7 +17,7 @@
17
  }
18
  }
19
 
20
- public function checkIfFileExists($path)
21
  {
22
  if (is_readable($path)) return true;
23
  else if (!file_exists($path)) return sprintf('File "%s" does not exist. Please check file path using.', $path);
8
  Functions
9
  --- */
10
 
11
+ public static function setSettings()
12
  {
13
  ini_set('memory_limit', '1G');
14
 
17
  }
18
  }
19
 
20
+ public static function checkIfFileExists($path)
21
  {
22
  if (is_readable($path)) return true;
23
  else if (!file_exists($path)) return sprintf('File "%s" does not exist. Please check file path using.', $path);
app/Error/ErrorAbstract.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ use WebpConverter\Error\ErrorInterface;
6
+
7
+ abstract class ErrorAbstract implements ErrorInterface
8
+ {
9
+ private $settings = [];
10
+
11
+ public function __construct()
12
+ {
13
+ $this->settings = apply_filters('webpc_get_values', []);
14
+ }
15
+
16
+ /* ---
17
+ Functions
18
+ --- */
19
+
20
+ public function getSettings()
21
+ {
22
+ return $this->settings;
23
+ }
24
+ }
app/Error/ErrorInterface.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ interface ErrorInterface
6
+ {
7
+ /* ---
8
+ Functions
9
+ --- */
10
+
11
+ public function getSettings();
12
+
13
+ public function getErrorCodes();
14
+ }
app/Error/LibsError.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ use WebpConverter\Error\ErrorAbstract;
6
+ use WebpConverter\Error\ErrorInterface;
7
+ use WebpConverter\Method\Gd;
8
+ use WebpConverter\Method\Imagick;
9
+
10
+ class LibsError extends ErrorAbstract implements ErrorInterface
11
+ {
12
+ /* ---
13
+ Functions
14
+ --- */
15
+
16
+ public function getErrorCodes()
17
+ {
18
+ $errors = [];
19
+
20
+ if ($this->ifLibsAreInstalled() !== true) {
21
+ $errors[] = 'libs_not_installed';
22
+ } else if ($this->ifLibsSupportWebp() !== true) {
23
+ $errors[] = 'libs_without_webp_support';
24
+ }
25
+
26
+ return $errors;
27
+ }
28
+
29
+ private function ifLibsAreInstalled()
30
+ {
31
+ return (Gd::isMethodInstalled() || Imagick::isMethodInstalled());
32
+ }
33
+
34
+ private function ifLibsSupportWebp()
35
+ {
36
+ $methods = apply_filters('webpc_get_methods', []);
37
+ return (count($methods) > 0);
38
+ }
39
+ }
app/Error/PassthruError.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ use WebpConverter\Error\ErrorAbstract;
6
+ use WebpConverter\Error\ErrorInterface;
7
+ use WebpConverter\Loader\Passthru;
8
+
9
+ class PassthruError extends ErrorAbstract implements ErrorInterface
10
+ {
11
+ /* ---
12
+ Functions
13
+ --- */
14
+
15
+ public function getErrorCodes()
16
+ {
17
+ $errors = [];
18
+
19
+ if ($this->ifPassthruExecutionAllowed() !== true) {
20
+ $errors[] = 'passthru_execution';
21
+ }
22
+
23
+ return $errors;
24
+ }
25
+
26
+ private function ifPassthruExecutionAllowed()
27
+ {
28
+ if (Passthru::isActiveLoader() !== true) {
29
+ return true;
30
+ }
31
+
32
+ $url = Passthru::getLoaderUrl() . '?nocache=1';
33
+ $ch = curl_init($url);
34
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
35
+ curl_setopt($ch, CURLOPT_NOBODY, 1);
36
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
37
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
38
+ curl_setopt($ch, CURLOPT_TIMEOUT, 3);
39
+ curl_exec($ch);
40
+ $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
41
+ curl_close($ch);
42
+
43
+ return ($code === 200);
44
+ }
45
+ }
app/Error/PathsError.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ use WebpConverter\Error\ErrorAbstract;
6
+ use WebpConverter\Error\ErrorInterface;
7
+
8
+ class PathsError extends ErrorAbstract implements ErrorInterface
9
+ {
10
+ /* ---
11
+ Functions
12
+ --- */
13
+
14
+ public function getErrorCodes()
15
+ {
16
+ $errors = [];
17
+
18
+ if ($this->ifUploadsPathExists() !== true) {
19
+ $errors[] = 'path_uploads_unavailable';
20
+ } else if ($this->ifHtaccessIsWriteable() !== true) {
21
+ $errors[] = 'path_htaccess_not_writable';
22
+ }
23
+ if ($this->ifPathsAreDifferent() !== true) {
24
+ $errors[] = 'path_webp_duplicated';
25
+ } else if ($this->ifWebpPathIsWriteable() !== true) {
26
+ $errors[] = 'path_webp_not_writable';
27
+ }
28
+
29
+ return $errors;
30
+ }
31
+
32
+ private function ifUploadsPathExists()
33
+ {
34
+ $path = apply_filters('webpc_dir_path', '', 'uploads');
35
+ return (is_dir($path) && ($path !== ABSPATH));
36
+ }
37
+
38
+ private function ifHtaccessIsWriteable()
39
+ {
40
+ $pathDir = apply_filters('webpc_dir_path', '', 'uploads');
41
+ $pathFile = $pathDir . '/.htaccess';
42
+ if (file_exists($pathFile)) return (is_readable($pathFile) && is_writable($pathFile));
43
+ else return is_writable($pathDir);
44
+ }
45
+
46
+ private function ifPathsAreDifferent()
47
+ {
48
+ $pathUploads = apply_filters('webpc_dir_path', '', 'uploads');
49
+ $pathWebp = apply_filters('webpc_dir_path', '', 'webp');
50
+ return ($pathUploads !== $pathWebp);
51
+ }
52
+
53
+ private function ifWebpPathIsWriteable()
54
+ {
55
+ $path = apply_filters('webpc_dir_path', '', 'webp');
56
+ return (is_dir($path) || is_writable(dirname($path)));
57
+ }
58
+ }
app/Error/RestapiError.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ use WebpConverter\Error\ErrorAbstract;
6
+ use WebpConverter\Error\ErrorInterface;
7
+
8
+ class RestapiError extends ErrorAbstract implements ErrorInterface
9
+ {
10
+ /* ---
11
+ Functions
12
+ --- */
13
+
14
+ public function getErrorCodes()
15
+ {
16
+ $errors = [];
17
+
18
+ if ($this->ifRestApiIsEnabled() !== true) {
19
+ $errors[] = 'rest_api_disabled';
20
+ }
21
+
22
+ return $errors;
23
+ }
24
+
25
+ private function ifRestApiIsEnabled()
26
+ {
27
+ return ((apply_filters('rest_enabled', true) === true)
28
+ && (apply_filters('rest_jsonp_enabled', true) === true)
29
+ && (apply_filters('rest_authentication_errors', true) === true));
30
+ }
31
+ }
app/Error/RewritesError.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ use WebpConverter\Error\ErrorAbstract;
6
+ use WebpConverter\Error\ErrorInterface;
7
+ use WebpConverter\Traits\FileLoaderTrait;
8
+ use WebpConverter\Convert\Directory;
9
+ use WebpConverter\Loader\LoaderAbstract;
10
+
11
+ class RewritesError extends ErrorAbstract implements ErrorInterface
12
+ {
13
+ use FileLoaderTrait;
14
+
15
+ const PATH_SOURCE_FILE_PNG = '/public/img/icon-test.png';
16
+ const PATH_SOURCE_FILE_WEBP = '/public/img/icon-test.webp';
17
+ const PATH_OUTPUT_FILE_PNG = '/webp-converter-for-media-test.png';
18
+ const PATH_OUTPUT_FILE_PNG2 = '/webp-converter-for-media-test.png2';
19
+ const PATH_OUTPUT_FILE_PNG_AS_WEBP = self::PATH_OUTPUT_FILE_PNG . '.webp';
20
+ const PATH_OUTPUT_FILE_PNG2_AS_WEBP = self::PATH_OUTPUT_FILE_PNG2 . '.webp';
21
+
22
+ /* ---
23
+ Functions
24
+ --- */
25
+
26
+ public function getErrorCodes()
27
+ {
28
+ $this->convertImagesForDebug();
29
+ $errors = [];
30
+
31
+ if ($this->ifRedirectsAreWorks() !== true) {
32
+ if ($this->ifBypassingApacheIsActive() === true) {
33
+ $errors[] = 'bypassing_apache';
34
+ } else {
35
+ $errors[] = 'rewrites_not_working';
36
+ }
37
+ } else if ($this->ifRedirectsAreCached() === true) {
38
+ $errors[] = 'rewrites_cached';
39
+ }
40
+
41
+ return $errors;
42
+ }
43
+
44
+ private function convertImagesForDebug()
45
+ {
46
+ $uploadsDir = apply_filters('webpc_dir_path', '', 'uploads');
47
+ $pathFilePng = $uploadsDir . self::PATH_OUTPUT_FILE_PNG;
48
+ $pathFilePng2 = $uploadsDir . self::PATH_OUTPUT_FILE_PNG2;
49
+ if (!is_writable($uploadsDir)) {
50
+ return;
51
+ }
52
+
53
+ if (!file_exists($pathFilePng) || !file_exists($pathFilePng2)) {
54
+ copy(WEBPC_PATH . self::PATH_SOURCE_FILE_PNG, $pathFilePng);
55
+ copy(WEBPC_PATH . self::PATH_SOURCE_FILE_PNG, $pathFilePng2);
56
+ }
57
+
58
+ if (($outputPath = Directory::getPath($pathFilePng, true)) && !file_exists($outputPath)) {
59
+ copy(WEBPC_PATH . self::PATH_SOURCE_FILE_WEBP, $outputPath);
60
+ }
61
+ if (($outputPath = Directory::getPath($pathFilePng2, true)) && !file_exists($outputPath)) {
62
+ copy(WEBPC_PATH . self::PATH_SOURCE_FILE_WEBP, $outputPath);
63
+ }
64
+ }
65
+
66
+ private function ifRedirectsAreWorks()
67
+ {
68
+ $uploadsDir = apply_filters('webpc_dir_path', '', 'uploads');
69
+ $uploadsUrl = apply_filters('webpc_dir_url', '', 'uploads');
70
+
71
+ $fileSize = $this->getFileSizeByPath($uploadsDir . self::PATH_OUTPUT_FILE_PNG);
72
+ $fileWebp = $this->getFileSizeByUrl($uploadsUrl . self::PATH_OUTPUT_FILE_PNG);
73
+
74
+ return ($fileWebp < $fileSize);
75
+ }
76
+
77
+ private function ifBypassingApacheIsActive()
78
+ {
79
+ $uploadsUrl = apply_filters('webpc_dir_url', '', 'uploads');
80
+
81
+ add_filter('webpc_get_values', ['WebpConverter\Settings\Errors', 'setExtensionsForDebug']);
82
+ do_action(LoaderAbstract::ACTION_NAME, true);
83
+
84
+ $filePng = $this->getFileSizeByUrl($uploadsUrl . self::PATH_OUTPUT_FILE_PNG);
85
+ $filePng2 = $this->getFileSizeByUrl($uploadsUrl . self::PATH_OUTPUT_FILE_PNG2);
86
+
87
+ remove_filter('webpc_get_values', ['WebpConverter\Settings\Errors', 'setExtensionsForDebug']);
88
+ do_action(LoaderAbstract::ACTION_NAME, true);
89
+
90
+ return ($filePng > $filePng2);
91
+ }
92
+
93
+ private function ifRedirectsAreCached()
94
+ {
95
+ $uploadsUrl = apply_filters('webpc_dir_url', '', 'uploads');
96
+
97
+ $fileWebp = $this->getFileSizeByUrl($uploadsUrl . self::PATH_OUTPUT_FILE_PNG);
98
+ $fileOriginal = $this->getFileSizeByUrl($uploadsUrl . self::PATH_OUTPUT_FILE_PNG, false);
99
+
100
+ return (($fileWebp > 0) && ($fileWebp === $fileOriginal));
101
+ }
102
+ }
app/Error/SettingsError.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Error;
4
+
5
+ use WebpConverter\Error\ErrorAbstract;
6
+ use WebpConverter\Error\ErrorInterface;
7
+
8
+ class SettingsError extends ErrorAbstract implements ErrorInterface
9
+ {
10
+ /* ---
11
+ Functions
12
+ --- */
13
+
14
+ public function getErrorCodes()
15
+ {
16
+ $errors = [];
17
+
18
+ if ($this->ifSettingsAreCorrect() !== true) {
19
+ $errors[] = 'settings_incorrect';
20
+ }
21
+
22
+ return $errors;
23
+ }
24
+
25
+ private function ifSettingsAreCorrect()
26
+ {
27
+ $settings = $this->getSettings();
28
+ if ((!isset($settings['extensions']) || !$settings['extensions'])
29
+ || (!isset($settings['dirs']) || !$settings['dirs'])
30
+ || (!isset($settings['method']) || !in_array($settings['method'], apply_filters('webpc_get_methods', [])))
31
+ || (!isset($settings['quality']) || !$settings['quality'])) return false;
32
+
33
+ return true;
34
+ }
35
+ }
app/{Media → Loader}/Htaccess.php RENAMED
@@ -1,25 +1,41 @@
1
  <?php
2
 
3
- namespace WebpConverter\Media;
4
 
5
- class Htaccess
6
- {
7
- const ACTION_NAME = 'webpc_rewrite_htaccess';
8
 
9
- public function __construct()
10
- {
11
- add_action(self::ACTION_NAME, [$this, 'addRewriteRulesToWpContent'], 10, 1);
12
- add_action(self::ACTION_NAME, [$this, 'addRewriteRulesToUploads'], 10, 1);
13
- add_action(self::ACTION_NAME, [$this, 'addRewriteRulesToUploadsWebp'], 10, 1);
14
- }
15
 
16
  /* ---
17
  Functions
18
  --- */
19
 
20
- public function addRewriteRulesToWpContent($isActive)
 
 
 
 
 
 
21
  {
22
- $path = dirname(apply_filters('webpc_uploads_path', ''));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  if (!$isActive) return $this->saveRewritesInHtaccesss($path);
24
 
25
  $settings = apply_filters('webpc_get_values', []);
@@ -32,14 +48,15 @@
32
  $this->saveRewritesInHtaccesss($path, $content);
33
  }
34
 
35
- public function addRewriteRulesToUploads($isActive)
36
  {
37
- $path = apply_filters('webpc_uploads_path', '');
38
  if (!$isActive) return $this->saveRewritesInHtaccesss($path);
39
 
40
- $settings = apply_filters('webpc_get_values', []);
41
- $rows = [
42
- $this->getModRewriteRules($settings, apply_filters('webpc_uploads_dir', '')),
 
43
  ];
44
 
45
  $content = $this->addCommentsToRules($rows);
@@ -47,9 +64,9 @@
47
  $this->saveRewritesInHtaccesss($path, $content);
48
  }
49
 
50
- public function addRewriteRulesToUploadsWebp($isActive)
51
  {
52
- $path = apply_filters('webpc_uploads_webp', '');
53
  if (!$isActive) return $this->saveRewritesInHtaccesss($path);
54
 
55
  $values = apply_filters('webpc_get_values', []);
@@ -69,7 +86,7 @@
69
  if (!$settings['extensions']) return $content;
70
 
71
  $path = apply_filters('webpc_uploads_prefix', '/');
72
- $path .= apply_filters('webpc_uploads_webp', '', true);
73
  if ($outputPath !== null) $path .= '/' . $outputPath;
74
 
75
  $content .= '<IfModule mod_rewrite.c>' . PHP_EOL;
1
  <?php
2
 
3
+ namespace WebpConverter\Loader;
4
 
5
+ use WebpConverter\Loader\LoaderAbstract;
6
+ use WebpConverter\Loader\LoaderInterface;
 
7
 
8
+ class Htaccess extends LoaderAbstract implements LoaderInterface
9
+ {
10
+ const LOADER_TYPE = 'htaccess';
 
 
 
11
 
12
  /* ---
13
  Functions
14
  --- */
15
 
16
+ public static function isActiveLoader()
17
+ {
18
+ $settings = apply_filters('webpc_get_values', []);
19
+ return (!isset($settings['loader_type']) || ($settings['loader_type'] === self::LOADER_TYPE));
20
+ }
21
+
22
+ public function activateLoader()
23
  {
24
+ $this->addRewriteRulesToWpContent(true);
25
+ $this->addRewriteRulesToUploads(true);
26
+ $this->addRewriteRulesToUploadsWebp(true);
27
+ }
28
+
29
+ public function deactivateLoader()
30
+ {
31
+ $this->addRewriteRulesToWpContent(false);
32
+ $this->addRewriteRulesToUploads(false);
33
+ $this->addRewriteRulesToUploadsWebp(false);
34
+ }
35
+
36
+ private function addRewriteRulesToWpContent($isActive)
37
+ {
38
+ $path = dirname(apply_filters('webpc_dir_path', '', 'uploads'));
39
  if (!$isActive) return $this->saveRewritesInHtaccesss($path);
40
 
41
  $settings = apply_filters('webpc_get_values', []);
48
  $this->saveRewritesInHtaccesss($path, $content);
49
  }
50
 
51
+ private function addRewriteRulesToUploads($isActive)
52
  {
53
+ $path = apply_filters('webpc_dir_path', '', 'uploads');
54
  if (!$isActive) return $this->saveRewritesInHtaccesss($path);
55
 
56
+ $settings = apply_filters('webpc_get_values', []);
57
+ $pathParts = explode('/', apply_filters('webpc_dir_name', '', 'uploads'));
58
+ $rows = [
59
+ $this->getModRewriteRules($settings, end($pathParts)),
60
  ];
61
 
62
  $content = $this->addCommentsToRules($rows);
64
  $this->saveRewritesInHtaccesss($path, $content);
65
  }
66
 
67
+ private function addRewriteRulesToUploadsWebp($isActive)
68
  {
69
+ $path = apply_filters('webpc_dir_path', '', 'webp');
70
  if (!$isActive) return $this->saveRewritesInHtaccesss($path);
71
 
72
  $values = apply_filters('webpc_get_values', []);
86
  if (!$settings['extensions']) return $content;
87
 
88
  $path = apply_filters('webpc_uploads_prefix', '/');
89
+ $path .= apply_filters('webpc_dir_name', '', 'webp');
90
  if ($outputPath !== null) $path .= '/' . $outputPath;
91
 
92
  $content .= '<IfModule mod_rewrite.c>' . PHP_EOL;
app/Loader/LoaderAbstract.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Loader;
4
+
5
+ use WebpConverter\Loader\LoaderInterface;
6
+ use WebpConverter\Settings\Errors;
7
+
8
+ abstract class LoaderAbstract implements LoaderInterface
9
+ {
10
+ const ACTION_NAME = 'webpc_rewrite_htaccess';
11
+
12
+ public function __construct()
13
+ {
14
+ add_action(self::ACTION_NAME, [$this, 'refreshLoader']);
15
+ add_action('plugins_loaded', [$this, 'initHooks']);
16
+ }
17
+
18
+ /* ---
19
+ Functions
20
+ --- */
21
+
22
+ public function initHooks()
23
+ {
24
+ if (!static::isActiveLoader() || get_option(Errors::ERRORS_CACHE_OPTION, [])) {
25
+ return;
26
+ }
27
+ $this->hooks();
28
+ }
29
+
30
+ public function hooks() {}
31
+
32
+ public function refreshLoader($isActive) {
33
+ if ($isActive && static::isActiveLoader()) {
34
+ $this->activateLoader();
35
+ } else {
36
+ $this->deactivateLoader();
37
+ }
38
+ }
39
+
40
+ public function activateLoader() {}
41
+
42
+ public function deactivateLoader() {}
43
+ }
app/Loader/LoaderInterface.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Loader;
4
+
5
+ interface LoaderInterface
6
+ {
7
+ /* ---
8
+ Functions
9
+ --- */
10
+
11
+ public function hooks();
12
+
13
+ public static function isActiveLoader();
14
+
15
+ public function refreshLoader($isActive);
16
+
17
+ public function activateLoader();
18
+
19
+ public function deactivateLoader();
20
+ }
app/Loader/Passthru.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Loader;
4
+
5
+ use WebpConverter\Loader\LoaderAbstract;
6
+ use WebpConverter\Loader\LoaderInterface;
7
+
8
+ class Passthru extends LoaderAbstract implements LoaderInterface
9
+ {
10
+ const LOADER_TYPE = 'passthru';
11
+ const PATH_LOADER = '/webpc-passthru.php';
12
+
13
+ /* ---
14
+ Functions
15
+ --- */
16
+
17
+ public function hooks()
18
+ {
19
+ add_action('get_header', [$this, 'startBuffer']);
20
+ }
21
+
22
+ public static function isActiveLoader()
23
+ {
24
+ $settings = apply_filters('webpc_get_values', []);
25
+ return (isset($settings['loader_type']) && ($settings['loader_type'] === self::LOADER_TYPE));
26
+ }
27
+
28
+ public function activateLoader()
29
+ {
30
+ $pathSource = WEBPC_PATH . 'libs/passthru.php';
31
+ $sourceCode = (is_readable($pathSource)) ? file_get_contents($pathSource) : '';
32
+ if (!$sourceCode) {
33
+ return;
34
+ }
35
+
36
+ $pathDirUploads = apply_filters('webpc_dir_name', '', 'uploads');
37
+ $pathDirWebp = apply_filters('webpc_dir_name', '', 'webp');
38
+ $uploadSuffix = implode('/', array_diff(explode('/', $pathDirUploads), explode('/', $pathDirWebp)));
39
+
40
+ $sourceCode = preg_replace(
41
+ '/(PATH_UPLOADS = \')(\')/',
42
+ '$1' . $pathDirUploads . '$2',
43
+ $sourceCode);
44
+ $sourceCode = preg_replace(
45
+ '/(PATH_UPLOADS_WEBP = \')(\')/',
46
+ '$1' . $pathDirWebp . '/' . $uploadSuffix . '$2',
47
+ $sourceCode);
48
+
49
+ $dirOutput = dirname(apply_filters('webpc_dir_path', '', 'uploads'));
50
+ if (is_writable($dirOutput)) {
51
+ file_put_contents($dirOutput . self::PATH_LOADER, $sourceCode);
52
+ }
53
+ }
54
+
55
+ public function deactivateLoader()
56
+ {
57
+ $pathOutput = dirname(apply_filters('webpc_dir_path', '', 'uploads')) . self::PATH_LOADER;
58
+ if (is_writable($pathOutput)) unlink($pathOutput);
59
+ }
60
+
61
+ public function startBuffer()
62
+ {
63
+ ob_start(['WebpConverter\Loader\Passthru', 'updateImageUrls']);
64
+ }
65
+
66
+ public static function updateImageUrls($buffer)
67
+ {
68
+ if (!self::isActiveLoader()) {
69
+ return $buffer;
70
+ }
71
+
72
+ $settings = apply_filters('webpc_get_values', []);
73
+ $extensions = implode('|', $settings['extensions'] ?? []);
74
+ if (!$extensions || (!$sourceDir = self::getLoaderUrl())
75
+ || (!$allowedDirs = self::getAllowedDirs())) {
76
+ return $buffer;
77
+ }
78
+
79
+ $dirPaths = str_replace('/', '\\/', implode('|', self::getAllowedDirs()));
80
+ return preg_replace(
81
+ '/(https?:\/\/(?:.*?)(?:' . $dirPaths . ')(?:.*?)\.(?:' . $extensions . '))/',
82
+ $sourceDir . '?src=$1&nocache=1',
83
+ $buffer);
84
+ }
85
+
86
+ public static function getLoaderUrl()
87
+ {
88
+ if (!$sourceDir = dirname(apply_filters('webpc_dir_url', '', 'uploads'))) {
89
+ return null;
90
+ }
91
+ return $sourceDir . self::PATH_LOADER;
92
+ }
93
+
94
+ public static function getAllowedDirs()
95
+ {
96
+ $settings = apply_filters('webpc_get_values', []);
97
+ $dirs = [];
98
+ foreach ($settings['dirs'] as $dir) {
99
+ $dirs[] = apply_filters('webpc_dir_name', null, $dir);
100
+ }
101
+ return array_filter($dirs);
102
+ }
103
+ }
app/Loader/_Core.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Loader;
4
+
5
+ class _Core
6
+ {
7
+ public function __construct()
8
+ {
9
+ new Htaccess();
10
+ new Passthru();
11
+ }
12
+ }
app/Media/_Core.php CHANGED
@@ -7,7 +7,6 @@
7
  public function __construct()
8
  {
9
  new Delete();
10
- new Htaccess();
11
  new Upload();
12
  }
13
  }
7
  public function __construct()
8
  {
9
  new Delete();
 
10
  new Upload();
11
  }
12
  }
app/Method/Gd.php CHANGED
@@ -2,181 +2,99 @@
2
 
3
  namespace WebpConverter\Method;
4
 
5
- use WebpConverter\Convert\Directory;
6
- use WebpConverter\Convert\Server;
7
 
8
- class Gd
9
  {
 
 
10
  /* ---
11
  Functions
12
  --- */
13
 
14
- public function convertImage($path, $settings)
15
  {
16
- (new Server())->setSettings();
17
-
18
- try {
19
- $status = (new Server())->checkIfFileExists($path);
20
- if ($status !== true) {
21
- $e = new \Exception($status);
22
- $e->status = 'file_unreadable';
23
- throw $e;
24
- }
25
-
26
- $response = $this->createImage($path);
27
- if (!$response['success']) {
28
- $e = new \Exception($response['message']);
29
- $e->status = isset($response['error_code']) ? $response['error_code'] : '';
30
- throw $e;
31
- } else {
32
- $image = $response['data'];
33
- }
34
-
35
- $response = $this->convertColorPalette($image, $path);
36
- if (!$response['success']) {
37
- $e = new \Exception($response['message']);
38
- $e->status = isset($response['error_code']) ? $response['error_code'] : '';
39
- throw $e;
40
- } else {
41
- $image = $response['data'];
42
- }
43
-
44
- $image = apply_filters('webpc_gd_before_saving', $image, $path);
45
- $response = $this->convertToWebp($image, $path, $settings);
46
- if (!$response['success']) {
47
- $e = new \Exception($response['message']);
48
- $e->status = isset($response['error_code']) ? $response['error_code'] : '';
49
- throw $e;
50
- } else {
51
- return [
52
- 'success' => true,
53
- 'data' => $response['data'],
54
- ];
55
- }
56
- } catch (\Exception $e) {
57
- if (in_array('debug_enabled', $settings['features'])) {
58
- error_log(sprintf('WebP Converter for Media: %s', $e->getMessage()));
59
- }
60
 
61
- return [
62
- 'success' => false,
63
- 'message' => apply_filters('webpc_convert_error', $e->getMessage(), $e->status),
64
- ];
65
- }
66
  }
67
 
68
- private function createImage($path)
69
  {
70
- $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
71
  $methods = apply_filters('webpc_gd_create_methods', [
72
  'imagecreatefromjpeg' => ['jpg', 'jpeg'],
73
  'imagecreatefrompng' => ['png'],
74
  'imagecreatefromgif' => ['gif'],
75
  ]);
76
- try {
77
- foreach ($methods as $method => $extensions) {
78
- if (!in_array($extension, $extensions)) {
79
- continue;
80
- } else if (!function_exists($method)) {
81
- $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', $method));
82
- $e->status = 'server_configuration';
83
- throw $e;
84
- } else if (!$image = @$method($path)) {
85
- $e = new \Exception(sprintf('"%s" is not a valid image file.', $path));
86
- $e->status = 'invalid_image';
87
- throw $e;
88
- }
89
- }
90
- if (!isset($image)) {
91
- $e = new \Exception(sprintf('Unsupported extension "%s" for file "%s"', $extension, $path));
92
- $e->status = 'unsupported_extension';
93
  throw $e;
94
  }
 
95
 
96
- return [
97
- 'success' => true,
98
- 'data' => $image,
99
- ];
100
- } catch (\Exception $e) {
101
- return [
102
- 'success' => false,
103
- 'message' => $e->getMessage(),
104
- 'error_code' => (isset($e->status)) ? $e->status : '',
105
- ];
106
  }
 
 
107
  }
108
 
109
- private function convertColorPalette($image)
110
  {
111
- try {
112
- if (!function_exists('imageistruecolor')) {
113
- $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', 'imageistruecolor'));
 
 
 
 
 
 
114
  $e->status = 'server_configuration';
115
  throw $e;
116
- } else if (!imageistruecolor($image)) {
117
- if (!function_exists('imagepalettetotruecolor')) {
118
- $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', 'imagepalettetotruecolor'));
119
- $e->status = 'server_configuration';
120
- throw $e;
121
- }
122
- imagepalettetotruecolor($image);
123
  }
124
-
125
- return [
126
- 'success' => true,
127
- 'data' => $image,
128
- ];
129
- } catch (\Exception $e) {
130
- return [
131
- 'success' => false,
132
- 'message' => $e->getMessage(),
133
- 'error_code' => (isset($e->status)) ? $e->status : '',
134
- ];
135
  }
 
 
136
  }
137
 
138
- private function convertToWebp($image, $path, $settings)
139
  {
140
- try {
141
- $output = (new Directory())->getPath($path, true);
142
- if (!$output) {
143
- $e = new \Exception(sprintf('An error occurred creating destination directory for "%s" file.', $path));
144
- $e->status = 'output_path';
145
- throw $e;
146
- } else if (!function_exists('imagewebp')) {
147
- $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', 'imagewebp'));
148
- $e->status = 'server_configuration';
149
- throw $e;
150
- } else if ((imagesx($image) > 8192) || (imagesy($image) > 8192)) {
151
- $e = new \Exception(sprintf('Image is larger than maximum 8K resolution: "%s".', $path));
152
- $e->status = 'max_resolution';
153
- throw $e;
154
- } else if (!$success = imagewebp($image, $output, $settings['quality'])) {
155
- $e = new \Exception(sprintf('Error occurred while converting image: "%s".', $path));
156
- $e->status = 'convert_error';
157
- throw $e;
158
- }
159
-
160
- if (filesize($output) % 2 === 1) file_put_contents($output, "\0", FILE_APPEND);
161
- do_action('webpc_convert_after', $output, $path);
162
-
163
- return [
164
- 'success' => true,
165
- 'data' => [
166
- 'size' => [
167
- 'before' => filesize($path),
168
- 'after' => filesize((file_exists($output)) ? $output : $path),
169
- ],
170
- ],
171
- ];
172
- } catch (\Exception $e) {
173
- return [
174
- 'success' => false,
175
- 'message' => $e->getMessage(),
176
- 'error_code' => (isset($e->status)) ? $e->status : '',
177
- ];
178
  }
179
 
180
- return $image;
 
 
181
  }
182
  }
2
 
3
  namespace WebpConverter\Method;
4
 
5
+ use WebpConverter\Method\MethodAbstract;
6
+ use WebpConverter\Method\MethodInterface;
7
 
8
+ class Gd extends MethodAbstract implements MethodInterface
9
  {
10
+ const METHOD_NAME = 'gd';
11
+
12
  /* ---
13
  Functions
14
  --- */
15
 
16
+ public static function isMethodInstalled()
17
  {
18
+ return (extension_loaded('gd'));
19
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ public static function isMethodActive()
22
+ {
23
+ return (self::isMethodInstalled() && function_exists('imagewebp'));
 
 
24
  }
25
 
26
+ public function createImageByPath($sourcePath)
27
  {
28
+ $extension = strtolower(pathinfo($sourcePath, PATHINFO_EXTENSION));
29
  $methods = apply_filters('webpc_gd_create_methods', [
30
  'imagecreatefromjpeg' => ['jpg', 'jpeg'],
31
  'imagecreatefrompng' => ['png'],
32
  'imagecreatefromgif' => ['gif'],
33
  ]);
34
+
35
+ foreach ($methods as $method => $extensions) {
36
+ if (!in_array($extension, $extensions)) {
37
+ continue;
38
+ } else if (!function_exists($method)) {
39
+ $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', $method));
40
+ $e->status = 'server_configuration';
41
+ throw $e;
42
+ } else if (!$image = @$method($sourcePath)) {
43
+ $e = new \Exception(sprintf('"%s" is not a valid image file.', $sourcePath));
44
+ $e->status = 'invalid_image';
 
 
 
 
 
 
45
  throw $e;
46
  }
47
+ }
48
 
49
+ if (!isset($image)) {
50
+ $e = new \Exception(sprintf('Unsupported extension "%s" for file "%s"', $extension, $sourcePath));
51
+ $e->status = 'unsupported_extension';
52
+ throw $e;
 
 
 
 
 
 
53
  }
54
+
55
+ return $this->updateImageResource($image);
56
  }
57
 
58
+ private function updateImageResource($image)
59
  {
60
+ if (!function_exists('imageistruecolor')) {
61
+ $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', 'imageistruecolor'));
62
+ $e->status = 'server_configuration';
63
+ throw $e;
64
+ }
65
+
66
+ if (!imageistruecolor($image)) {
67
+ if (!function_exists('imagepalettetotruecolor')) {
68
+ $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', 'imagepalettetotruecolor'));
69
  $e->status = 'server_configuration';
70
  throw $e;
 
 
 
 
 
 
 
71
  }
72
+ imagepalettetotruecolor($image);
 
 
 
 
 
 
 
 
 
 
73
  }
74
+
75
+ return $image;
76
  }
77
 
78
+ public function convertImageToWebP($image, $sourcePath, $outputPath)
79
  {
80
+ $image = apply_filters('webpc_gd_before_saving', $image, $sourcePath);
81
+
82
+ if (!function_exists('imagewebp')) {
83
+ $e = new \Exception(sprintf('Server configuration: "%s" function is not available.', 'imagewebp'));
84
+ $e->status = 'server_configuration';
85
+ throw $e;
86
+ } else if ((imagesx($image) > 8192) || (imagesy($image) > 8192)) {
87
+ $e = new \Exception(sprintf('Image is larger than maximum 8K resolution: "%s".', $sourcePath));
88
+ $e->status = 'max_resolution';
89
+ throw $e;
90
+ } else if (!$success = imagewebp($image, $outputPath, $this->getSettings('quality'))) {
91
+ $e = new \Exception(sprintf('Error occurred while converting image: "%s".', $sourcePath));
92
+ $e->status = 'convert_error';
93
+ throw $e;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
 
96
+ if (filesize($outputPath) % 2 === 1) {
97
+ file_put_contents($outputPath, "\0", FILE_APPEND);
98
+ }
99
  }
100
  }
app/Method/Imagick.php CHANGED
@@ -2,138 +2,76 @@
2
 
3
  namespace WebpConverter\Method;
4
 
5
- use WebpConverter\Convert\Directory;
6
- use WebpConverter\Convert\Server;
7
 
8
- class Imagick
9
  {
 
 
10
  /* ---
11
  Functions
12
  --- */
13
 
14
- public function convertImage($path, $settings)
15
  {
16
- (new Server())->setSettings();
17
-
18
- try {
19
- $status = (new Server())->checkIfFileExists($path);
20
- if ($status !== true) {
21
- $e = new \Exception($status);
22
- $e->status = 'file_unreadable';
23
- throw $e;
24
- }
25
-
26
- $response = $this->createImage($path);
27
- if (!$response['success']) {
28
- $e = new \Exception($response['message']);
29
- $e->status = isset($response['error_code']) ? $response['error_code'] : '';
30
- throw $e;
31
- } else {
32
- $image = $response['data'];
33
- }
34
-
35
- $image = apply_filters('webpc_imagick_before_saving', $image, $path);
36
- $response = $this->convertToWebp($image, $path, $settings);
37
- if (!$response['success']) {
38
- $e = new \Exception($response['message']);
39
- $e->status = isset($response['error_code']) ? $response['error_code'] : '';
40
- throw $e;
41
- } else {
42
- return [
43
- 'success' => true,
44
- 'data' => $response['data'],
45
- ];
46
- }
47
- } catch (\Exception $e) {
48
- if (in_array('debug_enabled', $settings['features'])) {
49
- error_log(sprintf('WebP Converter for Media: %s', $e->getMessage()));
50
- }
51
 
52
- return [
53
- 'success' => false,
54
- 'message' => apply_filters('webpc_convert_error', $e->getMessage(), $e->status),
55
- ];
56
  }
 
 
 
57
  }
58
 
59
- private function createImage($path)
60
  {
61
- $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
62
- try {
63
- if (!extension_loaded('imagick') || !class_exists('Imagick')) {
64
- $e = new \Exception('Server configuration: Imagick module is not available with this PHP installation.');
65
- $e->status = 'server_configuration';
66
- throw $e;
67
- } else if (!$image = new \Imagick($path)) {
68
- $e = new \Exception(sprintf('"%s" is not a valid image file.', $path));
69
- $e->status = 'invalid_image';
70
- throw $e;
71
- }
72
- if (!isset($image)) {
73
- $e = new \Exception(sprintf('Unsupported extension "%s" for file "%s"', $extension, $path));
74
- $e->status = 'unsupported_extension';
75
- throw $e;
76
- }
77
 
78
- return [
79
- 'success' => true,
80
- 'data' => $image,
81
- ];
82
- } catch (\Exception $e) {
83
- return [
84
- 'success' => false,
85
- 'message' => $e->getMessage(),
86
- 'error_code' => (isset($e->status)) ? $e->status : '',
87
- ];
88
  }
 
 
89
  }
90
 
91
- private function convertToWebp($image, $path, $settings)
92
  {
93
- try {
94
- $output = (new Directory())->getPath($path, true);
95
- if (!$output) {
96
- $e = new \Exception(sprintf('An error occurred creating destination directory for "%s" file.', $path));
97
- $e->status = 'output_path';
98
- throw $e;
99
- } else if (!in_array('WEBP', $image->queryFormats())) {
100
- $e = new \Exception('Server configuration: Imagick does not support WebP format.');
101
- $e->status = 'server_configuration';
102
- throw $e;
103
- }
104
-
105
- $image->setImageFormat('WEBP');
106
- if (!in_array('keep_metadata', $settings['features'])) {
107
- $image->stripImage();
108
- }
109
- $image->setImageCompressionQuality($settings['quality']);
110
- $blob = $image->getImageBlob();
111
 
112
- $success = file_put_contents($output, $blob);
113
- if (!$success) {
114
- $e = new \Exception('Error occurred while converting image.');
115
- $e->status = 'convert_error';
116
- throw $e;
117
- }
118
- do_action('webpc_convert_after', $output, $path);
119
 
120
- return [
121
- 'success' => true,
122
- 'data' => [
123
- 'size' => [
124
- 'before' => filesize($path),
125
- 'after' => filesize((file_exists($output)) ? $output : $path),
126
- ],
127
- ],
128
- ];
129
- } catch (\Exception $e) {
130
- return [
131
- 'success' => false,
132
- 'message' => $e->getMessage(),
133
- 'error_code' => (isset($e->status)) ? $e->status : '',
134
- ];
135
  }
 
 
136
 
137
- return $image;
 
 
 
 
 
138
  }
139
  }
2
 
3
  namespace WebpConverter\Method;
4
 
5
+ use WebpConverter\Method\MethodAbstract;
6
+ use WebpConverter\Method\MethodInterface;
7
 
8
+ class Imagick extends MethodAbstract implements MethodInterface
9
  {
10
+ const METHOD_NAME = 'imagick';
11
+
12
  /* ---
13
  Functions
14
  --- */
15
 
16
+ public static function isMethodInstalled()
17
  {
18
+ return (extension_loaded('imagick') && class_exists('\Imagick'));
19
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
+ public static function isMethodActive()
22
+ {
23
+ if (!self::isMethodInstalled()) {
24
+ return false;
25
  }
26
+
27
+ $formats = (new \Imagick)->queryformats();
28
+ return (in_array('WEBP', $formats));
29
  }
30
 
31
+ public function createImageByPath($sourcePath)
32
  {
33
+ $extension = strtolower(pathinfo($sourcePath, PATHINFO_EXTENSION));
34
+ if (!extension_loaded('imagick') || !class_exists('Imagick')) {
35
+ $e = new \Exception('Server configuration: Imagick module is not available with this PHP installation.');
36
+ $e->status = 'server_configuration';
37
+ throw $e;
38
+ } else if (!$image = new \Imagick($sourcePath)) {
39
+ $e = new \Exception(sprintf('"%s" is not a valid image file.', $sourcePath));
40
+ $e->status = 'invalid_image';
41
+ throw $e;
42
+ }
 
 
 
 
 
 
43
 
44
+ if (!isset($image)) {
45
+ $e = new \Exception(sprintf('Unsupported extension "%s" for file "%s"', $extension, $sourcePath));
46
+ $e->status = 'unsupported_extension';
47
+ throw $e;
 
 
 
 
 
 
48
  }
49
+
50
+ return $image;
51
  }
52
 
53
+ public function convertImageToWebP($image, $sourcePath, $outputPath)
54
  {
55
+ $image = apply_filters('webpc_imagick_before_saving', $image, $sourcePath);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ if (!in_array('WEBP', $image->queryFormats())) {
58
+ $e = new \Exception('Server configuration: Imagick does not support WebP format.');
59
+ $e->status = 'server_configuration';
60
+ throw $e;
61
+ }
 
 
62
 
63
+ $image->setImageFormat('WEBP');
64
+ if (!in_array('keep_metadata', $this->getSettings('features'))) {
65
+ $image->stripImage();
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
+ $image->setImageCompressionQuality($this->getSettings('quality'));
68
+ $blob = $image->getImageBlob();
69
 
70
+ $success = file_put_contents($outputPath, $blob);
71
+ if (!$success) {
72
+ $e = new \Exception('Error occurred while converting image.');
73
+ $e->status = 'convert_error';
74
+ throw $e;
75
+ }
76
  }
77
  }
app/Method/MethodAbstract.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Method;
4
+
5
+ use WebpConverter\Method\MethodInterface;
6
+ use WebpConverter\Convert\Directory;
7
+ use WebpConverter\Convert\Server;
8
+
9
+ abstract class MethodAbstract implements MethodInterface
10
+ {
11
+ private $settings = [];
12
+
13
+ public function __construct()
14
+ {
15
+ $this->settings = apply_filters('webpc_get_values', []);
16
+ }
17
+
18
+ /* ---
19
+ Functions
20
+ --- */
21
+
22
+ public function getSettings($settingsKey)
23
+ {
24
+ return $this->settings[$settingsKey] ?? null;
25
+ }
26
+
27
+ public function convertImage($path)
28
+ {
29
+ Server::setSettings();
30
+
31
+ try {
32
+ $sourcePath = $this->getImageSourcePath($path);
33
+ $image = $this->createImageByPath($sourcePath);
34
+ $outputPath = $this->getImageOutputPath($sourcePath);
35
+
36
+ $this->convertImageToWebP($image, $sourcePath, $outputPath);
37
+ do_action('webpc_convert_after', $outputPath, $sourcePath);
38
+
39
+ return [
40
+ 'success' => true,
41
+ 'message' => null,
42
+ 'data' => $this->getConversionStats($sourcePath, $outputPath),
43
+ ];
44
+ } catch (\Exception $e) {
45
+ if (in_array('debug_enabled', $this->getSettings('features'))) {
46
+ error_log(sprintf('WebP Converter for Media: %s', $e->getMessage()));
47
+ }
48
+
49
+ return [
50
+ 'success' => false,
51
+ 'message' => apply_filters('webpc_convert_error', $e->getMessage(), $e->status),
52
+ 'data' => null,
53
+ ];
54
+ }
55
+ }
56
+
57
+ public function getImageSourcePath($sourcePath)
58
+ {
59
+ if (!$status = Server::checkIfFileExists($sourcePath)) {
60
+ $e = new \Exception(sprintf('Source path "%s" for image does not exist.', $sourcePath));
61
+ $e->status = 'file_unreadable';
62
+ throw $e;
63
+ }
64
+
65
+ return $sourcePath;
66
+ }
67
+
68
+ public function getImageOutputPath($sourcePath)
69
+ {
70
+ if (!$outputPath = Directory::getPath($sourcePath, true)) {
71
+ $e = new \Exception(sprintf('An error occurred creating destination directory for "%s" file.', $sourcePath));
72
+ $e->status = 'output_path';
73
+ throw $e;
74
+ }
75
+
76
+ return $outputPath;
77
+ }
78
+
79
+ public function getConversionStats($sourcePath, $outputPath)
80
+ {
81
+ $sizeBefore = filesize($sourcePath);
82
+ $sizeAfter = (file_exists($outputPath)) ? filesize($outputPath) : $sizeBefore;
83
+
84
+ return [
85
+ 'size_before' => $sizeBefore,
86
+ 'size_after' => $sizeAfter,
87
+ ];
88
+ }
89
+ }
app/Method/MethodIntegrator.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Method;
4
+
5
+ use WebpConverter\Method\Gd;
6
+ use WebpConverter\Method\Imagick;
7
+ use WebpConverter\Settings\Errors;
8
+
9
+ class MethodIntegrator
10
+ {
11
+ /* ---
12
+ Functions
13
+ --- */
14
+
15
+ public function getMethodsActive()
16
+ {
17
+ $list = [];
18
+ if (Gd::isMethodActive()) {
19
+ $list[] = Gd::METHOD_NAME;
20
+ }
21
+ if (Imagick::isMethodActive()) {
22
+ $list[] = Imagick::METHOD_NAME;
23
+ }
24
+ return $list;
25
+ }
26
+
27
+ public function getMethodUsed($methodKey)
28
+ {
29
+ if (get_option(Errors::ERRORS_CACHE_OPTION, [])) {
30
+ return null;
31
+ }
32
+
33
+ if ($methodKey === Gd::METHOD_NAME) {
34
+ return (new Gd());
35
+ } else if ($methodKey === Imagick::METHOD_NAME) {
36
+ return (new Imagick());
37
+ }
38
+ return null;
39
+ }
40
+ }
app/Method/MethodInterface.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WebpConverter\Method;
4
+
5
+ use WebpConverter\Convert\Directory;
6
+ use WebpConverter\Convert\Server;
7
+
8
+ interface MethodInterface
9
+ {
10
+ /* ---
11
+ Functions
12
+ --- */
13
+
14
+ public function getSettings($settingsKey);
15
+
16
+ public static function isMethodInstalled();
17
+
18
+ public static function isMethodActive();
19
+
20
+ public function convertImage($path);
21
+
22
+ public function getImageSourcePath($sourcePath);
23
+
24
+ public function createImageByPath($sourcePath);
25
+
26
+ public function getImageOutputPath($sourcePath);
27
+
28
+ public function convertImageToWebP($image, $sourcePath, $outputPath);
29
+
30
+ public function getConversionStats($sourcePath, $outputPath);
31
+ }
app/Plugin/Activation.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  use WebpConverter\Action\Cron;
6
  use WebpConverter\Admin\Notice;
7
- use WebpConverter\Media\Htaccess;
8
 
9
  class Activation
10
  {
@@ -38,7 +38,7 @@
38
 
39
  public function createDirectoryForUploadsWebp()
40
  {
41
- $path = apply_filters('webpc_uploads_webp', '');
42
  if (!file_exists($path) && is_writable(dirname($path))) mkdir($path);
43
  }
44
 
@@ -50,7 +50,6 @@
50
 
51
  public function refreshRewriteRules()
52
  {
53
- do_action(Htaccess::ACTION_NAME, true);
54
- flush_rewrite_rules(true);
55
  }
56
  }
4
 
5
  use WebpConverter\Action\Cron;
6
  use WebpConverter\Admin\Notice;
7
+ use WebpConverter\Loader\LoaderAbstract;
8
 
9
  class Activation
10
  {
38
 
39
  public function createDirectoryForUploadsWebp()
40
  {
41
+ $path = apply_filters('webpc_dir_path', '', 'webp');
42
  if (!file_exists($path) && is_writable(dirname($path))) mkdir($path);
43
  }
44
 
50
 
51
  public function refreshRewriteRules()
52
  {
53
+ do_action(LoaderAbstract::ACTION_NAME, true);
 
54
  }
55
  }
app/Plugin/Deactivation.php CHANGED
@@ -3,7 +3,7 @@
3
  namespace WebpConverter\Plugin;
4
 
5
  use WebpConverter\Action\Cron;
6
- use WebpConverter\Media\Htaccess;
7
 
8
  class Deactivation
9
  {
@@ -19,8 +19,7 @@
19
 
20
  public function refreshRewriteRules()
21
  {
22
- do_action(Htaccess::ACTION_NAME, false);
23
- flush_rewrite_rules(true);
24
  }
25
 
26
  public function resetCronEvent()
3
  namespace WebpConverter\Plugin;
4
 
5
  use WebpConverter\Action\Cron;
6
+ use WebpConverter\Loader\LoaderAbstract;
7
 
8
  class Deactivation
9
  {
19
 
20
  public function refreshRewriteRules()
21
  {
22
+ do_action(LoaderAbstract::ACTION_NAME, false);
 
23
  }
24
 
25
  public function resetCronEvent()
app/Plugin/Uninstall.php CHANGED
@@ -5,6 +5,7 @@
5
  use WebpConverter\Admin\Notice;
6
  use WebpConverter\Settings\Save;
7
  use WebpConverter\Settings\Errors;
 
8
 
9
  class Uninstall
10
  {
@@ -32,13 +33,13 @@
32
 
33
  private static function removeHtaccessFile()
34
  {
35
- $path = sprintf('%s/.htaccess', apply_filters('webpc_uploads_webp', ''));
36
  if (is_writable($path)) unlink($path);
37
  }
38
 
39
  public static function removeWebpFiles()
40
  {
41
- $path = apply_filters('webpc_uploads_webp', '');
42
  $paths = self::getPathsFromLocation($path);
43
  $paths[] = $path;
44
  self::removeFiles($paths);
@@ -46,13 +47,13 @@
46
 
47
  public static function removeDebugFiles()
48
  {
49
- $uploadsDir = apply_filters('webpc_uploads_path', []);
50
 
51
- if (is_writable($uploadsDir . Errors::PATH_OUTPUT_FILE_PNG)) {
52
- unlink($uploadsDir . Errors::PATH_OUTPUT_FILE_PNG);
53
  }
54
- if (is_writable($uploadsDir . Errors::PATH_OUTPUT_FILE_PNG2)) {
55
- unlink($uploadsDir . Errors::PATH_OUTPUT_FILE_PNG2);
56
  }
57
  }
58
 
5
  use WebpConverter\Admin\Notice;
6
  use WebpConverter\Settings\Save;
7
  use WebpConverter\Settings\Errors;
8
+ use WebpConverter\Error\RewritesError;
9
 
10
  class Uninstall
11
  {
33
 
34
  private static function removeHtaccessFile()
35
  {
36
+ $path = sprintf('%s/.htaccess', apply_filters('webpc_dir_path', '', 'webp'));
37
  if (is_writable($path)) unlink($path);
38
  }
39
 
40
  public static function removeWebpFiles()
41
  {
42
+ $path = apply_filters('webpc_dir_path', '', 'webp');
43
  $paths = self::getPathsFromLocation($path);
44
  $paths[] = $path;
45
  self::removeFiles($paths);
47
 
48
  public static function removeDebugFiles()
49
  {
50
+ $uploadsDir = apply_filters('webpc_dir_path', '', 'uploads');
51
 
52
+ if (is_writable($uploadsDir . RewritesError::PATH_OUTPUT_FILE_PNG)) {
53
+ unlink($uploadsDir . RewritesError::PATH_OUTPUT_FILE_PNG);
54
  }
55
+ if (is_writable($uploadsDir . RewritesError::PATH_OUTPUT_FILE_PNG2)) {
56
+ unlink($uploadsDir . RewritesError::PATH_OUTPUT_FILE_PNG2);
57
  }
58
  }
59
 
app/Plugin/Update.php CHANGED
@@ -2,8 +2,9 @@
2
 
3
  namespace WebpConverter\Plugin;
4
 
5
- use WebpConverter\Media\Htaccess;
6
  use WebpConverter\Settings\Save;
 
7
 
8
  class Update
9
  {
@@ -25,14 +26,13 @@
25
 
26
  if ($version !== null) {
27
  update_option(Save::SETTINGS_OPTION, $this->updateSettingsForOldVersions($version));
28
- $this->moveFilesToUploadsSubdirectory(self::VERSION_OPTION);
29
 
30
  update_option(Activation::NEW_INSTALLATION_OPTION, '0');
31
  remove_action('admin_notices', ['WebpConverter\Admin\Notice', 'loadWelcomeNotice']);
32
  }
33
 
34
- do_action(Htaccess::ACTION_NAME, true);
35
- flush_rewrite_rules(true);
36
  update_option(self::VERSION_OPTION, WEBPC_VERSION);
37
  }
38
 
@@ -52,6 +52,10 @@
52
  $settings['features'][] = 'debug_enabled';
53
  }
54
 
 
 
 
 
55
  $settings['features'] = array_unique($settings['features']);
56
  return $settings;
57
  }
@@ -60,19 +64,7 @@
60
  {
61
  if (version_compare($version, '1.2.7', '>')) return;
62
 
63
- $webpRoot = apply_filters('webpc_uploads_webp', '');
64
- if (!is_writable($webpRoot)) return;
65
-
66
- $pathParts = explode('/', apply_filters('webpc_uploads_dir', ''));
67
- $oldPaths = scandir(apply_filters('webpc_uploads_webp', ''));
68
- for ($i = 1; $i <= count($pathParts); $i++) {
69
- $dirPath = $webpRoot . '/' . implode('/', array_slice($pathParts, 0, $i));
70
- if (!file_exists($dirPath)) mkdir($dirPath);
71
- }
72
-
73
- foreach ($oldPaths as $path) {
74
- if (in_array($path, ['.', '..', '.htaccess', $pathParts[0]])) continue;
75
- rename($webpRoot . '/'. $path, $dirPath . '/'. $path);
76
- }
77
  }
78
  }
2
 
3
  namespace WebpConverter\Plugin;
4
 
5
+ use WebpConverter\Loader\LoaderAbstract;
6
  use WebpConverter\Settings\Save;
7
+ use WebpConverter\Plugin\Uninstall;
8
 
9
  class Update
10
  {
26
 
27
  if ($version !== null) {
28
  update_option(Save::SETTINGS_OPTION, $this->updateSettingsForOldVersions($version));
29
+ $this->moveFilesToUploadsSubdirectory($version);
30
 
31
  update_option(Activation::NEW_INSTALLATION_OPTION, '0');
32
  remove_action('admin_notices', ['WebpConverter\Admin\Notice', 'loadWelcomeNotice']);
33
  }
34
 
35
+ do_action(LoaderAbstract::ACTION_NAME, true);
 
36
  update_option(self::VERSION_OPTION, WEBPC_VERSION);
37
  }
38
 
52
  $settings['features'][] = 'debug_enabled';
53
  }
54
 
55
+ if (version_compare($version, '1.6.0', '<=') && !isset($settings['loader_type'])) {
56
+ $settings['loader_type'] = 'htaccess';
57
+ }
58
+
59
  $settings['features'] = array_unique($settings['features']);
60
  return $settings;
61
  }
64
  {
65
  if (version_compare($version, '1.2.7', '>')) return;
66
 
67
+ Uninstall::removeWebpFiles();
68
+ do_action('webpc_regenerate_all');
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
  }
app/Regenerate/Regenerate.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  namespace WebpConverter\Regenerate;
4
 
5
- use WebpConverter\Method;
6
 
7
  class Regenerate
8
  {
@@ -17,18 +17,19 @@
17
  $sizeBefore = 0;
18
  $sizeAfter = 0;
19
 
20
- if ($settings['method'] === 'gd') $convert = new Method\Gd();
21
- else if ($settings['method'] === 'imagick') $convert = new Method\Imagick();
22
- if (!isset($convert)) return false;
 
23
 
24
  foreach ($paths as $path) {
25
- $response = $convert->convertImage($path, $settings);
26
 
27
  if ($response['success'] !== true) {
28
  $errors[] = $response['message'];
29
  } else {
30
- $sizeBefore += $response['data']['size']['before'];
31
- $sizeAfter += $response['data']['size']['after'];
32
  }
33
  }
34
  $errors = array_filter($errors);
2
 
3
  namespace WebpConverter\Regenerate;
4
 
5
+ use WebpConverter\Method\MethodIntegrator;
6
 
7
  class Regenerate
8
  {
17
  $sizeBefore = 0;
18
  $sizeAfter = 0;
19
 
20
+ $convertMethod = (new MethodIntegrator())->getMethodUsed($settings['method']);
21
+ if ($convertMethod === null) {
22
+ return false;
23
+ }
24
 
25
  foreach ($paths as $path) {
26
+ $response = $convertMethod->convertImage($path);
27
 
28
  if ($response['success'] !== true) {
29
  $errors[] = $response['message'];
30
  } else {
31
+ $sizeBefore += $response['data']['size_before'];
32
+ $sizeAfter += $response['data']['size_after'];
33
  }
34
  }
35
  $errors = array_filter($errors);
app/Settings/Errors.php CHANGED
@@ -2,18 +2,16 @@
2
 
3
  namespace WebpConverter\Settings;
4
 
5
- use WebpConverter\Media\Htaccess;
6
- use WebpConverter\Traits\FileLoaderTrait;
 
 
 
 
7
 
8
  class Errors
9
  {
10
- use FileLoaderTrait;
11
-
12
- const PATH_SOURCE_FILE_PNG = '/public/img/icon-test.png';
13
- const PATH_SOURCE_FILE_PNG2 = '/public/img/icon-test.png2';
14
- const PATH_OUTPUT_FILE_PNG = '/webp-converter-for-media-test.png';
15
- const PATH_OUTPUT_FILE_PNG2 = '/webp-converter-for-media-test.png2';
16
- const ERRORS_CACHE_OPTION = 'webpc_errors_cache';
17
 
18
  private $cache = null;
19
  private $filePath = WEBPC_PATH . '/resources/components/errors/%s.php';
@@ -42,8 +40,7 @@
42
  foreach ($errors as $error) {
43
  ob_start();
44
  include sprintf($this->filePath, str_replace('_', '-', $error));
45
- $list[$error] = ob_get_contents();
46
- ob_end_clean();
47
  }
48
 
49
  update_option(self::ERRORS_CACHE_OPTION, array_keys($list));
@@ -53,170 +50,33 @@
53
  private function getErrorsList()
54
  {
55
  $errors = [];
56
-
57
- if ($this->ifLibsAreInstalled() !== true) {
58
- $errors[] = 'libs_not_installed';
59
- } else if ($this->ifLibsSupportWebp() !== true) {
60
- $errors[] = 'libs_without_webp_support';
61
  }
62
- if ($errors) return $errors;
63
-
64
- if ($this->ifSettingsAreCorrect() !== true) {
65
- $errors[] = 'settings_incorrect';
66
  }
67
- if ($errors) return $errors;
68
-
69
- if ($this->ifRestApiIsEnabled() !== true) {
70
- $errors[] = 'rest_api_disabled';
71
  }
72
- if ($this->ifUploadsPathExists() !== true) {
73
- $errors[] = 'path_uploads_unavailable';
74
- } else if ($this->ifHtaccessIsWriteable() !== true) {
75
- $errors[] = 'path_htaccess_not_writable';
76
  }
77
- if ($this->ifPathsAreDifferent() !== true) {
78
- $errors[] = 'path_webp_duplicated';
79
- } else if ($this->ifWebpPathIsWriteable() !== true) {
80
- $errors[] = 'path_webp_not_writable';
81
- }
82
- if ($errors) return $errors;
83
-
84
- $this->copyFilesForDebug();
85
- add_filter('webpc_get_values', [$this, 'setExtensionsForDebug']);
86
- add_filter('webpc_gd_create_methods', [$this, 'setMethodsForDebug']);
87
- do_action(Htaccess::ACTION_NAME, true);
88
-
89
- if ($this->ifRedirectsAreWorks() !== true) {
90
- if ($this->ifBypassingApacheIsActive() === true) {
91
- $errors[] = 'bypassing_apache';
92
- } else {
93
- $errors[] = 'rewrites_not_working';
94
- }
95
- } else if ($this->ifRedirectsAreCached() === true) {
96
- $errors[] = 'rewrites_cached';
97
  }
98
 
99
- remove_filter('webpc_get_values', [$this, 'setExtensionsForDebug']);
100
- remove_filter('webpc_gd_create_methods', [$this, 'setMethodsForDebug']);
101
- do_action(Htaccess::ACTION_NAME, true);
102
-
103
  return $errors;
104
  }
105
 
106
- private function copyFilesForDebug()
107
  {
108
- $uploadsDir = apply_filters('webpc_uploads_path', []);
109
- if (!is_writable($uploadsDir)) return;
110
-
111
- copy(WEBPC_PATH . self::PATH_SOURCE_FILE_PNG, $uploadsDir . self::PATH_OUTPUT_FILE_PNG);
112
- copy(WEBPC_PATH . self::PATH_SOURCE_FILE_PNG2, $uploadsDir . self::PATH_OUTPUT_FILE_PNG2);
113
- }
114
-
115
- public function setExtensionsForDebug($settings)
116
- {
117
- $settings['extensions'][] = 'png';
118
- $settings['extensions'][] = 'png2';
119
  return $settings;
120
  }
121
-
122
- public function setMethodsForDebug($methods)
123
- {
124
- $methods['imagecreatefrompng'][] = 'png2';
125
- return $methods;
126
- }
127
-
128
- private function ifLibsAreInstalled()
129
- {
130
- return (extension_loaded('gd') || (extension_loaded('imagick') && class_exists('\Imagick')));
131
- }
132
-
133
- private function ifLibsSupportWebp()
134
- {
135
- $methods = apply_filters('webpc_get_methods', []);
136
- return (count($methods) > 0);
137
- }
138
-
139
- private function ifSettingsAreCorrect()
140
- {
141
- $settings = apply_filters('webpc_get_values', [], true);
142
- if ((!isset($settings['extensions']) || !$settings['extensions'])
143
- || (!isset($settings['dirs']) || !$settings['dirs'])
144
- || (!isset($settings['method']) || !$settings['method'])
145
- || (!isset($settings['quality']) || !$settings['quality'])) return false;
146
-
147
- return true;
148
- }
149
-
150
- private function ifRestApiIsEnabled()
151
- {
152
- return ((apply_filters('rest_enabled', true) === true)
153
- && (apply_filters('rest_jsonp_enabled', true) === true)
154
- && (apply_filters('rest_authentication_errors', true) === true));
155
- }
156
-
157
- private function ifUploadsPathExists()
158
- {
159
- $path = apply_filters('webpc_uploads_path', '');
160
- return (is_dir($path) && ($path !== ABSPATH));
161
- }
162
-
163
- private function ifHtaccessIsWriteable()
164
- {
165
- $pathDir = apply_filters('webpc_uploads_path', '');
166
- $pathFile = $pathDir . '/.htaccess';
167
- if (file_exists($pathFile)) return (is_readable($pathFile) && is_writable($pathFile));
168
- else return is_writable($pathDir);
169
- }
170
-
171
- private function ifPathsAreDifferent()
172
- {
173
- $pathUploads = apply_filters('webpc_uploads_path', '');
174
- $pathWebp = apply_filters('webpc_uploads_webp', '');
175
- return ($pathUploads !== $pathWebp);
176
- }
177
-
178
- private function ifWebpPathIsWriteable()
179
- {
180
- $path = apply_filters('webpc_uploads_webp', '');
181
- return (is_dir($path) || is_writable(dirname($path)));
182
- }
183
-
184
- private function ifRedirectsAreWorks()
185
- {
186
- $uploads = wp_upload_dir();
187
- $sourceFile = apply_filters('webpc_uploads_path', []) . self::PATH_OUTPUT_FILE_PNG;
188
-
189
- do_action('webpc_convert_paths', apply_filters('webpc_files_paths', [
190
- $sourceFile,
191
- ], true));
192
-
193
- $fileSize = $this->getFileSizeByPath($sourceFile);
194
- $fileWebp = $this->getFileSizeByUrl($uploads['baseurl'] . self::PATH_OUTPUT_FILE_PNG);
195
-
196
- return ($fileWebp < $fileSize);
197
- }
198
-
199
- private function ifBypassingApacheIsActive()
200
- {
201
- $uploads = wp_upload_dir();
202
- $sourceFile = apply_filters('webpc_uploads_path', []) . self::PATH_OUTPUT_FILE_PNG2;
203
-
204
- do_action('webpc_convert_paths', apply_filters('webpc_files_paths', [
205
- $sourceFile,
206
- ], true));
207
-
208
- $filePng = $this->getFileSizeByUrl($uploads['baseurl'] . self::PATH_OUTPUT_FILE_PNG);
209
- $filePng2 = $this->getFileSizeByUrl($uploads['baseurl'] . self::PATH_OUTPUT_FILE_PNG2);
210
-
211
- return ($filePng > $filePng2);
212
- }
213
-
214
- private function ifRedirectsAreCached()
215
- {
216
- $uploads = wp_upload_dir();
217
- $fileWebp = $this->getFileSizeByUrl($uploads['baseurl'] . self::PATH_OUTPUT_FILE_PNG);
218
- $fileOriginal = $this->getFileSizeByUrl($uploads['baseurl'] . self::PATH_OUTPUT_FILE_PNG, false);
219
-
220
- return (($fileWebp > 0) && ($fileWebp === $fileOriginal));
221
- }
222
  }
2
 
3
  namespace WebpConverter\Settings;
4
 
5
+ use WebpConverter\Error\LibsError;
6
+ use WebpConverter\Error\PassthruError;
7
+ use WebpConverter\Error\PathsError;
8
+ use WebpConverter\Error\RestapiError;
9
+ use WebpConverter\Error\RewritesError;
10
+ use WebpConverter\Error\SettingsError;
11
 
12
  class Errors
13
  {
14
+ const ERRORS_CACHE_OPTION = 'webpc_errors_cache';
 
 
 
 
 
 
15
 
16
  private $cache = null;
17
  private $filePath = WEBPC_PATH . '/resources/components/errors/%s.php';
40
  foreach ($errors as $error) {
41
  ob_start();
42
  include sprintf($this->filePath, str_replace('_', '-', $error));
43
+ $list[$error] = ob_get_clean();
 
44
  }
45
 
46
  update_option(self::ERRORS_CACHE_OPTION, array_keys($list));
50
  private function getErrorsList()
51
  {
52
  $errors = [];
53
+ if ($newErrors = (new LibsError())->getErrorCodes()) {
54
+ $errors = array_merge($errors, $newErrors);
 
 
 
55
  }
56
+ if ($newErrors = (new RestapiError())->getErrorCodes()) {
57
+ $errors = array_merge($errors, $newErrors);
 
 
58
  }
59
+ if ($newErrors = (new PathsError())->getErrorCodes()) {
60
+ $errors = array_merge($errors, $newErrors);
 
 
61
  }
62
+ if ($newErrors = (new PassthruError())->getErrorCodes()) {
63
+ $errors = array_merge($errors, $newErrors);
64
+ } else if ($newErrors = (new RewritesError())->getErrorCodes()) {
65
+ $errors = array_merge($errors, $newErrors);
66
  }
67
+ if (!$errors && ($newErrors = (new SettingsError())->getErrorCodes())) {
68
+ $errors = array_merge($errors, $newErrors);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
 
 
 
 
 
71
  return $errors;
72
  }
73
 
74
+ public static function setExtensionsForDebug($settings)
75
  {
76
+ $settings['extensions'] = array_unique(array_merge(
77
+ ['png2', 'png'],
78
+ $settings['extensions']
79
+ ));
 
 
 
 
 
 
 
80
  return $settings;
81
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  }
app/Settings/Methods.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace WebpConverter\Settings;
4
 
 
 
5
  class Methods
6
  {
7
  private $cache = null;
@@ -19,14 +21,7 @@
19
  {
20
  if ($this->cache !== null) return $this->cache;
21
 
22
- $this->cache = [];
23
- if (extension_loaded('gd') && function_exists('imagewebp')) {
24
- $this->cache[] = 'gd';
25
- }
26
- if (extension_loaded('imagick') && class_exists('\Imagick')) {
27
- $formats = (new \Imagick)->queryformats();
28
- if (in_array('WEBP', $formats)) $this->cache[] = 'imagick';
29
- }
30
  return $this->cache;
31
  }
32
  }
2
 
3
  namespace WebpConverter\Settings;
4
 
5
+ use WebpConverter\Method\MethodIntegrator;
6
+
7
  class Methods
8
  {
9
  private $cache = null;
21
  {
22
  if ($this->cache !== null) return $this->cache;
23
 
24
+ $this->cache = (new MethodIntegrator())->getMethodsActive();
 
 
 
 
 
 
 
25
  return $this->cache;
26
  }
27
  }
app/Settings/Options.php CHANGED
@@ -2,6 +2,11 @@
2
 
3
  namespace WebpConverter\Settings;
4
 
 
 
 
 
 
5
  class Options
6
  {
7
  public function __construct()
@@ -16,6 +21,21 @@
16
  public function getOptions($options)
17
  {
18
  return [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  [
20
  'name' => 'extensions',
21
  'type' => 'checkbox',
@@ -47,8 +67,8 @@
47
  'label' => __('Conversion method', 'webp-converter-for-media'),
48
  'info' => __('The configuration for advanced users.', 'webp-converter-for-media'),
49
  'values' => [
50
- 'gd' => sprintf(__('%s (recommended)', 'webp-converter-for-media'), 'GD'),
51
- 'imagick' => 'Imagick',
52
  ],
53
  'disabled' => $this->getDisabledValues('method'),
54
  ],
@@ -91,8 +111,12 @@
91
  switch ($optionName) {
92
  case 'method':
93
  $methods = apply_filters('webpc_get_methods', []);
94
- if (!in_array('gd', $methods)) $list[] = 'gd';
95
- if (!in_array('imagick', $methods)) $list[] = 'imagick';
 
 
 
 
96
  break;
97
  case 'features':
98
  $settings = apply_filters('webpc_get_values', []);
2
 
3
  namespace WebpConverter\Settings;
4
 
5
+ use WebpConverter\Loader\Htaccess;
6
+ use WebpConverter\Loader\Passthru;
7
+ use WebpConverter\Method\Gd;
8
+ use WebpConverter\Method\Imagick;
9
+
10
  class Options
11
  {
12
  public function __construct()
21
  public function getOptions($options)
22
  {
23
  return [
24
+ [
25
+ 'name' => 'loader_type',
26
+ 'type' => 'radio',
27
+ 'label' => __('Image loading mode', 'webp-converter-for-media'),
28
+ 'info' => __('By changing image loading mode it allows you to bypass some server configuration problems.', 'webp-converter-for-media'),
29
+ 'values' => [
30
+ Htaccess::LOADER_TYPE => sprintf(
31
+ __('%s (recommended)', 'webp-converter-for-media'),
32
+ __('via .htaccess', 'webp-converter-for-media')),
33
+ Passthru::LOADER_TYPE => sprintf(
34
+ __('%s (without rewrites in .htacces files or Nginx configuration)', 'webp-converter-for-media'),
35
+ 'Pass Thru'),
36
+ ],
37
+ 'disabled' => $this->getDisabledValues('loader_type'),
38
+ ],
39
  [
40
  'name' => 'extensions',
41
  'type' => 'checkbox',
67
  'label' => __('Conversion method', 'webp-converter-for-media'),
68
  'info' => __('The configuration for advanced users.', 'webp-converter-for-media'),
69
  'values' => [
70
+ Gd::METHOD_NAME => sprintf(__('%s (recommended)', 'webp-converter-for-media'), 'GD'),
71
+ Imagick::METHOD_NAME => 'Imagick',
72
  ],
73
  'disabled' => $this->getDisabledValues('method'),
74
  ],
111
  switch ($optionName) {
112
  case 'method':
113
  $methods = apply_filters('webpc_get_methods', []);
114
+ if (!in_array(Gd::METHOD_NAME, $methods)) {
115
+ $list[] = Gd::METHOD_NAME;
116
+ }
117
+ if (!in_array(Imagick::METHOD_NAME, $methods)) {
118
+ $list[] = Imagick::METHOD_NAME;
119
+ }
120
  break;
121
  case 'features':
122
  $settings = apply_filters('webpc_get_values', []);
app/Settings/Save.php CHANGED
@@ -3,7 +3,7 @@
3
  namespace WebpConverter\Settings;
4
 
5
  use WebpConverter\Action\Cron;
6
- use WebpConverter\Media\Htaccess;
7
 
8
  class Save
9
  {
@@ -27,7 +27,7 @@
27
  update_option(self::SETTINGS_OPTION, $values);
28
  $settings = apply_filters('webpc_get_values', [], true);
29
 
30
- do_action(Htaccess::ACTION_NAME, true);
31
  wp_clear_scheduled_hook(Cron::CRON_ACTION);
32
  }
33
 
3
  namespace WebpConverter\Settings;
4
 
5
  use WebpConverter\Action\Cron;
6
+ use WebpConverter\Loader\LoaderAbstract;
7
 
8
  class Save
9
  {
27
  update_option(self::SETTINGS_OPTION, $values);
28
  $settings = apply_filters('webpc_get_values', [], true);
29
 
30
+ do_action(LoaderAbstract::ACTION_NAME, true);
31
  wp_clear_scheduled_hook(Cron::CRON_ACTION);
32
  }
33
 
app/Settings/Server.php CHANGED
@@ -2,7 +2,9 @@
2
 
3
  namespace WebpConverter\Settings;
4
 
 
5
  use WebpConverter\Settings\Errors;
 
6
  use WebpConverter\Traits\FileLoaderTrait;
7
 
8
  class Server
@@ -24,7 +26,12 @@
24
  {
25
  ob_start();
26
 
 
 
27
  echo $this->getFiltersInfo();
 
 
 
28
  foreach ($this->extensions as $extension) {
29
  $this->getExtensionInfo($extension);
30
  }
@@ -51,8 +58,8 @@
51
 
52
  private function getFiltersInfo()
53
  {
54
- $uploads = wp_upload_dir();
55
- $sourceDir = apply_filters('webpc_uploads_path', []);
56
 
57
  ob_start();
58
 
@@ -73,47 +80,47 @@
73
  </td>
74
  </tr>
75
  <tr>
76
- <td class="e">webpc_uploads_root</td>
77
  <td class="v">
78
- <?= apply_filters('webpc_uploads_root', ABSPATH); ?>
79
  </td>
80
  </tr>
81
  <tr>
82
- <td class="e">webpc_uploads_prefix</td>
83
  <td class="v">
84
- <?= apply_filters('webpc_uploads_prefix', '/'); ?>
85
  </td>
86
  </tr>
87
- <tr>
88
- <td class="e">webpc_uploads_path</td>
89
  <td class="v">
90
- <?= apply_filters('webpc_uploads_path', '', false); ?>
91
  </td>
92
  </tr>
93
  <tr>
94
- <td class="e">webpc_uploads_webp</td>
95
  <td class="v">
96
- <?= apply_filters('webpc_uploads_webp', '', false); ?>
97
  </td>
98
  </tr>
99
  <tr>
100
- <td class="e">webpc_dir_path <em>(plugins)</em></td>
101
  <td class="v">
102
- <?= apply_filters('webpc_dir_path', '', 'plugins'); ?>
103
  </td>
104
  </tr>
105
  <tr>
106
- <td class="e">webpc_dir_path <em>(themes)</em></td>
107
  <td class="v">
108
- <?= apply_filters('webpc_dir_path', '', 'themes'); ?>
109
  </td>
110
  </tr>
111
  <tr>
112
- <td class="e">webpc_dir_path <em>(uploads)</em></td>
113
  <td class="v">
114
- <?= apply_filters('webpc_dir_path', '', 'uploads'); ?>
115
  </td>
116
  </tr>
 
117
  <tr>
118
  <td class="e">webpc_dir_excluded</td>
119
  <td class="v">
@@ -139,37 +146,37 @@
139
  <tr>
140
  <td class="e">Size of PNG <em>(by server path)</em></td>
141
  <td class="v">
142
- <?= $this->getFileSizeByPath($sourceDir . Errors::PATH_OUTPUT_FILE_PNG); ?>
143
  </td>
144
  </tr>
145
  <tr>
146
  <td class="e">Size of PNG2 <em>(by server path)</em></td>
147
  <td class="v">
148
- <?= $this->getFileSizeByPath($sourceDir . Errors::PATH_OUTPUT_FILE_PNG2); ?>
149
  </td>
150
  </tr>
151
  <tr>
152
  <td class="e">Size of PNG as WEBP <em>(by URL)</em></td>
153
  <td class="v">
154
- <?= $this->getFileSizeByUrl($uploads['baseurl'] . Errors::PATH_OUTPUT_FILE_PNG); ?>
155
  </td>
156
  </tr>
157
  <tr>
158
  <td class="e">Size of PNG as PNG <em>(by URL)</em></td>
159
  <td class="v">
160
- <?= $this->getFileSizeByUrl($uploads['baseurl'] . Errors::PATH_OUTPUT_FILE_PNG, false); ?>
161
  </td>
162
  </tr>
163
  <tr>
164
  <td class="e">Size of PNG2 as WEBP <em>(by URL)</em></td>
165
  <td class="v">
166
- <?= $this->getFileSizeByUrl($uploads['baseurl'] . Errors::PATH_OUTPUT_FILE_PNG2); ?>
167
  </td>
168
  </tr>
169
  <tr>
170
  <td class="e">Size of PNG2 as PNG2 <em>(by URL)</em></td>
171
  <td class="v">
172
- <?= $this->getFileSizeByUrl($uploads['baseurl'] . Errors::PATH_OUTPUT_FILE_PNG2, false); ?>
173
  </td>
174
  </tr>
175
  </tbody>
2
 
3
  namespace WebpConverter\Settings;
4
 
5
+ use WebpConverter\Loader\LoaderAbstract;
6
  use WebpConverter\Settings\Errors;
7
+ use WebpConverter\Error\RewritesError;
8
  use WebpConverter\Traits\FileLoaderTrait;
9
 
10
  class Server
26
  {
27
  ob_start();
28
 
29
+ add_filter('webpc_get_values', ['WebpConverter\Settings\Errors', 'setExtensionsForDebug']);
30
+ do_action(LoaderAbstract::ACTION_NAME, true);
31
  echo $this->getFiltersInfo();
32
+ remove_filter('webpc_get_values', ['WebpConverter\Settings\Errors', 'setExtensionsForDebug']);
33
+ do_action(LoaderAbstract::ACTION_NAME, true);
34
+
35
  foreach ($this->extensions as $extension) {
36
  $this->getExtensionInfo($extension);
37
  }
58
 
59
  private function getFiltersInfo()
60
  {
61
+ $uploadsUrl = apply_filters('webpc_dir_url', '', 'uploads');
62
+ $uploadsPath = apply_filters('webpc_dir_path', '', 'uploads');
63
 
64
  ob_start();
65
 
80
  </td>
81
  </tr>
82
  <tr>
83
+ <td class="e">webpc_site_root</td>
84
  <td class="v">
85
+ <?= apply_filters('webpc_site_root', ABSPATH); ?>
86
  </td>
87
  </tr>
88
  <tr>
89
+ <td class="e">webpc_site_url</td>
90
  <td class="v">
91
+ <?= apply_filters('webpc_site_url', get_site_url()); ?>
92
  </td>
93
  </tr>
94
+ <td class="e">webpc_dir_path <em>(plugins)</em></td>
 
95
  <td class="v">
96
+ <?= apply_filters('webpc_dir_path', '', 'plugins'); ?>
97
  </td>
98
  </tr>
99
  <tr>
100
+ <td class="e">webpc_dir_path <em>(themes)</em></td>
101
  <td class="v">
102
+ <?= apply_filters('webpc_dir_path', '', 'themes'); ?>
103
  </td>
104
  </tr>
105
  <tr>
106
+ <td class="e">webpc_dir_path <em>(uploads)</em></td>
107
  <td class="v">
108
+ <?= apply_filters('webpc_dir_path', '', 'uploads'); ?>
109
  </td>
110
  </tr>
111
  <tr>
112
+ <td class="e">webpc_dir_path <em>(webp)</em></td>
113
  <td class="v">
114
+ <?= apply_filters('webpc_dir_path', '', 'webp'); ?>
115
  </td>
116
  </tr>
117
  <tr>
118
+ <td class="e">webpc_uploads_prefix</td>
119
  <td class="v">
120
+ <?= apply_filters('webpc_uploads_prefix', '/'); ?>
121
  </td>
122
  </tr>
123
+ <tr>
124
  <tr>
125
  <td class="e">webpc_dir_excluded</td>
126
  <td class="v">
146
  <tr>
147
  <td class="e">Size of PNG <em>(by server path)</em></td>
148
  <td class="v">
149
+ <?= $this->getFileSizeByPath($uploadsPath . RewritesError::PATH_OUTPUT_FILE_PNG); ?>
150
  </td>
151
  </tr>
152
  <tr>
153
  <td class="e">Size of PNG2 <em>(by server path)</em></td>
154
  <td class="v">
155
+ <?= $this->getFileSizeByPath($uploadsPath . RewritesError::PATH_OUTPUT_FILE_PNG2); ?>
156
  </td>
157
  </tr>
158
  <tr>
159
  <td class="e">Size of PNG as WEBP <em>(by URL)</em></td>
160
  <td class="v">
161
+ <?= $this->getFileSizeByUrl($uploadsUrl . RewritesError::PATH_OUTPUT_FILE_PNG); ?>
162
  </td>
163
  </tr>
164
  <tr>
165
  <td class="e">Size of PNG as PNG <em>(by URL)</em></td>
166
  <td class="v">
167
+ <?= $this->getFileSizeByUrl($uploadsUrl . RewritesError::PATH_OUTPUT_FILE_PNG, false); ?>
168
  </td>
169
  </tr>
170
  <tr>
171
  <td class="e">Size of PNG2 as WEBP <em>(by URL)</em></td>
172
  <td class="v">
173
+ <?= $this->getFileSizeByUrl($uploadsUrl . RewritesError::PATH_OUTPUT_FILE_PNG2); ?>
174
  </td>
175
  </tr>
176
  <tr>
177
  <td class="e">Size of PNG2 as PNG2 <em>(by URL)</em></td>
178
  <td class="v">
179
+ <?= $this->getFileSizeByUrl($uploadsUrl . RewritesError::PATH_OUTPUT_FILE_PNG2, false); ?>
180
  </td>
181
  </tr>
182
  </tbody>
app/Settings/Values.php CHANGED
@@ -21,11 +21,12 @@
21
 
22
  $methods = apply_filters('webpc_get_methods', []);
23
  $this->cache = get_option(Save::SETTINGS_OPTION, [
24
- 'extensions' => ['jpg', 'jpeg', 'png'],
25
- 'dirs' => ['uploads'],
26
- 'method' => ($methods) ? $methods[0] : '',
27
- 'features' => ['only_smaller', 'mod_expires', 'debug_enabled'],
28
- 'quality' => 85,
 
29
  ]);
30
  return $this->cache;
31
  }
21
 
22
  $methods = apply_filters('webpc_get_methods', []);
23
  $this->cache = get_option(Save::SETTINGS_OPTION, [
24
+ 'loader_type' => 'htaccess',
25
+ 'extensions' => ['jpg', 'jpeg', 'png'],
26
+ 'dirs' => ['uploads'],
27
+ 'method' => ($methods) ? $methods[0] : '',
28
+ 'features' => ['only_smaller', 'mod_expires', 'debug_enabled'],
29
+ 'quality' => 85,
30
  ]);
31
  return $this->cache;
32
  }
app/Traits/FileLoaderTrait.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace WebpConverter\Traits;
4
 
 
 
5
  trait FileLoaderTrait
6
  {
7
  /* ---
@@ -14,7 +16,9 @@
14
  'Accept: image/webp',
15
  'Referer: ' . WEBPC_URL,
16
  ];
17
- return $this->getFileSizeForLoadedFile($url, ($setHeaders) ? $headers : []);
 
 
18
  }
19
 
20
  private function getFileSizeByPath($path)
@@ -25,12 +29,15 @@
25
 
26
  private function getFileSizeForLoadedFile($url, $headers)
27
  {
28
- $headers[] = 'Cache-Control: no-cache';
 
 
29
 
30
  $ch = curl_init($url);
31
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
32
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
33
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
 
34
  curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
35
  curl_setopt($ch, CURLOPT_TIMEOUT, 10);
36
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
2
 
3
  namespace WebpConverter\Traits;
4
 
5
+ use WebpConverter\Loader\Passthru;
6
+
7
  trait FileLoaderTrait
8
  {
9
  /* ---
16
  'Accept: image/webp',
17
  'Referer: ' . WEBPC_URL,
18
  ];
19
+
20
+ $imageUrl = Passthru::updateImageUrls($url);
21
+ return $this->getFileSizeForLoadedFile($imageUrl, ($setHeaders) ? $headers : []);
22
  }
23
 
24
  private function getFileSizeByPath($path)
29
 
30
  private function getFileSizeForLoadedFile($url, $headers)
31
  {
32
+ foreach (wp_get_nocache_headers() as $headerKey => $headerValue) {
33
+ $headers[] = sprintf('%s: %s', $headerKey, $headerValue);
34
+ }
35
 
36
  $ch = curl_init($url);
37
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
38
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
39
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
40
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
41
  curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
42
  curl_setopt($ch, CURLOPT_TIMEOUT, 10);
43
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
app/WebpConverter.php CHANGED
@@ -9,6 +9,7 @@
9
  new Action\_Core();
10
  new Admin\_Core();
11
  new Convert\_Core();
 
12
  new Media\_Core();
13
  new Plugin\_Core();
14
  new Regenerate\_Core();
9
  new Action\_Core();
10
  new Admin\_Core();
11
  new Convert\_Core();
12
+ new Loader\_Core();
13
  new Media\_Core();
14
  new Plugin\_Core();
15
  new Regenerate\_Core();
libs/passthru.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Loads images in WebP format or original images if browser does not support WebP.
5
+ *
6
+ * @category WordPress Plugin
7
+ * @package WebP Converter for Media
8
+ * @author Mateusz Gbiorczyk
9
+ * @link https://wordpress.org/plugins/webp-converter-for-media/
10
+ */
11
+
12
+ class PassthruLoader
13
+ {
14
+ const PATH_UPLOADS = '';
15
+ const PATH_UPLOADS_WEBP = '';
16
+
17
+ public function __construct()
18
+ {
19
+ if (!isset($_GET['src'])) {
20
+ return;
21
+ }
22
+
23
+ $this->loadImageWebP($_GET['src']);
24
+ }
25
+
26
+ private function loadImageWebP($imageUrl)
27
+ {
28
+ $header = getallheaders()['Accept'] ?? '';
29
+ if ((strpos($header, 'image/webp') === false)
30
+ || (!$source = $this->loadWebpSource($imageUrl))) {
31
+ return $this->loadImageDefault($imageUrl);
32
+ }
33
+
34
+ header('Content-Type: image/webp');
35
+ echo $source;
36
+ }
37
+
38
+ private function loadImageDefault($imageUrl)
39
+ {
40
+ header('Location: ' . $imageUrl);
41
+ }
42
+
43
+ private function loadWebpSource($imageUrl)
44
+ {
45
+ $url = $this->generateWebpUrl($imageUrl);
46
+ $ch = curl_init($url);
47
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
48
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
49
+
50
+ $response = curl_exec($ch);
51
+ $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
52
+ curl_close($ch);
53
+
54
+ if (($code !== 200) || !$response) {
55
+ return null;
56
+ } else {
57
+ return $response;
58
+ }
59
+ }
60
+
61
+ private function generateWebpUrl($imageUrl)
62
+ {
63
+ return str_replace(self::PATH_UPLOADS, self::PATH_UPLOADS_WEBP, $imageUrl) . '.webp';
64
+ }
65
+ }
66
+
67
+ new PassthruLoader();
public/build/js/scripts.js CHANGED
@@ -1 +1 @@
1
- !function(t){var e={};function r(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(n,i,function(e){return t[e]}.bind(null,i));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="/",r(r.s=0)}([function(t,e,r){r(1),t.exports=r(2)},function(t,e,r){"use strict";function n(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}r.r(e);var i=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.setVars()&&this.setEvents()}var e,r,i;return e=t,(r=[{key:"setVars",value:function(){if(this.buttonOpen=document.querySelector('[data-slug="webp-converter-for-media"] a[id="deactivate-webp-converter-for-media"'),this.modal=document.querySelector(".webpModal"),this.buttonOpen&&this.modal)return this.outer=this.modal.querySelector(".webpModal__outer"),this.form=this.outer.querySelector(".webpModal__form"),this.formOptions=this.form.querySelectorAll('[name="webpc_reason"]'),this.formComment=this.form.querySelector('[name="webpc_comment"]'),this.buttonSubmit=this.form.querySelector('button[type="submit"]'),this.buttonCancel=this.form.querySelector('button[type="button"]'),this.events={openModal:this.openModal.bind(this)},this.atts={optionPlaceholder:"data-placeholder"},!0}},{key:"setEvents",value:function(){var t=this;this.buttonOpen.addEventListener("click",this.events.openModal),this.buttonSubmit.addEventListener("click",this.submitForm.bind(this)),this.buttonCancel.addEventListener("click",this.cancelForm.bind(this)),this.outer.addEventListener("click",this.closeModal.bind(this)),this.form.addEventListener("click",(function(t){t.stopPropagation()}));for(var e=this.formOptions.length,r=function(e){t.formOptions[e].addEventListener("change",(function(){t.setCurrentOption(e)}))},n=0;n<e;n++)r(n)}},{key:"openModal",value:function(t){t.preventDefault(),this.buttonOpen.removeEventListener("click",this.events.openModal),this.modal.removeAttribute("hidden")}},{key:"closeModal",value:function(){this.modal.setAttribute("hidden","hidden")}},{key:"submitForm",value:function(t){var e=this;t.preventDefault(),this.closeModal(),setTimeout((function(){var t=new FormData(e.form),r=e.form.getAttribute("action"),n=new XMLHttpRequest;n.open("POST",r,!0),n.send(t),e.buttonOpen.click()}),0)}},{key:"cancelForm",value:function(t){var e=this;t.preventDefault(),this.closeModal(),setTimeout((function(){e.buttonOpen.click()}),0)}},{key:"setCurrentOption",value:function(t){this.formComment.value="";var e=this.formOptions[t].getAttribute(this.atts.optionPlaceholder);this.formComment.setAttribute("placeholder",e)}}])&&n(e.prototype,r),i&&n(e,i),t}();function s(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}var o=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.setVars()&&this.setEvents()}var e,r,n;return e=t,(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 t=this;this.buttonClose.addEventListener("click",(function(){t.hideNotice(!1)})),this.buttonPermanently.addEventListener("click",(function(e){e.preventDefault(),t.hideNotice(!0)}))}},{key:"hideNotice",value:function(t){this.settings.isHidden||(this.settings.isHidden=!0,jQuery.ajax(this.settings.ajaxUrl,{type:"POST",data:{action:"webpc_notice",is_permanently:t?1:0}}),this.buttonClose.click())}}])&&s(e.prototype,r),n&&s(e,n),t}();function a(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}var u=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.setVars()&&this.setEvents()}var e,r,n;return e=t,(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.succesPopup=this.section.querySelector(".webpLoader__popup"),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(t){if(t.preventDefault(),!this.settings.isDisabled){this.settings.isDisabled=!0,this.button.classList.add(this.classes.buttonDisabled);for(var e=this.inputOptions.length,r=0;r<e;r++)this.inputOptions[r].setAttribute("disabled",!0);this.wrapper.removeAttribute("hidden"),this.getImagesList()}}},{key:"getImagesList",value:function(){var t=this;jQuery.ajax(this.settings.ajax.urlPaths,{type:"POST",data:this.getDataForPathsRequest()}).done((function(e){t.data.items=e,t.data.max=e.length,t.regenerateNextImages()})).fail((function(){t.progress.classList.add(t.classes.progressError),t.errorsMessage.removeAttribute("hidden"),t.errors.removeAttribute("hidden")}))}},{key:"getDataForPathsRequest",value:function(){for(var t={},e=this.inputOptions.length,r=0;r<e;r++)t[this.inputOptions[r].getAttribute("name")]=this.inputOptions[r].checked?1:0;return t}},{key:"regenerateNextImages",value:function(){if(0===this.data.max&&this.updateProgress(),!(this.data.count>=this.data.max)){var t=this.data.items[this.data.count];this.data.count++,this.sendRequest(t)}}},{key:"sendRequest",value:function(t){var e=this;jQuery.ajax(this.settings.ajax.urlRegenerate,{type:"POST",data:{paths:t}}).done((function(t){e.updateErrors(t.errors),e.updateSize(t),e.updateProgress(),e.regenerateNextImages()})).fail((function(){var r=JSON.stringify(t),n=e.settings.ajax.errorMessage.replace("%s","<code>".concat(r,"</code>"));e.updateErrors([n]),e.regenerateNextImages()}))}},{key:"updateErrors",value:function(t){0!==t.length&&(this.data.errors=this.data.errors.concat(t),this.errorsInner.innerHTML=this.data.errors.join("<br>"),this.errors.removeAttribute("hidden"))}},{key:"updateSize",value:function(t){var e=this.data.size;e.before+=t.size.before,e.after+=t.size.after;var r=e.before-e.after;if(r<0&&(r=0),0!==r){var n=Math.round(100*(1-e.after/e.before));n<0&&(n=0);var i=-1;do{i++,r/=1024}while(r>1024);var s=r.toFixed(2),o=this.settings.units[i],a="".concat(s," ").concat(o," (").concat(n,"%)");this.progressSize.innerHTML=a}}},{key:"updateProgress",value:function(){var t=this.data.max>0?Math.floor(this.data.count/this.data.max*100):100;t>100&&(t=100),100===t&&(this.success.removeAttribute("hidden"),this.succesPopup.removeAttribute("hidden")),this.progress.setAttribute(this.atts.progress,t)}}])&&a(e.prototype,r),n&&a(e,n),t}();new function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),new i,new o,new u}},function(t,e){}]);
1
+ !function(t){var e={};function r(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(n,i,function(e){return t[e]}.bind(null,i));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="/",r(r.s=0)}([function(t,e,r){r(1),t.exports=r(2)},function(t,e,r){"use strict";function n(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}r.r(e);var i=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.setVars()&&this.setEvents()}var e,r,i;return e=t,(r=[{key:"setVars",value:function(){if(this.buttonOpen=document.querySelector('[data-slug="webp-converter-for-media"] a[href*="action=deactivate"]'),this.modal=document.querySelector(".webpModal"),this.buttonOpen&&this.modal)return this.outer=this.modal.querySelector(".webpModal__outer"),this.form=this.outer.querySelector(".webpModal__form"),this.formOptions=this.form.querySelectorAll('[name="webpc_reason"]'),this.formComment=this.form.querySelector('[name="webpc_comment"]'),this.buttonSubmit=this.form.querySelector('button[type="submit"]'),this.buttonCancel=this.form.querySelector('button[type="button"]'),this.events={openModal:this.openModal.bind(this)},this.atts={optionPlaceholder:"data-placeholder"},!0}},{key:"setEvents",value:function(){var t=this;this.buttonOpen.addEventListener("click",this.events.openModal),this.buttonSubmit.addEventListener("click",this.submitForm.bind(this)),this.buttonCancel.addEventListener("click",this.cancelForm.bind(this)),this.outer.addEventListener("click",this.closeModal.bind(this)),this.form.addEventListener("click",(function(t){t.stopPropagation()}));for(var e=this.formOptions.length,r=function(e){t.formOptions[e].addEventListener("change",(function(){t.setCurrentOption(e)}))},n=0;n<e;n++)r(n)}},{key:"openModal",value:function(t){t.preventDefault(),this.buttonOpen.removeEventListener("click",this.events.openModal),this.modal.removeAttribute("hidden")}},{key:"closeModal",value:function(){this.modal.setAttribute("hidden","hidden")}},{key:"submitForm",value:function(t){var e=this;t.preventDefault(),this.closeModal(),setTimeout((function(){var t=new FormData(e.form),r=e.form.getAttribute("action"),n=new XMLHttpRequest;n.open("POST",r,!0),n.send(t),e.buttonOpen.click()}),0)}},{key:"cancelForm",value:function(t){var e=this;t.preventDefault(),this.closeModal(),setTimeout((function(){e.buttonOpen.click()}),0)}},{key:"setCurrentOption",value:function(t){this.formComment.value="";var e=this.formOptions[t].getAttribute(this.atts.optionPlaceholder);this.formComment.setAttribute("placeholder",e)}}])&&n(e.prototype,r),i&&n(e,i),t}();function s(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}var o=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.setVars()&&this.setEvents()}var e,r,n;return e=t,(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 t=this;this.buttonClose.addEventListener("click",(function(){t.hideNotice(!1)})),this.buttonPermanently.addEventListener("click",(function(e){e.preventDefault(),t.hideNotice(!0)}))}},{key:"hideNotice",value:function(t){this.settings.isHidden||(this.settings.isHidden=!0,jQuery.ajax(this.settings.ajaxUrl,{type:"POST",data:{action:"webpc_notice",is_permanently:t?1:0}}),this.buttonClose.click())}}])&&s(e.prototype,r),n&&s(e,n),t}();function a(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}var u=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.setVars()&&this.setEvents()}var e,r,n;return e=t,(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.succesPopup=this.section.querySelector(".webpLoader__popup"),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(t){if(t.preventDefault(),!this.settings.isDisabled){this.settings.isDisabled=!0,this.button.classList.add(this.classes.buttonDisabled);for(var e=this.inputOptions.length,r=0;r<e;r++)this.inputOptions[r].setAttribute("disabled",!0);this.wrapper.removeAttribute("hidden"),this.getImagesList()}}},{key:"getImagesList",value:function(){var t=this;jQuery.ajax(this.settings.ajax.urlPaths,{type:"POST",data:this.getDataForPathsRequest()}).done((function(e){t.data.items=e,t.data.max=e.length,t.regenerateNextImages()})).fail((function(){t.progress.classList.add(t.classes.progressError),t.errorsMessage.removeAttribute("hidden"),t.errors.removeAttribute("hidden")}))}},{key:"getDataForPathsRequest",value:function(){for(var t={},e=this.inputOptions.length,r=0;r<e;r++)t[this.inputOptions[r].getAttribute("name")]=this.inputOptions[r].checked?1:0;return t}},{key:"regenerateNextImages",value:function(){if(0===this.data.max&&this.updateProgress(),!(this.data.count>=this.data.max)){var t=this.data.items[this.data.count];this.data.count++,this.sendRequest(t)}}},{key:"sendRequest",value:function(t){var e=this;jQuery.ajax(this.settings.ajax.urlRegenerate,{type:"POST",data:{paths:t}}).done((function(t){e.updateErrors(t.errors),e.updateSize(t),e.updateProgress(),e.regenerateNextImages()})).fail((function(){var r=JSON.stringify(t),n=e.settings.ajax.errorMessage.replace("%s","<code>".concat(r,"</code>"));e.updateErrors([n]),e.regenerateNextImages()}))}},{key:"updateErrors",value:function(t){0!==t.length&&(this.data.errors=this.data.errors.concat(t),this.errorsInner.innerHTML=this.data.errors.join("<br>"),this.errors.removeAttribute("hidden"))}},{key:"updateSize",value:function(t){var e=this.data.size;e.before+=t.size.before,e.after+=t.size.after;var r=e.before-e.after;if(r<0&&(r=0),0!==r){var n=Math.round(100*(1-e.after/e.before));n<0&&(n=0);var i=-1;do{i++,r/=1024}while(r>1024);var s=r.toFixed(2),o=this.settings.units[i],a="".concat(s," ").concat(o," (").concat(n,"%)");this.progressSize.innerHTML=a}}},{key:"updateProgress",value:function(){var t=this.data.max>0?Math.floor(this.data.count/this.data.max*100):100;t>100&&(t=100),100===t&&(this.success.removeAttribute("hidden"),this.succesPopup.removeAttribute("hidden")),this.progress.setAttribute(this.atts.progress,t)}}])&&a(e.prototype,r),n&&a(e,n),t}();new function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),new i,new o,new u}},function(t,e){}]);
public/img/icon-test.png2 DELETED
Binary file
public/img/icon-test.webp ADDED
Binary file
readme.txt CHANGED
@@ -17,13 +17,13 @@ Speed up your website by serving WebP images. By replacing files in standard JPE
17
 
18
  When installing a plugin you do not have to do anything more. Your current images will be converted into a new format. Users will automatically receive new, much lighter images than the original ones.
19
 
20
- As of today, nearly 80% of users use browsers that support the WebP format. The loading time of your website depends to a large extent on its weight. Now you can speed up it in a few seconds without much effort!
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
 
@@ -33,16 +33,12 @@ Now you can also convert files from the `/uploads` directory into WebP and gener
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.
36
- - **The plugin does not change image URLs, so there are no problems with saving the HTML code of website to the cache and time of its generation does not increase.** It does not matter if the image display as an `img` HTML tag or you use `background-image`. It works always!
37
  - The name of the loaded image does not contain the WebP extension. Only the source of the loaded file changes to a WebP file. As a result, you always have one URL to a file. Regardless of whether the browser supports WebP or not.
38
  - Image URLs are modified using the module `mod_rewrite` on the server, i.e. the same, and thanks to this we can use friendly links in WordPress. Additionally, the MIME type of the sent file is modified to `image/webp`.
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.
@@ -73,35 +69,17 @@ Please always adding your thread, **read all other questions in the FAQ of plugi
73
 
74
  When adding a thread, follow these steps and reply to each of them:
75
 
76
- **1.** Do you have any error on the plugin settings page? If so, which one? Have you consulted your server administrator or developer? If not, please do it first.
77
 
78
  **2.** URL of your website. If your site is not publicly available, add it to test environment.
79
 
80
- **3.** Does your server meet the technical requirements described in the FAQ? Please send configuration of your server *(link to it can be found on the settings page of plugin in the section **"We are waiting for your message"**)* - please take a screenshot of the ENTIRE page and send it to me.
81
-
82
- **4.** Do you use CDN? If so, please see the question **"Does the plugin support CDN?"** in plugin FAQ.
83
-
84
- **5.** Check if in `/wp-content/uploads-webpc` directory are all files that should be converted.
85
-
86
- If not, please enable `WP_DEBUG_LOG` in your `wp-config.php` *(more about debugging: [https://codex.wordpress.org/WP_DEBUG](https://codex.wordpress.org/WP_DEBUG))*. That's what you should have in this file:
87
-
88
- `define('WP_DEBUG', true);
89
- define('WP_DEBUG_LOG', true);
90
- define('WP_DEBUG_DISPLAY', false);`
91
 
92
- Then follow these steps:
93
 
94
- > 1. Go to administration panel and go to plugin settings page.
95
- 2. Run Google Chrome and enable Dev Tools *(F12)*.
96
- 3. Go to the Network tab and select filtering for `XHR` *(XHR and Fetch)*.
97
- 4. Click button `Regenerate All` on the plugin settings page *(do not close the console during this time)*.
98
- 5. Go to Dev Tools and find request that is marked in red. Click on them and go to `Preview` tab.
99
- 6. Take screenshot of all information presented there.
100
- 7. Please check also if you have any errors in `/wp-content/debug.log`?
101
 
102
- Send a screenshot from console if an error occurred while converting images. Of you have errors in `/wp-content/debug.log` send their?
103
-
104
- **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.
105
 
106
  **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)*.
107
 
@@ -111,7 +89,7 @@ Send a screenshot from console if an error occurred while converting images. Of
111
 
112
  **10.** Used Wordpress version.
113
 
114
- **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.**
115
 
116
  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.
117
 
@@ -159,13 +137,13 @@ Also REST API must be enabled and work without additional restrictions. If you h
159
 
160
  The size of the image is a limited. Its resolution cannot be bigger than `8192 x 8192px`. This is due to the limitations of the PHP library.
161
 
162
- Please remember that **Safari and Internet Explorer do not support the WebP format**. Therefore, using these browsers you will receive original images.
163
 
164
  You can find more about WebP support by browsers [here](https://caniuse.com/#feat=webp).
165
 
166
  = Damaged images on iOS or other browsers =
167
 
168
- The plugin uses rules in the .htaccess file to redirect from the original image to an image in WebP format. Verifies whether the WebP file exists and whether your browser supports the WebP format. It does this every time you try to load an image.
169
 
170
  When you enter from a WebP supporting device, it will redirect. However, when someone uses a browser that does not support WebP, the redirection will not work and you get the original file.
171
 
@@ -200,9 +178,9 @@ When you have installed plugin and converted all images, follow these steps:
200
  7. In addition, you can check weight of website before and after using plugin. The difference will be huge!
201
  8. More information: [here](https://gbiorczyk.pl/webp-converter/check-devtools.png)
202
 
203
- Please remember that URLs will remain unchanged. When you open the image in a new tab or look at its URL, you'll see the original URL. When you try to save the image to disk *(e.g. by clicking Save as...)* the original image will be saved.
204
 
205
- WebP is only used when loading a image on a website. This is done by the rules from the .htaccess file, on the server side, without the visible URL change to the image. Yes, it can be called magic :)
206
 
207
  That is why the plugin should be tested in Dev Tools. If the Type of file 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.
208
 
@@ -236,21 +214,27 @@ This is possible using the following types of filters to change default paths. I
236
 
237
  Path to the root installation directory of WordPress *(`ABSPATH` by default)*:
238
 
239
- `add_filter('webpc_uploads_root', function($path) {
240
  return ABSPATH;
241
  });`
242
 
243
  Path to `/uploads` directory *(relative to the root directory)*:
244
 
245
- `add_filter('webpc_uploads_path', function($path) {
 
 
 
246
  return 'wp-content/uploads';
247
- });`
248
 
249
  Directory path with converted WebP files *(relative to the root directory)*:
250
 
251
- `add_filter('webpc_uploads_webp', function($path) {
 
 
 
252
  return 'wp-content/uploads-webpc';
253
- });`
254
 
255
  **Note that the `/uploads-webpc` directory must be at the same nesting level as the `/uploads`, `/plugins` and `/themes` directories.**
256
 
@@ -275,15 +259,21 @@ For the following sample custom WordPress structure:
275
 
276
  Use the following filters:
277
 
278
- `add_filter('webpc_uploads_root', function($path) {
279
- return 'C:/WAMP/www/project/webp'; // your valid path
280
  });
281
- add_filter('webpc_uploads_path', function($path) {
 
 
 
282
  return 'app/uploads';
283
- });
284
- add_filter('webpc_uploads_webp', function($path) {
 
 
 
285
  return 'app/uploads-webpc';
286
- });`
287
  `add_filter('webpc_uploads_prefix', function($prefix) {
288
  return '/';
289
  });`
@@ -396,9 +386,9 @@ If you are using a CDN server, find one that automatically converts images to We
396
  = Configuration for Apache =
397
 
398
  In the case of Apache, when saving the settings, .htaccess files will be generated automatically in the following locations:
399
- * `/wp-content/.htaccess`
400
- * `/wp-content/uploads/.htaccess`
401
- * `/wp-content/uploads-webpc/.htaccess`
402
 
403
  If these files are missing or empty, try disabling and re-enabling the plugin or saving the plugin settings again. Also check the write permissions of the directories where these files are located.
404
 
@@ -407,35 +397,34 @@ If your server is a combination of Apache and Nginx, remember that the image fil
407
  = Configuration for Nginx =
408
 
409
  Please edit the configuration file:
 
410
 
411
- `/etc/nginx/mime.types`
412
-
413
- and add this code:
414
 
415
  `types {`
416
- ` # ...
417
-
418
- image/webp webp;
419
- }`
420
-
421
- Then please find your configuration file in the path *(default is default file)*:
422
 
423
- `/etc/nginx/sites-available/`
 
 
424
 
425
- and add below code in this file:
426
 
427
  `server {`
428
- ` # ...
429
-
430
- location ~ /wp-content/(?<path>.+)\.(?<ext>jpe?g|png|gif)$ {
431
- if ($http_accept !~* "image/webp") {
432
- break;
433
- }
434
- add_header Vary Accept;
435
- expires 365d;
436
- try_files /wp-content/uploads-webpc/$path.$ext.webp $uri =404;
437
- }
438
- }`
 
439
 
440
  = Configuration for Multisite Network =
441
 
@@ -493,6 +482,30 @@ This is all very important to us and allows us to do even better things for you!
493
 
494
  == Changelog ==
495
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  = 1.6.0 (2020-12-12) =
497
  * `[Added]` Escaping functions for translated phrases
498
  * `[Added]` Error codes in error messages on plugin settings page
17
 
18
  When installing a plugin you do not have to do anything more. Your current images will be converted into a new format. Users will automatically receive new, much lighter images than the original ones.
19
 
20
+ As of today, nearly 90% of users use browsers that support the WebP format. The loading time of your website depends to a large extent on its weight. Now you can speed up it in a few seconds without much effort!
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
+ #### Support for additional directories
25
 
26
+ Now you can also convert files not only from `/uploads` directory but also from `/plugins` and `/themes` directories. This allows full integration with the WebP format!
27
 
28
  #### How does this work?
29
 
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.
36
+ - In default loading mode **the plugin does not change image URLs, so there are no problems with saving the HTML code of website to the cache and time of its generation does not increase.** It does not matter if the image display as an `img` HTML tag or you use `background-image`. It works always!
37
  - The name of the loaded image does not contain the WebP extension. Only the source of the loaded file changes to a WebP file. As a result, you always have one URL to a file. Regardless of whether the browser supports WebP or not.
38
  - Image URLs are modified using the module `mod_rewrite` on the server, i.e. the same, and thanks to this we can use friendly links in WordPress. Additionally, the MIME type of the sent file is modified to `image/webp`.
39
+ - In case rewriting by rules from .htaccess file is blocked, a mode is available which loads images via PHP file. Then image URLs are changed, but the logic of operation is the same as in the case of the default mode.
40
  - The final result is that your users download less than half of the data, and the website itself loads faster!
41
 
 
 
 
 
42
  #### WebP images are the future!
43
 
44
  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.
69
 
70
  When adding a thread, follow these steps and reply to each of them:
71
 
72
+ **1.** Do you have any error on the plugin settings page? Enter error codes. Have you consulted your server administrator or developer?
73
 
74
  **2.** URL of your website. If your site is not publicly available, add it to test environment.
75
 
76
+ **3.** Configuration of your server *(link to it can be found on the settings page of plugin in the section **"We are waiting for your message"**)* - please take a screenshot of the ENTIRE page and send it to me.
 
 
 
 
 
 
 
 
 
 
77
 
78
+ **4.** Settings of plugin - please take a screenshot of the ENTIRE page and send it to me.
79
 
80
+ **5.** Do you use CDN? If so, please see the question **"Does the plugin support CDN?"** in plugin FAQ.
 
 
 
 
 
 
81
 
82
+ **6.** 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.
 
 
83
 
84
  **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)*.
85
 
89
 
90
  **10.** Used Wordpress version.
91
 
92
+ **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.
93
 
94
  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.
95
 
137
 
138
  The size of the image is a limited. Its resolution cannot be bigger than `8192 x 8192px`. This is due to the limitations of the PHP library.
139
 
140
+ Please remember that **Safari *(version 13 or earlier)* and Internet Explorer do not support the WebP format**. Therefore, using these browsers you will receive original images.
141
 
142
  You can find more about WebP support by browsers [here](https://caniuse.com/#feat=webp).
143
 
144
  = Damaged images on iOS or other browsers =
145
 
146
+ The plugin in default loading mode *(via .htaccess)* uses rules in the .htaccess file to redirect from the original image to an image in WebP format. Verifies whether the WebP file exists and whether your browser supports the WebP format. It does this every time you try to load an image.
147
 
148
  When you enter from a WebP supporting device, it will redirect. However, when someone uses a browser that does not support WebP, the redirection will not work and you get the original file.
149
 
178
  7. In addition, you can check weight of website before and after using plugin. The difference will be huge!
179
  8. More information: [here](https://gbiorczyk.pl/webp-converter/check-devtools.png)
180
 
181
+ Please remember that in default loading mode *(via .htaccess)* URLs will remain unchanged. When you open the image in a new tab or look at its URL, you'll see the original URL. When you try to save the image to disk *(e.g. by clicking Save as...)* the original image will be saved.
182
 
183
+ WebP is only used when loading a image on a website. In default loading mode *(via .htaccess)* it is done by the rules from the .htaccess file, on the server side, without the visible URL change to the image. Yes, it can be called magic :)
184
 
185
  That is why the plugin should be tested in Dev Tools. If the Type of file 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.
186
 
214
 
215
  Path to the root installation directory of WordPress *(`ABSPATH` by default)*:
216
 
217
+ `add_filter('webpc_site_root', function($path) {
218
  return ABSPATH;
219
  });`
220
 
221
  Path to `/uploads` directory *(relative to the root directory)*:
222
 
223
+ `add_filter('webpc_dir_name', function($path, $directory) {
224
+ if ($directory !== 'uploads') {
225
+ return $path;
226
+ }
227
  return 'wp-content/uploads';
228
+ }, 10, 2);`
229
 
230
  Directory path with converted WebP files *(relative to the root directory)*:
231
 
232
+ `add_filter('webpc_dir_name', function($path, $directory) {
233
+ if ($directory !== 'webp') {
234
+ return $path;
235
+ }
236
  return 'wp-content/uploads-webpc';
237
+ }, 10, 2);`
238
 
239
  **Note that the `/uploads-webpc` directory must be at the same nesting level as the `/uploads`, `/plugins` and `/themes` directories.**
240
 
259
 
260
  Use the following filters:
261
 
262
+ `add_filter('webpc_site_root', function($path) {
263
+ return 'C:/WAMP/www/project/webp'; // your valid path to root
264
  });
265
+ add_filter('webpc_dir_name', function($path, $directory) {
266
+ if ($directory !== 'uploads') {
267
+ return $path;
268
+ }
269
  return 'app/uploads';
270
+ }, 10, 2);
271
+ add_filter('webpc_dir_name', function($path, $directory) {
272
+ if ($directory !== 'webp') {
273
+ return $path;
274
+ }
275
  return 'app/uploads-webpc';
276
+ }, 10, 2);`
277
  `add_filter('webpc_uploads_prefix', function($prefix) {
278
  return '/';
279
  });`
386
  = Configuration for Apache =
387
 
388
  In the case of Apache, when saving the settings, .htaccess files will be generated automatically in the following locations:
389
+ - `/wp-content/.htaccess`
390
+ - `/wp-content/uploads/.htaccess`
391
+ - `/wp-content/uploads-webpc/.htaccess`
392
 
393
  If these files are missing or empty, try disabling and re-enabling the plugin or saving the plugin settings again. Also check the write permissions of the directories where these files are located.
394
 
397
  = Configuration for Nginx =
398
 
399
  Please edit the configuration file:
400
+ - `/etc/nginx/mime.types`
401
 
402
+ and add this code line:
 
 
403
 
404
  `types {`
405
+ ` # ...`
406
+ ` image/webp webp;`
407
+ `}`
 
 
 
408
 
409
+ Then find the configuration file in one of the paths *(remember to select configuration file used by your vhost)*:
410
+ - `/etc/nginx/sites-enabled/`
411
+ - `/etc/nginx/conf.d/`
412
 
413
+ and add below code in this file *(add these lines to very beginning of file if possible - if they will be at the bottom, other rules may block the rules for WebP from working)*:
414
 
415
  `server {`
416
+ ` location ~ /wp-content/(?<path>.+)\.(?<ext>jpe?g|png|gif)$ {`
417
+ ` if ($http_accept !~* "image/webp") {`
418
+ ` break;`
419
+ ` }`
420
+ ` add_header Vary Accept;`
421
+ ` expires 365d;`
422
+ ` try_files /wp-content/uploads-webpc/$path.$ext.webp $uri =404;`
423
+ ` }`
424
+ ` # ...`
425
+ `}`
426
+
427
+ After making changes, remember to restart the machine: `systemctl restart nginx`.
428
 
429
  = Configuration for Multisite Network =
430
 
482
 
483
  == Changelog ==
484
 
485
+ = 2.1.2 (2020-12-27) =
486
+ * `[Fixed]` Converting images using Imagick method
487
+
488
+ = 2.1.1 (2020-12-21) =
489
+ * `[Fixed]` Modal when deactivating plugin
490
+
491
+ = 2.1.0 (2020-12-21) =
492
+ * `[Changed]` Structure of conversion methods
493
+ * `[Changed]` Structure of error detection methods
494
+
495
+ = 2.0.1 (2020-12-16) =
496
+ * `[Fixed]` Actions initiated after plugin update
497
+
498
+ = 2.0.0 (2020-12-16) =
499
+ * `[Removed]` Filter `webpc_uploads_path`
500
+ * `[Removed]` Filter `webpc_uploads_webp`
501
+ * `[Removed]` Filter `webpc_uploads_dir`
502
+ * `[Removed]` Filter `webpc_uploads_root`
503
+ * `[Changed]` Error messages in administration panel
504
+ * `[Added]` Image loading mode: `Pass Thru` (without rewrites in .htacces files or Nginx configuration)
505
+ * `[Added]` Filter `webpc_dir_name` to change default directory paths
506
+ * `[Added]` Filter `webpc_site_root` to change path for root installation directory of WordPress
507
+ * `[Added]` Filter `webpc_site_url` to change Site URL of WordPress
508
+
509
  = 1.6.0 (2020-12-12) =
510
  * `[Added]` Escaping functions for translated phrases
511
  * `[Added]` Error codes in error messages on plugin settings page
resources/components/errors/bypassing-apache.php CHANGED
@@ -11,4 +11,5 @@
11
  '</em>',
12
  '<br><br>'
13
  )); ?>
14
- </p>
 
11
  '</em>',
12
  '<br><br>'
13
  )); ?>
14
+ </p>
15
+ <?php require __DIR__ . '/passthru-info.php'; ?>
resources/components/errors/passthru-execution.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ use WebpConverter\Loader\Passthru;
3
+ $url = Passthru::getLoaderUrl();
4
+ ?>
5
+
6
+ <p>
7
+ <?= wp_kses_post(sprintf(
8
+ __('Execution of the PHP file from path "%s" is blocked on your server, or access to this file is blocked. Add an exception and enable this file to be executed via HTTP request. To do this, check the security plugin settings (if you are using) or the security settings of your server.%sIn this case, please contact your server administrator.', 'webp-converter-for-media'),
9
+ '<a href="' . $url . '" target="_blank">' . $url . '</a>',
10
+ '<br><br>'
11
+ )); ?>
12
+ </p>
resources/components/errors/passthru-info.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <p>
2
+ <?= wp_kses_post(sprintf(
3
+ __('%sAlso try changing option "Image loading mode" to a different one.%s Issues about rewrites can often be resolved by setting this option to "%s". You can do this in plugin settings below. After changing settings, remember to flush cache if you use caching plugin or caching via hosting.', 'webp-converter-for-media'),
4
+ '<strong>',
5
+ '</strong>',
6
+ 'Pass Thru'
7
+ )); ?>
8
+ </p>
resources/components/errors/path-htaccess-not-writable.php CHANGED
@@ -3,6 +3,6 @@
3
  __('Unable to create or edit .htaccess file %s(function is_readable() or is_writable() returns false)%s. Change directory permissions. The current using path of file is: %s. Please contact your server administrator.', 'webp-converter-for-media'),
4
  '<em>',
5
  '</em>',
6
- '<strong>' . apply_filters('webpc_uploads_path', '') . '/.htaccess</strong>'
7
  )); ?>
8
  </p>
3
  __('Unable to create or edit .htaccess file %s(function is_readable() or is_writable() returns false)%s. Change directory permissions. The current using path of file is: %s. Please contact your server administrator.', 'webp-converter-for-media'),
4
  '<em>',
5
  '</em>',
6
+ '<strong>' . apply_filters('webpc_dir_path', '', 'uploads') . '/.htaccess</strong>'
7
  )); ?>
8
  </p>
resources/components/errors/path-uploads-unavailable.php CHANGED
@@ -1,10 +1,9 @@
1
  <p>
2
  <?= wp_kses_post(sprintf(
3
- __('The path for /uploads files does not exist %s(function is_dir() returns false)%s. Use filters %s or %s to set the correct path. The current using path is: %s. Please read the plugin FAQ to learn more.', 'webp-converter-for-media'),
4
  '<em>',
5
  '</em>',
6
- '<strong>webpc_uploads_root</strong>',
7
- '<strong>webpc_uploads_path</strong>',
8
- '<strong>' . apply_filters('webpc_uploads_path', '') . '</strong>'
9
  )); ?>
10
  </p>
1
  <p>
2
  <?= wp_kses_post(sprintf(
3
+ __('The path for /uploads files does not exist %s(function is_dir() returns false)%s. Use filter %s to set the correct path. The current using path is: %s. Please read the plugin FAQ to learn more.', 'webp-converter-for-media'),
4
  '<em>',
5
  '</em>',
6
+ '<strong>webpc_dir_path</strong>',
7
+ '<strong>' . apply_filters('webpc_dir_path', '', 'uploads') . '</strong>'
 
8
  )); ?>
9
  </p>
resources/components/errors/path-webp-duplicated.php CHANGED
@@ -1,8 +1,7 @@
1
  <p>
2
  <?= wp_kses_post(sprintf(
3
- __('The paths for /uploads files and for saving converted WebP files are the same. Change them using filters %s or %s. The current path for them is: %s.', 'webp-converter-for-media'),
4
- '<strong>webpc_uploads_path</strong>',
5
- '<strong>webpc_uploads_webp</strong>',
6
- '<strong>' . apply_filters('webpc_uploads_path', '') . '</strong>'
7
  )); ?>
8
  </p>
1
  <p>
2
  <?= wp_kses_post(sprintf(
3
+ __('The paths for /uploads files and for saving converted WebP files are the same. Change them using filter %s. The current path for them is: %s.', 'webp-converter-for-media'),
4
+ '<strong>webpc_dir_path</strong>',
5
+ '<strong>' . apply_filters('webpc_dir_path', '', 'uploads') . '</strong>'
 
6
  )); ?>
7
  </p>
resources/components/errors/path-webp-not-writable.php CHANGED
@@ -1,10 +1,9 @@
1
  <p>
2
  <?= wp_kses_post(sprintf(
3
- __('The path for saving converted WebP files does not exist and cannot be created %s(function is_writable() returns false)%s. Use filters %s or %s to set the correct path. The current using path is: %s. Please read the plugin FAQ to learn more.', 'webp-converter-for-media'),
4
  '<em>',
5
  '</em>',
6
- '<strong>webpc_uploads_root</strong>',
7
- '<strong>webpc_uploads_webp</strong>',
8
- '<strong>' . apply_filters('webpc_uploads_webp', '') . '</strong>'
9
  )); ?>
10
  </p>
1
  <p>
2
  <?= wp_kses_post(sprintf(
3
+ __('The path for saving converted WebP files does not exist and cannot be created %s(function is_writable() returns false)%s. Use filter %s to set the correct path. The current using path is: %s. Please read the plugin FAQ to learn more.', 'webp-converter-for-media'),
4
  '<em>',
5
  '</em>',
6
+ '<strong>webpc_dir_path</strong>',
7
+ '<strong>' . apply_filters('webpc_dir_path', '', 'webp') . '</strong>'
 
8
  )); ?>
9
  </p>
resources/components/errors/rewrites-cached.php CHANGED
@@ -3,4 +3,5 @@
3
  __('Your server uses the cache for HTTP requests. The rules from .htaccess file or from Nginx configuration are not executed every time when the image is loaded, but the last redirect from cache is performed. With each request to image, your server should execute the rules from .htaccess file or from Nginx configuration. Now it only does this the first time and then uses cache. This means that if your server redirected image to WebP format the first time, it does so on every request. It should check the rules from .htaccess file or from Nginx configuration each time during request to image and redirect only when the conditions are met. %sIf you have enabled caching HTTP reverse proxy or another HTTP caching, you must disable it. Otherwise the plugin cannot work properly. In this case, please contact your server administrator.', 'webp-converter-for-media'),
4
  '<br><br>'
5
  )); ?>
6
- </p>
 
3
  __('Your server uses the cache for HTTP requests. The rules from .htaccess file or from Nginx configuration are not executed every time when the image is loaded, but the last redirect from cache is performed. With each request to image, your server should execute the rules from .htaccess file or from Nginx configuration. Now it only does this the first time and then uses cache. This means that if your server redirected image to WebP format the first time, it does so on every request. It should check the rules from .htaccess file or from Nginx configuration each time during request to image and redirect only when the conditions are met. %sIf you have enabled caching HTTP reverse proxy or another HTTP caching, you must disable it. Otherwise the plugin cannot work properly. In this case, please contact your server administrator.', 'webp-converter-for-media'),
4
  '<br><br>'
5
  )); ?>
6
+ </p>
7
+ <?php require __DIR__ . '/passthru-info.php'; ?>
resources/components/errors/rewrites-not-working.php CHANGED
@@ -5,4 +5,5 @@
5
  '</a>',
6
  '<br><br>'
7
  )); ?>
8
- </p>
 
5
  '</a>',
6
  '<br><br>'
7
  )); ?>
8
+ </p>
9
+ <?php require __DIR__ . '/passthru-info.php'; ?>
resources/components/widgets/about.php CHANGED
@@ -16,7 +16,7 @@
16
  )); ?>
17
  </p>
18
  <p>
19
- <?= wp_kses_post(__('The plugin does not change file URLs, so there are no problems with saving the page to the cache and the page generation time does not increase.', 'webp-converter-for-media')); ?>
20
  </p>
21
  <p>
22
  <?= wp_kses_post(sprintf(
16
  )); ?>
17
  </p>
18
  <p>
19
+ <?= wp_kses_post(__('The plugin in default loading mode (via .htaccess) does not change file URLs, so there are no problems with saving the page to the cache and the page generation time does not increase.', 'webp-converter-for-media')); ?>
20
  </p>
21
  <p>
22
  <?= wp_kses_post(sprintf(
resources/components/widgets/errors.php CHANGED
@@ -4,7 +4,8 @@
4
  <?= esc_html(__('Server configuration error', 'webp-converter-for-media')); ?>
5
  </h3>
6
  <div class="webpContent webpContent--wide">
7
- <?= implode(PHP_EOL, $errors); ?>
 
8
  <p>
9
  <?= sprintf(
10
  __('%sError codes:%s %s', 'webp-converter-for-media'),
4
  <?= esc_html(__('Server configuration error', 'webp-converter-for-media')); ?>
5
  </h3>
6
  <div class="webpContent webpContent--wide">
7
+ <?= implode('<p>---</p>', $errors); ?>
8
+ <p>---</p>
9
  <p>
10
  <?= sprintf(
11
  __('%sError codes:%s %s', 'webp-converter-for-media'),
resources/components/widgets/regenerate.php CHANGED
@@ -32,6 +32,7 @@
32
  <div class="webpLoader__success" hidden>
33
  <div class="webpLoader__successContent">
34
  <?= wp_kses_post(__('The process was completed successfully. Your images have been converted!', 'webp-converter-for-media')); ?>
 
35
  <br>
36
  <?= wp_kses_post(sprintf(
37
  __('Do you want to know how a plugin works and how to check if it is working properly? Read our %splugin FAQ%s.', 'webp-converter-for-media'),
32
  <div class="webpLoader__success" hidden>
33
  <div class="webpLoader__successContent">
34
  <?= wp_kses_post(__('The process was completed successfully. Your images have been converted!', 'webp-converter-for-media')); ?>
35
+ <?= wp_kses_post(__('Please flush cache if you use caching plugin or caching via hosting.', 'webp-converter-for-media')); ?>
36
  <br>
37
  <?= wp_kses_post(sprintf(
38
  __('Do you want to know how a plugin works and how to check if it is working properly? Read our %splugin FAQ%s.', 'webp-converter-for-media'),
resources/views/deactivation-modal.php CHANGED
@@ -75,7 +75,12 @@
75
  </button>
76
  </li>
77
  </ul>
78
- <input type="hidden" name="webpc_error_codes" value="<?= esc_attr($errors); ?>">
 
 
 
 
 
79
  </form>
80
  </div>
81
  </div>
75
  </button>
76
  </li>
77
  </ul>
78
+ <input type="hidden" name="webpc_error_codes"
79
+ value="<?= esc_attr($errors); ?>">
80
+ <input type="hidden" name="webpc_plugin_settings"
81
+ value='<?= json_encode(apply_filters('webpc_get_values', [])); ?>'>
82
+ <input type="hidden" name="webpc_plugin_version"
83
+ value="<?= esc_attr(WEBPC_VERSION); ?>">
84
  </form>
85
  </div>
86
  </div>
resources/views/settings.php CHANGED
@@ -12,6 +12,7 @@
12
  <?php if ($_POST) : ?>
13
  <div class="webpPage__alert">
14
  <?= esc_html(__('Changes were successfully saved!', 'webp-converter-for-media')); ?>
 
15
  </div>
16
  <?php endif; ?>
17
  <?php
12
  <?php if ($_POST) : ?>
13
  <div class="webpPage__alert">
14
  <?= esc_html(__('Changes were successfully saved!', 'webp-converter-for-media')); ?>
15
+ <?= esc_html(__('Please flush cache if you use caching plugin or caching via hosting.', 'webp-converter-for-media')); ?>
16
  </div>
17
  <?php endif; ?>
18
  <?php
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit88991bcbd0ccbed597697ff83d9e0d23::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitf6f394339146bc91ffde2c0ccd9f5844::getLoader();
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit88991bcbd0ccbed597697ff83d9e0d23
6
  {
7
  private static $loader;
8
 
@@ -22,15 +22,15 @@ class ComposerAutoloaderInit88991bcbd0ccbed597697ff83d9e0d23
22
  return self::$loader;
23
  }
24
 
25
- spl_autoload_register(array('ComposerAutoloaderInit88991bcbd0ccbed597697ff83d9e0d23', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
- spl_autoload_unregister(array('ComposerAutoloaderInit88991bcbd0ccbed597697ff83d9e0d23', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
- call_user_func(\Composer\Autoload\ComposerStaticInit88991bcbd0ccbed597697ff83d9e0d23::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitf6f394339146bc91ffde2c0ccd9f5844
6
  {
7
  private static $loader;
8
 
22
  return self::$loader;
23
  }
24
 
25
+ spl_autoload_register(array('ComposerAutoloaderInitf6f394339146bc91ffde2c0ccd9f5844', 'loadClassLoader'), true, true);
26
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInitf6f394339146bc91ffde2c0ccd9f5844', 'loadClassLoader'));
28
 
29
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
  if ($useStaticLoader) {
31
  require_once __DIR__ . '/autoload_static.php';
32
 
33
+ call_user_func(\Composer\Autoload\ComposerStaticInitf6f394339146bc91ffde2c0ccd9f5844::getInitializer($loader));
34
  } else {
35
  $map = require __DIR__ . '/autoload_namespaces.php';
36
  foreach ($map as $namespace => $path) {
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit88991bcbd0ccbed597697ff83d9e0d23
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'W' =>
@@ -23,8 +23,8 @@ class ComposerStaticInit88991bcbd0ccbed597697ff83d9e0d23
23
  public static function getInitializer(ClassLoader $loader)
24
  {
25
  return \Closure::bind(function () use ($loader) {
26
- $loader->prefixLengthsPsr4 = ComposerStaticInit88991bcbd0ccbed597697ff83d9e0d23::$prefixLengthsPsr4;
27
- $loader->prefixDirsPsr4 = ComposerStaticInit88991bcbd0ccbed597697ff83d9e0d23::$prefixDirsPsr4;
28
 
29
  }, null, ClassLoader::class);
30
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitf6f394339146bc91ffde2c0ccd9f5844
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'W' =>
23
  public static function getInitializer(ClassLoader $loader)
24
  {
25
  return \Closure::bind(function () use ($loader) {
26
+ $loader->prefixLengthsPsr4 = ComposerStaticInitf6f394339146bc91ffde2c0ccd9f5844::$prefixLengthsPsr4;
27
+ $loader->prefixDirsPsr4 = ComposerStaticInitf6f394339146bc91ffde2c0ccd9f5844::$prefixDirsPsr4;
28
 
29
  }, null, ClassLoader::class);
30
  }
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.6.0
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter-for-media
10
  */
11
 
12
- define('WEBPC_VERSION', '1.6.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: 2.1.2
7
  Author: Mateusz Gbiorczyk
8
  Author URI: https://gbiorczyk.pl/
9
  Text Domain: webp-converter-for-media
10
  */
11
 
12
+ define('WEBPC_VERSION', '2.1.2');
13
  define('WEBPC_FILE', __FILE__);
14
  define('WEBPC_NAME', plugin_basename(__FILE__));
15
  define('WEBPC_PATH', plugin_dir_path(__FILE__));