Version Description
Release date: 27th November 2019 * Ask if WebP files should be created before bulk optimization : checkbox added in Bulk page. * Added filters for optimal chunk size when selecting records from wp_postmeta while bulk processing: 'shortpixel/db/chunk_size'. * Optimize images also on edit-media screen. * Experimental support for static cache firewalls, and sending images w/ timestamp: SHORTPIXEL_EXPERIMENTAL_SECURICACHE. * Limit loading of JS / CSS to pages we do work on. * Refactoring & speed optimizations: - new external class for gravity forms, nextgen and visual composer, new controller for global admin hooks, new front controller, updated plugin init, clean(ish) root file, database optimization(reduced number of queries), unlistedThumbs checker only fires when the optimize unlisted check is active, optimizations for filesystem and findFileByPattern. * WPML Duplicates - Don't mark empty GUID's as duplicate. * Fix broken styles on WP 5.3. * Fix in case meta_value in processCountable has a WP_Error object instead of normal metadata. * Fix on WP Engine when large wp_postmeta table: limit to 16K the size of the query with ID list. * Fixed: error when log path is not writeable * Fixed: double sends within the same images, can happen with something like WPML and it's duplicated media. * Fixed: bug when searching unlisted images, in some circumstances. * Fixed: max_execution_time when time is set lower than 0. * Fixed: directories with no permission would give PHP error * Fixed: pathToUrl now also works for paths outside wp uploads * Fixed: check for DOING_AJAX on redirect to settings. * Fixed: Shortpixel icon + exclamation mark in toolbar showing on every page load. * Fixed: Add Custom media browser doesn't display files anymore * Fixed: WebP option adds an extra border if image already has a border -> borders will not be replicated to
Release Info
Developer | ShortPixel |
Plugin | ShortPixel Image Optimizer |
Version | 4.15.0 |
Comparing to | |
See all releases |
Code changes from version 4.14.6 to 4.15.0
- build/shortpixel/log/composer.json +1 -1
- build/shortpixel/log/src/ShortPixelLogger.php +9 -7
- build/shortpixel/notices/composer.json +1 -1
- build/shortpixel/notices/src/NoticeController.php +19 -9
- build/shortpixel/notices/src/NoticeModel.php +1 -10
- changelog.txt +184 -0
- class/controller/admin_controller.php +55 -0
- class/controller/cache_controller.php +65 -0
- class/controller/controller.php +1 -13
- class/controller/edit_media_controller.php +22 -1
- class/controller/filesystem_controller.php +105 -2
- class/controller/front_controller.php +104 -0
- class/controller/settings.php +13 -14
- class/db/shortpixel-custom-meta-dao.php +106 -39
- class/db/shortpixel-meta-facade.php +234 -23
- class/db/wp-shortpixel-db.php +26 -1
- class/db/wp-shortpixel-media-library-adapter.php +60 -30
- class/external/gravityforms.php +40 -0
- class/external/helpscout.php +1 -1
- class/external/nextgen.php +28 -13
- class/external/securi.php +33 -0
- class/external/visualcomposer.php +23 -0
- class/external/wp-offload-media.php +145 -40
- class/external/wpengine.php +14 -0
- class/front/img-to-picture-webp.php +35 -3
- class/model/apikey_model.php +4 -2
- class/model/cache_model.php +76 -0
- class/model/directory_model.php +125 -4
- class/model/environment_model.php +93 -8
- class/model/file_model.php +87 -47
- class/model/image_model.php +59 -5
- class/model/shortpixel-folder.php +20 -7
- class/shortpixel-png2jpg.php +40 -12
- class/shortpixel-tools.php +24 -0
- class/shortpixel_queue.php +2 -1
- class/view/settings/part-advanced.php +1 -1
- class/view/settings/part-debug.php +2 -0
- class/view/settings/part-general.php +4 -4
- class/view/settings/part-nokey.php +2 -2
- class/view/shortpixel-list-table.php +1 -1
- class/view/shortpixel_view.php +44 -28
- class/wp-short-pixel.php +347 -136
- class/wp-shortpixel-settings.php +12 -4
- readme.txt +59 -193
- res/css/short-pixel.css +2 -1
- res/css/short-pixel.min.css +1 -1
- res/js/shortpixel.js +1 -1
- shortpixel-plugin.php +193 -9
- shortpixel_api.php +22 -7
- wp-shortpixel-req.php +7 -10
- wp-shortpixel.php +24 -191
@@ -1,7 +1,7 @@
|
|
1 |
{
|
2 |
"name": "shortpixel/log",
|
3 |
"description": "ShortPixel Logging",
|
4 |
-
"version": "1.1.
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
1 |
{
|
2 |
"name": "shortpixel/log",
|
3 |
"description": "ShortPixel Logging",
|
4 |
+
"version": "1.1.3",
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
@@ -88,12 +88,14 @@ namespace ShortPixel\ShortPixelLogger;
|
|
88 |
|
89 |
}
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
|
|
97 |
|
98 |
if ($this->is_active && count($this->hooks) > 0)
|
99 |
$this->monitorHooks();
|
@@ -171,7 +173,7 @@ namespace ShortPixel\ShortPixelLogger;
|
|
171 |
$line = $this->formatLine($items);
|
172 |
|
173 |
// try to write to file. Don't write if directory doesn't exists (leads to notices)
|
174 |
-
if ($this->logPath && is_dir(dirname($this->logPath) )
|
175 |
{
|
176 |
file_put_contents($this->logPath,$line, FILE_APPEND);
|
177 |
}
|
88 |
|
89 |
}
|
90 |
|
91 |
+
if ($this->is_active)
|
92 |
+
{
|
93 |
+
/* On Early init, this function might not exist, then queue it when needed */
|
94 |
+
if (! function_exists('wp_get_current_user'))
|
95 |
+
add_action('init', array($this, 'initView'));
|
96 |
+
else
|
97 |
+
$this->initView();
|
98 |
+
}
|
99 |
|
100 |
if ($this->is_active && count($this->hooks) > 0)
|
101 |
$this->monitorHooks();
|
173 |
$line = $this->formatLine($items);
|
174 |
|
175 |
// try to write to file. Don't write if directory doesn't exists (leads to notices)
|
176 |
+
if ($this->logPath && is_dir(dirname($this->logPath)) )
|
177 |
{
|
178 |
file_put_contents($this->logPath,$line, FILE_APPEND);
|
179 |
}
|
@@ -1,7 +1,7 @@
|
|
1 |
{
|
2 |
"name": "shortpixel/notices",
|
3 |
"description": "ShortPixel WordPress Notice System",
|
4 |
-
"version": "1.
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
1 |
{
|
2 |
"name": "shortpixel/notices",
|
3 |
"description": "ShortPixel WordPress Notice System",
|
4 |
+
"version": "1.2",
|
5 |
"type": "library",
|
6 |
"license": "MIT",
|
7 |
"authors": [
|
@@ -64,9 +64,18 @@ class NoticeController //extends ShortPixelController
|
|
64 |
}
|
65 |
|
66 |
|
67 |
-
public function addNotice($message, $code)
|
68 |
{
|
69 |
$notice = new NoticeModel($message, $code);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
self::$notices[] = $notice;
|
71 |
$this->countNotices();
|
72 |
Log::addDebug('Adding notice - ', $notice);
|
@@ -124,38 +133,39 @@ class NoticeController //extends ShortPixelController
|
|
124 |
|
125 |
/** Adds a notice, quick and fast method
|
126 |
* @param String $message The Message you want to notify
|
|
|
127 |
* @param int $code A value of messageType as defined in model
|
128 |
* @returm Object Instance of noticeModel
|
129 |
*/
|
130 |
|
131 |
-
public static function addNormal($message)
|
132 |
{
|
133 |
$noticeController = self::getInstance();
|
134 |
-
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_NORMAL);
|
135 |
return $notice;
|
136 |
|
137 |
}
|
138 |
|
139 |
-
public static function addError($message)
|
140 |
{
|
141 |
$noticeController = self::getInstance();
|
142 |
-
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_ERROR);
|
143 |
return $notice;
|
144 |
|
145 |
}
|
146 |
|
147 |
-
public static function addWarning($message)
|
148 |
{
|
149 |
$noticeController = self::getInstance();
|
150 |
-
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_WARNING);
|
151 |
return $notice;
|
152 |
|
153 |
}
|
154 |
|
155 |
-
public static function addSuccess($message)
|
156 |
{
|
157 |
$noticeController = self::getInstance();
|
158 |
-
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_SUCCESS);
|
159 |
return $notice;
|
160 |
|
161 |
}
|
64 |
}
|
65 |
|
66 |
|
67 |
+
public function addNotice($message, $code, $unique)
|
68 |
{
|
69 |
$notice = new NoticeModel($message, $code);
|
70 |
+
|
71 |
+
if ($unique)
|
72 |
+
{
|
73 |
+
foreach(self::$notices as $nitem)
|
74 |
+
{
|
75 |
+
if ($nitem->message == $notice->message && $nitem->code == $notice->code) // same message.
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
}
|
79 |
self::$notices[] = $notice;
|
80 |
$this->countNotices();
|
81 |
Log::addDebug('Adding notice - ', $notice);
|
133 |
|
134 |
/** Adds a notice, quick and fast method
|
135 |
* @param String $message The Message you want to notify
|
136 |
+
* @param Boolean $unique If unique, check to not repeat notice exact same text in notices. Discard if so
|
137 |
* @param int $code A value of messageType as defined in model
|
138 |
* @returm Object Instance of noticeModel
|
139 |
*/
|
140 |
|
141 |
+
public static function addNormal($message, $unique = false)
|
142 |
{
|
143 |
$noticeController = self::getInstance();
|
144 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_NORMAL, $unique);
|
145 |
return $notice;
|
146 |
|
147 |
}
|
148 |
|
149 |
+
public static function addError($message, $unique = false)
|
150 |
{
|
151 |
$noticeController = self::getInstance();
|
152 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_ERROR, $unique);
|
153 |
return $notice;
|
154 |
|
155 |
}
|
156 |
|
157 |
+
public static function addWarning($message, $unique = false)
|
158 |
{
|
159 |
$noticeController = self::getInstance();
|
160 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_WARNING, $unique);
|
161 |
return $notice;
|
162 |
|
163 |
}
|
164 |
|
165 |
+
public static function addSuccess($message, $unique = false)
|
166 |
{
|
167 |
$noticeController = self::getInstance();
|
168 |
+
$notice = $noticeController->addNotice($message, NoticeModel::NOTICE_SUCCESS, $unique);
|
169 |
return $notice;
|
170 |
|
171 |
}
|
@@ -3,7 +3,7 @@ namespace ShortPixel\Notices;
|
|
3 |
|
4 |
class NoticeModel //extends ShortPixelModel
|
5 |
{
|
6 |
-
|
7 |
public $code;
|
8 |
|
9 |
protected $viewed = false;
|
@@ -88,9 +88,6 @@ class NoticeModel //extends ShortPixelModel
|
|
88 |
break;
|
89 |
}
|
90 |
|
91 |
-
/*$image = '<img src="' . plugins_url('/shortpixel-image-optimiser/res/img/robo-' . $icon . '.png') . '"
|
92 |
-
srcset="' . plugins_url( 'shortpixel-image-optimiser/res/img/robo-' . $icon . '.png' ) . ' 1x, ' . plugins_url( 'shortpixel-image-optimiser/res/img/robo-' . $icon . '@2x.png') . ' 2x" class="short-pixel-notice-icon">';
|
93 |
-
*/
|
94 |
|
95 |
if ($this->is_removable)
|
96 |
{
|
@@ -107,10 +104,4 @@ class NoticeModel //extends ShortPixelModel
|
|
107 |
}
|
108 |
|
109 |
|
110 |
-
|
111 |
-
// @todo Transient save, since that is used in some parts.
|
112 |
-
// save
|
113 |
-
// load
|
114 |
-
|
115 |
-
|
116 |
}
|
3 |
|
4 |
class NoticeModel //extends ShortPixelModel
|
5 |
{
|
6 |
+
public $message;
|
7 |
public $code;
|
8 |
|
9 |
protected $viewed = false;
|
88 |
break;
|
89 |
}
|
90 |
|
|
|
|
|
|
|
91 |
|
92 |
if ($this->is_removable)
|
93 |
{
|
104 |
}
|
105 |
|
106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
}
|
@@ -1,3 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 4.8.10 =
|
2 |
* restore compatibility with PHP 5.2.x
|
3 |
* finding unlisted thumbnails - don't bother if dialog dismissed.
|
1 |
+
= 4.12.8 =
|
2 |
+
|
3 |
+
Release date: 25th February 2019
|
4 |
+
|
5 |
+
* fix CSS for the top bar ShortPixel icon on post pages
|
6 |
+
* i18n some text which was left out by mistake
|
7 |
+
* include the green "CAN" WebP image which shows that the .htaccess works with WebP images having extensions like .jpg.webp
|
8 |
+
* display notice if ShortPixel Adaptive Images is active and the Generate WebP markup option is checked. Do not generate the WebP markup in this case.
|
9 |
+
|
10 |
+
= 4.12.7 =
|
11 |
+
|
12 |
+
Release date: 12th February 2019
|
13 |
+
|
14 |
+
* solved conflicting WebP file names when image.jpg and image.png exist in the same folder - use image.jpg.webp filename.
|
15 |
+
* fixed .htaccess rules for some Apache versions which seemingly don't honour the RewriteRule backreferences in the RewriteCond's (Apache bug?)
|
16 |
+
* remove the WebP .htaccess rules on plugin deactivation and add them back on plugin activation
|
17 |
+
* fixed alt attribute for <picture> tags - now it is included properly only on the enclosed <img> tag.
|
18 |
+
|
19 |
+
= 4.12.6 =
|
20 |
+
|
21 |
+
Release date: 27th January 2019
|
22 |
+
|
23 |
+
* Improvements to the .htaccess WebP method
|
24 |
+
* Improve performance of backup deletion - get rid of unnecessary checks
|
25 |
+
* Fixed: wrong calculation of remaining credits
|
26 |
+
* Fixed: discrepancy between the description of the exclude size option and the behaviour for the exact size case.
|
27 |
+
|
28 |
+
= 4.12.5 =
|
29 |
+
|
30 |
+
Release date: 10th Ianuary 2019
|
31 |
+
|
32 |
+
* change the JS name in order to circumveit cache problem on many WP installs
|
33 |
+
* sorting the Media Library entries by ShortPixel optimization: also sort based on compression level
|
34 |
+
* Fixed: case sensitive search for guid duplicates of image posts (needed for finding Polylang versions)
|
35 |
+
* Fixed: the data-lazy-src/srcset detection for WebP
|
36 |
+
* Improvements to the Deliver WebP options and especially messages with caveats
|
37 |
+
* Load the ShortPixel CSS only on admin pages that need it
|
38 |
+
|
39 |
+
= 4.12.4 =
|
40 |
+
|
41 |
+
Release date: 27th December 2018
|
42 |
+
|
43 |
+
* Fixed: shortpixel-thumbnails-regenerated action when not all the thumbnails were regenerated
|
44 |
+
|
45 |
+
= 4.12.3 =
|
46 |
+
|
47 |
+
Release date: 19th December 2018
|
48 |
+
|
49 |
+
* Fixed: error in getting the lazy- attributes of <img> for WebP handling.
|
50 |
+
|
51 |
+
= 4.12.2 =
|
52 |
+
|
53 |
+
Release date: 13th December 2018
|
54 |
+
|
55 |
+
* Improved: The Webp options interface. Now the user can implement Webp images both via .htaccess and by altering the page code on the server before being sent to the browser.
|
56 |
+
* Improved: The settings data handling interface in the Plugin deactivation dialogue. Now the option to delete or keep the user settings on plugin deletion is more clear.
|
57 |
+
* Added: Option to download image with thumbnails in a single archive file, to speed-up the optimization.
|
58 |
+
* Added: A "shortpixel_get_backup" filter, which receives the local path of the media image and returns the ShortPixel backup path, if a backup image exists
|
59 |
+
* Added: The "Simple Image Sizes" plugin to the conflicting plugins list
|
60 |
+
* Added: A new compatibility check for the "Jetpack" plugin, alerting the user about potential overlapping functionality
|
61 |
+
* Added: A safety alert before switching to Code Altering mode (where IMG tgs get inserted into PICTURE tags, to better serve Webp images)
|
62 |
+
* Added: Enhanced "Envira" plugin compatibility by adding more suffixes to be looked for: _tl, _tr, _bl, _br
|
63 |
+
* Added: More customized FAQ suggestions in the HelpScout Beacon helper, to address each Plugin TAB separately
|
64 |
+
* Fixed: The post-uninstall redirect when uninstalling a plugin from within the respective plugin's Settings page
|
65 |
+
* Fixed: The credits display on the Statistics page
|
66 |
+
* Fixed: Refreshing a plugin page now loads directly in the previously selected TAB
|
67 |
+
* Fixed: Removed a stray "SP_CELL_MESSAGE" div from the interface
|
68 |
+
|
69 |
+
= 4.12.1 =
|
70 |
+
|
71 |
+
Release date: 6th November 2018
|
72 |
+
|
73 |
+
* Fix WebP replacement for lazy-loaded images
|
74 |
+
* Fix WebP replacement with output buffering on some WP installs
|
75 |
+
|
76 |
+
= 4.12.0 =
|
77 |
+
|
78 |
+
Release date: 31st October 2018
|
79 |
+
|
80 |
+
* Generate WebP <picture> tags - use the output buffer instead of the_content which is not triggered by some themes on all content.
|
81 |
+
* compatibility of the WebP <picture> tag with lazy loading plugins (that support <picture>)
|
82 |
+
* Compatibility with Polylang.
|
83 |
+
* hooks to be used by thumbnail regeneration plugins: 'shortpixel-thumbnails-before-regenerate' and 'shortpixel-thumbnails-regenerated'
|
84 |
+
* Proper error message when the custom tables cannot be created.
|
85 |
+
* exclude the PNGs from conversion to JPEG when they match the exclude patterns.
|
86 |
+
* properly warn when cURL is not enabled that Cloudflare integration won't work.
|
87 |
+
* send only one url for metadata thumbnails which correspond to the same physical file.
|
88 |
+
* JavaScript delayed init for cases when some plugins deffer the load of javascript files.
|
89 |
+
* fix identifying filenames with basename length == 3 as retina
|
90 |
+
* display improvements for the bulk errors list
|
91 |
+
|
92 |
+
= 4.11.3 =
|
93 |
+
|
94 |
+
Release date: 27th September 2018
|
95 |
+
|
96 |
+
* fix error when metadata is returned as string by wp_get_attachment_metadata (happens to PDFs when using PDF Image Generator)
|
97 |
+
* remove the configurable Affiliate code as per new WP Themes rules.
|
98 |
+
|
99 |
+
= 4.11.2 =
|
100 |
+
|
101 |
+
Release date: 30th August 2018
|
102 |
+
|
103 |
+
* Fix "Image files are missing" warning when thumbails optimization is activated but all the thumbnails are excepted from optimization and the bulk is ran a second time.
|
104 |
+
* Fix not saving properly the metadata on some situations
|
105 |
+
|
106 |
+
= 4.11.1 =
|
107 |
+
|
108 |
+
Release date: 28th August 2018
|
109 |
+
|
110 |
+
* compatibility with the MediaPress plugin
|
111 |
+
* new action to be called by when thumbnails are regenerated: shortpixel-thumbnails-regenerated
|
112 |
+
* accept '+' inside the e-mail address
|
113 |
+
* fix optimization not working on internationalized domain names
|
114 |
+
* better count of the not optimized thumbs for an image, in some circumstances
|
115 |
+
* fallback to ABSPATH when get_home_path() returns '/'
|
116 |
+
* fix settings tabs navigation when url ends with #/
|
117 |
+
* extract all release notes < 4.9 from readme.txt into changelog.txt
|
118 |
+
* display the thumbnail name for some errors which refer only to a specific thumbnail.
|
119 |
+
* use update_post_meta() instead of wp_update_attachment_metadata() for cases when other plugins cannot be concerned by the meta change (specific to ShortPixel)
|
120 |
+
* add the attributes of the original <img> to the <picture> replacement tag, in case the "Generate WebP Markup" option is active.
|
121 |
+
* fix action buttons in media edit view overflowing their box
|
122 |
+
* restore full compatibility with WP < 4.1 by checking first before using wp_json_encode
|
123 |
+
* fix admin when domain is internationalized but the setting in admin uses the punycode-encrypted version
|
124 |
+
|
125 |
+
= 4.11.0 =
|
126 |
+
|
127 |
+
Release date: 3rd July 2018
|
128 |
+
|
129 |
+
* add bulk menu options: restore, reoptimize
|
130 |
+
* filter the media list by optimization status
|
131 |
+
* sort the media list by optimization status
|
132 |
+
* do not display the Media Library (years) folders in the selection list for Other Media folders
|
133 |
+
* force PNG 2 JPG conversion option
|
134 |
+
* integrate with Gravity Forms
|
135 |
+
* integrate with WP Stateless
|
136 |
+
* add several actions and a filter (see the Actions and Filters section of the readme)
|
137 |
+
* UI improvements to the settings page
|
138 |
+
* fix the WPML compatibility when converting from PNG
|
139 |
+
* fix SELECT IN image counting bug on rare cases and when >100k records in wp_postmeta
|
140 |
+
* add option to delete ShortPixel settings and give feedback form on deactivate plugin
|
141 |
+
|
142 |
+
= 4.10.5 =
|
143 |
+
* GDPR compliance
|
144 |
+
|
145 |
+
= 4.10.4 =
|
146 |
+
* replace back the PNG links when restoring a PNG converted to JPG
|
147 |
+
* fix incompatibility with Dynamics 365 Integration plugin
|
148 |
+
* improve restore capabilities after certain types of PNG to JPG errors which left the media item in an unconsistent state.
|
149 |
+
* remove AUTH credentials on server too, if removed in plugin's settings.
|
150 |
+
* more performance improvements to PNG 2 JPG conversion
|
151 |
+
* fix replacing PNG urls having http:// instead of https:// for a SSL site. (and viceversa)
|
152 |
+
* fix string not appearing in translations
|
153 |
+
|
154 |
+
= 4.10.3 =
|
155 |
+
* improvements to context help beacon
|
156 |
+
* performance improvements to PNG to JPG conversion
|
157 |
+
|
158 |
+
= 4.10.2 =
|
159 |
+
* fix error when listing Other media in some circumstances
|
160 |
+
|
161 |
+
= 4.10.1 =
|
162 |
+
* fix missing file from commit
|
163 |
+
|
164 |
+
= 4.10.0 =
|
165 |
+
* option to exclude thumbnails from optimization
|
166 |
+
* options to delete Cloudflare cache for optimized images
|
167 |
+
* method to define affilate codes for themes
|
168 |
+
* error message when restore could not be performed
|
169 |
+
* better handling of situations with files with different owner but with write permissions for all
|
170 |
+
* fix bug for inner resize when setting and unsetting the resize parameter
|
171 |
+
* fix bug for third-party WebP thumbnails registered in the 'sizes' metadata array which were sent to optimization.
|
172 |
+
* check if function mb_convert_encoding exists before using it
|
173 |
+
|
174 |
+
= 4.9.1 =
|
175 |
+
* fix error for older WP versions which don't have wp_raise_memory_limit
|
176 |
+
|
177 |
+
= 4.9.0 =
|
178 |
+
* inline help beacon
|
179 |
+
* fix exclude patterns not working after last update
|
180 |
+
* handle situations when not enough memory to convert from PNG to JPG.
|
181 |
+
* fix particular situations where there was no 'file' property in the metadata.
|
182 |
+
* fix slider optimized percent over the bulk warning box.
|
183 |
+
* display the x close link for the bulk warning box.
|
184 |
+
|
185 |
= 4.8.10 =
|
186 |
* restore compatibility with PHP 5.2.x
|
187 |
* finding unlisted thumbnails - don't bother if dialog dismissed.
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace ShortPixel;
|
3 |
+
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
use ShortPixel\Notices\NoticeController as Notices;
|
5 |
+
|
6 |
+
/* AdminController is meant for handling events, hooks, filters in WordPress where there is *NO* specific or more precise Shortpixel Page active.
|
7 |
+
*
|
8 |
+
* This should be a delegation class connection global hooks and such to the best shortpixel handler.
|
9 |
+
*/
|
10 |
+
class adminController extends ShortPixelController
|
11 |
+
{
|
12 |
+
protected static $instance;
|
13 |
+
|
14 |
+
public function __construct()
|
15 |
+
{
|
16 |
+
|
17 |
+
}
|
18 |
+
|
19 |
+
public static function getInstance()
|
20 |
+
{
|
21 |
+
if (is_null(self::$instance))
|
22 |
+
self::$instance = new adminController();
|
23 |
+
|
24 |
+
return self::$instance;
|
25 |
+
}
|
26 |
+
|
27 |
+
/** Handling upload actions
|
28 |
+
* @hook wp_generate_attachment_metadata
|
29 |
+
*/
|
30 |
+
public function handleImageUploadHook($meta, $ID = null)
|
31 |
+
{
|
32 |
+
return \wpSPIO()->getShortPixel()->handleMediaLibraryImageUpload($meta, $ID);
|
33 |
+
}
|
34 |
+
|
35 |
+
/** For conversion
|
36 |
+
* @hook wp_handle_upload
|
37 |
+
*/
|
38 |
+
public function handlePng2JpgHook($params)
|
39 |
+
{
|
40 |
+
return \wpSPIO()->getShortPixel()->convertPng2Jpg($params);
|
41 |
+
}
|
42 |
+
|
43 |
+
/** When replacing happens.
|
44 |
+
* @hook wp_handle_replace
|
45 |
+
*/
|
46 |
+
public function handleReplaceHook($params)
|
47 |
+
{
|
48 |
+
if(isset($params['post_id'])) { //integration with EnableMediaReplace - that's an upload for replacing an existing ID
|
49 |
+
$itemHandler = \wpSPIO()->getShortPixel()->onDeleteImage( intval($params['post_id']) );
|
50 |
+
$itemHandler->deleteAllSPMeta();
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
}
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace ShortPixel;
|
3 |
+
use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
// Future replacement for everything that needs temporary storage
|
6 |
+
// Storage agnostic -> called function should not need to know what is stored where, this is job of controller.
|
7 |
+
// Works with cache-model, which handles the data representation and storage.
|
8 |
+
//
|
9 |
+
|
10 |
+
class CacheController extends ShortPixelController
|
11 |
+
{
|
12 |
+
protected static $cached_items = array();
|
13 |
+
|
14 |
+
public function __construct()
|
15 |
+
{
|
16 |
+
$this->loadModel('cache');
|
17 |
+
}
|
18 |
+
|
19 |
+
public function storeItem($name, $value, $expires = HOUR_IN_SECONDS)
|
20 |
+
{
|
21 |
+
$cache = $this->getItem($name);
|
22 |
+
$cache->setValue($value);
|
23 |
+
$cache->setExpires($expires);
|
24 |
+
$cache->save();
|
25 |
+
$cache = apply_filters('shortpixel/cache/save', $cache, $name);
|
26 |
+
self::$cached_items[$name] = $cache;
|
27 |
+
|
28 |
+
return $cache;
|
29 |
+
}
|
30 |
+
|
31 |
+
/** Store a cacheModel Object.
|
32 |
+
* This can be used after requesting a cache item for instance.
|
33 |
+
* @param CacheModel $cache The Cache Model Item.
|
34 |
+
*/
|
35 |
+
public function storeItemObject(CacheModel $cache)
|
36 |
+
{
|
37 |
+
self::$cached_items[$cache->getName()] = $cache;
|
38 |
+
$cache->save();
|
39 |
+
}
|
40 |
+
|
41 |
+
public function getItem($name)
|
42 |
+
{
|
43 |
+
if (isset(self::$cached_items[$name]))
|
44 |
+
return self::$cached_items[$name];
|
45 |
+
|
46 |
+
$cache = new cacheModel($name);
|
47 |
+
$cache = apply_filters('shortpixel/cache/get', $cache, $name);
|
48 |
+
self::$cached_items[$name] = $cache;
|
49 |
+
|
50 |
+
return $cache;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function deleteItem($name)
|
54 |
+
{
|
55 |
+
$cache = $this->getItem($name);
|
56 |
+
|
57 |
+
if ($cache->exists())
|
58 |
+
{
|
59 |
+
$cache->delete();
|
60 |
+
}
|
61 |
+
|
62 |
+
|
63 |
+
}
|
64 |
+
|
65 |
+
}
|
@@ -5,7 +5,6 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
|
|
5 |
class ShortPixelController
|
6 |
{
|
7 |
protected static $controllers = array();
|
8 |
-
protected static $modelsLoaded = array(); // don't require twice, limit amount of require looksups..
|
9 |
|
10 |
protected $shortPixel;
|
11 |
|
@@ -126,18 +125,7 @@ class ShortPixelController
|
|
126 |
* @param string $name Name of the model
|
127 |
*/
|
128 |
protected function loadModel($name){
|
129 |
-
|
130 |
-
|
131 |
-
if (! in_array($name, self::$modelsLoaded))
|
132 |
-
{
|
133 |
-
self::$modelsLoaded[] = $name;
|
134 |
-
if(file_exists($path)){
|
135 |
-
require_once($path);
|
136 |
-
}
|
137 |
-
else {
|
138 |
-
Log::addError("Model $name could not be found");
|
139 |
-
}
|
140 |
-
}
|
141 |
}
|
142 |
|
143 |
|
5 |
class ShortPixelController
|
6 |
{
|
7 |
protected static $controllers = array();
|
|
|
8 |
|
9 |
protected $shortPixel;
|
10 |
|
125 |
* @param string $name Name of the model
|
126 |
*/
|
127 |
protected function loadModel($name){
|
128 |
+
return wpSPIO()->loadModel($name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
}
|
130 |
|
131 |
|
@@ -18,6 +18,7 @@ class editMediaController extends ShortPixelController
|
|
18 |
{
|
19 |
|
20 |
$this->loadModel($this->model);
|
|
|
21 |
parent::__construct();
|
22 |
}
|
23 |
|
@@ -216,6 +217,10 @@ class editMediaController extends ShortPixelController
|
|
216 |
return null;
|
217 |
}
|
218 |
|
|
|
|
|
|
|
|
|
219 |
$sizes = isset($this->data['sizes']) ? $this->data['sizes'] : array();
|
220 |
|
221 |
$debugInfo = array();
|
@@ -223,7 +228,23 @@ class editMediaController extends ShortPixelController
|
|
223 |
$debugInfo[] = array(__('WPML Duplicates'), json_encode(\ShortPixelMetaFacade::getWPMLDuplicates($this->post_id)) );
|
224 |
$debugInfo[] = array(__('Data'), $this->data);
|
225 |
$debugInfo[] = array(__('Meta'), wp_get_attachment_metadata($this->post_id) );
|
226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
$debugInfo[] = array(__('Status'), $this->imageModel->getMeta()->getStatus() );
|
228 |
|
229 |
return $debugInfo;
|
18 |
{
|
19 |
|
20 |
$this->loadModel($this->model);
|
21 |
+
$this->loadModel('image');
|
22 |
parent::__construct();
|
23 |
}
|
24 |
|
217 |
return null;
|
218 |
}
|
219 |
|
220 |
+
$imageObj = new ImageModel();
|
221 |
+
$imageObj->setByPostID($this->post_id);
|
222 |
+
$imageFile = $imageObj->getFile();
|
223 |
+
|
224 |
$sizes = isset($this->data['sizes']) ? $this->data['sizes'] : array();
|
225 |
|
226 |
$debugInfo = array();
|
228 |
$debugInfo[] = array(__('WPML Duplicates'), json_encode(\ShortPixelMetaFacade::getWPMLDuplicates($this->post_id)) );
|
229 |
$debugInfo[] = array(__('Data'), $this->data);
|
230 |
$debugInfo[] = array(__('Meta'), wp_get_attachment_metadata($this->post_id) );
|
231 |
+
if ($imageFile->hasBackup())
|
232 |
+
{
|
233 |
+
$backupFile = $imageFile->getBackupFile();
|
234 |
+
$debugInfo[] = array(__('Backup Folder'), $this->shortPixel->getBackupFolderAny($this->imageModel->getFile()->getFullPath(), $sizes));
|
235 |
+
$debugInfo[] = array(__('Backup File'), (string) $backupFile . '(' . \ShortPixelTools::formatBytes($backupFile->getFileSize()) . ')' );
|
236 |
+
}
|
237 |
+
else {
|
238 |
+
$debugInfo[] = array(__("No Backup Available"), '');
|
239 |
+
}
|
240 |
+
if ($or = $imageObj->has_original())
|
241 |
+
{
|
242 |
+
$debugInfo[] = array(__('Original File'), $or->getFullPath() . '(' . \ShortPixelTools::formatBytes($or->getFileSize()) . ')');
|
243 |
+
$orbackup = $or->getBackupFile();
|
244 |
+
if ($orbackup)
|
245 |
+
$debugInfo[] = array(__('Backup'), $orbackup->getFullPath() . '(' . \ShortPixelTools::formatBytes($orbackup->getFileSize()) . ')');
|
246 |
+
}
|
247 |
+
|
248 |
$debugInfo[] = array(__('Status'), $this->imageModel->getMeta()->getStatus() );
|
249 |
|
250 |
return $debugInfo;
|
@@ -15,9 +15,9 @@ Class FileSystemController extends ShortPixelController
|
|
15 |
{
|
16 |
$this->loadModel('file');
|
17 |
$this->loadModel('directory');
|
18 |
-
|
19 |
|
20 |
-
$this->env =
|
21 |
|
22 |
}
|
23 |
|
@@ -31,6 +31,33 @@ Class FileSystemController extends ShortPixelController
|
|
31 |
return new FileModel($path);
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
/** Get DirectoryModel for a certain path. This can exist or not
|
35 |
*
|
36 |
* @param String $path Full Path to the Directory.
|
@@ -69,6 +96,26 @@ Class FileSystemController extends ShortPixelController
|
|
69 |
}
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
/** Not in use yet, do not use. Future replacement. */
|
73 |
public function createBackUpFolder($folder = SHORTPIXEL_BACKUP_FOLDER)
|
74 |
{
|
@@ -99,6 +146,15 @@ Class FileSystemController extends ShortPixelController
|
|
99 |
}
|
100 |
}
|
101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
if (parse_url($url) !== false)
|
103 |
return $url;
|
104 |
else {
|
@@ -106,9 +162,56 @@ Class FileSystemController extends ShortPixelController
|
|
106 |
}
|
107 |
}
|
108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
|
|
110 |
|
|
|
111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
|
113 |
|
114 |
}
|
15 |
{
|
16 |
$this->loadModel('file');
|
17 |
$this->loadModel('directory');
|
18 |
+
// $this->loadModel('environment');
|
19 |
|
20 |
+
$this->env = wpSPIO()->env();
|
21 |
|
22 |
}
|
23 |
|
31 |
return new FileModel($path);
|
32 |
}
|
33 |
|
34 |
+
/** Get FileModel for a mediaLibrary post_id .
|
35 |
+
*
|
36 |
+
* This function exists to put get_attached_file to plugin control
|
37 |
+
* Externals / Interals maybe filter it.
|
38 |
+
*
|
39 |
+
* @param $id Attachement ID for the media library item
|
40 |
+
* @return FileModel returns a FileModel file.
|
41 |
+
* @todo This function will be more at home in a medialibrary_model
|
42 |
+
*/
|
43 |
+
public function getAttachedFile($id)
|
44 |
+
{
|
45 |
+
$filepath = get_attached_file($id);
|
46 |
+
// same signature as wordpress' filter. Only for this plugin.
|
47 |
+
$filepath = apply_filters('shortpixel_get_attached_file', $filepath, $id);
|
48 |
+
|
49 |
+
return new FileModel($filepath);
|
50 |
+
|
51 |
+
}
|
52 |
+
|
53 |
+
/* wp_get_original_image_path with specific ShortPixel filter */
|
54 |
+
public function getOriginalPath($id)
|
55 |
+
{
|
56 |
+
$filepath = \wp_get_original_image_path($id);
|
57 |
+
$filepath = apply_filters('shortpixel_get_original_image_path', $filepath, $id);
|
58 |
+
return new FileModel($filepath);
|
59 |
+
}
|
60 |
+
|
61 |
/** Get DirectoryModel for a certain path. This can exist or not
|
62 |
*
|
63 |
* @param String $path Full Path to the Directory.
|
96 |
}
|
97 |
}
|
98 |
|
99 |
+
/** Get the base folder from where custom paths are possible (from WP-base / sitebase)
|
100 |
+
|
101 |
+
*/
|
102 |
+
public function getWPFileBase()
|
103 |
+
{
|
104 |
+
if(\wpSPIO()->env()->is_mainsite) {
|
105 |
+
$path = get_home_path();
|
106 |
+
|
107 |
+
} else {
|
108 |
+
$up = wp_upload_dir();
|
109 |
+
$path = realpath($up['basedir']);
|
110 |
+
}
|
111 |
+
$dir = $this->getDirectory($path);
|
112 |
+
if (! $dir->exists())
|
113 |
+
Log::addWarn('getWPFileBase - Base path doesnt exist');
|
114 |
+
|
115 |
+
return $dir;
|
116 |
+
|
117 |
+
}
|
118 |
+
|
119 |
/** Not in use yet, do not use. Future replacement. */
|
120 |
public function createBackUpFolder($folder = SHORTPIXEL_BACKUP_FOLDER)
|
121 |
{
|
146 |
}
|
147 |
}
|
148 |
|
149 |
+
$wp_home_path = trailingslashit(get_home_path());
|
150 |
+
// If the whole WP homepath is still in URL, assume the replace when wrong ( not replaced w/ URL)
|
151 |
+
// This happens when file is outside of wp_uploads_dir
|
152 |
+
if (strpos($url, $wp_home_path) !== false)
|
153 |
+
{
|
154 |
+
$home_url = trailingslashit(get_home_url());
|
155 |
+
$url = str_replace($wp_home_path, $home_url, $filepath);
|
156 |
+
}
|
157 |
+
|
158 |
if (parse_url($url) !== false)
|
159 |
return $url;
|
160 |
else {
|
162 |
}
|
163 |
}
|
164 |
|
165 |
+
/** Sort files / directories in a certain way.
|
166 |
+
* Future dev to include options via arg.
|
167 |
+
*/
|
168 |
+
public function sortFiles($array, $args = array() )
|
169 |
+
{
|
170 |
+
if (count($array) == 0)
|
171 |
+
return $array;
|
172 |
+
|
173 |
+
// what are we sorting.
|
174 |
+
$class = get_class($array[0]);
|
175 |
+
$is_files = ($class == 'ShortPixel\FileModel') ? true : false; // if not files, then dirs.
|
176 |
+
|
177 |
+
usort($array, function ($a, $b) use ($is_files)
|
178 |
+
{
|
179 |
+
if ($is_files)
|
180 |
+
return strcmp($a->getFileName(), $b->getFileName());
|
181 |
+
else {
|
182 |
+
return strcmp($a->getName(), $b->getName());
|
183 |
+
}
|
184 |
+
}
|
185 |
+
);
|
186 |
|
187 |
+
return $array;
|
188 |
|
189 |
+
}
|
190 |
|
191 |
+
/** Get all files from a directory tree, starting at given dir.
|
192 |
+
* @param DirectoryModel $dir to recursive into
|
193 |
+
* @param Array $filters Collection of optional filters as accepted by FileFilter in directoryModel
|
194 |
+
* @return Array Array of FileModel Objects
|
195 |
+
**/
|
196 |
+
public function getFilesRecursive(DirectoryModel $dir, $filters = array() )
|
197 |
+
{
|
198 |
+
$fileArray = array();
|
199 |
+
|
200 |
+
if (! $dir->exists())
|
201 |
+
return $fileArray;
|
202 |
+
|
203 |
+
$files = $dir->getFiles($filters);
|
204 |
+
$fileArray = array_merge($fileArray, $files);
|
205 |
+
|
206 |
+
$subdirs = $dir->getSubDirectories();
|
207 |
+
|
208 |
+
foreach($subdirs as $subdir)
|
209 |
+
{
|
210 |
+
$fileArray = array_merge($fileArray, $this->getFilesRecursive($subdir, $filters));
|
211 |
+
}
|
212 |
+
|
213 |
+
return $fileArray;
|
214 |
+
}
|
215 |
|
216 |
|
217 |
}
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace ShortPixel;
|
3 |
+
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
use ShortPixel\Notices\NoticeController as Notices;
|
5 |
+
|
6 |
+
|
7 |
+
/** Handle everything that SP is doing front-wise */
|
8 |
+
class frontController extends ShortPixelController
|
9 |
+
{
|
10 |
+
// DeliverWebp option settings for front-end delivery of webp
|
11 |
+
const WEBP_GLOBAL = 1;
|
12 |
+
const WEBP_WP = 2;
|
13 |
+
const WEBP_NOCHANGE = 3;
|
14 |
+
|
15 |
+
public function __construct()
|
16 |
+
{
|
17 |
+
if (wpSPIO()->env()->is_front) // if is front.
|
18 |
+
{
|
19 |
+
$this->initWebpHooks();
|
20 |
+
$this->hookFrontProcessing();
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
public function initWebpHooks()
|
25 |
+
{
|
26 |
+
$webp_option = \wpSPIO()->settings()->deliverWebp;
|
27 |
+
|
28 |
+
if ( $webp_option ) {
|
29 |
+
if(\ShortPixelTools::shortPixelIsPluginActive('shortpixel-adaptive-images/short-pixel-ai.php')) {
|
30 |
+
Notices::addWarning(__('Please deactivate the ShortPixel Image Optimizer\'s
|
31 |
+
<a href="options-general.php?page=wp-shortpixel-settings&part=adv-settings">Deliver WebP using PICTURE tag</a>
|
32 |
+
option when the ShortPixel Adaptive Images plugin is active.','shortpixel-image-optimiser'), true);
|
33 |
+
}
|
34 |
+
elseif( $webp_option == self::WEBP_GLOBAL ){
|
35 |
+
add_action( 'wp_head', array($this, 'addPictureJs') ); // adds polyfill JS to the header
|
36 |
+
add_action( 'init', array($this, 'startOutputBuffer'), 1 ); // start output buffer to capture content
|
37 |
+
} elseif ($webp_option == self::WEBP_WP){
|
38 |
+
add_filter( 'the_content', array($this, 'convertImgToPictureAddWebp'), 10000 ); // priority big, so it will be executed last
|
39 |
+
add_filter( 'the_excerpt', array($this, 'convertImgToPictureAddWebp'), 10000 );
|
40 |
+
add_filter( 'post_thumbnail_html', array($this,'convertImgToPictureAddWebp') );
|
41 |
+
}
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
public function hookFrontProcessing()
|
46 |
+
{
|
47 |
+
if (! \wpSPIO()->settings()->frontBootstrap)
|
48 |
+
return;
|
49 |
+
|
50 |
+
$prio = (! defined('SHORTPIXEL_NOFLOCK')) ? \ShortPixelQueue::get() : \ShortPixelQueueDB::get();
|
51 |
+
|
52 |
+
if ($prio && is_array($prio) && count($prio))
|
53 |
+
{
|
54 |
+
//also need to have it in the front footer then
|
55 |
+
add_action( 'wp_footer', array( \wpSPIO()->getShortPixel(), 'shortPixelJS') );
|
56 |
+
//need to add the nopriv action for when items exist in the queue and no user is logged in
|
57 |
+
add_action( 'wp_ajax_nopriv_shortpixel_image_processing', array( \wpSPIO()->getShortPixel(), 'handleImageProcessing') );
|
58 |
+
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
/* Picture generation, hooked on the_content filter
|
63 |
+
* @param $content String The content to check and convert
|
64 |
+
* @return String Converted content
|
65 |
+
*/
|
66 |
+
public function convertImgToPictureAddWebp($content) {
|
67 |
+
|
68 |
+
if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
|
69 |
+
//for AMP pages the <picture> tag is not allowed
|
70 |
+
return $content . (isset($_GET['SHORTPIXEL_DEBUG']) ? '<!-- SPDBG is AMP -->' : '');
|
71 |
+
}
|
72 |
+
require_once(\ShortPixelTools::getPluginPath() . 'class/front/img-to-picture-webp.php');
|
73 |
+
return \ShortPixelImgToPictureWebp::convert($content);// . "<!-- PICTURE TAGS BY SHORTPIXEL -->";
|
74 |
+
}
|
75 |
+
|
76 |
+
public function addPictureJs() {
|
77 |
+
// Don't do anything with the RSS feed.
|
78 |
+
if ( is_feed() || is_admin() ) { return; }
|
79 |
+
|
80 |
+
echo '<script>'
|
81 |
+
. 'var spPicTest = document.createElement( "picture" );'
|
82 |
+
. 'if(!window.HTMLPictureElement && document.addEventListener) {'
|
83 |
+
. 'window.addEventListener("DOMContentLoaded", function() {'
|
84 |
+
. 'var scriptTag = document.createElement("script");'
|
85 |
+
. 'scriptTag.src = "' . plugins_url('/res/js/picturefill.min.js', __FILE__) . '";'
|
86 |
+
. 'document.body.appendChild(scriptTag);'
|
87 |
+
. '});'
|
88 |
+
. '}'
|
89 |
+
. '</script>';
|
90 |
+
}
|
91 |
+
|
92 |
+
|
93 |
+
public function startOutputBuffer() {
|
94 |
+
$env = wpSPIO()->env();
|
95 |
+
if ($env->is_admin || $env->is_ajaxcall)
|
96 |
+
return;
|
97 |
+
|
98 |
+
$call = array($this, 'convertImgToPictureAddWebp');
|
99 |
+
ob_start( $call );
|
100 |
+
}
|
101 |
+
|
102 |
+
|
103 |
+
|
104 |
+
} // class
|
@@ -80,8 +80,16 @@ class SettingsController extends shortPixelController
|
|
80 |
Log::addDebug('Settings Action - addkey ', array($this->is_form_submit, $this->postData) );
|
81 |
if ($this->is_form_submit && isset($this->postData['apiKey']))
|
82 |
{
|
83 |
-
$this->
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
/*if (isset($this->postData['verifiedKey']) && $this->postData['verifiedKey'])
|
86 |
{
|
87 |
$this->model->apiKey = $this->postData['apiKey'];
|
@@ -111,7 +119,7 @@ class SettingsController extends shortPixelController
|
|
111 |
|
112 |
if ($this->postData['includeNextGen'] == 1)
|
113 |
{
|
114 |
-
$nextgen = new NextGen(
|
115 |
$previous = $this->model->includeNextGen;
|
116 |
$nextgen->nextGenEnabled($previous);
|
117 |
}
|
@@ -172,7 +180,7 @@ class SettingsController extends shortPixelController
|
|
172 |
/** Checks on things and set them for information. */
|
173 |
protected function loadEnv()
|
174 |
{
|
175 |
-
$env =
|
176 |
|
177 |
$this->is_nginx = $env->is_nginx;
|
178 |
$this->is_gd_installed = $env->is_gd_installed;
|
@@ -188,13 +196,6 @@ class SettingsController extends shortPixelController
|
|
188 |
|
189 |
}
|
190 |
|
191 |
-
public function getEnv()
|
192 |
-
{
|
193 |
-
$this->loadModel('environment');
|
194 |
-
$env = new EnvironmentModel();
|
195 |
-
|
196 |
-
return $env;
|
197 |
-
}
|
198 |
|
199 |
/** Check if everything is OK with the Key **/
|
200 |
/*public function checkKey()
|
@@ -321,7 +322,7 @@ class SettingsController extends shortPixelController
|
|
321 |
protected function loadCustomFolders()
|
322 |
{
|
323 |
$notice = null;
|
324 |
-
$customFolders = $this->shortPixel->refreshCustomFolders(
|
325 |
|
326 |
if (! is_null($notice))
|
327 |
{
|
@@ -331,7 +332,6 @@ class SettingsController extends shortPixelController
|
|
331 |
else
|
332 |
Notice::addNormal($message);
|
333 |
|
334 |
-
|
335 |
}
|
336 |
|
337 |
if ($this->has_nextgen)
|
@@ -398,7 +398,6 @@ class SettingsController extends shortPixelController
|
|
398 |
if(!$folderMsg) {
|
399 |
//$notice = array("status" => "success", "msg" => __('Folder added successfully.','shortpixel-image-optimiser'));
|
400 |
$folderMsg = __('Folder added successfully.','shortpixel-image-optimiser');
|
401 |
-
|
402 |
$is_warning = false;
|
403 |
}
|
404 |
if ($is_warning)
|
80 |
Log::addDebug('Settings Action - addkey ', array($this->is_form_submit, $this->postData) );
|
81 |
if ($this->is_form_submit && isset($this->postData['apiKey']))
|
82 |
{
|
83 |
+
$apiKey = $this->postData['apiKey'];
|
84 |
+
if (strlen(trim($apiKey)) == 0) // display notice when submitting empty API key
|
85 |
+
{
|
86 |
+
Notice::addError(sprintf(__("The key you provided has %s characters. The API key should have 20 characters, letters and numbers only.",'shortpixel-image-optimiser'), strlen($apiKey) ));
|
87 |
+
}
|
88 |
+
else
|
89 |
+
{
|
90 |
+
$this->keyModel->resetTried();
|
91 |
+
$this->keyModel->checkKey($this->postData['apiKey']);
|
92 |
+
}
|
93 |
/*if (isset($this->postData['verifiedKey']) && $this->postData['verifiedKey'])
|
94 |
{
|
95 |
$this->model->apiKey = $this->postData['apiKey'];
|
119 |
|
120 |
if ($this->postData['includeNextGen'] == 1)
|
121 |
{
|
122 |
+
$nextgen = new NextGen();
|
123 |
$previous = $this->model->includeNextGen;
|
124 |
$nextgen->nextGenEnabled($previous);
|
125 |
}
|
180 |
/** Checks on things and set them for information. */
|
181 |
protected function loadEnv()
|
182 |
{
|
183 |
+
$env = wpSPIO()->env();
|
184 |
|
185 |
$this->is_nginx = $env->is_nginx;
|
186 |
$this->is_gd_installed = $env->is_gd_installed;
|
196 |
|
197 |
}
|
198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
|
200 |
/** Check if everything is OK with the Key **/
|
201 |
/*public function checkKey()
|
322 |
protected function loadCustomFolders()
|
323 |
{
|
324 |
$notice = null;
|
325 |
+
$customFolders = $this->shortPixel->refreshCustomFolders();
|
326 |
|
327 |
if (! is_null($notice))
|
328 |
{
|
332 |
else
|
333 |
Notice::addNormal($message);
|
334 |
|
|
|
335 |
}
|
336 |
|
337 |
if ($this->has_nextgen)
|
398 |
if(!$folderMsg) {
|
399 |
//$notice = array("status" => "success", "msg" => __('Folder added successfully.','shortpixel-image-optimiser'));
|
400 |
$folderMsg = __('Folder added successfully.','shortpixel-image-optimiser');
|
|
|
401 |
$is_warning = false;
|
402 |
}
|
403 |
if ($is_warning)
|
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
|
3 |
-
|
4 |
|
5 |
class ShortPixelCustomMetaDao {
|
6 |
const META_VERSION = 1;
|
@@ -138,7 +138,7 @@ class ShortPixelCustomMetaDao {
|
|
138 |
}
|
139 |
|
140 |
public function getFolder($path, $deleted = false) {
|
141 |
-
$sql = "SELECT * FROM {$this->db->getPrefix()}shortpixel_folders" . ($deleted ? "" : " WHERE path = %s AND status <> -1");
|
142 |
$rows = $this->db->query($sql, array($path));
|
143 |
$folders = array();
|
144 |
foreach($rows as $row) {
|
@@ -156,11 +156,14 @@ class ShortPixelCustomMetaDao {
|
|
156 |
return false;
|
157 |
}
|
158 |
|
159 |
-
|
160 |
-
|
161 |
-
|
|
|
|
|
|
|
162 |
return $this->db->insert($this->db->getPrefix().'shortpixel_folders',
|
163 |
-
array("path" => $
|
164 |
array("path" => "%s", "path_md5" => "%s", "file_count" => "%d", "ts_updated" => "%s"));
|
165 |
}
|
166 |
|
@@ -199,37 +202,46 @@ class ShortPixelCustomMetaDao {
|
|
199 |
$this->db->query($sql, array($folderPath));
|
200 |
}
|
201 |
|
202 |
-
|
203 |
//$this->db->restoreErrors();
|
204 |
}
|
205 |
|
206 |
public function newFolderFromPath($path, $uploadPath, $rootPath) {
|
207 |
WpShortPixelDb::checkCustomTables(); // check if custom tables are created, if not, create them
|
208 |
-
|
209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
return __('Folder could not be found: ' . $uploadPath . $path ,'shortpixel-image-optimiser');
|
211 |
}
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
if(strpos($addedFolderReal, $rootPath) !== 0) {
|
216 |
return( sprintf(__('The %s folder cannot be processed as it\'s not inside the root path of your website (%s).','shortpixel-image-optimiser'),$addedFolder, $rootPath));
|
217 |
-
} else {
|
218 |
-
$addedFolder = $addedFolderReal; //addedFolder is a symlink inside the root to a folder outside root - addedFolderReal. Use the inside symlink
|
219 |
-
}
|
220 |
}
|
221 |
-
|
|
|
222 |
return __('Folder already added.','shortpixel-image-optimiser');
|
223 |
}
|
224 |
-
|
225 |
-
|
|
|
226 |
$folder->setFileCount($folder->countFiles());
|
227 |
} catch(ShortPixelFileRightsException $ex) {
|
228 |
return $ex->getMessage();
|
229 |
-
}
|
|
|
230 |
if(ShortPixelMetaFacade::isMediaSubfolder($folder->getPath())) {
|
231 |
return __('This folder contains Media Library images. To optimize Media Library images please go to <a href="upload.php?mode=list">Media Library list view</a> or to <a href="upload.php?page=wp-short-pixel-bulk">SortPixel Bulk page</a>.','shortpixel-image-optimiser');
|
232 |
}
|
|
|
|
|
|
|
|
|
|
|
233 |
$folderMsg = $this->saveFolder($folder);
|
234 |
if(!$folder->getId()) {
|
235 |
//try again creating the tables first.
|
@@ -242,12 +254,54 @@ class ShortPixelCustomMetaDao {
|
|
242 |
}
|
243 |
|
244 |
if(!$folderMsg) {
|
245 |
-
|
246 |
-
$this->
|
247 |
}
|
248 |
return $folderMsg;
|
249 |
|
250 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
/**
|
252 |
*
|
253 |
* @param type $path
|
@@ -269,7 +323,7 @@ class ShortPixelCustomMetaDao {
|
|
269 |
if($sub) {
|
270 |
$id = $this->updateFolder($sub, $addedPath, 0, $folder->getFileCount());
|
271 |
} else {
|
272 |
-
$id = $this->addFolder($
|
273 |
}
|
274 |
$folder->setId($id);
|
275 |
return false;
|
@@ -309,31 +363,44 @@ class ShortPixelCustomMetaDao {
|
|
309 |
return $id;
|
310 |
}
|
311 |
|
312 |
-
|
313 |
-
$pathsFileHandle = fopen($pathsFile, 'r');
|
314 |
-
|
315 |
//facem un delete pe cele care nu au shortpixel_folder, pentru curatenie - am mai intalnit situatii in care stergerea s-a agatat (stop monitoring)
|
|
|
|
|
316 |
$sqlCleanup = "DELETE FROM {$this->db->getPrefix()}shortpixel_meta WHERE folder_id NOT IN (SELECT id FROM {$this->db->getPrefix()}shortpixel_folders)";
|
317 |
$this->db->query($sqlCleanup);
|
318 |
|
319 |
-
$values =
|
320 |
$sql = "INSERT IGNORE INTO {$this->db->getPrefix()}shortpixel_meta(folder_id, path, name, path_md5, status) VALUES ";
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
329 |
}
|
|
|
330 |
}
|
331 |
if($values) {
|
332 |
-
|
|
|
|
|
|
|
|
|
333 |
}
|
334 |
-
|
335 |
-
unlink($pathsFile);
|
336 |
-
return $inserted;
|
337 |
}
|
338 |
|
339 |
public function resetFailed() {
|
1 |
<?php
|
2 |
use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
|
3 |
+
use ShortPixel\Notices\NoticeController as Notice;
|
4 |
|
5 |
class ShortPixelCustomMetaDao {
|
6 |
const META_VERSION = 1;
|
138 |
}
|
139 |
|
140 |
public function getFolder($path, $deleted = false) {
|
141 |
+
$sql = "SELECT * FROM {$this->db->getPrefix()}shortpixel_folders" . ($deleted ? "WHERE path = %s " : " WHERE path = %s AND status <> -1");
|
142 |
$rows = $this->db->query($sql, array($path));
|
143 |
$folders = array();
|
144 |
foreach($rows as $row) {
|
156 |
return false;
|
157 |
}
|
158 |
|
159 |
+
/** Folder is ShortPixelFolder object */
|
160 |
+
public function addFolder(ShortPixelFolder $folder, $fileCount = 0) {
|
161 |
+
$path = $folder->getPath();
|
162 |
+
$tsUpdated = date("Y-m-d H:i:s", $folder->getTsUpdated());
|
163 |
+
|
164 |
+
|
165 |
return $this->db->insert($this->db->getPrefix().'shortpixel_folders',
|
166 |
+
array("path" => $path, "path_md5" => md5($path), "file_count" => $fileCount, "ts_updated" => $tsUpdated, "ts_created" => date("Y-m-d H:i:s")),
|
167 |
array("path" => "%s", "path_md5" => "%s", "file_count" => "%d", "ts_updated" => "%s"));
|
168 |
}
|
169 |
|
202 |
$this->db->query($sql, array($folderPath));
|
203 |
}
|
204 |
|
|
|
205 |
//$this->db->restoreErrors();
|
206 |
}
|
207 |
|
208 |
public function newFolderFromPath($path, $uploadPath, $rootPath) {
|
209 |
WpShortPixelDb::checkCustomTables(); // check if custom tables are created, if not, create them
|
210 |
+
|
211 |
+
$fs = \wpSPIO()->filesystem();
|
212 |
+
|
213 |
+
//$addedFolder = ShortPixelFolder::checkFolder($path, $uploadPath);
|
214 |
+
$newfolder = $fs->getDirectory($path);
|
215 |
+
$rootPath = $fs->getWPFileBase();
|
216 |
+
|
217 |
+
if(! $newfolder->exists() ) {
|
218 |
return __('Folder could not be found: ' . $uploadPath . $path ,'shortpixel-image-optimiser');
|
219 |
}
|
220 |
+
|
221 |
+
if (! $newfolder->isSubFolderOf($rootPath))
|
222 |
+
{
|
|
|
223 |
return( sprintf(__('The %s folder cannot be processed as it\'s not inside the root path of your website (%s).','shortpixel-image-optimiser'),$addedFolder, $rootPath));
|
|
|
|
|
|
|
224 |
}
|
225 |
+
|
226 |
+
if($this->getFolder($newfolder->getPath())) {
|
227 |
return __('Folder already added.','shortpixel-image-optimiser');
|
228 |
}
|
229 |
+
|
230 |
+
$folder = new ShortPixelFolder(array("path" => $newfolder->getPath()), $this->excludePatterns);
|
231 |
+
/* try {
|
232 |
$folder->setFileCount($folder->countFiles());
|
233 |
} catch(ShortPixelFileRightsException $ex) {
|
234 |
return $ex->getMessage();
|
235 |
+
} */
|
236 |
+
|
237 |
if(ShortPixelMetaFacade::isMediaSubfolder($folder->getPath())) {
|
238 |
return __('This folder contains Media Library images. To optimize Media Library images please go to <a href="upload.php?mode=list">Media Library list view</a> or to <a href="upload.php?page=wp-short-pixel-bulk">SortPixel Bulk page</a>.','shortpixel-image-optimiser');
|
239 |
}
|
240 |
+
|
241 |
+
// Set this to 0 on new, not null since mysql will auto-complete that to current TS.
|
242 |
+
$folder->setTSUpdated(0);
|
243 |
+
$folder->setFileCount(0);
|
244 |
+
|
245 |
$folderMsg = $this->saveFolder($folder);
|
246 |
if(!$folder->getId()) {
|
247 |
//try again creating the tables first.
|
254 |
}
|
255 |
|
256 |
if(!$folderMsg) {
|
257 |
+
//$fileList = $folder->getFileList();
|
258 |
+
$this->refreshFolder($newfolder);
|
259 |
}
|
260 |
return $folderMsg;
|
261 |
|
262 |
}
|
263 |
+
|
264 |
+
/** Check files and add what's needed */
|
265 |
+
public function refreshFolder(ShortPixel\DirectoryModel $folder)
|
266 |
+
{
|
267 |
+
|
268 |
+
$folderObj = $this->getFolder($folder->getPath());
|
269 |
+
|
270 |
+
if ($folderObj === false)
|
271 |
+
{
|
272 |
+
Log::addWarn('FolderObj from database is not there, while folder seems ok ' . $folder->getPath() );
|
273 |
+
return false;
|
274 |
+
}
|
275 |
+
|
276 |
+
Log::addDebug('Doing Refresh Folder for (DirectoryModel / ShortpixelFolder) ', array($folder->getPath(), $folderObj->getPath()) );
|
277 |
+
|
278 |
+
$fs = \wpSPIO()->fileSystem();
|
279 |
+
|
280 |
+
if (! $folder->exists())
|
281 |
+
{
|
282 |
+
Notice::addError( sprintf(__('Folder %s does not exist! ', 'shortpixel-image-optimiser'), $folder->getPath()) );
|
283 |
+
return false;
|
284 |
+
}
|
285 |
+
if (! $folder->is_writable())
|
286 |
+
{
|
287 |
+
Notice::addWarning( sprintf(__('Folder %s is not writeable. Please check permissions and try again.','shortpixel-image-optimiser'),$folder->getPath()) );
|
288 |
+
}
|
289 |
+
|
290 |
+
$filter = array('date_newer' => strtotime($folderObj->getTsUpdated()));
|
291 |
+
$files = $fs->getFilesRecursive($folder, $filter);
|
292 |
+
|
293 |
+
$shortpixel = \wpSPIO()->getShortPixel();
|
294 |
+
// check processable by invoking filter, for now processablepath takes only paths, not objects.
|
295 |
+
$files = array_filter($files, function($file) use($shortpixel) { return $shortpixel->isProcessablePath($file->getFullPath()); });
|
296 |
+
|
297 |
+
Log::addDebug('Found Files for custom media ' . count($files));
|
298 |
+
$folderObj->setTsUpdated(date("Y-m-d H:i:s", $folderObj->getFolderContentsChangeDate()) );
|
299 |
+
$folderObj->setFileCount($folderObj->countFiles() );
|
300 |
+
$this->update($folderObj);
|
301 |
+
|
302 |
+
$this->batchInsertImages($files, $folderObj->getId());
|
303 |
+
}
|
304 |
+
|
305 |
/**
|
306 |
*
|
307 |
* @param type $path
|
323 |
if($sub) {
|
324 |
$id = $this->updateFolder($sub, $addedPath, 0, $folder->getFileCount());
|
325 |
} else {
|
326 |
+
$id = $this->addFolder($folder, $folder->getFileCount());
|
327 |
}
|
328 |
$folder->setId($id);
|
329 |
return false;
|
363 |
return $id;
|
364 |
}
|
365 |
|
366 |
+
private function batchInsertImages($files, $folderId) {
|
|
|
|
|
367 |
//facem un delete pe cele care nu au shortpixel_folder, pentru curatenie - am mai intalnit situatii in care stergerea s-a agatat (stop monitoring)
|
368 |
+
global $wpdb;
|
369 |
+
|
370 |
$sqlCleanup = "DELETE FROM {$this->db->getPrefix()}shortpixel_meta WHERE folder_id NOT IN (SELECT id FROM {$this->db->getPrefix()}shortpixel_folders)";
|
371 |
$this->db->query($sqlCleanup);
|
372 |
|
373 |
+
$values = array();
|
374 |
$sql = "INSERT IGNORE INTO {$this->db->getPrefix()}shortpixel_meta(folder_id, path, name, path_md5, status) VALUES ";
|
375 |
+
$format = '(%d,%s,%s,%s,%d)';
|
376 |
+
$i = 0;
|
377 |
+
$count = 0;
|
378 |
+
$placeholders = array();
|
379 |
+
foreach($files as $file) {
|
380 |
+
$filepath = $file->getFullPath();
|
381 |
+
$filename = $file->getFileName();
|
382 |
+
|
383 |
+
array_push($values, $folderId, $filepath, $filename, md5($filepath), 0);
|
384 |
+
$placeholders[] = $format;
|
385 |
+
|
386 |
+
|
387 |
+
if($i % 500 == 499) {
|
388 |
+
$query = $sql;
|
389 |
+
$query .= implode(', ', $placeholders);
|
390 |
+
$this->db->query( $this->db->prepare("$query ", $values));
|
391 |
+
|
392 |
+
$values = array();
|
393 |
}
|
394 |
+
$i++;
|
395 |
}
|
396 |
if($values) {
|
397 |
+
$query = $sql;
|
398 |
+
$query .= implode(', ', $placeholders);
|
399 |
+
$result = $wpdb->query( $wpdb->prepare("$query ", $values) );
|
400 |
+
Log::addDebug('Q Result', array($result, $wpdb->last_error));
|
401 |
+
//$this->db->query( $this->db->prepare("$query ", $values));
|
402 |
}
|
403 |
+
|
|
|
|
|
404 |
}
|
405 |
|
406 |
public function resetFailed() {
|
@@ -1,5 +1,8 @@
|
|
1 |
<?php
|
2 |
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
|
|
|
|
|
|
3 |
|
4 |
class ShortPixelMetaFacade {
|
5 |
const MEDIA_LIBRARY_TYPE = 1;
|
@@ -47,7 +50,9 @@ class ShortPixelMetaFacade {
|
|
47 |
}
|
48 |
|
49 |
private static function rawMetaToMeta($ID, $rawMeta) {
|
50 |
-
$
|
|
|
|
|
51 |
return new ShortPixelMeta(array(
|
52 |
"id" => $ID,
|
53 |
"name" => ShortPixelAPI::MB_basename($path),
|
@@ -103,6 +108,9 @@ class ShortPixelMetaFacade {
|
|
103 |
|
104 |
// Update MetaData of Image.
|
105 |
public function updateMeta($newMeta = null, $replaceThumbs = false) {
|
|
|
|
|
|
|
106 |
if($newMeta) {
|
107 |
$this->meta = $newMeta;
|
108 |
}
|
@@ -222,6 +230,8 @@ class ShortPixelMetaFacade {
|
|
222 |
* This function only hits with images that were optimized, pending or have an error state.
|
223 |
*/
|
224 |
public function cleanupMeta($fakeOptPending = false) {
|
|
|
|
|
225 |
if($this->type == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
|
226 |
if(!isset($this->rawMeta)) {
|
227 |
$rawMeta = $this->sanitizeMeta(wp_get_attachment_metadata($this->getId()));
|
@@ -250,9 +260,108 @@ class ShortPixelMetaFacade {
|
|
250 |
}
|
251 |
}
|
252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
// remove SPFoudnMeta from image. Dirty. @todo <--
|
254 |
public function removeSPFoundMeta()
|
255 |
{
|
|
|
256 |
if($this->type == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
|
257 |
if(!isset($this->rawMeta)) {
|
258 |
$rawMeta = $this->sanitizeMeta(wp_get_attachment_metadata($this->getId()));
|
@@ -266,16 +375,22 @@ class ShortPixelMetaFacade {
|
|
266 |
if (strpos($size, ShortPixelMeta::FOUND_THUMB_PREFIX) !== false)
|
267 |
{
|
268 |
unset($rawMeta['sizes'][$size]);
|
|
|
269 |
Log::addDebug('Unset sp-found- size' . $size);
|
270 |
}
|
271 |
}
|
272 |
}
|
273 |
$this->rawMeta = $rawMeta;
|
274 |
-
|
|
|
|
|
|
|
|
|
275 |
}
|
276 |
}
|
277 |
|
278 |
function deleteMeta() {
|
|
|
279 |
if($this->type == self::CUSTOM_TYPE) {
|
280 |
throw new Exception("Not implemented 1");
|
281 |
} else {
|
@@ -283,9 +398,11 @@ class ShortPixelMetaFacade {
|
|
283 |
update_post_meta($this->ID, '_wp_attachment_metadata', $this->rawMeta);
|
284 |
//wp_update_attachment_metadata($this->ID, $this->rawMeta);
|
285 |
}
|
|
|
286 |
}
|
287 |
|
288 |
function deleteAllSPMeta() {
|
|
|
289 |
if($this->type == self::CUSTOM_TYPE) {
|
290 |
throw new Exception("Not implemented 1");
|
291 |
} else {
|
@@ -375,14 +492,21 @@ class ShortPixelMetaFacade {
|
|
375 |
* @param $id
|
376 |
* @return false|string
|
377 |
* @throws Exception
|
|
|
378 |
*/
|
379 |
public static function safeGetAttachmentUrl($id) {
|
380 |
$attURL = wp_get_attachment_url($id);
|
381 |
-
Log::addDebug('Attachment URL - safeGotten - ' . $attURL);
|
382 |
if(!$attURL || !strlen($attURL)) {
|
383 |
throw new Exception("Post metadata is corrupt (No attachment URL for $id)", ShortPixelAPI::ERR_POSTMETA_CORRUPT);
|
384 |
}
|
385 |
if ( !parse_url($attURL, PHP_URL_SCHEME) ) {//no absolute URLs used -> we implement a hack
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
386 |
return self::getHomeUrl() . ltrim($attURL,'/');//get the file URL
|
387 |
}
|
388 |
else {
|
@@ -390,22 +514,63 @@ class ShortPixelMetaFacade {
|
|
390 |
}
|
391 |
}
|
392 |
|
393 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
394 |
$sizesMissing = array();
|
395 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
|
397 |
if($this->type == self::CUSTOM_TYPE) {
|
398 |
$meta = $this->getMeta();
|
399 |
|
|
|
|
|
|
|
|
|
400 |
//fix for situations where site_url is lala.com/en and home_url is lala.com - if using the site_url will get a duplicated /en in the URL
|
401 |
-
|
402 |
-
|
403 |
|
404 |
$filePaths[] = $meta->getPath();
|
405 |
} else {
|
406 |
-
|
407 |
-
$
|
408 |
-
$
|
|
|
|
|
|
|
|
|
|
|
409 |
try
|
410 |
{
|
411 |
$predownload_url = $url = self::safeGetAttachmentUrl($this->ID); // This function *can* return an PHP error.
|
@@ -417,11 +582,12 @@ class ShortPixelMetaFacade {
|
|
417 |
return array("URLs" => array(), "PATHs" => array(), "sizesMissing" => array());
|
418 |
}
|
419 |
$urlList = array(); $filePaths = array();
|
420 |
-
|
421 |
-
|
|
|
422 |
|
423 |
if(!$mainExists) {
|
424 |
-
list($url, $path) = $this->attemptRemoteDownload($url, $
|
425 |
$downloadFile = $fs->getFile($path);
|
426 |
if ($downloadFile->exists()) // check for success.
|
427 |
{
|
@@ -432,13 +598,38 @@ class ShortPixelMetaFacade {
|
|
432 |
|
433 |
if($mainExists) {
|
434 |
$urlList[] = $url;
|
435 |
-
$filePaths[] = $
|
436 |
if($addRetina) {
|
437 |
-
$this->addRetina($
|
438 |
}
|
439 |
}
|
440 |
|
441 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
|
443 |
$meta = $this->getMeta();
|
444 |
$sizes = $meta->getThumbs();
|
@@ -479,7 +670,7 @@ class ShortPixelMetaFacade {
|
|
479 |
if($count >= SHORTPIXEL_MAX_THUMBS) break;
|
480 |
$count++;
|
481 |
|
482 |
-
$origPath = $tPath = str_replace(ShortPixelAPI::MB_basename($
|
483 |
$origFile = $fs->getFile($origPath);
|
484 |
|
485 |
if ($origFile->getExtension() == 'webp') // never include any webp extension.
|
@@ -488,6 +679,8 @@ class ShortPixelMetaFacade {
|
|
488 |
$file_exists = apply_filters('shortpixel_image_exists', file_exists($origPath), $origPath, $this->ID);
|
489 |
$tUrl = str_replace(ShortPixelAPI::MB_basename($predownload_url), $thumbnailInfo['file'], $predownload_url);
|
490 |
|
|
|
|
|
491 |
// Working on low-key replacement for path handling via FileSystemController.
|
492 |
// This specific fix is related to the possibility of URLs' in metadata
|
493 |
if ( !$file_exists && !file_exists($tPath) )
|
@@ -519,6 +712,11 @@ class ShortPixelMetaFacade {
|
|
519 |
//try and download the image from the URL (images present only on CDN)
|
520 |
// Log::addDebug('URLs and Paths - File didnt exists, trying to download', array($tUrl, $origPath));
|
521 |
// $tempThumb = download_url($tUrl, $downloadTimeout);
|
|
|
|
|
|
|
|
|
|
|
522 |
|
523 |
list($tUrl, $tPath) = $this->attemptRemoteDownload($tUrl, $tPath, $this->ID);
|
524 |
|
@@ -553,11 +751,22 @@ class ShortPixelMetaFacade {
|
|
553 |
//convert the + which are replaced with spaces by wp_remote_post
|
554 |
array_walk($urlList, array( &$this, 'replacePlusChar') );
|
555 |
|
556 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
557 |
return array("URLs" => $urlList, "PATHs" => $filePaths, "sizesMissing" => $sizesMissing);
|
558 |
}
|
559 |
|
560 |
-
|
|
|
|
|
|
|
561 |
{
|
562 |
$downloadTimeout = max(SHORTPIXEL_MAX_EXECUTION_TIME - 10, 15);
|
563 |
$fs = new \ShortPixel\FileSystemController();
|
@@ -631,14 +840,15 @@ class ShortPixelMetaFacade {
|
|
631 |
return (substr($baseName, -3) === '@2x');
|
632 |
}
|
633 |
|
634 |
-
// @todo
|
635 |
public static function getWPMLDuplicates( $id ) {
|
636 |
global $wpdb;
|
|
|
637 |
|
638 |
$parentId = get_post_meta ($id, '_icl_lang_duplicate_of', true );
|
639 |
if($parentId) $id = $parentId;
|
640 |
|
641 |
-
$mainFile =
|
642 |
|
643 |
$duplicates = $wpdb->get_col( $wpdb->prepare( "
|
644 |
SELECT pm.post_id FROM {$wpdb->postmeta} pm
|
@@ -649,7 +859,7 @@ class ShortPixelMetaFacade {
|
|
649 |
$moreDuplicates = $wpdb->get_results( $wpdb->prepare( "
|
650 |
SELECT p.ID, p.guid FROM {$wpdb->posts} p
|
651 |
INNER JOIN {$wpdb->posts} pbase ON p.guid = pbase.guid
|
652 |
-
WHERE pbase.ID = %s
|
653 |
", $id ) );
|
654 |
//MySQL is doing a CASE INSENSITIVE join on p.guid!! so double check the results.
|
655 |
$guid = false;
|
@@ -674,7 +884,8 @@ class ShortPixelMetaFacade {
|
|
674 |
if(count($transGroupId)) {
|
675 |
$transGroup = $wpdb->get_results("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE trid = " . $transGroupId[0]->trid);
|
676 |
foreach($transGroup as $trans) {
|
677 |
-
|
|
|
678 |
$duplicates[] = $trans->element_id;
|
679 |
}
|
680 |
}
|
1 |
<?php
|
2 |
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
3 |
+
use ShortPixel\ImageModel as ImageModel;
|
4 |
+
use ShortPixel\FileSystemController as FileSystem;
|
5 |
+
use ShortPixel\CacheController as Cache;
|
6 |
|
7 |
class ShortPixelMetaFacade {
|
8 |
const MEDIA_LIBRARY_TYPE = 1;
|
50 |
}
|
51 |
|
52 |
private static function rawMetaToMeta($ID, $rawMeta) {
|
53 |
+
$file = \wpSPIO()->filesystem()->getAttachedFile($ID);
|
54 |
+
$path = $file->getFullPath();
|
55 |
+
|
56 |
return new ShortPixelMeta(array(
|
57 |
"id" => $ID,
|
58 |
"name" => ShortPixelAPI::MB_basename($path),
|
108 |
|
109 |
// Update MetaData of Image.
|
110 |
public function updateMeta($newMeta = null, $replaceThumbs = false) {
|
111 |
+
|
112 |
+
$this->deleteItemCache();
|
113 |
+
|
114 |
if($newMeta) {
|
115 |
$this->meta = $newMeta;
|
116 |
}
|
230 |
* This function only hits with images that were optimized, pending or have an error state.
|
231 |
*/
|
232 |
public function cleanupMeta($fakeOptPending = false) {
|
233 |
+
$this->deleteItemCache(); // remove any caching.
|
234 |
+
|
235 |
if($this->type == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
|
236 |
if(!isset($this->rawMeta)) {
|
237 |
$rawMeta = $this->sanitizeMeta(wp_get_attachment_metadata($this->getId()));
|
260 |
}
|
261 |
}
|
262 |
|
263 |
+
/** Checks if there are unlisted files present in system. Save them into sizes
|
264 |
+
* @return int Number 'Unlisted' Items in metadta.
|
265 |
+
*/
|
266 |
+
public function searchUnlistedFiles()
|
267 |
+
{
|
268 |
+
// must be media library, setting must be on.
|
269 |
+
$settings = \wpSPIO()->settings();
|
270 |
+
|
271 |
+
if($this->getType() != ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE
|
272 |
+
|| ! $settings->optimizeUnlisted) {
|
273 |
+
return 0;
|
274 |
+
}
|
275 |
+
|
276 |
+
//exit($this->_settings->optimizeUnlisted);
|
277 |
+
|
278 |
+
$meta = $this->getMeta();
|
279 |
+
Log::addDebug('Finding Thumbs on path' . $meta->getPath());
|
280 |
+
$thumbs = WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
|
281 |
+
|
282 |
+
$fs = new \ShortPixel\FileSystemController();
|
283 |
+
$mainFile = $fs->getFile($meta->getPath());
|
284 |
+
|
285 |
+
// Find Thumbs returns *full file path*
|
286 |
+
$foundThumbs = WpShortPixelMediaLbraryAdapter::findThumbs($mainFile->getFullPath());
|
287 |
+
|
288 |
+
// no thumbs, then done.
|
289 |
+
if (count($foundThumbs) == 0)
|
290 |
+
return 0;
|
291 |
+
|
292 |
+
//first identify which thumbs are not in the sizes
|
293 |
+
$sizes = $meta->getThumbs();
|
294 |
+
$mimeType = false;
|
295 |
+
|
296 |
+
$allSizes = array();
|
297 |
+
$basepath = $mainFile->getFileDir()->getPath();
|
298 |
+
|
299 |
+
foreach($sizes as $size) {
|
300 |
+
// Thumbs should have filename only. This is shortpixel-meta ! Not metadata!
|
301 |
+
// Provided filename can be unexpected (URL, fullpath), so first do check, get filename, then check the full path
|
302 |
+
$sizeFileCheck = $fs->getFile($size['file']);
|
303 |
+
$sizeFilePath = $basepath . $sizeFileCheck->getFileName();
|
304 |
+
$sizeFile = $fs->getFile($sizeFilePath);
|
305 |
+
|
306 |
+
//get the mime-type from one of the thumbs metas
|
307 |
+
if(isset($size['mime-type'])) { //situation from support case #9351 Ramesh Mehay
|
308 |
+
$mimeType = $size['mime-type'];
|
309 |
+
}
|
310 |
+
$allSizes[] = $sizeFile;
|
311 |
+
}
|
312 |
+
|
313 |
+
foreach($foundThumbs as $id => $found) {
|
314 |
+
$foundFile = $fs->getFile($found);
|
315 |
+
|
316 |
+
foreach($allSizes as $sizeFile) {
|
317 |
+
if ($sizeFile->getExtension() !== $foundFile->getExtension())
|
318 |
+
{
|
319 |
+
$foundThumbs[$id] = false;
|
320 |
+
}
|
321 |
+
elseif ($sizeFile->getFileName() === $foundFile->getFileName())
|
322 |
+
{
|
323 |
+
$foundThumbs[$id] = false;
|
324 |
+
}
|
325 |
+
}
|
326 |
+
}
|
327 |
+
// add the unfound ones to the sizes array
|
328 |
+
$ind = 1;
|
329 |
+
$counter = 0;
|
330 |
+
// Assumption:: there is no point in adding to this array since findThumbs should find *all* thumbs that are relevant to this image.
|
331 |
+
/*while (isset($sizes[ShortPixelMeta::FOUND_THUMB_PREFIX . str_pad("".$start, 2, '0', STR_PAD_LEFT)]))
|
332 |
+
{
|
333 |
+
$start++;
|
334 |
+
} */
|
335 |
+
// $start = $ind;
|
336 |
+
|
337 |
+
foreach($foundThumbs as $found) {
|
338 |
+
if($found !== false) {
|
339 |
+
Log::addDebug('Adding File to sizes -> ' . $found);
|
340 |
+
$size = getimagesize($found);
|
341 |
+
Log::addDebug('Add Unlisted, add size' . $found );
|
342 |
+
|
343 |
+
$sizes[ShortPixelMeta::FOUND_THUMB_PREFIX . str_pad("".$ind, 2, '0', STR_PAD_LEFT)]= array( // it's a file that has no corresponding thumb so it's the WEBP for the main file
|
344 |
+
'file' => ShortPixelAPI::MB_basename($found),
|
345 |
+
'width' => $size[0],
|
346 |
+
'height' => $size[1],
|
347 |
+
'mime-type' => $mimeType
|
348 |
+
);
|
349 |
+
$ind++;
|
350 |
+
$counter++;
|
351 |
+
}
|
352 |
+
}
|
353 |
+
if($ind > 1) { // at least one thumbnail added, update
|
354 |
+
$meta->setThumbs($sizes);
|
355 |
+
$this->updateMeta($meta);
|
356 |
+
}
|
357 |
+
|
358 |
+
return $counter;
|
359 |
+
}
|
360 |
+
|
361 |
// remove SPFoudnMeta from image. Dirty. @todo <--
|
362 |
public function removeSPFoundMeta()
|
363 |
{
|
364 |
+
$unset = false; // something was removed?
|
365 |
if($this->type == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) {
|
366 |
if(!isset($this->rawMeta)) {
|
367 |
$rawMeta = $this->sanitizeMeta(wp_get_attachment_metadata($this->getId()));
|
375 |
if (strpos($size, ShortPixelMeta::FOUND_THUMB_PREFIX) !== false)
|
376 |
{
|
377 |
unset($rawMeta['sizes'][$size]);
|
378 |
+
$unset = true;
|
379 |
Log::addDebug('Unset sp-found- size' . $size);
|
380 |
}
|
381 |
}
|
382 |
}
|
383 |
$this->rawMeta = $rawMeta;
|
384 |
+
if ($unset) // only update on changes.
|
385 |
+
{
|
386 |
+
$this->deleteItemCache();
|
387 |
+
update_post_meta($this->ID, '_wp_attachment_metadata', $rawMeta);
|
388 |
+
}
|
389 |
}
|
390 |
}
|
391 |
|
392 |
function deleteMeta() {
|
393 |
+
$this->deleteItemCache();
|
394 |
if($this->type == self::CUSTOM_TYPE) {
|
395 |
throw new Exception("Not implemented 1");
|
396 |
} else {
|
398 |
update_post_meta($this->ID, '_wp_attachment_metadata', $this->rawMeta);
|
399 |
//wp_update_attachment_metadata($this->ID, $this->rawMeta);
|
400 |
}
|
401 |
+
|
402 |
}
|
403 |
|
404 |
function deleteAllSPMeta() {
|
405 |
+
$this->deleteItemCache();
|
406 |
if($this->type == self::CUSTOM_TYPE) {
|
407 |
throw new Exception("Not implemented 1");
|
408 |
} else {
|
492 |
* @param $id
|
493 |
* @return false|string
|
494 |
* @throws Exception
|
495 |
+
* @todo hack the hack to a solid solution.
|
496 |
*/
|
497 |
public static function safeGetAttachmentUrl($id) {
|
498 |
$attURL = wp_get_attachment_url($id);
|
|
|
499 |
if(!$attURL || !strlen($attURL)) {
|
500 |
throw new Exception("Post metadata is corrupt (No attachment URL for $id)", ShortPixelAPI::ERR_POSTMETA_CORRUPT);
|
501 |
}
|
502 |
if ( !parse_url($attURL, PHP_URL_SCHEME) ) {//no absolute URLs used -> we implement a hack
|
503 |
+
|
504 |
+
if (! is_null($attURL, PHP_URL_HOST)) // This is for URL's for // without http or https. hackhack.
|
505 |
+
{
|
506 |
+
$scheme = is_ssl() ? 'https:' : 'http:';
|
507 |
+
return $scheme. $attURL;
|
508 |
+
|
509 |
+
}
|
510 |
return self::getHomeUrl() . ltrim($attURL,'/');//get the file URL
|
511 |
}
|
512 |
else {
|
514 |
}
|
515 |
}
|
516 |
|
517 |
+
/** Get the name for cached items, for now just the URLPATH stuff
|
518 |
+
*/
|
519 |
+
protected function getCacheName()
|
520 |
+
{
|
521 |
+
return trim('META_URLPATH_' . $this->getQueuedId());
|
522 |
+
}
|
523 |
+
|
524 |
+
public function deleteItemCache()
|
525 |
+
{
|
526 |
+
// in any update, clear the caching
|
527 |
+
$cacheController = new Cache();
|
528 |
+
Log::adDDebug('Removing Item Cache -> ' . $this->getCacheName() );
|
529 |
+
$cacheController->deleteItem( $this->getCacheName());
|
530 |
+
|
531 |
+
}
|
532 |
+
|
533 |
+
/* Function that gathers URLs' and PATHs of attachment. When local file does not exist ( offloading, CDN, etc ), try to download it.
|
534 |
+
* This function caches it's result! use deleteItemCache
|
535 |
+
*
|
536 |
+
* @param $no_exist_check Don't check if returned file exists. This prevents remote downloading it ( in use for onDeleteImage atm)
|
537 |
+
* @todo This function needs splitting into urls / paths and made to function more clear .
|
538 |
+
*/
|
539 |
+
public function getURLsAndPATHs($processThumbnails, $onlyThumbs = false, $addRetina = true, $excludeSizes = array(), $includeOptimized = false, $no_exist_check = false) {
|
540 |
$sizesMissing = array();
|
541 |
+
$cacheController = new Cache();
|
542 |
+
|
543 |
+
$cacheItem = $cacheController->getItem( $this->getCacheName() );
|
544 |
+
if ($cacheItem->exists())
|
545 |
+
{
|
546 |
+
Log::addDebug('Get Urls / Paths hit cache -> ', $this->getCacheName());
|
547 |
+
return $cacheItem->getValue();
|
548 |
+
}
|
549 |
+
|
550 |
+
$fs = new FileSystem();
|
551 |
+
\wpSPIO()->loadModel('image');
|
552 |
|
553 |
if($this->type == self::CUSTOM_TYPE) {
|
554 |
$meta = $this->getMeta();
|
555 |
|
556 |
+
$path = $meta->getPath();
|
557 |
+
$fsFile = $fs->getFile($path);
|
558 |
+
$url = $fs->pathToUrl($fsFile);
|
559 |
+
|
560 |
//fix for situations where site_url is lala.com/en and home_url is lala.com - if using the site_url will get a duplicated /en in the URL
|
561 |
+
// $homeUrl = self::getHomeUrl();
|
562 |
+
$urlList[] = $url; // self::replaceHomePath($meta->getPath(), $homeUrl);
|
563 |
|
564 |
$filePaths[] = $meta->getPath();
|
565 |
} else {
|
566 |
+
|
567 |
+
$imageObj = new \ShortPixel\ImageModel();
|
568 |
+
$imageObj->setbyPostID($this->ID);
|
569 |
+
|
570 |
+
$fsFile = $imageObj->getFile(); //\wpSPIO()->filesystem()->getAttachedFile($this->ID);//get the full file PATH
|
571 |
+
|
572 |
+
//$fsFile = $fs->getFile($path);
|
573 |
+
$mainExists = apply_filters('shortpixel_image_exists', $fsFile->exists(), $fsFile->getFullPath(), $this->ID);
|
574 |
try
|
575 |
{
|
576 |
$predownload_url = $url = self::safeGetAttachmentUrl($this->ID); // This function *can* return an PHP error.
|
582 |
return array("URLs" => array(), "PATHs" => array(), "sizesMissing" => array());
|
583 |
}
|
584 |
$urlList = array(); $filePaths = array();
|
585 |
+
Log::addDebug('attached file path: ' . (string) $fsFile, array( (string) $fsFile->getFileDir() ) );
|
586 |
+
if ($no_exist_check)
|
587 |
+
$mainExists = true;
|
588 |
|
589 |
if(!$mainExists) {
|
590 |
+
list($url, $path) = $this->attemptRemoteDownload($url, $fsFile->getFullPath(), $this->ID);
|
591 |
$downloadFile = $fs->getFile($path);
|
592 |
if ($downloadFile->exists()) // check for success.
|
593 |
{
|
598 |
|
599 |
if($mainExists) {
|
600 |
$urlList[] = $url;
|
601 |
+
$filePaths[] = $fsFile->getFullPath();
|
602 |
if($addRetina) {
|
603 |
+
$this->addRetina($fsFile->getFullPath(), $url, $filePaths, $urlList);
|
604 |
}
|
605 |
}
|
606 |
|
607 |
+
// new WP 5.3 function, check if file has original ( was scaled )
|
608 |
+
$origFile = $imageObj->has_original();
|
609 |
+
Log::addDebug('Get Paths and such, original', $origFile);
|
610 |
+
if (is_object($origFile))
|
611 |
+
{
|
612 |
+
//$origFile = $imageObj->getOriginalFile();
|
613 |
+
$origurl = wp_get_original_image_url($this->ID); //$fs->pathToUrl($origFile);
|
614 |
+
if (! $origFile->exists() && ! $no_exist_check )
|
615 |
+
{
|
616 |
+
list($origurl, $path) = $this->attemptRemoteDownload($origurl, $origFile->getFullPath(), $this->ID);
|
617 |
+
$downloadFile = $fs->getFile($path);
|
618 |
+
if ($downloadFile->exists())
|
619 |
+
{
|
620 |
+
$urlList[] = $origurl;
|
621 |
+
$filePaths[] = $downloadFile->getFullPath();
|
622 |
+
}
|
623 |
+
}
|
624 |
+
else
|
625 |
+
{
|
626 |
+
$urlList[] = $origurl;
|
627 |
+
$filePaths[] = $origFile->getFullPath();
|
628 |
+
}
|
629 |
+
|
630 |
+
}
|
631 |
+
|
632 |
+
Log::addDebug('Main file turnout - ', array($url, (string) $fsFile));
|
633 |
|
634 |
$meta = $this->getMeta();
|
635 |
$sizes = $meta->getThumbs();
|
670 |
if($count >= SHORTPIXEL_MAX_THUMBS) break;
|
671 |
$count++;
|
672 |
|
673 |
+
$origPath = $tPath = str_replace(ShortPixelAPI::MB_basename($fsFile->getFullPath() ), $thumbnailInfo['file'], $fsFile->getFullPath());
|
674 |
$origFile = $fs->getFile($origPath);
|
675 |
|
676 |
if ($origFile->getExtension() == 'webp') // never include any webp extension.
|
679 |
$file_exists = apply_filters('shortpixel_image_exists', file_exists($origPath), $origPath, $this->ID);
|
680 |
$tUrl = str_replace(ShortPixelAPI::MB_basename($predownload_url), $thumbnailInfo['file'], $predownload_url);
|
681 |
|
682 |
+
if ($no_exist_check)
|
683 |
+
$file_exists = true;
|
684 |
// Working on low-key replacement for path handling via FileSystemController.
|
685 |
// This specific fix is related to the possibility of URLs' in metadata
|
686 |
if ( !$file_exists && !file_exists($tPath) )
|
712 |
//try and download the image from the URL (images present only on CDN)
|
713 |
// Log::addDebug('URLs and Paths - File didnt exists, trying to download', array($tUrl, $origPath));
|
714 |
// $tempThumb = download_url($tUrl, $downloadTimeout);
|
715 |
+
$args_for_get = array(
|
716 |
+
'stream' => true,
|
717 |
+
'filename' => $origFile->getFullPath(),
|
718 |
+
'timeout' => max(SHORTPIXEL_MAX_EXECUTION_TIME - 10, 15),
|
719 |
+
);
|
720 |
|
721 |
list($tUrl, $tPath) = $this->attemptRemoteDownload($tUrl, $tPath, $this->ID);
|
722 |
|
751 |
//convert the + which are replaced with spaces by wp_remote_post
|
752 |
array_walk($urlList, array( &$this, 'replacePlusChar') );
|
753 |
|
754 |
+
if (! $no_exist_check)
|
755 |
+
$filePaths = ShortPixelAPI::CheckAndFixImagePaths($filePaths);//check for images to make sure they exist on disk
|
756 |
+
|
757 |
+
$result = array("URLs" => $urlList, "PATHs" => $filePaths, "sizesMissing" => $sizesMissing);
|
758 |
+
|
759 |
+
$cacheItem->setValue($result);
|
760 |
+
$cacheItem->setExpires(5 * MINUTE_IN_SECONDS);
|
761 |
+
$cacheController->storeItemObject($cacheItem);
|
762 |
+
|
763 |
return array("URLs" => $urlList, "PATHs" => $filePaths, "sizesMissing" => $sizesMissing);
|
764 |
}
|
765 |
|
766 |
+
/** @todo Separate download try and post / attach_id functions .
|
767 |
+
* Also used by S3-Offload
|
768 |
+
*/
|
769 |
+
public function attemptRemoteDownload($url, $path, $attach_id)
|
770 |
{
|
771 |
$downloadTimeout = max(SHORTPIXEL_MAX_EXECUTION_TIME - 10, 15);
|
772 |
$fs = new \ShortPixel\FileSystemController();
|
840 |
return (substr($baseName, -3) === '@2x');
|
841 |
}
|
842 |
|
843 |
+
// @todo Function gets duplicated images over WPML. Same image, different language so doesn't need duplication.
|
844 |
public static function getWPMLDuplicates( $id ) {
|
845 |
global $wpdb;
|
846 |
+
$fs = \wpSPIO()->filesystem();
|
847 |
|
848 |
$parentId = get_post_meta ($id, '_icl_lang_duplicate_of', true );
|
849 |
if($parentId) $id = $parentId;
|
850 |
|
851 |
+
$mainFile = $fs->getAttachedFile($id);
|
852 |
|
853 |
$duplicates = $wpdb->get_col( $wpdb->prepare( "
|
854 |
SELECT pm.post_id FROM {$wpdb->postmeta} pm
|
859 |
$moreDuplicates = $wpdb->get_results( $wpdb->prepare( "
|
860 |
SELECT p.ID, p.guid FROM {$wpdb->posts} p
|
861 |
INNER JOIN {$wpdb->posts} pbase ON p.guid = pbase.guid
|
862 |
+
WHERE pbase.ID = %s and p.guid != ''
|
863 |
", $id ) );
|
864 |
//MySQL is doing a CASE INSENSITIVE join on p.guid!! so double check the results.
|
865 |
$guid = false;
|
884 |
if(count($transGroupId)) {
|
885 |
$transGroup = $wpdb->get_results("SELECT element_id FROM {$wpdb->prefix}icl_translations WHERE trid = " . $transGroupId[0]->trid);
|
886 |
foreach($transGroup as $trans) {
|
887 |
+
$transFile = $fs->getFile($trans->element_id);
|
888 |
+
if($mainFile->getFullPath() == $transFile->getFullPath() ){
|
889 |
$duplicates[] = $trans->element_id;
|
890 |
}
|
891 |
}
|
@@ -1,10 +1,17 @@
|
|
1 |
<?php
|
|
|
|
|
2 |
|
3 |
class WpShortPixelDb implements ShortPixelDb {
|
4 |
|
5 |
protected $prefix;
|
6 |
protected $defaultShowErrors;
|
7 |
|
|
|
|
|
|
|
|
|
|
|
8 |
public function __construct($prefix = null) {
|
9 |
$this->prefix = $prefix;
|
10 |
}
|
@@ -62,7 +69,11 @@ class WpShortPixelDb implements ShortPixelDb {
|
|
62 |
|
63 |
public function insert($table, $params, $format = null) {
|
64 |
global $wpdb;
|
65 |
-
|
|
|
|
|
|
|
|
|
66 |
return $wpdb->insert_id;
|
67 |
}
|
68 |
|
@@ -79,6 +90,20 @@ class WpShortPixelDb implements ShortPixelDb {
|
|
79 |
return $wpdb->prepare($query, $args);
|
80 |
}
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
public function hideErrors() {
|
83 |
global $wpdb;
|
84 |
$this->defaultShowErrors = $wpdb->show_errors;
|
1 |
<?php
|
2 |
+
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
3 |
+
use ShortPixel\Notices\NoticeController as Notice;
|
4 |
|
5 |
class WpShortPixelDb implements ShortPixelDb {
|
6 |
|
7 |
protected $prefix;
|
8 |
protected $defaultShowErrors;
|
9 |
|
10 |
+
// mostly unimplemented.
|
11 |
+
const QTYPE_INSERT = 1;
|
12 |
+
const QTYPE_DELETE = 2;
|
13 |
+
const QTYPE_UPDATE = 3;
|
14 |
+
|
15 |
public function __construct($prefix = null) {
|
16 |
$this->prefix = $prefix;
|
17 |
}
|
69 |
|
70 |
public function insert($table, $params, $format = null) {
|
71 |
global $wpdb;
|
72 |
+
|
73 |
+
$num_inserted = $wpdb->insert($table, $params, $format);
|
74 |
+
if ($num_inserted === false)
|
75 |
+
$this->handleError(self::QTYPE_INSERT);
|
76 |
+
|
77 |
return $wpdb->insert_id;
|
78 |
}
|
79 |
|
90 |
return $wpdb->prepare($query, $args);
|
91 |
}
|
92 |
|
93 |
+
public function handleError($error_type)
|
94 |
+
{
|
95 |
+
Log::addError('WP Database error: ' . $wpdb->last_error);
|
96 |
+
|
97 |
+
global $wpdb;
|
98 |
+
switch($error_type)
|
99 |
+
{
|
100 |
+
case self::QTYPE_INSERT:
|
101 |
+
Notice::addError('Shortpixel tried to run a database query, but it failed. See the logs for details', 'shortpixel-image-optimiser');
|
102 |
+
break;
|
103 |
+
}
|
104 |
+
|
105 |
+
}
|
106 |
+
|
107 |
public function hideErrors() {
|
108 |
global $wpdb;
|
109 |
$this->defaultShowErrors = $wpdb->show_errors;
|
@@ -3,6 +3,8 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
|
|
3 |
|
4 |
class WpShortPixelMediaLbraryAdapter {
|
5 |
|
|
|
|
|
6 |
// Testing is this is better / faster than previous function.
|
7 |
public static function countAllProcessable($settings, $maxId = PHP_INT_MAX, $minId = 0)
|
8 |
{
|
@@ -20,6 +22,7 @@ class WpShortPixelMediaLbraryAdapter {
|
|
20 |
|
21 |
$foundUnlistedThumbs = false;
|
22 |
$counter = 0;
|
|
|
23 |
|
24 |
$filesWithErrors = array(); $moreFilesWithErrors = 0;
|
25 |
$excludePatterns = WPShortPixelSettings::getOpt("excludePatterns");
|
@@ -51,9 +54,7 @@ class WpShortPixelMediaLbraryAdapter {
|
|
51 |
continue;
|
52 |
}
|
53 |
|
54 |
-
$filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta
|
55 |
-
WHERE post_id IN (" . implode(',', $idInfo->ids) . ")
|
56 |
-
AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )");
|
57 |
/* $filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta
|
58 |
WHERE post_id >= $minId and post_id <= $maxId
|
59 |
AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )"); */
|
@@ -85,10 +86,15 @@ class WpShortPixelMediaLbraryAdapter {
|
|
85 |
elseif ( $file->meta_key == "_wp_attachment_metadata" ) //_wp_attachment_metadata
|
86 |
{
|
87 |
$attachment = maybe_unserialize($file->meta_value);
|
|
|
|
|
|
|
|
|
88 |
$sizesCount = isset($attachment['sizes']) ? self::countSizesNotExcluded($attachment['sizes'], $settings->excludeSizes) : 0;
|
89 |
|
90 |
// LA FIECARE 100 de imagini facem un test si daca findThumbs da diferit, sa dam o avertizare si eventual optiune
|
91 |
$dismissed = $settings->dismissedNotices ? $settings->dismissedNotices : array();
|
|
|
92 |
if( $foundUnlistedThumbs === false && $maxId == PHP_INT_MAX && !isset($dismissed['unlisted'])
|
93 |
&& ( in_array($counter, array(2,4,6,8)) || floor($counter/100) == 0 && $counter%10 == 0
|
94 |
|| floor($counter/1000) == 0 && $counter%100 == 0 || floor($counter/10000) == 0 && $counter%1000 == 0))
|
@@ -98,8 +104,12 @@ class WpShortPixelMediaLbraryAdapter {
|
|
98 |
( !isset($attachment['ShortPixelImprovement']) || $attachment['ShortPixelImprovement'] === 0
|
99 |
|| $attachment['ShortPixelImprovement'] === 0.0 || $attachment['ShortPixelImprovement'] === "0"))
|
100 |
{
|
101 |
-
|
|
|
|
|
102 |
|
|
|
|
|
103 |
$foundCount = count($foundThumbs);
|
104 |
|
105 |
if(count($foundThumbs) > $sizesCount) {
|
@@ -117,6 +127,8 @@ class WpShortPixelMediaLbraryAdapter {
|
|
117 |
$realSizesCount = $sizesCount;
|
118 |
}
|
119 |
}
|
|
|
|
|
120 |
//processable
|
121 |
$isProcessable = false;
|
122 |
$isProcessed = isset($attachment['ShortPixelImprovement'])
|
@@ -219,10 +231,10 @@ class WpShortPixelMediaLbraryAdapter {
|
|
219 |
$totalFilesM4 += $totalFilesThis;
|
220 |
}
|
221 |
}
|
222 |
-
}
|
223 |
unset($filesList);
|
224 |
$pointer += $limit;
|
225 |
-
|
226 |
}//end while
|
227 |
|
228 |
return array("totalFiles" => $totalFiles, "mainFiles" => $mainFiles,
|
@@ -284,9 +296,8 @@ class WpShortPixelMediaLbraryAdapter {
|
|
284 |
continue;
|
285 |
}
|
286 |
|
287 |
-
$filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta
|
288 |
-
|
289 |
-
AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )");
|
290 |
/* $filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta
|
291 |
WHERE post_id >= $minId and post_id <= $maxId
|
292 |
AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )"); */
|
@@ -577,6 +588,9 @@ class WpShortPixelMediaLbraryAdapter {
|
|
577 |
global $wpdb;
|
578 |
//$time = microtime(true);
|
579 |
|
|
|
|
|
|
|
580 |
$sqlmeta = "SELECT DISTINCT post_id FROM " . $wpdb->prefix . "postmeta where (meta_key = %s or meta_key = %s) and post_id <= %d and post_id >= %d order by post_id DESC LIMIT %d";
|
581 |
$sqlmeta = $wpdb->prepare($sqlmeta, '_wp_attached_file', '_wp_attachment_metadata', $startId, $endId, $limit);
|
582 |
|
@@ -732,7 +746,7 @@ class WpShortPixelMediaLbraryAdapter {
|
|
732 |
if (! $thumbfile->exists()) // thing must exist.
|
733 |
continue;
|
734 |
|
735 |
-
$results[] = $thumbfile
|
736 |
}
|
737 |
|
738 |
/* Returns array with full path, as string */
|
@@ -741,24 +755,16 @@ class WpShortPixelMediaLbraryAdapter {
|
|
741 |
|
742 |
private static function getFilesByPattern($path, $pattern)
|
743 |
{
|
744 |
-
$fs =
|
745 |
-
|
746 |
-
try
|
747 |
-
{
|
748 |
-
$dirIterator = new \DirectoryIterator($path);
|
749 |
-
$regExIterator = new \RegexIterator($dirIterator, $pattern);
|
750 |
-
}
|
751 |
-
catch(\Exception $e)
|
752 |
-
{
|
753 |
-
Log::addWarn('GetFilesbyPattern issue with directory. ', $e->getMessage());
|
754 |
-
return array();
|
755 |
-
}
|
756 |
|
|
|
|
|
|
|
757 |
|
758 |
$images = array();
|
759 |
-
foreach($
|
760 |
{
|
761 |
-
$images[] = $fs->getFile($
|
762 |
}
|
763 |
|
764 |
return $images;
|
@@ -773,17 +779,20 @@ class WpShortPixelMediaLbraryAdapter {
|
|
773 |
} else {
|
774 |
$cnt = $wpdb->get_results("SELECT count(*) posts FROM " . $wpdb->prefix . $table);
|
775 |
}
|
776 |
-
|
777 |
$posts = isset($cnt) && count($cnt) > 0 ? $cnt[0]->posts : 0;
|
778 |
if($posts > 100000) {
|
779 |
-
|
780 |
} elseif ($posts > 50000) {
|
781 |
-
|
782 |
} elseif($posts > 10000) {
|
783 |
-
|
784 |
} else {
|
785 |
-
|
786 |
}
|
|
|
|
|
|
|
787 |
}
|
788 |
|
789 |
protected static function getPostIdsChunk($minId, $maxId, $pointer, $limit, $byMinMax = false) {
|
@@ -817,7 +826,28 @@ class WpShortPixelMediaLbraryAdapter {
|
|
817 |
}
|
818 |
}
|
819 |
|
820 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
821 |
}
|
822 |
|
823 |
/* Recount images from the media library when something went wrong badly */
|
3 |
|
4 |
class WpShortPixelMediaLbraryAdapter {
|
5 |
|
6 |
+
private static $urls_this_run = array();
|
7 |
+
|
8 |
// Testing is this is better / faster than previous function.
|
9 |
public static function countAllProcessable($settings, $maxId = PHP_INT_MAX, $minId = 0)
|
10 |
{
|
22 |
|
23 |
$foundUnlistedThumbs = false;
|
24 |
$counter = 0;
|
25 |
+
$fs = new \ShortPixel\FileSystemController();
|
26 |
|
27 |
$filesWithErrors = array(); $moreFilesWithErrors = 0;
|
28 |
$excludePatterns = WPShortPixelSettings::getOpt("excludePatterns");
|
54 |
continue;
|
55 |
}
|
56 |
|
57 |
+
$filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta WHERE post_id IN (" . implode(',', $idInfo->ids) . ") AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )");
|
|
|
|
|
58 |
/* $filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta
|
59 |
WHERE post_id >= $minId and post_id <= $maxId
|
60 |
AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )"); */
|
86 |
elseif ( $file->meta_key == "_wp_attachment_metadata" ) //_wp_attachment_metadata
|
87 |
{
|
88 |
$attachment = maybe_unserialize($file->meta_value);
|
89 |
+
/* Check if array. It's possible to find garbage like WP_Error objects or other random garble in meta_value, so be sure it's an ok thingie.
|
90 |
+
*/
|
91 |
+
if (! is_array($attachment))
|
92 |
+
continue;
|
93 |
$sizesCount = isset($attachment['sizes']) ? self::countSizesNotExcluded($attachment['sizes'], $settings->excludeSizes) : 0;
|
94 |
|
95 |
// LA FIECARE 100 de imagini facem un test si daca findThumbs da diferit, sa dam o avertizare si eventual optiune
|
96 |
$dismissed = $settings->dismissedNotices ? $settings->dismissedNotices : array();
|
97 |
+
// @ todo Figure out what this is intended to do.
|
98 |
if( $foundUnlistedThumbs === false && $maxId == PHP_INT_MAX && !isset($dismissed['unlisted'])
|
99 |
&& ( in_array($counter, array(2,4,6,8)) || floor($counter/100) == 0 && $counter%10 == 0
|
100 |
|| floor($counter/1000) == 0 && $counter%100 == 0 || floor($counter/10000) == 0 && $counter%1000 == 0))
|
104 |
( !isset($attachment['ShortPixelImprovement']) || $attachment['ShortPixelImprovement'] === 0
|
105 |
|| $attachment['ShortPixelImprovement'] === 0.0 || $attachment['ShortPixelImprovement'] === "0"))
|
106 |
{
|
107 |
+
// $foundThumbs = WpShortPixelMediaLbraryAdapter::findThumbs($filePath);
|
108 |
+
// findThumbs returns fullfilepath.
|
109 |
+
$foundThumbs = array();
|
110 |
|
111 |
+
if ($settings->optimizeUnlisted)
|
112 |
+
$foundThumbs = WpShortPixelMediaLbraryAdapter::findThumbs($fs->getFile($filePath));
|
113 |
$foundCount = count($foundThumbs);
|
114 |
|
115 |
if(count($foundThumbs) > $sizesCount) {
|
127 |
$realSizesCount = $sizesCount;
|
128 |
}
|
129 |
}
|
130 |
+
$counter++;
|
131 |
+
|
132 |
//processable
|
133 |
$isProcessable = false;
|
134 |
$isProcessed = isset($attachment['ShortPixelImprovement'])
|
231 |
$totalFilesM4 += $totalFilesThis;
|
232 |
}
|
233 |
}
|
234 |
+
} // foreach fileslist
|
235 |
unset($filesList);
|
236 |
$pointer += $limit;
|
237 |
+
// $counter++;
|
238 |
}//end while
|
239 |
|
240 |
return array("totalFiles" => $totalFiles, "mainFiles" => $mainFiles,
|
296 |
continue;
|
297 |
}
|
298 |
|
299 |
+
$filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta WHERE post_id IN (" . implode(',', $idInfo->ids) . ") AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )");
|
300 |
+
|
|
|
301 |
/* $filesList= $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM " . $wpdb->prefix . "postmeta
|
302 |
WHERE post_id >= $minId and post_id <= $maxId
|
303 |
AND ( meta_key = '_wp_attached_file' OR meta_key = '_wp_attachment_metadata' )"); */
|
588 |
global $wpdb;
|
589 |
//$time = microtime(true);
|
590 |
|
591 |
+
// Current idea for salvation::
|
592 |
+
//SELECT DISTINCT post_id, meta_value FROM wp_postmeta where (meta_key = '_wp_attached_file' or meta_key = '_wp_attachment_metadata') and post_id <= 68677 group by meta_value order by post_id DESC LIMIT 50
|
593 |
+
|
594 |
$sqlmeta = "SELECT DISTINCT post_id FROM " . $wpdb->prefix . "postmeta where (meta_key = %s or meta_key = %s) and post_id <= %d and post_id >= %d order by post_id DESC LIMIT %d";
|
595 |
$sqlmeta = $wpdb->prepare($sqlmeta, '_wp_attached_file', '_wp_attachment_metadata', $startId, $endId, $limit);
|
596 |
|
746 |
if (! $thumbfile->exists()) // thing must exist.
|
747 |
continue;
|
748 |
|
749 |
+
$results[] = (string) $thumbfile;
|
750 |
}
|
751 |
|
752 |
/* Returns array with full path, as string */
|
755 |
|
756 |
private static function getFilesByPattern($path, $pattern)
|
757 |
{
|
758 |
+
$fs = \wpSPIO()->filesystem();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
759 |
|
760 |
+
$path = trailingslashit($path);
|
761 |
+
$files = scandir($path, SCANDIR_SORT_NONE);
|
762 |
+
$files = preg_grep($pattern, $files);
|
763 |
|
764 |
$images = array();
|
765 |
+
foreach ($files as $filepath)
|
766 |
{
|
767 |
+
$images[] = $fs->getFile($path . $filepath);
|
768 |
}
|
769 |
|
770 |
return $images;
|
779 |
} else {
|
780 |
$cnt = $wpdb->get_results("SELECT count(*) posts FROM " . $wpdb->prefix . $table);
|
781 |
}
|
782 |
+
|
783 |
$posts = isset($cnt) && count($cnt) > 0 ? $cnt[0]->posts : 0;
|
784 |
if($posts > 100000) {
|
785 |
+
$chunk = 10000;
|
786 |
} elseif ($posts > 50000) {
|
787 |
+
$chunk = 5000;
|
788 |
} elseif($posts > 10000) {
|
789 |
+
$chunk = 2000;
|
790 |
} else {
|
791 |
+
$chunk = 500;
|
792 |
}
|
793 |
+
|
794 |
+
// allow a filter to fine-tune specific sql-engines
|
795 |
+
return apply_filters('shortpixel/db/chunk_size', $chunk);
|
796 |
}
|
797 |
|
798 |
protected static function getPostIdsChunk($minId, $maxId, $pointer, $limit, $byMinMax = false) {
|
826 |
}
|
827 |
}
|
828 |
|
829 |
+
$last_id = end($ids);
|
830 |
+
reset($ids); // just in case.
|
831 |
+
return (object)array('ids' => $ids, 'idDates' => $idDates, 'last_id' => $last_id );
|
832 |
+
}
|
833 |
+
|
834 |
+
/** It happens that URLS are multiple times offered in the same run (sendProcessing) to be processed.
|
835 |
+
* - WPML can have duplicate URL's
|
836 |
+
* - This function prevents sending a URL's twice in a --single run--
|
837 |
+
*/
|
838 |
+
public static function checkRequestLimiter($urls)
|
839 |
+
{
|
840 |
+
$hash = md5(serialize($urls));
|
841 |
+
Log::addDebug('New Hash -->' . $hash);
|
842 |
+
|
843 |
+
if (in_array($hash, self::$urls_this_run))
|
844 |
+
{
|
845 |
+
return false; // no!.
|
846 |
+
}
|
847 |
+
|
848 |
+
self::$urls_this_run[] = $hash;
|
849 |
+
Log::addDebug('Hash not found, adding', self::$urls_this_run);
|
850 |
+
return true; // ok, process.
|
851 |
}
|
852 |
|
853 |
/* Recount images from the media library when something went wrong badly */
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace ShortPixel;
|
3 |
+
|
4 |
+
// Gravity Forms integrations.
|
5 |
+
class gravityForms
|
6 |
+
{
|
7 |
+
|
8 |
+
public function __construct()
|
9 |
+
{
|
10 |
+
add_filter( 'gform_save_field_value', array($this,'shortPixelGravityForms'), 10, 5 );
|
11 |
+
}
|
12 |
+
|
13 |
+
function shortPixelGravityForms( $value, $lead, $field, $form ) {
|
14 |
+
if($field->type == 'post_image') {
|
15 |
+
$this->handleGravityFormsImageField($value);
|
16 |
+
}
|
17 |
+
return $value;
|
18 |
+
}
|
19 |
+
|
20 |
+
public function handleGravityFormsImageField($value) {
|
21 |
+
|
22 |
+
$shortPixelObj = wpSPIO()->getShortPixel();
|
23 |
+
|
24 |
+
if(!($folder = $shortpixelObj->getSpMetaDao()->getFolder(SHORTPIXEL_UPLOADS_BASE . '/gravity_forms'))) {
|
25 |
+
return;
|
26 |
+
}
|
27 |
+
if(strpos($value , '|:|')) {
|
28 |
+
$cleanup = explode('|:|', $value);
|
29 |
+
$value = $cleanup[0];
|
30 |
+
}
|
31 |
+
//ShortPixel is monitoring the gravity forms folder, add the image to queue
|
32 |
+
$uploadDir = wp_upload_dir();
|
33 |
+
$localPath = str_replace($uploadDir['baseurl'], SHORTPIXEL_UPLOADS_BASE, $value);
|
34 |
+
|
35 |
+
return $shortpixelObj->addPathToCustomFolder($localPath, $folder->getId(), 0);
|
36 |
+
}
|
37 |
+
|
38 |
+
} // class
|
39 |
+
|
40 |
+
$g = new gravityForms();
|
@@ -90,7 +90,7 @@ class HelpScout
|
|
90 |
<div id="shortpixel-hs-button-blind" class="shortpixel-hs-button-blind"></div>
|
91 |
<div id="shortpixel-hs-tools" class="shortpixel-hs-tools">
|
92 |
<a href="javascript:shortpixelToggleHS();" class="shortpixel-hs-tools-docs" title="<?php _e('Search through our online documentation.', 'shortpixel-image-optimiser'); ?>">
|
93 |
-
<img src="<?php echo(
|
94 |
</a>
|
95 |
</div>
|
96 |
<script>
|
90 |
<div id="shortpixel-hs-button-blind" class="shortpixel-hs-button-blind"></div>
|
91 |
<div id="shortpixel-hs-tools" class="shortpixel-hs-tools">
|
92 |
<a href="javascript:shortpixelToggleHS();" class="shortpixel-hs-tools-docs" title="<?php _e('Search through our online documentation.', 'shortpixel-image-optimiser'); ?>">
|
93 |
+
<img src="<?php echo( wpSPIO()->plugin_url('res/img/notes-sp.png') );?>" style="margin-bottom: 2px;width: 36px;">
|
94 |
</a>
|
95 |
</div>
|
96 |
<script>
|
@@ -4,24 +4,30 @@ use ShortPixel\Notices\NoticeController as Notice;
|
|
4 |
|
5 |
class NextGen
|
6 |
{
|
7 |
-
protected $
|
8 |
|
9 |
-
|
10 |
-
public function __construct($shortPixel)
|
11 |
{
|
12 |
-
$this
|
13 |
}
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
/** Enables nextGen, add galleries to custom folders
|
16 |
* @param boolean $silent Throw a notice or not. This seems to be based if nextgen was already activated previously or not.
|
17 |
*/
|
18 |
public function nextGenEnabled($silent)
|
19 |
{
|
20 |
\WpShortPixelDb::checkCustomTables(); // check if custom tables are created, if not, create them
|
21 |
-
|
22 |
$this->addNextGenGalleriesToCustom($silent);
|
23 |
-
|
24 |
-
// $customFolders = $ret["customFolders"];
|
25 |
}
|
26 |
|
27 |
/** Adds nextGen galleries to custom table
|
@@ -29,12 +35,13 @@ class NextGen
|
|
29 |
* Enabled checks are not an external class issue, so must be done before calling.
|
30 |
*/
|
31 |
public function addNextGenGalleriesToCustom($silent = true) {
|
32 |
-
|
|
|
33 |
$folderMsg = "";
|
34 |
|
35 |
//add the NextGen galleries to custom folders
|
36 |
$ngGalleries = \ShortPixelNextGenAdapter::getGalleries();
|
37 |
-
$meta = $
|
38 |
foreach($ngGalleries as $gallery) {
|
39 |
$msg = $meta->newFolderFromPath($gallery, get_home_path(), \WPShortPixel::getCustomFolderBase());
|
40 |
if($msg) { //try again with ABSPATH as maybe WP is in a subdir
|
@@ -47,16 +54,24 @@ class NextGen
|
|
47 |
if (count($ngGalleries) > 0)
|
48 |
{
|
49 |
// put timestamp to this setting.
|
50 |
-
$settings =
|
51 |
$settings->hasCustomFolders = time();
|
52 |
|
53 |
}
|
54 |
-
// $customFolders = $this->spMetaDao->getFolders();
|
55 |
if (! $silent)
|
56 |
{
|
57 |
Notice::addNormal($folderMsg);
|
58 |
}
|
59 |
|
60 |
-
// return array("message" => $silent? "" : $folderMsg, "customFolders" => $customFolders);
|
61 |
}
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
class NextGen
|
6 |
{
|
7 |
+
protected $instance;
|
8 |
|
9 |
+
public function __construct()
|
|
|
10 |
{
|
11 |
+
add_action('ngg_added_new_image', array($this,'new_image'));
|
12 |
}
|
13 |
|
14 |
+
|
15 |
+
public static function getInstance()
|
16 |
+
{
|
17 |
+
if (is_null(self::$instance))
|
18 |
+
self::$instance = new nextGen();
|
19 |
+
|
20 |
+
return self::$instance;
|
21 |
+
}
|
22 |
/** Enables nextGen, add galleries to custom folders
|
23 |
* @param boolean $silent Throw a notice or not. This seems to be based if nextgen was already activated previously or not.
|
24 |
*/
|
25 |
public function nextGenEnabled($silent)
|
26 |
{
|
27 |
\WpShortPixelDb::checkCustomTables(); // check if custom tables are created, if not, create them
|
28 |
+
|
29 |
$this->addNextGenGalleriesToCustom($silent);
|
30 |
+
|
|
|
31 |
}
|
32 |
|
33 |
/** Adds nextGen galleries to custom table
|
35 |
* Enabled checks are not an external class issue, so must be done before calling.
|
36 |
*/
|
37 |
public function addNextGenGalleriesToCustom($silent = true) {
|
38 |
+
$shortPixel = \wpSPIO()->getShortPixel();
|
39 |
+
|
40 |
$folderMsg = "";
|
41 |
|
42 |
//add the NextGen galleries to custom folders
|
43 |
$ngGalleries = \ShortPixelNextGenAdapter::getGalleries();
|
44 |
+
$meta = $shortPixel->getSpMetaDao();
|
45 |
foreach($ngGalleries as $gallery) {
|
46 |
$msg = $meta->newFolderFromPath($gallery, get_home_path(), \WPShortPixel::getCustomFolderBase());
|
47 |
if($msg) { //try again with ABSPATH as maybe WP is in a subdir
|
54 |
if (count($ngGalleries) > 0)
|
55 |
{
|
56 |
// put timestamp to this setting.
|
57 |
+
$settings = \wpSPIO()->settings();
|
58 |
$settings->hasCustomFolders = time();
|
59 |
|
60 |
}
|
|
|
61 |
if (! $silent)
|
62 |
{
|
63 |
Notice::addNormal($folderMsg);
|
64 |
}
|
65 |
|
|
|
66 |
}
|
67 |
+
|
68 |
+
/** @todo Move handling also to the integration */
|
69 |
+
public function add_image($image)
|
70 |
+
{
|
71 |
+
wpSPIO()->getShortPixel()->handleNextGenImageUpload($image);
|
72 |
+
}
|
73 |
+
} // class .
|
74 |
+
|
75 |
+
|
76 |
+
|
77 |
+
$ng = new nextGen();
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace ShortPixel;
|
3 |
+
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
if (defined("SHORTPIXEL_EXPERIMENTAL_SECURICACHE"))
|
6 |
+
{
|
7 |
+
$v = new securiVersion();
|
8 |
+
}
|
9 |
+
|
10 |
+
class securiVersion
|
11 |
+
{
|
12 |
+
public function __construct()
|
13 |
+
{
|
14 |
+
add_filter('shortpixel_image_urls', array($this, 'timestamp_cache'), 10, 2 );
|
15 |
+
}
|
16 |
+
|
17 |
+
public function timestamp_cache($urls, $id)
|
18 |
+
{
|
19 |
+
|
20 |
+
//$urls = add_filter('shortpixel_image_urls', );
|
21 |
+
// https://developer.wordpress.org/reference/functions/get_post_modified_time/
|
22 |
+
$time = get_post_modified_time('U', false, $id );
|
23 |
+
foreach($urls as $index => $url)
|
24 |
+
{
|
25 |
+
$urls[$index] = add_query_arg('ver', $time, $url);
|
26 |
+
}
|
27 |
+
|
28 |
+
Log::addDebug('SecuriVersion - URLS being versioned', $urls);
|
29 |
+
return $urls;
|
30 |
+
}
|
31 |
+
|
32 |
+
|
33 |
+
}
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Visual Composer and compat class.
|
4 |
+
class visualComp
|
5 |
+
{
|
6 |
+
|
7 |
+
public function __construct()
|
8 |
+
{
|
9 |
+
add_filter('shortpixel/init/automedialibrary', array($this, 'check_vcinline'));
|
10 |
+
}
|
11 |
+
|
12 |
+
// autolibrary should not do things when VC is being inline somewhere.
|
13 |
+
public function check_vcinline($bool)
|
14 |
+
{
|
15 |
+
if ( function_exists( 'vc_action' ) && vc_action() == 'vc_inline' )
|
16 |
+
return false;
|
17 |
+
else
|
18 |
+
return $bool;
|
19 |
+
}
|
20 |
+
|
21 |
+
} // Class
|
22 |
+
|
23 |
+
$vc = new visualComp();
|
@@ -2,11 +2,13 @@
|
|
2 |
namespace ShortPixel;
|
3 |
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
use ShortPixel\FileSystemController as FileSystem;
|
|
|
5 |
|
6 |
class wpOffload
|
7 |
{
|
8 |
protected $as3cf;
|
9 |
protected $active = false;
|
|
|
10 |
|
11 |
protected $settings;
|
12 |
|
@@ -18,16 +20,27 @@ class wpOffload
|
|
18 |
|
19 |
public function init($as3cf)
|
20 |
{
|
21 |
-
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
$this->as3cf = $as3cf;
|
25 |
$this->active = true;
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
add_action('shortpixel_image_optimised', array($this, 'image_upload'));
|
28 |
add_action('shortpixel_after_restore_image', array($this, 'image_restore')); // hit this when restoring.
|
29 |
add_action('shortpixel/image/convertpng2jpg_after', array($this, 'image_converted'));
|
30 |
-
add_action('
|
31 |
add_action('shortpixel/image/convertpng2jpg_before', array($this, 'remove_remote'));
|
32 |
add_filter('as3cf_attachment_file_paths', array($this, 'add_webp_paths'));
|
33 |
add_filter('as3cf_remove_attachment_paths', array($this, 'remove_webp_paths'));
|
@@ -36,15 +49,39 @@ class wpOffload
|
|
36 |
|
37 |
add_filter('as3cf_pre_update_attachment_metadata', array($this, 'preventInitialUpload'), 10,4);
|
38 |
|
39 |
-
add_filter('
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
{
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
public function addURLforDownload($bool, $url, $host)
|
@@ -64,15 +101,39 @@ class wpOffload
|
|
64 |
|
65 |
public function image_restore($id)
|
66 |
{
|
67 |
-
|
68 |
-
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
-
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
-
|
75 |
-
// delete_post_meta( $post_id, 'amazonS3_info' );
|
76 |
|
77 |
$this->image_upload($id);
|
78 |
|
@@ -80,44 +141,82 @@ class wpOffload
|
|
80 |
|
81 |
public function remove_remote($id)
|
82 |
{
|
83 |
-
$
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
}
|
86 |
|
87 |
public function image_converted($id)
|
88 |
{
|
89 |
$fs = new \ShortPixel\FileSystemController();
|
90 |
|
|
|
91 |
// delete the old file.
|
92 |
-
|
93 |
-
// $this->as3cf->remove_attachment_files_from_provider($id, $provider_object);
|
94 |
|
|
|
95 |
// get some new ones.
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
$newFile = $fs->getFile($this->returnOriginalFile(null, $id));
|
98 |
|
99 |
// convert
|
100 |
-
|
101 |
if ($providerFile->getExtension() !== $newFile->getExtension())
|
102 |
{
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
109 |
|
110 |
// upload
|
111 |
-
$provider_object['key'] = $newfilemeta;
|
112 |
-
update_post_meta( $id, 'amazonS3_info', $provider_object );
|
113 |
-
|
114 |
$this->image_upload($id); // delete and reupload
|
115 |
}
|
116 |
|
117 |
public function image_upload($id)
|
118 |
{
|
119 |
-
|
120 |
-
|
|
|
121 |
// abort if not already uploaded to provider and the copy setting is off
|
122 |
Log::addDebug('As3cf image upload is off and object not previously uploaded');
|
123 |
return false;
|
@@ -128,15 +227,21 @@ class wpOffload
|
|
128 |
}
|
129 |
|
130 |
/** This function will cut out the initial upload to S3Offload and rely solely on the image_upload function provided here, after shortpixel optimize.
|
131 |
-
* Function will only work when plugin is set to auto-optimize new entries to the media library
|
|
|
|
|
132 |
public function preventInitialUpload($bool, $data, $post_id, $old_provider_object)
|
133 |
{
|
134 |
-
|
135 |
-
$settings = new \WPShortPixelSettings();
|
136 |
|
137 |
if ($settings->autoMediaLibrary)
|
138 |
{
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
140 |
}
|
141 |
return $bool;
|
142 |
}
|
@@ -185,14 +290,14 @@ class wpOffload
|
|
185 |
{
|
186 |
// Log::addDebug('Received Paths', array($paths));
|
187 |
$paths = $this->getWebpPaths($paths, true);
|
188 |
-
|
189 |
return $paths;
|
190 |
}
|
191 |
|
192 |
public function remove_webp_paths($paths)
|
193 |
{
|
194 |
$paths = $this->getWebpPaths($paths, false);
|
195 |
-
|
196 |
return $paths;
|
197 |
}
|
198 |
|
2 |
namespace ShortPixel;
|
3 |
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
use ShortPixel\FileSystemController as FileSystem;
|
5 |
+
use ShortPixel\Notices\NoticeController as Notice;
|
6 |
|
7 |
class wpOffload
|
8 |
{
|
9 |
protected $as3cf;
|
10 |
protected $active = false;
|
11 |
+
private $itemClassName;
|
12 |
|
13 |
protected $settings;
|
14 |
|
20 |
|
21 |
public function init($as3cf)
|
22 |
{
|
23 |
+
if (! class_exists('\DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item'))
|
24 |
+
{
|
25 |
+
Notice::addWarning(__('Your S3-Offload plugin version doesn\'t seem to be compatible. Please upgrade the S3-Offload plugin', 'shortpixel-image-optimiser'));
|
26 |
+
}
|
27 |
+
else {
|
28 |
+
$this->itemClassName = '\DeliciousBrains\WP_Offload_Media\Items\Media_Library_Item';
|
29 |
+
}
|
30 |
|
31 |
$this->as3cf = $as3cf;
|
32 |
$this->active = true;
|
33 |
|
34 |
+
// if setting to upload to bucket is off, don't hook or do anything really.
|
35 |
+
if (! $this->as3cf->get_setting( 'copy-to-s3' ))
|
36 |
+
{
|
37 |
+
return;
|
38 |
+
}
|
39 |
+
|
40 |
add_action('shortpixel_image_optimised', array($this, 'image_upload'));
|
41 |
add_action('shortpixel_after_restore_image', array($this, 'image_restore')); // hit this when restoring.
|
42 |
add_action('shortpixel/image/convertpng2jpg_after', array($this, 'image_converted'));
|
43 |
+
add_action('shortpixel_restore_after_pathget', array($this, 'remove_remote')); // not optimal -> has to do w/ doRestore and when URL/PATH is available when not on server .
|
44 |
add_action('shortpixel/image/convertpng2jpg_before', array($this, 'remove_remote'));
|
45 |
add_filter('as3cf_attachment_file_paths', array($this, 'add_webp_paths'));
|
46 |
add_filter('as3cf_remove_attachment_paths', array($this, 'remove_webp_paths'));
|
49 |
|
50 |
add_filter('as3cf_pre_update_attachment_metadata', array($this, 'preventInitialUpload'), 10,4);
|
51 |
|
52 |
+
add_filter('shortpixel_get_attached_file', array($this, 'get_raw_attached_file'),10, 2);
|
53 |
+
add_filter('shortpixel_get_original_image_path', array($this, 'get_raw_original_path'), 10, 2);
|
54 |
+
}
|
55 |
+
|
56 |
+
public function get_raw_attached_file($file, $id)
|
57 |
+
{
|
58 |
+
$scheme = parse_url($file, PHP_URL_SCHEME);
|
59 |
+
if ($scheme !== false && strpos($scheme, 's3') !== false)
|
60 |
{
|
61 |
+
return get_attached_file($id, true);
|
62 |
+
}
|
63 |
+
return $file;
|
64 |
+
}
|
65 |
+
|
66 |
+
// partial copy of the wp_get_original_image_path function. It doesn't support raw filter on get_attached_file
|
67 |
+
public function get_raw_original_path($file, $id)
|
68 |
+
{
|
69 |
+
|
70 |
+
$scheme = parse_url($file, PHP_URL_SCHEME);
|
71 |
+
if ($scheme !== false && strpos($scheme, 's3') !== false)
|
72 |
+
{
|
73 |
+
$image_meta = wp_get_attachment_metadata( $id );
|
74 |
+
$image_file = get_attached_file( $id, true );
|
75 |
+
|
76 |
+
if ( empty( $image_meta['original_image'] ) ) {
|
77 |
+
$original_image = $image_file;
|
78 |
+
} else {
|
79 |
+
$original_image = path_join( dirname( $image_file ), $image_meta['original_image'] );
|
80 |
+
}
|
81 |
+
$file = $original_image;
|
82 |
+
}
|
83 |
+
|
84 |
+
return $file;
|
85 |
}
|
86 |
|
87 |
public function addURLforDownload($bool, $url, $host)
|
101 |
|
102 |
public function image_restore($id)
|
103 |
{
|
104 |
+
/* voodoo . When images is excluded via S3, it might not exist anymore on server (when option is on). And it will not be in the backups. So before removing remote, and restoring, check this */
|
105 |
+
/*
|
106 |
+
Seems not needed to make it work, for now.
|
107 |
+
$settings = \wpSPIO()->settings();
|
108 |
+
$fs = \wpSPIO()->filesystem();
|
109 |
+
$excludeSizes = $settings->excludeSizes;
|
110 |
+
|
111 |
+
$itemHandler = new \ShortPixelMetaFacade($id);
|
112 |
+
$itemHandler->deleteItemCache();
|
113 |
+
|
114 |
+
// get all paths, without anything excluded.
|
115 |
+
$paths_all = $itemHandler->getURLsAndPATHs(true, false, true, array(), true,true);
|
116 |
+
Log::addDebug('Image Restore, Paths ALL', array($paths_all));
|
117 |
|
118 |
+
if (isset($paths_all['PATHs']))
|
119 |
+
{
|
120 |
+
foreach($paths_all['PATHs'] as $index => $path)
|
121 |
+
{
|
122 |
+
$restoredFile = $fs->getFile($path);
|
123 |
+
if (! $restoredFile->exists())
|
124 |
+
{
|
125 |
+
$url = $paths_all['URLs'][$index];
|
126 |
+
Log::addDebug('Missing size on restored image data, doing remote download :' . $path);
|
127 |
+
$itemHandler->attemptRemoteDownload($url, $path, $id);
|
128 |
+
}
|
129 |
+
}
|
130 |
+
} */
|
131 |
+
// sizes without excluded paths
|
132 |
+
//$paths_excludes = $itemHandler->getURLsAndPATHs(true, false, true, $excludeSizes, true,true);
|
133 |
+
|
134 |
+
//$itemHandler->deleteItemCache();
|
135 |
|
136 |
+
$this->remove_remote($id);
|
|
|
137 |
|
138 |
$this->image_upload($id);
|
139 |
|
141 |
|
142 |
public function remove_remote($id)
|
143 |
{
|
144 |
+
$mediaItem = $this->getItemById($id);
|
145 |
+
if ($mediaItem === false)
|
146 |
+
{
|
147 |
+
Log::addDebug('S3-Offload MediaItem not remote - ' . $id);
|
148 |
+
return false;
|
149 |
+
}
|
150 |
+
// $provider_object = $this->as3cf->get_attachment_provider_info($id);
|
151 |
+
$this->as3cf->remove_attachment_files_from_provider($id, $mediaItem);
|
152 |
+
}
|
153 |
+
|
154 |
+
/** @return Returns S3Ofload MediaItem, or false when this does not exist */
|
155 |
+
protected function getItemById($id)
|
156 |
+
{
|
157 |
+
$mediaItem = $this->itemClassName::get_by_source_id($id);
|
158 |
+
return $mediaItem;
|
159 |
}
|
160 |
|
161 |
public function image_converted($id)
|
162 |
{
|
163 |
$fs = new \ShortPixel\FileSystemController();
|
164 |
|
165 |
+
// Don't offload when setting is off.
|
166 |
// delete the old file.
|
167 |
+
// $provider_object = $this->as3cf->get_attachment_provider_info($id);
|
|
|
168 |
|
169 |
+
// $this->as3cf->remove_attachment_files_from_provider($id, $provider_object);
|
170 |
// get some new ones.
|
171 |
+
|
172 |
+
// delete the old file
|
173 |
+
$mediaItem = $this->getItemById($id);
|
174 |
+
if ($mediaItem === false) // mediaItem seems not present. Probably not a remote file
|
175 |
+
return;
|
176 |
+
|
177 |
+
$this->as3cf->remove_attachment_files_from_provider($id, $mediaItem);
|
178 |
+
$providerSourcePath = $mediaItem->source_path();
|
179 |
+
|
180 |
+
//$providerFile = $fs->getFile($provider_object['key']);
|
181 |
+
$providerFile = $fs->getFile($providerSourcePath);
|
182 |
$newFile = $fs->getFile($this->returnOriginalFile(null, $id));
|
183 |
|
184 |
// convert
|
185 |
+
//$newfilemeta = $provider_object['key'];
|
186 |
if ($providerFile->getExtension() !== $newFile->getExtension())
|
187 |
{
|
188 |
+
// $newfilemeta = str_replace($providerFile->getFileName(), $newFile->getFileName(), $newfilemeta);
|
189 |
+
$data = $mediaItem->key_values(true);
|
190 |
+
$record_id = $data['id'];
|
191 |
+
/* $data['path']
|
192 |
+
$data['original_path']
|
193 |
+
$data['original_source_path']
|
194 |
+
$data['source_path'] */
|
195 |
+
|
196 |
+
$data['path'] = str_replace($providerFile->getFileName(), $newFile->getFileName(), $data['path']);
|
197 |
+
/*$data['original_path'] = str_replace($providerFile->getFileName(), $newFile->getFileName(), $data['original_path']);
|
198 |
+
$data['source_path'] = str_replace($providerFile->getFileName(), $newFile->getFileName(), $data['source_path']);
|
199 |
+
$data['original_source_path'] = str_replace($providerFile->getFileName(), $newFile->getFileName(), $data['original_source_path']);
|
200 |
+
*/
|
201 |
+
|
202 |
+
|
203 |
+
//$provider, $region, $bucket, $path, $is_private, $source_id, $source_path, $original_filename = null, $private_sizes = array(), $id = null
|
204 |
+
$newItem = new $this->itemClassName($data['provider'], $data['region'], $data['bucket'], $data['path'], $data['is_private'], $data['source_id'], $data['source_path'], $newFile->getFileName(), $data['extra_info'], $record_id );
|
205 |
+
|
206 |
+
$newItem->save();
|
207 |
+
|
208 |
+
Log::addDebug('S3Offload - Uploading converted file ');
|
209 |
}
|
210 |
|
211 |
// upload
|
|
|
|
|
|
|
212 |
$this->image_upload($id); // delete and reupload
|
213 |
}
|
214 |
|
215 |
public function image_upload($id)
|
216 |
{
|
217 |
+
$item = $this->getItemById($id);
|
218 |
+
|
219 |
+
if ( $item === false && ! $this->as3cf->get_setting( 'copy-to-s3' ) ) {
|
220 |
// abort if not already uploaded to provider and the copy setting is off
|
221 |
Log::addDebug('As3cf image upload is off and object not previously uploaded');
|
222 |
return false;
|
227 |
}
|
228 |
|
229 |
/** This function will cut out the initial upload to S3Offload and rely solely on the image_upload function provided here, after shortpixel optimize.
|
230 |
+
* Function will only work when plugin is set to auto-optimize new entries to the media library
|
231 |
+
* Since S3-Offload 2.3 this will be called on every thumbnail ( changes in WP 5.3 )
|
232 |
+
*/
|
233 |
public function preventInitialUpload($bool, $data, $post_id, $old_provider_object)
|
234 |
{
|
235 |
+
$settings = \wpSPIO()->settings();
|
|
|
236 |
|
237 |
if ($settings->autoMediaLibrary)
|
238 |
{
|
239 |
+
// Don't prevent whaffever if shortpixel is already done. This can be caused by plugins doing a metadata update, we don't care then.
|
240 |
+
if (! isset($data['ShortPixelImprovement']))
|
241 |
+
{
|
242 |
+
Log::addDebug('Preventing Initial Upload', $post_id);
|
243 |
+
return true;
|
244 |
+
}
|
245 |
}
|
246 |
return $bool;
|
247 |
}
|
290 |
{
|
291 |
// Log::addDebug('Received Paths', array($paths));
|
292 |
$paths = $this->getWebpPaths($paths, true);
|
293 |
+
// Log::addDebug('Webp Path Founder (S3)', array($paths));
|
294 |
return $paths;
|
295 |
}
|
296 |
|
297 |
public function remove_webp_paths($paths)
|
298 |
{
|
299 |
$paths = $this->getWebpPaths($paths, false);
|
300 |
+
// Log::addDebug('Remove S3 Paths', array($paths));
|
301 |
return $paths;
|
302 |
}
|
303 |
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace ShortPixel;
|
3 |
+
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
if ( class_exists( 'WPE_API', false ) ) {
|
6 |
+
|
7 |
+
/* WPE has a limit on Query size (16K). After that it won't execute the query. */
|
8 |
+
add_filter('shortpixel/db/chunk_size', function ($size)
|
9 |
+
{
|
10 |
+
// 16K chars = 2500 * size of ID 6 chars (until post_id 100.000);
|
11 |
+
if ($size > 2500)
|
12 |
+
return 2500;
|
13 |
+
});
|
14 |
+
}
|
@@ -106,16 +106,18 @@ class ShortPixelImgToPictureWebp
|
|
106 |
public static function convertImage($match)
|
107 |
{
|
108 |
// Do nothing with images that have the 'sp-no-webp' class.
|
109 |
-
if (strpos($match[0], 'sp-no-webp')) {
|
110 |
Log::addInfo('SPDBG convertImage skipped, sp-no-webp found');
|
111 |
return $match[0]; //. (isset($_GET['SHORTPIXEL_DEBUG']) ? '<!-- SPDBG convertImage sp-no-webp -->' : '');
|
112 |
}
|
113 |
|
114 |
$img = self::get_attributes($match[0]);
|
|
|
115 |
if(isset($img['style']) && strpos($img['style'], 'background') !== false) {
|
116 |
//don't replace for <img>'s that have background
|
117 |
return $match[0];
|
118 |
}
|
|
|
119 |
// [BS] Can return false in case of Module fail. Escape in that case with unmodified image
|
120 |
if ($img === false)
|
121 |
return $match[0];
|
@@ -138,7 +140,6 @@ class ShortPixelImgToPictureWebp
|
|
138 |
if(!$id) {
|
139 |
return $match[0];
|
140 |
}
|
141 |
-
$imageBase = dirname(get_attached_file($id)) . '/';
|
142 |
*/
|
143 |
|
144 |
/* [BS] $updir = wp_upload_dir();
|
@@ -193,6 +194,7 @@ class ShortPixelImgToPictureWebp
|
|
193 |
unset($img['data-lazy-src']);
|
194 |
unset($img['srcset']);
|
195 |
unset($img['sizes']);
|
|
|
196 |
//nor the ones that belong to <img>
|
197 |
unset($img['alt']);
|
198 |
unset($img['id']);
|
@@ -251,7 +253,11 @@ class ShortPixelImgToPictureWebp
|
|
251 |
//add the exclude class so if this content is processed again in other filter, the img is not converted again in picture
|
252 |
$img['class'] = (isset($img['class']) ? $img['class'] . " " : "") . "sp-no-webp";
|
253 |
|
254 |
-
|
|
|
|
|
|
|
|
|
255 |
.'<source ' . $srcsetPrefix . 'srcset="' . $srcsetWebP . '"' . ($sizes ? ' ' . $sizesPrefix . 'sizes="' . $sizes . '"' : '') . ' type="image/webp">'
|
256 |
.'<source ' . $srcsetPrefix . 'srcset="' . $srcset . '"' . ($sizes ? ' ' . $sizesPrefix . 'sizes="' . $sizes . '"' : '') . '>'
|
257 |
.'<img ' . $srcPrefix . 'src="' . $src . '" ' . self::create_attributes($img) . $idAttr . $altAttr . $heightAttr . $widthAttr
|
@@ -259,6 +265,31 @@ class ShortPixelImgToPictureWebp
|
|
259 |
.'</picture>';
|
260 |
}
|
261 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
public static function testInlineStyle($content)
|
263 |
{
|
264 |
//preg_match_all('/background.*[^:](url\(.*\))[;]/isU', $content, $matches);
|
@@ -438,6 +469,7 @@ class ShortPixelImgToPictureWebp
|
|
438 |
foreach ($attribute_array as $attribute => $value) {
|
439 |
$attributes .= $attribute . '="' . $value . '" ';
|
440 |
}
|
|
|
441 |
// Removes the extra space after the last attribute
|
442 |
return substr($attributes, 0, -1);
|
443 |
}
|
106 |
public static function convertImage($match)
|
107 |
{
|
108 |
// Do nothing with images that have the 'sp-no-webp' class.
|
109 |
+
if (strpos($match[0], 'sp-no-webp') || strpos($match[0], 'rev-sildebg')) {
|
110 |
Log::addInfo('SPDBG convertImage skipped, sp-no-webp found');
|
111 |
return $match[0]; //. (isset($_GET['SHORTPIXEL_DEBUG']) ? '<!-- SPDBG convertImage sp-no-webp -->' : '');
|
112 |
}
|
113 |
|
114 |
$img = self::get_attributes($match[0]);
|
115 |
+
|
116 |
if(isset($img['style']) && strpos($img['style'], 'background') !== false) {
|
117 |
//don't replace for <img>'s that have background
|
118 |
return $match[0];
|
119 |
}
|
120 |
+
|
121 |
// [BS] Can return false in case of Module fail. Escape in that case with unmodified image
|
122 |
if ($img === false)
|
123 |
return $match[0];
|
140 |
if(!$id) {
|
141 |
return $match[0];
|
142 |
}
|
|
|
143 |
*/
|
144 |
|
145 |
/* [BS] $updir = wp_upload_dir();
|
194 |
unset($img['data-lazy-src']);
|
195 |
unset($img['srcset']);
|
196 |
unset($img['sizes']);
|
197 |
+
|
198 |
//nor the ones that belong to <img>
|
199 |
unset($img['alt']);
|
200 |
unset($img['id']);
|
253 |
//add the exclude class so if this content is processed again in other filter, the img is not converted again in picture
|
254 |
$img['class'] = (isset($img['class']) ? $img['class'] . " " : "") . "sp-no-webp";
|
255 |
|
256 |
+
$imgpicture = $img;
|
257 |
+
// remove certain elements for the main picture element.
|
258 |
+
$imgpicture = self::filterForPicture($imgpicture);
|
259 |
+
|
260 |
+
return '<picture ' . self::create_attributes($imgpicture) . '>'
|
261 |
.'<source ' . $srcsetPrefix . 'srcset="' . $srcsetWebP . '"' . ($sizes ? ' ' . $sizesPrefix . 'sizes="' . $sizes . '"' : '') . ' type="image/webp">'
|
262 |
.'<source ' . $srcsetPrefix . 'srcset="' . $srcset . '"' . ($sizes ? ' ' . $sizesPrefix . 'sizes="' . $sizes . '"' : '') . '>'
|
263 |
.'<img ' . $srcPrefix . 'src="' . $src . '" ' . self::create_attributes($img) . $idAttr . $altAttr . $heightAttr . $widthAttr
|
265 |
.'</picture>';
|
266 |
}
|
267 |
|
268 |
+
/** Check and remove elements that should not be in the picture tag. Especially items within attributes. */
|
269 |
+
private static function filterForPicture($img)
|
270 |
+
{
|
271 |
+
|
272 |
+
if (isset($img['style']))
|
273 |
+
{
|
274 |
+
$bordercount = substr_count($img['style'], 'border');
|
275 |
+
for ($i = 0; $i <= $bordercount; $i++)
|
276 |
+
{
|
277 |
+
$offset = strpos($img['style'], 'border');
|
278 |
+
$end = strpos($img['style'], ';', $offset);
|
279 |
+
|
280 |
+
$nstyle = substr($img['style'], 0, $offset);
|
281 |
+
|
282 |
+
// if end is false, ; terminator does not exist, assume full string is border.
|
283 |
+
if ($end !== false)
|
284 |
+
$nstyle .= substr($img['style'], ($end+1) ); // do not include ;
|
285 |
+
|
286 |
+
$img['style'] = $nstyle;
|
287 |
+
}
|
288 |
+
}
|
289 |
+
|
290 |
+
return $img;
|
291 |
+
}
|
292 |
+
|
293 |
public static function testInlineStyle($content)
|
294 |
{
|
295 |
//preg_match_all('/background.*[^:](url\(.*\))[;]/isU', $content, $matches);
|
469 |
foreach ($attribute_array as $attribute => $value) {
|
470 |
$attributes .= $attribute . '="' . $value . '" ';
|
471 |
}
|
472 |
+
|
473 |
// Removes the extra space after the last attribute
|
474 |
return substr($attributes, 0, -1);
|
475 |
}
|
@@ -104,7 +104,7 @@ class ApiKeyModel extends ShortPixelModel
|
|
104 |
*/
|
105 |
public function checkKey($key)
|
106 |
{
|
107 |
-
|
108 |
if (strlen($key) == 0)
|
109 |
{
|
110 |
// first-timers, redirect to nokey screen
|
@@ -193,6 +193,7 @@ class ApiKeyModel extends ShortPixelModel
|
|
193 |
// first, save Auth to satisfy getquotainformation
|
194 |
|
195 |
$quotaData = $this->remoteValidate($key);
|
|
|
196 |
$checked_key = ($quotaData['APIKeyValid']) ? true : false;
|
197 |
|
198 |
Log::addDebug('Verify Result', $quotaData);
|
@@ -273,7 +274,8 @@ class ApiKeyModel extends ShortPixelModel
|
|
273 |
|
274 |
protected function checkRedirect()
|
275 |
{
|
276 |
-
|
|
|
277 |
$this->redirectedSettings = 1;
|
278 |
$this->update();
|
279 |
wp_redirect(admin_url("options-general.php?page=wp-shortpixel-settings"));
|
104 |
*/
|
105 |
public function checkKey($key)
|
106 |
{
|
107 |
+
|
108 |
if (strlen($key) == 0)
|
109 |
{
|
110 |
// first-timers, redirect to nokey screen
|
193 |
// first, save Auth to satisfy getquotainformation
|
194 |
|
195 |
$quotaData = $this->remoteValidate($key);
|
196 |
+
|
197 |
$checked_key = ($quotaData['APIKeyValid']) ? true : false;
|
198 |
|
199 |
Log::addDebug('Verify Result', $quotaData);
|
274 |
|
275 |
protected function checkRedirect()
|
276 |
{
|
277 |
+
|
278 |
+
if(! \wpSPIO()->env()->is_ajaxcall && !$this->redirectedSettings && !$this->verifiedKey && (!function_exists("is_multisite") || ! is_multisite())) {
|
279 |
$this->redirectedSettings = 1;
|
280 |
$this->update();
|
281 |
wp_redirect(admin_url("options-general.php?page=wp-shortpixel-settings"));
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace ShortPixel;
|
3 |
+
use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
|
4 |
+
|
5 |
+
|
6 |
+
/* Model for storing cached data
|
7 |
+
*
|
8 |
+
* Use this in conjunction with cache controller, don't call it stand-alone.
|
9 |
+
*/
|
10 |
+
class CacheModel
|
11 |
+
{
|
12 |
+
|
13 |
+
protected $name;
|
14 |
+
protected $value;
|
15 |
+
protected $expires = HOUR_IN_SECONDS;
|
16 |
+
|
17 |
+
protected $exists = false;
|
18 |
+
|
19 |
+
|
20 |
+
public function __construct($name)
|
21 |
+
{
|
22 |
+
$this->name = $name;
|
23 |
+
$this->load($name);
|
24 |
+
}
|
25 |
+
|
26 |
+
/** Set the expiration of this item. In seconds
|
27 |
+
* @param $time Expiration in Seconds
|
28 |
+
*/
|
29 |
+
public function setExpires($time)
|
30 |
+
{
|
31 |
+
$this->expires = $time;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function setValue($value)
|
35 |
+
{
|
36 |
+
$this->value = $value;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function exists()
|
40 |
+
{
|
41 |
+
return $this->exists;
|
42 |
+
}
|
43 |
+
|
44 |
+
public function getValue()
|
45 |
+
{
|
46 |
+
return $this->value;
|
47 |
+
}
|
48 |
+
|
49 |
+
public function getName()
|
50 |
+
{
|
51 |
+
return $this->name;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function save()
|
55 |
+
{
|
56 |
+
$this->exists = set_transient($this->name, $this->value, $this->expires);
|
57 |
+
}
|
58 |
+
|
59 |
+
public function delete()
|
60 |
+
{
|
61 |
+
delete_transient($this->name);
|
62 |
+
$this->exists = false;
|
63 |
+
}
|
64 |
+
|
65 |
+
protected function load()
|
66 |
+
{
|
67 |
+
$item = get_transient($this->name);
|
68 |
+
|
69 |
+
if ($item)
|
70 |
+
{
|
71 |
+
$this->value = $item;
|
72 |
+
$this->exists = true;
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
}
|
@@ -13,20 +13,29 @@ class DirectoryModel extends ShortPixelModel
|
|
13 |
{
|
14 |
// Directory info
|
15 |
protected $path;
|
|
|
16 |
|
17 |
// Directory status
|
18 |
protected $exists = false;
|
19 |
protected $is_writable = false;
|
|
|
|
|
|
|
20 |
|
21 |
protected $new_directory_permission = 0755;
|
22 |
|
23 |
/** Creates a directory model object. DirectoryModel directories don't need to exist on FileSystem
|
24 |
*
|
25 |
* When a filepath is given, it will remove the file part.
|
|
|
26 |
*/
|
27 |
public function __construct($path)
|
28 |
{
|
29 |
-
|
|
|
|
|
|
|
|
|
30 |
|
31 |
$path = wp_normalize_path($path);
|
32 |
if (! is_dir($path)) // path is wrong, *or* simply doesn't exist.
|
@@ -45,11 +54,13 @@ class DirectoryModel extends ShortPixelModel
|
|
45 |
}
|
46 |
|
47 |
$this->path = trailingslashit($path);
|
|
|
48 |
|
49 |
if (file_exists($this->path))
|
50 |
{
|
51 |
$this->exists();
|
52 |
$this->is_writable();
|
|
|
53 |
}
|
54 |
}
|
55 |
|
@@ -67,6 +78,17 @@ class DirectoryModel extends ShortPixelModel
|
|
67 |
return $this->path;
|
68 |
}
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
public function exists()
|
71 |
{
|
72 |
$this->exists = file_exists($this->path);
|
@@ -79,6 +101,11 @@ class DirectoryModel extends ShortPixelModel
|
|
79 |
return $this->is_writable;
|
80 |
}
|
81 |
|
|
|
|
|
|
|
|
|
|
|
82 |
/** Try to obtain the path, minus the installation directory.
|
83 |
* @return Mixed False if this didn't work, Path as string without basedir if it did. With trailing slash, without starting slash.
|
84 |
*/
|
@@ -93,7 +120,6 @@ class DirectoryModel extends ShortPixelModel
|
|
93 |
}
|
94 |
|
95 |
$install_dir = trailingslashit($install_dir);
|
96 |
-
//Log::addDebug('Install Dir - ' . $install_dir);
|
97 |
|
98 |
$path = $this->getPath();
|
99 |
// try to build relativePath without first slash.
|
@@ -161,8 +187,10 @@ class DirectoryModel extends ShortPixelModel
|
|
161 |
return $testpath;
|
162 |
}
|
163 |
|
164 |
-
/** Checks the directory
|
165 |
-
*
|
|
|
|
|
166 |
*/
|
167 |
public function check($check_writable = false)
|
168 |
{
|
@@ -196,5 +224,98 @@ class DirectoryModel extends ShortPixelModel
|
|
196 |
return true;
|
197 |
}
|
198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
|
200 |
}
|
13 |
{
|
14 |
// Directory info
|
15 |
protected $path;
|
16 |
+
protected $name;
|
17 |
|
18 |
// Directory status
|
19 |
protected $exists = false;
|
20 |
protected $is_writable = false;
|
21 |
+
protected $is_readable = false;
|
22 |
+
|
23 |
+
|
24 |
|
25 |
protected $new_directory_permission = 0755;
|
26 |
|
27 |
/** Creates a directory model object. DirectoryModel directories don't need to exist on FileSystem
|
28 |
*
|
29 |
* When a filepath is given, it will remove the file part.
|
30 |
+
* @param $path String The Path
|
31 |
*/
|
32 |
public function __construct($path)
|
33 |
{
|
34 |
+
/* Check if realpath improves things. We support non-existing paths, which realpath fails on, so only apply on result.
|
35 |
+
*/
|
36 |
+
$testpath = realpath($path);
|
37 |
+
if ($testpath)
|
38 |
+
$path = $testpath;
|
39 |
|
40 |
$path = wp_normalize_path($path);
|
41 |
if (! is_dir($path)) // path is wrong, *or* simply doesn't exist.
|
54 |
}
|
55 |
|
56 |
$this->path = trailingslashit($path);
|
57 |
+
$this->name = basename($this->path);
|
58 |
|
59 |
if (file_exists($this->path))
|
60 |
{
|
61 |
$this->exists();
|
62 |
$this->is_writable();
|
63 |
+
$this->is_readable();
|
64 |
}
|
65 |
}
|
66 |
|
78 |
return $this->path;
|
79 |
}
|
80 |
|
81 |
+
public function getModified()
|
82 |
+
{
|
83 |
+
return filemtime($this->path);
|
84 |
+
}
|
85 |
+
|
86 |
+
/** Get basename of the directory. Without path */
|
87 |
+
public function getName()
|
88 |
+
{
|
89 |
+
return $this->name;
|
90 |
+
}
|
91 |
+
|
92 |
public function exists()
|
93 |
{
|
94 |
$this->exists = file_exists($this->path);
|
101 |
return $this->is_writable;
|
102 |
}
|
103 |
|
104 |
+
public function is_readable()
|
105 |
+
{
|
106 |
+
$this->is_readable = is_readable($this->path);
|
107 |
+
return $this->is_readable;
|
108 |
+
}
|
109 |
/** Try to obtain the path, minus the installation directory.
|
110 |
* @return Mixed False if this didn't work, Path as string without basedir if it did. With trailing slash, without starting slash.
|
111 |
*/
|
120 |
}
|
121 |
|
122 |
$install_dir = trailingslashit($install_dir);
|
|
|
123 |
|
124 |
$path = $this->getPath();
|
125 |
// try to build relativePath without first slash.
|
187 |
return $testpath;
|
188 |
}
|
189 |
|
190 |
+
/** Checks the directory into working order
|
191 |
+
* Tries to create directory if it doesn't exist
|
192 |
+
* Tries to fix file permission if writable is needed
|
193 |
+
* @param $check_writable Boolean Directory should be writable
|
194 |
*/
|
195 |
public function check($check_writable = false)
|
196 |
{
|
224 |
return true;
|
225 |
}
|
226 |
|
227 |
+
/* Get files from directory
|
228 |
+
* @todo In future this should accept some basic filters via args.
|
229 |
+
* @returns Array|boolean Returns false if something wrong w/ directory, otherwise a files array of FileModel Object.
|
230 |
+
*/
|
231 |
+
public function getFiles($args = array())
|
232 |
+
{
|
233 |
+
|
234 |
+
$defaults = array(
|
235 |
+
'date_newer' => null,
|
236 |
+
);
|
237 |
+
$args = wp_parse_args($args, $defaults);
|
238 |
+
|
239 |
+
// if all filters are set to null, so point in checking those.
|
240 |
+
$has_filters = (count(array_filter($args)) > 0) ? true : false;
|
241 |
+
|
242 |
+
if ( ! $this->exists() || ! $this->is_readable() )
|
243 |
+
return false;
|
244 |
+
|
245 |
+
$fileArray = array();
|
246 |
+
|
247 |
+
if ($handle = opendir($this->path)) {
|
248 |
+
while (false !== ($entry = readdir($handle))) {
|
249 |
+
if ( ($entry != "." && $entry != "..") && ! is_dir($this->path . $entry) ) {
|
250 |
+
$fileArray[] = new FileModel($this->path . $entry);
|
251 |
+
}
|
252 |
+
}
|
253 |
+
closedir($handle);
|
254 |
+
}
|
255 |
+
|
256 |
+
if ($has_filters)
|
257 |
+
{
|
258 |
+
$fileArray = array_filter($fileArray, function ($file) use ($args) {
|
259 |
+
return $this->fileFilter($file, $args);
|
260 |
+
} );
|
261 |
+
}
|
262 |
+
return $fileArray;
|
263 |
+
}
|
264 |
+
|
265 |
+
// @return boolean true if it should be kept in array, false if not.
|
266 |
+
private function fileFilter(FileModel $file, $args)
|
267 |
+
{
|
268 |
+
$filter = true;
|
269 |
+
|
270 |
+
if (! is_null($args['date_newer']))
|
271 |
+
{
|
272 |
+
$modified = $file->getModified();
|
273 |
+
if ($modified < $args['date_newer'] )
|
274 |
+
$filter = false;
|
275 |
+
}
|
276 |
+
|
277 |
+
return $filter;
|
278 |
+
}
|
279 |
+
|
280 |
+
/** Get subdirectories from directory
|
281 |
+
* * @returns Array|boolean Returns false if something wrong w/ directory, otherwise a files array of DirectoryModel Object.
|
282 |
+
*/
|
283 |
+
public function getSubDirectories()
|
284 |
+
{
|
285 |
+
$fs = \wpSPIO()->fileSystem();
|
286 |
+
|
287 |
+
if (! $this->exists() || ! $this->is_readable() )
|
288 |
+
return false;
|
289 |
+
|
290 |
+
$dirIt = new \DirectoryIterator($this->path);
|
291 |
+
$dirArray = array();
|
292 |
+
foreach($dirIt as $fileInfo)
|
293 |
+
{
|
294 |
+
if ($fileInfo->isDir() && $fileInfo->isReadable() && ! $fileInfo->isDot() )
|
295 |
+
{
|
296 |
+
$dir = new DirectoryModel($fileInfo->getRealPath());
|
297 |
+
if ($dir->exists())
|
298 |
+
$dirArray[] = $dir;
|
299 |
+
}
|
300 |
+
|
301 |
+
}
|
302 |
+
return $dirArray;
|
303 |
+
}
|
304 |
+
|
305 |
+
/** Check if this dir is a subfolder
|
306 |
+
* @param DirectoryModel The directoryObject that is tested as the parent */
|
307 |
+
public function isSubFolderOf(DirectoryModel $dir)
|
308 |
+
{
|
309 |
+
// the same path, is not a subdir of.
|
310 |
+
if ($this->getPath() === $dir->getPath())
|
311 |
+
return false;
|
312 |
+
|
313 |
+
// the main path must be followed from the beginning to be a subfolder.
|
314 |
+
if (strpos($this->getPath(), $dir->getPath() ) === 0)
|
315 |
+
{
|
316 |
+
return true;
|
317 |
+
}
|
318 |
+
return false;
|
319 |
+
}
|
320 |
|
321 |
}
|
@@ -3,7 +3,7 @@ namespace ShortPixel;
|
|
3 |
|
4 |
/** Loads a few environment variables handy to have nearby
|
5 |
*
|
6 |
-
* Notice - This is meant to be loaded
|
7 |
*/
|
8 |
class EnvironmentModel extends ShortPixelModel
|
9 |
{
|
@@ -20,17 +20,102 @@ class EnvironmentModel extends ShortPixelModel
|
|
20 |
// Integrations
|
21 |
public $has_nextgen;
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
public function __construct()
|
24 |
{
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
-
|
31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
}
|
36 |
}
|
3 |
|
4 |
/** Loads a few environment variables handy to have nearby
|
5 |
*
|
6 |
+
* Notice - This is meant to be loaded via the plugin class. Easy access with wpSPIO()->getEnv().
|
7 |
*/
|
8 |
class EnvironmentModel extends ShortPixelModel
|
9 |
{
|
20 |
// Integrations
|
21 |
public $has_nextgen;
|
22 |
|
23 |
+
// WordPress
|
24 |
+
public $is_front = false;
|
25 |
+
public $is_admin = false;
|
26 |
+
public $is_ajaxcall = false;
|
27 |
+
|
28 |
+
private $screen_is_set = false;
|
29 |
+
public $is_screen_to_use = false; // where shortpixel loads
|
30 |
+
public $is_our_screen = false;
|
31 |
+
|
32 |
+
|
33 |
+
protected static $instance;
|
34 |
+
|
35 |
+
|
36 |
public function __construct()
|
37 |
{
|
38 |
+
$this->setServer();
|
39 |
+
$this->setWordPress();
|
40 |
+
$this->setIntegrations();
|
41 |
+
$this->setScreen(); // This might not be set on construct time!
|
42 |
+
}
|
43 |
+
|
44 |
+
public static function getInstance()
|
45 |
+
{
|
46 |
+
if (is_null(self::$instance))
|
47 |
+
self::$instance = new EnvironmentModel();
|
48 |
|
49 |
+
if (! self::$instance->screen_is_set)
|
50 |
+
self::$instance->setScreen();
|
51 |
+
|
52 |
+
return self::$instance;
|
53 |
+
}
|
54 |
+
|
55 |
+
private function setServer()
|
56 |
+
{
|
57 |
+
$this->is_nginx = strpos(strtolower($_SERVER["SERVER_SOFTWARE"]), 'nginx') !== false ? true : false;
|
58 |
+
$this->is_apache = strpos(strtolower($_SERVER["SERVER_SOFTWARE"]), 'apache') !== false ? true : false;
|
59 |
+
$this->is_gd_installed = function_exists('imagecreatefrompng');
|
60 |
+
$this->is_curl_installed = function_exists('curl_init');
|
61 |
+
|
62 |
+
}
|
63 |
+
|
64 |
+
private function setWordPress()
|
65 |
+
{
|
66 |
+
$this->is_multisite = (function_exists("is_multisite") && is_multisite()) ? true : false;
|
67 |
+
$this->is_mainsite = is_main_site();
|
68 |
|
69 |
+
if ( is_admin() )
|
70 |
+
$this->is_admin = true;
|
71 |
+
else
|
72 |
+
$this->is_front = true;
|
73 |
+
|
74 |
+
if (defined('DOING_AJAX') && DOING_AJAX)
|
75 |
+
{
|
76 |
+
$this->is_ajaxcall = true;
|
77 |
+
}
|
78 |
+
|
79 |
+
}
|
80 |
+
|
81 |
+
public function setScreen()
|
82 |
+
{
|
83 |
+
if (! function_exists('get_current_screen')) // way too early.
|
84 |
+
return false;
|
85 |
+
|
86 |
+
$screen = get_current_screen();
|
87 |
+
|
88 |
+
if (is_null($screen)) // too early
|
89 |
+
return false;
|
90 |
+
|
91 |
+
// WordPress pages where we'll be active on.
|
92 |
+
if(in_array($screen->id, array('upload', 'edit', 'edit-tags', 'post-new', 'post', 'attachment'))) {
|
93 |
+
$this->is_screen_to_use = true;
|
94 |
+
}
|
95 |
+
|
96 |
+
// Our pages.
|
97 |
+
$pages = \wpSPIO()->get_admin_pages();
|
98 |
+
|
99 |
+
/* pages can be null in certain cases i.e. plugin activation.
|
100 |
+
* treat those cases as improper screen set.
|
101 |
+
*/
|
102 |
+
if (is_null($pages))
|
103 |
+
{
|
104 |
+
return false;
|
105 |
+
}
|
106 |
+
|
107 |
+
if ( in_array($screen->id, $pages))
|
108 |
+
{
|
109 |
+
$this->is_screen_to_use = true;
|
110 |
+
$this->is_our_screen = true;
|
111 |
+
}
|
112 |
+
|
113 |
+
$this->screen_is_set = true;
|
114 |
+
}
|
115 |
+
|
116 |
+
private function setIntegrations()
|
117 |
+
{
|
118 |
+
$this->has_nextgen = \ShortPixelNextGenAdapter::hasNextGen();
|
119 |
|
120 |
}
|
121 |
}
|
@@ -16,17 +16,16 @@ class FileModel extends ShortPixelModel
|
|
16 |
{
|
17 |
|
18 |
// File info
|
19 |
-
protected $fullpath;
|
20 |
-
protected $filename; // filename + extension
|
21 |
-
protected $filebase; // filename without extension
|
22 |
-
protected $directory;
|
23 |
-
protected $extension;
|
24 |
|
25 |
// File Status
|
26 |
-
protected $exists =
|
27 |
-
protected $is_writable =
|
28 |
-
protected $is_readable =
|
29 |
-
|
30 |
|
31 |
protected $status;
|
32 |
|
@@ -39,17 +38,13 @@ class FileModel extends ShortPixelModel
|
|
39 |
/** Creates a file model object. FileModel files don't need to exist on FileSystem */
|
40 |
public function __construct($path)
|
41 |
{
|
42 |
-
|
43 |
-
if ($processed_path !== false)
|
44 |
-
$this->fullpath = $processed_path; // set processed path if that went alright
|
45 |
-
else {
|
46 |
-
$this->fullpath = $path; // fallback, but there should be error state
|
47 |
-
}
|
48 |
-
|
49 |
-
// $this->fullpath =
|
50 |
-
$this->setFileInfo();
|
51 |
}
|
52 |
|
|
|
|
|
|
|
|
|
53 |
public function __toString()
|
54 |
{
|
55 |
return (string) $this->fullpath;
|
@@ -57,57 +52,69 @@ class FileModel extends ShortPixelModel
|
|
57 |
|
58 |
protected function setFileInfo()
|
59 |
{
|
60 |
-
|
61 |
-
|
62 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
$info = pathinfo($this->fullpath);
|
|
|
64 |
$this->filename = isset($info['basename']) ? $info['basename'] : null; // filename + extension
|
65 |
$this->filebase = isset($info['filename']) ? $info['filename'] : null; // only filename
|
66 |
$this->extension = isset($info['extension']) ? $info['extension'] : null; // only (last) extension
|
67 |
-
$this->directory = isset($info['dirname']) ? new DirectoryModel($info['dirname']) : null;
|
68 |
-
$this->is_writable();
|
69 |
-
$this->is_readable();
|
70 |
-
}
|
71 |
-
else {
|
72 |
-
$this->exists = false;
|
73 |
-
$this->is_writable = false;
|
74 |
-
$this->is_readable = false;
|
75 |
|
76 |
-
|
77 |
-
$this->filename = basename($this->fullpath);
|
78 |
|
79 |
-
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
82 |
}
|
83 |
|
84 |
public function exists()
|
85 |
{
|
86 |
-
|
|
|
|
|
87 |
return $this->exists;
|
88 |
}
|
89 |
|
90 |
public function is_writable()
|
91 |
{
|
92 |
-
|
|
|
|
|
93 |
return $this->is_writable;
|
94 |
}
|
95 |
|
96 |
public function is_readable()
|
97 |
{
|
98 |
-
|
|
|
|
|
99 |
return $this->is_readable;
|
100 |
}
|
101 |
|
|
|
|
|
|
|
|
|
|
|
102 |
public function hasBackup()
|
103 |
{
|
104 |
$directory = $this->getBackupDirectory();
|
105 |
if (! $directory)
|
106 |
return false;
|
107 |
|
108 |
-
$backupFile = $directory . $this->
|
109 |
|
110 |
-
if (file_exists($backupFile))
|
111 |
return true;
|
112 |
else {
|
113 |
return false;
|
@@ -121,7 +128,7 @@ class FileModel extends ShortPixelModel
|
|
121 |
public function getBackupFile()
|
122 |
{
|
123 |
if ($this->hasBackup())
|
124 |
-
return new FileModel($this->getBackupDirectory() . $this->
|
125 |
else
|
126 |
return false;
|
127 |
}
|
@@ -131,10 +138,22 @@ class FileModel extends ShortPixelModel
|
|
131 |
* @return DirectoryModel Directorymodel Object
|
132 |
*/
|
133 |
public function getFileDir()
|
134 |
-
|
|
|
|
|
|
|
|
|
135 |
return $this->directory;
|
136 |
}
|
137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
/** Copy a file to somewhere
|
139 |
*
|
140 |
* @param $destination String Full Path to new file.
|
@@ -151,12 +170,19 @@ class FileModel extends ShortPixelModel
|
|
151 |
return false;
|
152 |
}
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
$is_new = ($destination->exists()) ? false : true;
|
155 |
$status = copy($sourcePath, $destinationPath);
|
156 |
|
157 |
if (! $status)
|
158 |
Log::addWarn('Could not copy file ' . $sourcePath . ' to' . $destinationPath);
|
159 |
else {
|
|
|
160 |
$destination->setFileInfo(); // refresh info.
|
161 |
}
|
162 |
//
|
@@ -174,6 +200,8 @@ class FileModel extends ShortPixelModel
|
|
174 |
if ($this->copy($destination))
|
175 |
{
|
176 |
$result = $this->delete();
|
|
|
|
|
177 |
}
|
178 |
return $result;
|
179 |
}
|
@@ -183,36 +211,50 @@ class FileModel extends ShortPixelModel
|
|
183 |
*/
|
184 |
public function delete()
|
185 |
{
|
186 |
-
|
187 |
-
$this->
|
188 |
|
189 |
if (! file_exists($this->fullpath))
|
190 |
{
|
|
|
191 |
return true;
|
192 |
}
|
193 |
else {
|
194 |
return false;
|
195 |
Log::addWarn('File seems not removed - ' . $this->fullpath);
|
196 |
}
|
|
|
197 |
}
|
198 |
|
199 |
public function getFullPath()
|
200 |
{
|
|
|
|
|
|
|
201 |
return $this->fullpath;
|
202 |
}
|
203 |
|
204 |
public function getFileName()
|
205 |
{
|
|
|
|
|
|
|
206 |
return $this->filename;
|
207 |
}
|
208 |
|
209 |
public function getFileBase()
|
210 |
{
|
|
|
|
|
|
|
211 |
return $this->filebase;
|
212 |
}
|
213 |
|
214 |
public function getExtension()
|
215 |
{
|
|
|
|
|
|
|
216 |
return $this->extension;
|
217 |
}
|
218 |
|
@@ -221,7 +263,7 @@ class FileModel extends ShortPixelModel
|
|
221 |
*/
|
222 |
private function getBackupDirectory()
|
223 |
{
|
224 |
-
if (is_null($this->
|
225 |
{
|
226 |
return false;
|
227 |
}
|
@@ -248,9 +290,7 @@ class FileModel extends ShortPixelModel
|
|
248 |
*/
|
249 |
protected function processPath($path)
|
250 |
{
|
251 |
-
|
252 |
$original_path = $path;
|
253 |
-
$path = trim($path);
|
254 |
|
255 |
if ($this->pathIsUrl($path))
|
256 |
{
|
@@ -359,7 +399,7 @@ class FileModel extends ShortPixelModel
|
|
359 |
|
360 |
private function getUploadPath()
|
361 |
{
|
362 |
-
$upload_dir = wp_upload_dir(null, false);
|
363 |
$basedir = $upload_dir['basedir'];
|
364 |
|
365 |
return $basedir;
|
16 |
{
|
17 |
|
18 |
// File info
|
19 |
+
protected $fullpath = null;
|
20 |
+
protected $filename = null; // filename + extension
|
21 |
+
protected $filebase = null; // filename without extension
|
22 |
+
protected $directory = null;
|
23 |
+
protected $extension = null;
|
24 |
|
25 |
// File Status
|
26 |
+
protected $exists = null;
|
27 |
+
protected $is_writable = null;
|
28 |
+
protected $is_readable = null;
|
|
|
29 |
|
30 |
protected $status;
|
31 |
|
38 |
/** Creates a file model object. FileModel files don't need to exist on FileSystem */
|
39 |
public function __construct($path)
|
40 |
{
|
41 |
+
$this->fullpath = trim($path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
}
|
43 |
|
44 |
+
/* Get a string representation of file, the fullpath
|
45 |
+
* Note - this might be risky, without processedpath, in cases.
|
46 |
+
* @return String Full path processed or unprocessed.
|
47 |
+
*/
|
48 |
public function __toString()
|
49 |
{
|
50 |
return (string) $this->fullpath;
|
52 |
|
53 |
protected function setFileInfo()
|
54 |
{
|
55 |
+
|
56 |
+
$processed_path = $this->processPath($this->fullpath);
|
57 |
+
if ($processed_path !== false)
|
58 |
+
$this->fullpath = $processed_path; // set processed path if that went alright
|
59 |
+
|
60 |
+
/* else {
|
61 |
+
$this->fullpath = $path; // fallback, but there should be error state
|
62 |
+
} */
|
63 |
+
|
64 |
$info = pathinfo($this->fullpath);
|
65 |
+
// Todo, maybe replace this with splFileINfo.
|
66 |
$this->filename = isset($info['basename']) ? $info['basename'] : null; // filename + extension
|
67 |
$this->filebase = isset($info['filename']) ? $info['filename'] : null; // only filename
|
68 |
$this->extension = isset($info['extension']) ? $info['extension'] : null; // only (last) extension
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
|
70 |
+
}
|
|
|
71 |
|
72 |
+
/** Call when file status changed, so writable / readable / exists are not reliable anymore */
|
73 |
+
public function resetStatus()
|
74 |
+
{
|
75 |
+
$this->is_writable = null;
|
76 |
+
$this->is_readable = null;
|
77 |
+
$this->exists = null;
|
78 |
}
|
79 |
|
80 |
public function exists()
|
81 |
{
|
82 |
+
if (is_null($this->exists))
|
83 |
+
$this->exists = file_exists($this->fullpath);
|
84 |
+
|
85 |
return $this->exists;
|
86 |
}
|
87 |
|
88 |
public function is_writable()
|
89 |
{
|
90 |
+
if (is_null($this->is_writable))
|
91 |
+
$this->is_writable = is_writable($this->fullpath);
|
92 |
+
|
93 |
return $this->is_writable;
|
94 |
}
|
95 |
|
96 |
public function is_readable()
|
97 |
{
|
98 |
+
if (is_null($this->is_readable))
|
99 |
+
$this->is_readable = is_readable($this->fullpath);
|
100 |
+
|
101 |
return $this->is_readable;
|
102 |
}
|
103 |
|
104 |
+
public function getModified()
|
105 |
+
{
|
106 |
+
return filemtime($this->fullpath);
|
107 |
+
}
|
108 |
+
|
109 |
public function hasBackup()
|
110 |
{
|
111 |
$directory = $this->getBackupDirectory();
|
112 |
if (! $directory)
|
113 |
return false;
|
114 |
|
115 |
+
$backupFile = $directory . $this->getFileName();
|
116 |
|
117 |
+
if (file_exists($backupFile) && ! is_dir($backupFile) )
|
118 |
return true;
|
119 |
else {
|
120 |
return false;
|
128 |
public function getBackupFile()
|
129 |
{
|
130 |
if ($this->hasBackup())
|
131 |
+
return new FileModel($this->getBackupDirectory() . $this->getFileName() );
|
132 |
else
|
133 |
return false;
|
134 |
}
|
138 |
* @return DirectoryModel Directorymodel Object
|
139 |
*/
|
140 |
public function getFileDir()
|
141 |
+
{
|
142 |
+
// create this only when needed.
|
143 |
+
if (is_null($this->directory) && strlen($this->fullpath) > 0)
|
144 |
+
$this->directory = new DirectoryModel(dirname($this->fullpath));
|
145 |
+
|
146 |
return $this->directory;
|
147 |
}
|
148 |
|
149 |
+
public function getFileSize()
|
150 |
+
{
|
151 |
+
if ($this->exists())
|
152 |
+
return filesize($this->fullpath);
|
153 |
+
else
|
154 |
+
return 0;
|
155 |
+
}
|
156 |
+
|
157 |
/** Copy a file to somewhere
|
158 |
*
|
159 |
* @param $destination String Full Path to new file.
|
170 |
return false;
|
171 |
}
|
172 |
|
173 |
+
if (! $this->exists())
|
174 |
+
{
|
175 |
+
Log::addWarn('Tried to copy non-existing file - ' . $sourcePath);
|
176 |
+
return false;
|
177 |
+
}
|
178 |
+
|
179 |
$is_new = ($destination->exists()) ? false : true;
|
180 |
$status = copy($sourcePath, $destinationPath);
|
181 |
|
182 |
if (! $status)
|
183 |
Log::addWarn('Could not copy file ' . $sourcePath . ' to' . $destinationPath);
|
184 |
else {
|
185 |
+
$destination->resetStatus();
|
186 |
$destination->setFileInfo(); // refresh info.
|
187 |
}
|
188 |
//
|
200 |
if ($this->copy($destination))
|
201 |
{
|
202 |
$result = $this->delete();
|
203 |
+
$this->resetStatus();
|
204 |
+
$destination->resetStatus();
|
205 |
}
|
206 |
return $result;
|
207 |
}
|
211 |
*/
|
212 |
public function delete()
|
213 |
{
|
214 |
+
if ($this->exists())
|
215 |
+
\wp_delete_file($this->fullpath); // delete file hook via wp_delete_file
|
216 |
|
217 |
if (! file_exists($this->fullpath))
|
218 |
{
|
219 |
+
$this->resetStatus();
|
220 |
return true;
|
221 |
}
|
222 |
else {
|
223 |
return false;
|
224 |
Log::addWarn('File seems not removed - ' . $this->fullpath);
|
225 |
}
|
226 |
+
|
227 |
}
|
228 |
|
229 |
public function getFullPath()
|
230 |
{
|
231 |
+
if (is_null($this->filename))
|
232 |
+
$this->setFileInfo();
|
233 |
+
|
234 |
return $this->fullpath;
|
235 |
}
|
236 |
|
237 |
public function getFileName()
|
238 |
{
|
239 |
+
if (is_null($this->filename))
|
240 |
+
$this->setFileInfo();
|
241 |
+
|
242 |
return $this->filename;
|
243 |
}
|
244 |
|
245 |
public function getFileBase()
|
246 |
{
|
247 |
+
if (is_null($this->filename))
|
248 |
+
$this->setFileInfo();
|
249 |
+
|
250 |
return $this->filebase;
|
251 |
}
|
252 |
|
253 |
public function getExtension()
|
254 |
{
|
255 |
+
if (is_null($this->filename))
|
256 |
+
$this->setFileInfo();
|
257 |
+
|
258 |
return $this->extension;
|
259 |
}
|
260 |
|
263 |
*/
|
264 |
private function getBackupDirectory()
|
265 |
{
|
266 |
+
if (is_null($this->getFileDir()))
|
267 |
{
|
268 |
return false;
|
269 |
}
|
290 |
*/
|
291 |
protected function processPath($path)
|
292 |
{
|
|
|
293 |
$original_path = $path;
|
|
|
294 |
|
295 |
if ($this->pathIsUrl($path))
|
296 |
{
|
399 |
|
400 |
private function getUploadPath()
|
401 |
{
|
402 |
+
$upload_dir = wp_upload_dir(null, false, false);
|
403 |
$basedir = $upload_dir['basedir'];
|
404 |
|
405 |
return $basedir;
|
@@ -5,7 +5,7 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
|
|
5 |
/* ImageModel class.
|
6 |
*
|
7 |
*
|
8 |
-
* - Represents a -single- image *not file*.
|
9 |
* - Can be either MediaLibrary, or Custom .
|
10 |
* - Not a replacement of Meta, but might be.
|
11 |
* - Goal: Structural ONE method calls of image related information, and combining information. Same task is now done on many places.
|
@@ -19,6 +19,10 @@ class ImageModel extends ShortPixelModel
|
|
19 |
private $facade; // ShortPixelMetaFacade
|
20 |
|
21 |
protected $thumbsnails = array(); // thumbnails of this
|
|
|
|
|
|
|
|
|
22 |
|
23 |
|
24 |
public function __construct()
|
@@ -29,15 +33,52 @@ class ImageModel extends ShortPixelModel
|
|
29 |
public function setByPostID($post_id)
|
30 |
{
|
31 |
// Set Meta
|
32 |
-
$fs =
|
|
|
33 |
$this->facade = new \ShortPixelMetaFacade($post_id);
|
34 |
$this->meta = $this->facade->getMeta();
|
35 |
|
36 |
-
$file =
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
}
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
public function getMeta()
|
42 |
{
|
43 |
return $this->meta;
|
@@ -48,6 +89,19 @@ class ImageModel extends ShortPixelModel
|
|
48 |
return $this->file;
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
/* Sanity check in process. Should only be called upon special request, or with single image displays. Should check and recheck stats, thumbs, unlistedthumbs and all assumptions of data that might corrupt or change outside of this plugin */
|
52 |
public function reAcquire()
|
53 |
{
|
@@ -111,7 +165,7 @@ class ImageModel extends ShortPixelModel
|
|
111 |
Log::addDebug('Finding Thumbs on path' . $meta->getPath());
|
112 |
$thumbs = \WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
|
113 |
|
114 |
-
$fs =
|
115 |
$mainFile = $this->file;
|
116 |
|
117 |
// Find Thumbs returns *full file path*
|
5 |
/* ImageModel class.
|
6 |
*
|
7 |
*
|
8 |
+
* - Represents a -single- image entity *not file*.
|
9 |
* - Can be either MediaLibrary, or Custom .
|
10 |
* - Not a replacement of Meta, but might be.
|
11 |
* - Goal: Structural ONE method calls of image related information, and combining information. Same task is now done on many places.
|
19 |
private $facade; // ShortPixelMetaFacade
|
20 |
|
21 |
protected $thumbsnails = array(); // thumbnails of this
|
22 |
+
protected $original_file;
|
23 |
+
|
24 |
+
private $post_id;
|
25 |
+
private $is_scaled = false;
|
26 |
|
27 |
|
28 |
public function __construct()
|
33 |
public function setByPostID($post_id)
|
34 |
{
|
35 |
// Set Meta
|
36 |
+
$fs = \wpSPIO()->filesystem();
|
37 |
+
$this->post_id = $post_id;
|
38 |
$this->facade = new \ShortPixelMetaFacade($post_id);
|
39 |
$this->meta = $this->facade->getMeta();
|
40 |
|
41 |
+
$this->file = $fs->getAttachedFile($post_id);
|
42 |
+
|
43 |
+
// WP 5.3 and higher. Check for original file.
|
44 |
+
if (function_exists('wp_get_original_image_path'))
|
45 |
+
{
|
46 |
+
$this->setOriginalFile();
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
|
51 |
+
protected function setOriginalFile()
|
52 |
+
{
|
53 |
+
$fs = \wpSPIO()->filesystem();
|
54 |
+
|
55 |
+
if (is_null($this->post_id))
|
56 |
+
return false;
|
57 |
+
|
58 |
+
$originalFile = $fs->getOriginalPath($this->post_id);
|
59 |
+
|
60 |
+
if ($originalFile->getFullPath() !== $this->file->getfullPath() )
|
61 |
+
{
|
62 |
+
$this->original_file = $originalFile;
|
63 |
+
$this->is_scaled = true;
|
64 |
+
}
|
65 |
|
66 |
}
|
67 |
|
68 |
+
// Not sure if it will work like this.
|
69 |
+
public function is_scaled()
|
70 |
+
{
|
71 |
+
return $this->is_scaled;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function has_original()
|
75 |
+
{
|
76 |
+
if (is_null($this->original_file))
|
77 |
+
return false;
|
78 |
+
|
79 |
+
return $this->original_file;
|
80 |
+
}
|
81 |
+
|
82 |
public function getMeta()
|
83 |
{
|
84 |
return $this->meta;
|
89 |
return $this->file;
|
90 |
}
|
91 |
|
92 |
+
/** Get the facade object.
|
93 |
+
* @todo Ideally, the facade will be an internal thing, separating the custom and media library functions.
|
94 |
+
*/
|
95 |
+
public function getFacade()
|
96 |
+
{
|
97 |
+
return $this->facade;
|
98 |
+
}
|
99 |
+
|
100 |
+
/* public function getOriginalFile()
|
101 |
+
{
|
102 |
+
return $this->origin_file;
|
103 |
+
} */
|
104 |
+
|
105 |
/* Sanity check in process. Should only be called upon special request, or with single image displays. Should check and recheck stats, thumbs, unlistedthumbs and all assumptions of data that might corrupt or change outside of this plugin */
|
106 |
public function reAcquire()
|
107 |
{
|
165 |
Log::addDebug('Finding Thumbs on path' . $meta->getPath());
|
166 |
$thumbs = \WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
|
167 |
|
168 |
+
$fs = \wpSPIO()->filesystem();
|
169 |
$mainFile = $this->file;
|
170 |
|
171 |
// Find Thumbs returns *full file path*
|
@@ -36,11 +36,16 @@ class ShortPixelFolder extends ShortPixelEntity{
|
|
36 |
public static function createBackUpFolder($folder = SHORTPIXEL_BACKUP_FOLDER)
|
37 |
{
|
38 |
// create backup folder
|
39 |
-
$
|
|
|
|
|
40 |
|
41 |
-
if ($
|
42 |
{
|
43 |
-
|
|
|
|
|
|
|
44 |
}
|
45 |
|
46 |
return $result;
|
@@ -50,14 +55,22 @@ class ShortPixelFolder extends ShortPixelEntity{
|
|
50 |
{
|
51 |
$rules = "Options -Indexes";
|
52 |
/* Plugin init is before loading these admin scripts. So it can happen misc.php is not yet loaded */
|
53 |
-
|
|
|
54 |
{
|
55 |
-
require_once( ABSPATH . 'wp-admin/includes/misc.php' );
|
56 |
-
|
57 |
-
|
|
|
|
|
58 |
// note - this doesn't bring the same protection. Subdirs without files written will still be listable.
|
59 |
file_put_contents(trailingslashit($dirname) . 'index.html', chr(0)); // extra - for non-apache
|
60 |
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
|
63 |
/** @todo This function is double with wp-short-pixel - deleteDir */
|
36 |
public static function createBackUpFolder($folder = SHORTPIXEL_BACKUP_FOLDER)
|
37 |
{
|
38 |
// create backup folder
|
39 |
+
$fs = \wpSPIO()->filesystem();
|
40 |
+
$dir = $fs->getDirectory($folder);
|
41 |
+
$result = false;
|
42 |
|
43 |
+
if (! $dir->exists() )
|
44 |
{
|
45 |
+
$dir->check();
|
46 |
+
//$result = @mkdir($folder, 0777, true);
|
47 |
+
self::protectDirectoryListing($folder);
|
48 |
+
$result = true;
|
49 |
}
|
50 |
|
51 |
return $result;
|
55 |
{
|
56 |
$rules = "Options -Indexes";
|
57 |
/* Plugin init is before loading these admin scripts. So it can happen misc.php is not yet loaded */
|
58 |
+
// This crashes at 5.3.
|
59 |
+
/* if (! function_exists('insert_with_markers'))
|
60 |
{
|
61 |
+
//require_once( ABSPATH . 'wp-admin/includes/misc.php' );
|
62 |
+
return; // sadly then no.
|
63 |
+
} */
|
64 |
+
|
65 |
+
// insert_with_markers( trailingslashit($dirname) . '.htaccess', 'ShortPixel', $rules);
|
66 |
// note - this doesn't bring the same protection. Subdirs without files written will still be listable.
|
67 |
file_put_contents(trailingslashit($dirname) . 'index.html', chr(0)); // extra - for non-apache
|
68 |
|
69 |
+
if (\wpSPIO()->env()->is_nginx) // nginx has no htaccess support.
|
70 |
+
return;
|
71 |
+
|
72 |
+
file_put_contents(trailingslashit($dirname) . '.htaccess', $rules);
|
73 |
+
|
74 |
}
|
75 |
|
76 |
/** @todo This function is double with wp-short-pixel - deleteDir */
|
@@ -43,7 +43,7 @@ class ShortPixelPng2Jpg {
|
|
43 |
$img = @imagecreatefrompng($image);
|
44 |
WPShortPixel::log("PNG2JPG created from png");
|
45 |
if(!$img) {
|
46 |
-
WPShortPixel::log("PNG2JPG not a PNG");
|
47 |
$transparent = true; //it's not a PNG, can't convert it
|
48 |
} else {
|
49 |
WPShortPixel::log("PNG2JPG is PNG");
|
@@ -62,7 +62,7 @@ class ShortPixelPng2Jpg {
|
|
62 |
}
|
63 |
}
|
64 |
}
|
65 |
-
}
|
66 |
|
67 |
WPShortPixel::log("PNG2JPG is " . (!$transparent && !$transparent_pixel ? " not" : "") . " transparent");
|
68 |
//pass on the img too, if it was already loaded from PNG, matter of performance
|
@@ -80,6 +80,8 @@ class ShortPixelPng2Jpg {
|
|
80 |
|
81 |
protected function doConvertPng2Jpg($params, $backup, $suffixRegex = false, $img = false) {
|
82 |
$image = $params['file'];
|
|
|
|
|
83 |
WPShortPixel::log("PNG2JPG doConvert $image");
|
84 |
if(!$img) {
|
85 |
WPShortPixel::log("PNG2JPG doConvert create from PNG");
|
@@ -101,15 +103,24 @@ class ShortPixelPng2Jpg {
|
|
101 |
imagealphablending($bg, 1);
|
102 |
imagecopy($bg, $img, 0, 0, 0, 0, $x, $y);
|
103 |
imagedestroy($img);
|
104 |
-
|
105 |
-
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
if($suffixRegex) {
|
108 |
$newPath = preg_replace("/(" . $suffixRegex . ")\.png$/i", $i . '-$1.jpg', $image);
|
109 |
}else {
|
110 |
$newPath = preg_replace("/\.png$/i", "-" . $i . ".jpg", $image);
|
111 |
}
|
112 |
-
}
|
113 |
if (imagejpeg($bg, $newPath, 90)) {
|
114 |
WPShortPixel::log("PNG2JPG doConvert created JPEG at $newPath");
|
115 |
$newSize = filesize($newPath);
|
@@ -170,7 +181,7 @@ class ShortPixelPng2Jpg {
|
|
170 |
|
171 |
/**
|
172 |
* Convert an uploaded image from PNG to JPG
|
173 |
-
* @param type $params
|
174 |
* @return string
|
175 |
*/
|
176 |
public function convertPng2Jpg($params) {
|
@@ -182,7 +193,7 @@ class ShortPixelPng2Jpg {
|
|
182 |
if($this->isExcluded($params)) { return $params; }
|
183 |
|
184 |
$image = $params['file'];
|
185 |
-
|
186 |
|
187 |
if($this->_settings->png2jpg == 2) {
|
188 |
$doConvert = true;
|
@@ -222,7 +233,7 @@ class ShortPixelPng2Jpg {
|
|
222 |
|
223 |
$meta = $itemHandler->getRawMeta();
|
224 |
$ID = $itemHandler->getId();
|
225 |
-
$fs =
|
226 |
|
227 |
if(!$this->_settings->png2jpg || !isset($meta['file']) || strtolower(substr($meta['file'], -4)) !== '.png') {
|
228 |
return ;
|
@@ -232,7 +243,8 @@ class ShortPixelPng2Jpg {
|
|
232 |
WPShortPixel::log("Send to processing: Convert Media PNG to JPG #{$ID} META: " . json_encode($meta));
|
233 |
|
234 |
$image = $meta['file']; // This is not a full path!
|
235 |
-
$
|
|
|
236 |
$basePath = trailingslashit(str_replace($image, "", $imagePath));
|
237 |
$imageUrl = wp_get_attachment_url($ID);
|
238 |
$baseUrl = self::removeUrlProtocol(trailingslashit(str_replace($image, "", $imageUrl))); //make the base url protocol agnostic if it's not already
|
@@ -250,16 +262,18 @@ class ShortPixelPng2Jpg {
|
|
250 |
$meta['ShortPixel']['Retries'] = isset($meta['ShortPixel']['Retries']) ? $meta['ShortPixel']['Retries'] + 1 : 1;
|
251 |
$meta['ShortPixel']['ErrCode'] = ShortPixelAPI::ERR_PNG2JPG_MEMORY;
|
252 |
//wp_update_attachment_metadata($ID, $meta);
|
|
|
253 |
update_post_meta($ID, '_wp_attachment_metadata', $meta);
|
254 |
|
255 |
if($this->_settings->png2jpg == 2) {
|
256 |
$doConvert = true;
|
257 |
} else {
|
258 |
$retC = $this->canConvertPng2Jpg($imagePath);
|
|
|
259 |
$doConvert = $retC['notTransparent'];
|
260 |
}
|
261 |
if (!$doConvert) {
|
262 |
-
Log::addDebug("PNG2JPG not a PNG");
|
263 |
return $meta; //cannot convert it
|
264 |
}
|
265 |
|
@@ -332,11 +346,14 @@ class ShortPixelPng2Jpg {
|
|
332 |
'optimizationPercent' => round(100.0 * (1.00 - $jpgSize / $pngSize)));
|
333 |
//wp_update_attachment_metadata($ID, $meta);
|
334 |
update_post_meta($ID, '_wp_attachment_metadata', $meta);
|
|
|
335 |
Log::addDebug("Updated meta: " . json_encode($meta));
|
336 |
do_action('shortpixel/image/convertpng2jpg_after', $ID, $meta);
|
337 |
}
|
338 |
|
339 |
-
|
|
|
|
|
340 |
$fs = new \ShortPixel\FileSystemController();
|
341 |
|
342 |
foreach($toUnlink as $unlink) {
|
@@ -412,6 +429,7 @@ class ShortPixelPng2Jpg {
|
|
412 |
if(count($options) == 0) {
|
413 |
$options = array_keys($queries);
|
414 |
}
|
|
|
415 |
foreach($options as $option){
|
416 |
WPShortPixel::log("PNG2JPG update URLS on $option ");
|
417 |
if( $option == 'custom' ){
|
@@ -439,6 +457,16 @@ class ShortPixelPng2Jpg {
|
|
439 |
$n++;
|
440 |
}
|
441 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
}
|
443 |
$results[$option] = array($n, $queries[$option][1]);
|
444 |
}
|
43 |
$img = @imagecreatefrompng($image);
|
44 |
WPShortPixel::log("PNG2JPG created from png");
|
45 |
if(!$img) {
|
46 |
+
WPShortPixel::log("PNG2JPG not a PNG, imagecreatefrompng failed ");
|
47 |
$transparent = true; //it's not a PNG, can't convert it
|
48 |
} else {
|
49 |
WPShortPixel::log("PNG2JPG is PNG");
|
62 |
}
|
63 |
}
|
64 |
}
|
65 |
+
} // non-transparant.
|
66 |
|
67 |
WPShortPixel::log("PNG2JPG is " . (!$transparent && !$transparent_pixel ? " not" : "") . " transparent");
|
68 |
//pass on the img too, if it was already loaded from PNG, matter of performance
|
80 |
|
81 |
protected function doConvertPng2Jpg($params, $backup, $suffixRegex = false, $img = false) {
|
82 |
$image = $params['file'];
|
83 |
+
$fs = \wpSPIO()->filesystem();
|
84 |
+
|
85 |
WPShortPixel::log("PNG2JPG doConvert $image");
|
86 |
if(!$img) {
|
87 |
WPShortPixel::log("PNG2JPG doConvert create from PNG");
|
103 |
imagealphablending($bg, 1);
|
104 |
imagecopy($bg, $img, 0, 0, 0, 0, $x, $y);
|
105 |
imagedestroy($img);
|
106 |
+
//$newPath = preg_replace("/\.png$/i", ".jpg", $image);
|
107 |
+
|
108 |
+
$fsFile = $fs->getFile($image); // the original png file
|
109 |
+
$filename = $fsFile->getFileName();
|
110 |
+
$newFileName = $fsFile->getFileBase() . '.jpg'; // convert extension to .png
|
111 |
+
|
112 |
+
$uniquepath = wp_unique_filename($fsFile->getFullPath(), $newFileName);
|
113 |
+
$newPath = (string) $fsFile->getFileDir() . $uniquepath;
|
114 |
+
|
115 |
+
// check old filename, replace with uniqued filename.
|
116 |
+
$newUrl = str_replace($filename, $uniquepath, $params['url']); //preg_replace("/\.png$/i", ".jpg", $params['url']);
|
117 |
+
/*(for ($i = 1; file_exists($newPath); $i++) {
|
118 |
if($suffixRegex) {
|
119 |
$newPath = preg_replace("/(" . $suffixRegex . ")\.png$/i", $i . '-$1.jpg', $image);
|
120 |
}else {
|
121 |
$newPath = preg_replace("/\.png$/i", "-" . $i . ".jpg", $image);
|
122 |
}
|
123 |
+
} */
|
124 |
if (imagejpeg($bg, $newPath, 90)) {
|
125 |
WPShortPixel::log("PNG2JPG doConvert created JPEG at $newPath");
|
126 |
$newSize = filesize($newPath);
|
181 |
|
182 |
/**
|
183 |
* Convert an uploaded image from PNG to JPG
|
184 |
+
* @param type $params ( file, url, type ) - Connected to https://developer.wordpress.org/reference/hooks/wp_handle_upload/
|
185 |
* @return string
|
186 |
*/
|
187 |
public function convertPng2Jpg($params) {
|
193 |
if($this->isExcluded($params)) { return $params; }
|
194 |
|
195 |
$image = $params['file'];
|
196 |
+
Log::addDebug("Convert Media PNG to JPG on upload: {$image}");
|
197 |
|
198 |
if($this->_settings->png2jpg == 2) {
|
199 |
$doConvert = true;
|
233 |
|
234 |
$meta = $itemHandler->getRawMeta();
|
235 |
$ID = $itemHandler->getId();
|
236 |
+
$fs = \wpSPIO()->filesystem();
|
237 |
|
238 |
if(!$this->_settings->png2jpg || !isset($meta['file']) || strtolower(substr($meta['file'], -4)) !== '.png') {
|
239 |
return ;
|
243 |
WPShortPixel::log("Send to processing: Convert Media PNG to JPG #{$ID} META: " . json_encode($meta));
|
244 |
|
245 |
$image = $meta['file']; // This is not a full path!
|
246 |
+
$imageFile = $fs->getAttachedFile($ID);
|
247 |
+
$imagePath = $imageFile->getFullPath(); // This is a full path.
|
248 |
$basePath = trailingslashit(str_replace($image, "", $imagePath));
|
249 |
$imageUrl = wp_get_attachment_url($ID);
|
250 |
$baseUrl = self::removeUrlProtocol(trailingslashit(str_replace($image, "", $imageUrl))); //make the base url protocol agnostic if it's not already
|
262 |
$meta['ShortPixel']['Retries'] = isset($meta['ShortPixel']['Retries']) ? $meta['ShortPixel']['Retries'] + 1 : 1;
|
263 |
$meta['ShortPixel']['ErrCode'] = ShortPixelAPI::ERR_PNG2JPG_MEMORY;
|
264 |
//wp_update_attachment_metadata($ID, $meta);
|
265 |
+
|
266 |
update_post_meta($ID, '_wp_attachment_metadata', $meta);
|
267 |
|
268 |
if($this->_settings->png2jpg == 2) {
|
269 |
$doConvert = true;
|
270 |
} else {
|
271 |
$retC = $this->canConvertPng2Jpg($imagePath);
|
272 |
+
|
273 |
$doConvert = $retC['notTransparent'];
|
274 |
}
|
275 |
if (!$doConvert) {
|
276 |
+
Log::addDebug("PNG2JPG not a PNG, or transparent when this setting is off - " . $imagePath);
|
277 |
return $meta; //cannot convert it
|
278 |
}
|
279 |
|
346 |
'optimizationPercent' => round(100.0 * (1.00 - $jpgSize / $pngSize)));
|
347 |
//wp_update_attachment_metadata($ID, $meta);
|
348 |
update_post_meta($ID, '_wp_attachment_metadata', $meta);
|
349 |
+
$itemHandler->deleteItemCache(); // remove cache since filetype changes.
|
350 |
Log::addDebug("Updated meta: " . json_encode($meta));
|
351 |
do_action('shortpixel/image/convertpng2jpg_after', $ID, $meta);
|
352 |
}
|
353 |
|
354 |
+
if(count($toReplace)) {
|
355 |
+
self::png2JpgUpdateUrls(array(), $toReplace);
|
356 |
+
}
|
357 |
$fs = new \ShortPixel\FileSystemController();
|
358 |
|
359 |
foreach($toUnlink as $unlink) {
|
429 |
if(count($options) == 0) {
|
430 |
$options = array_keys($queries);
|
431 |
}
|
432 |
+
$startTime = microtime(true);
|
433 |
foreach($options as $option){
|
434 |
WPShortPixel::log("PNG2JPG update URLS on $option ");
|
435 |
if( $option == 'custom' ){
|
457 |
$n++;
|
458 |
}
|
459 |
}
|
460 |
+
//check time. This loop could take long because it's scanning all the postmeta table which in some cases becomes huge...
|
461 |
+
$timeElapsed = microtime(true) - $startTime;
|
462 |
+
if($timeElapsed > SHORTPIXEL_MAX_EXECUTION_TIME / 2) {
|
463 |
+
//try to add some time or get out if not
|
464 |
+
if(set_time_limit(SHORTPIXEL_MAX_EXECUTION_TIME)) {
|
465 |
+
$startTime += SHORTPIXEL_MAX_EXECUTION_TIME / 2;
|
466 |
+
} else {
|
467 |
+
break;
|
468 |
+
}
|
469 |
+
}
|
470 |
}
|
471 |
$results[$option] = array($n, $queries[$option][1]);
|
472 |
}
|
@@ -12,6 +12,18 @@ class ShortPixelTools {
|
|
12 |
return $data;
|
13 |
}*/
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
public static function snakeToCamel($snake_case) {
|
16 |
return str_replace(' ', '', ucwords(str_replace('_', ' ', $snake_case)));
|
17 |
}
|
@@ -75,6 +87,18 @@ class ShortPixelTools {
|
|
75 |
return $h_time;
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
public static function commonPrefix($str1, $str2) {
|
79 |
$limit = min(strlen($str1), strlen($str2));
|
80 |
for ($i = 0; $i < $limit && $str1[$i] === $str2[$i]; $i++);
|
12 |
return $data;
|
13 |
}*/
|
14 |
|
15 |
+
/** Find if a certain plugin is active
|
16 |
+
* @param String $plugin The name of plugin being searched for
|
17 |
+
* @return Boolean Active or not
|
18 |
+
*/
|
19 |
+
public static function shortPixelIsPluginActive($plugin) {
|
20 |
+
$activePlugins = apply_filters( 'active_plugins', get_option( 'active_plugins', array()));
|
21 |
+
if ( is_multisite() ) {
|
22 |
+
$activePlugins = array_merge($activePlugins, get_site_option( 'active_sitewide_plugins'));
|
23 |
+
}
|
24 |
+
return in_array( $plugin, $activePlugins);
|
25 |
+
}
|
26 |
+
|
27 |
public static function snakeToCamel($snake_case) {
|
28 |
return str_replace(' ', '', ucwords(str_replace('_', ' ', $snake_case)));
|
29 |
}
|
87 |
return $h_time;
|
88 |
}
|
89 |
|
90 |
+
static public function formatBytes($bytes, $precision = 2) {
|
91 |
+
$units = array('B', 'KB', 'MB', 'GB', 'TB');
|
92 |
+
|
93 |
+
$bytes = max($bytes, 0);
|
94 |
+
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
95 |
+
$pow = min($pow, count($units) - 1);
|
96 |
+
|
97 |
+
$bytes /= pow(1024, $pow);
|
98 |
+
|
99 |
+
return round($bytes, $precision) . ' ' . $units[$pow];
|
100 |
+
}
|
101 |
+
|
102 |
public static function commonPrefix($str1, $str2) {
|
103 |
$limit = min(strlen($str1), strlen($str2));
|
104 |
for ($i = 0; $i < $limit && $str1[$i] === $str2[$i]; $i++);
|
@@ -299,7 +299,7 @@ class ShortPixelQueue {
|
|
299 |
|
300 |
public function setBulkPreviousPercent() {
|
301 |
//processable and already processed
|
302 |
-
$res =
|
303 |
$this->settings->bulkCount = $res["mainFiles"];
|
304 |
|
305 |
//if compression type changed, add also the images with the other compression type
|
@@ -355,6 +355,7 @@ class ShortPixelQueue {
|
|
355 |
}
|
356 |
|
357 |
public function startBulk($type = self::BULK_TYPE_OPTIMIZE) {
|
|
|
358 |
$this->resetStartBulkId(); //start downwards from the biggest item ID
|
359 |
$this->resetStopBulkId();
|
360 |
$this->flagBulkStart(); //we use this to detect new added files while bulk is running
|
299 |
|
300 |
public function setBulkPreviousPercent() {
|
301 |
//processable and already processed
|
302 |
+
$res = $this->settings->currentStats; //this is only called when the bulk is started and the stats are already refreshed in bulkProcess()...
|
303 |
$this->settings->bulkCount = $res["mainFiles"];
|
304 |
|
305 |
//if compression type changed, add also the images with the other compression type
|
355 |
}
|
356 |
|
357 |
public function startBulk($type = self::BULK_TYPE_OPTIMIZE) {
|
358 |
+
Log::addDebug('startBulk 0');
|
359 |
$this->resetStartBulkId(); //start downwards from the biggest item ID
|
360 |
$this->resetStopBulkId();
|
361 |
$this->flagBulkStart(); //we use this to detect new added files while bulk is running
|
@@ -85,7 +85,7 @@ namespace ShortPixel;
|
|
85 |
<td>
|
86 |
<?php if(!($st == "Empty")) { ?>
|
87 |
<a href="javascript:none();" title="<?php echo $fullStat; ?>" style="text-decoration: none;">
|
88 |
-
<img src='<?php echo(
|
89 |
</a> <?php } echo($typ.$st.$err); ?>
|
90 |
|
91 |
</td>
|
85 |
<td>
|
86 |
<?php if(!($st == "Empty")) { ?>
|
87 |
<a href="javascript:none();" title="<?php echo $fullStat; ?>" style="text-decoration: none;">
|
88 |
+
<img src='<?php echo( wpSPIO()->plugin_url('res/img/info-icon.png' ));?>' style="margin-bottom: -2px;"/>
|
89 |
</a> <?php } echo($typ.$st.$err); ?>
|
90 |
|
91 |
</td>
|
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
namespace ShortPixel;
|
3 |
|
|
|
|
|
4 |
?>
|
5 |
|
6 |
<section id="tab-debug" <?php echo ($this->display_part == 'debug') ? ' class="sel-tab" ' :''; ?>>
|
1 |
<?php
|
2 |
namespace ShortPixel;
|
3 |
|
4 |
+
$path = '/var/www/shortpixel/wp-content/uploads/2019/09/';
|
5 |
+
|
6 |
?>
|
7 |
|
8 |
<section id="tab-debug" <?php echo ($this->display_part == 'debug') ? ' class="sel-tab" ' :''; ?>>
|
@@ -159,12 +159,12 @@
|
|
159 |
</p>
|
160 |
<div style="margin-top: 10px;">
|
161 |
<input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?php echo($view->data->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
|
162 |
-
<img src="<?php echo(
|
163 |
-
srcset='<?php echo(
|
164 |
title="<?php _e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
|
165 |
<input type="radio" name="resizeType" id="resize_type_inner" value="inner" <?php echo($view->data->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
|
166 |
-
<img src="<?php echo(
|
167 |
-
srcset='<?php echo(
|
168 |
title="<?php _e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
|
169 |
<div style="display:inline-block;margin-left: 20px;"><a href="https://blog.shortpixel.com/resize-images/" class="shortpixel-help-link" target="_blank">
|
170 |
<span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
|
159 |
</p>
|
160 |
<div style="margin-top: 10px;">
|
161 |
<input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?php echo($view->data->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
|
162 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?>"
|
163 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/resize-outer@2x.png' ));?> 2x'
|
164 |
title="<?php _e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
|
165 |
<input type="radio" name="resizeType" id="resize_type_inner" value="inner" <?php echo($view->data->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
|
166 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?>"
|
167 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/resize-inner@2x.png' ));?> 2x'
|
168 |
title="<?php _e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
|
169 |
<div style="display:inline-block;margin-left: 20px;"><a href="https://blog.shortpixel.com/resize-images/" class="shortpixel-help-link" target="_blank">
|
170 |
<span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
|
@@ -64,8 +64,8 @@ if($adminEmail == 'noreply@addendio.com') $adminEmail = false; //hack for the ad
|
|
64 |
}
|
65 |
?><br><span style="position:relative;">
|
66 |
<input name="tos" type="checkbox" id="tos">
|
67 |
-
<img id="tos-robo" src="<?php echo(
|
68 |
-
<img id="tos-hand" src="<?php echo(
|
69 |
</span>
|
70 |
<?php _e('I have read and I agree to the <a href="https://shortpixel.com/tos" target="_blank">Terms of Service</a> and the <a href="https://shortpixel.com/privacy" target="_blank">Privacy Policy</a> (<a href="https://shortpixel.com/privacy#gdpr" target="_blank">GDPR compliant</a>).','shortpixel-image-optimiser');
|
71 |
?>
|
64 |
}
|
65 |
?><br><span style="position:relative;">
|
66 |
<input name="tos" type="checkbox" id="tos">
|
67 |
+
<img id="tos-robo" src="<?php echo(wpSPIO()->plugin_url('res/img/slider.png' ));?>" style="position: absolute;left: -95px;bottom: -26px;display:none;">
|
68 |
+
<img id="tos-hand" src="<?php echo(wpSPIO()->plugin_url('res/img/point.png' ));?>" style="position: absolute;left: -39px;bottom: -9px;display:none;">
|
69 |
</span>
|
70 |
<?php _e('I have read and I agree to the <a href="https://shortpixel.com/tos" target="_blank">Terms of Service</a> and the <a href="https://shortpixel.com/privacy" target="_blank">Privacy Policy</a> (<a href="https://shortpixel.com/privacy#gdpr" target="_blank">GDPR compliant</a>).','shortpixel-image-optimiser');
|
71 |
?>
|
@@ -155,7 +155,7 @@ class ShortPixelListTable extends WP_List_Table {
|
|
155 |
: __('Reduced by','shortpixel-image-optimiser') . " <strong>" . $item->message . "%</strong>"
|
156 |
. (0 + intval($item->message) < 5 ? "<br>" . __('Bonus processing','shortpixel-image-optimiser') . "." : "");
|
157 |
break;
|
158 |
-
case 1: $msg = "<img src=\"" .
|
159 |
. __('Pending','shortpixel-image-optimiser');
|
160 |
break;
|
161 |
case 0: $msg = __('Waiting','shortpixel-image-optimiser');
|
155 |
: __('Reduced by','shortpixel-image-optimiser') . " <strong>" . $item->message . "%</strong>"
|
156 |
. (0 + intval($item->message) < 5 ? "<br>" . __('Bonus processing','shortpixel-image-optimiser') . "." : "");
|
157 |
break;
|
158 |
+
case 1: $msg = "<img src=\"" . wpSPIO()->plugin_url('res/img/loading.gif') . "\" class='sp-loading-small'> "
|
159 |
. __('Pending','shortpixel-image-optimiser');
|
160 |
break;
|
161 |
case 0: $msg = __('Waiting','shortpixel-image-optimiser');
|
@@ -33,8 +33,8 @@ class ShortPixelView {
|
|
33 |
</div>
|
34 |
</div>
|
35 |
<?php } ?>
|
36 |
-
<img src="<?php echo(
|
37 |
-
srcset='<?php echo(
|
38 |
class='short-pixel-notice-icon'>
|
39 |
<h3><?php /* translators: header of the alert box */ _e('Quota Exceeded','shortpixel-image-optimiser');?></h3>
|
40 |
<p><?php /* translators: body of the alert box */
|
@@ -118,8 +118,8 @@ class ShortPixelView {
|
|
118 |
<?php }
|
119 |
}
|
120 |
if($icon){ ?>
|
121 |
-
<img src="<?php echo(
|
122 |
-
srcset='<?php echo(
|
123 |
class='short-pixel-notice-icon'>
|
124 |
<?php } ?>
|
125 |
<h3><?php _e('ShortPixel Image Optimizer','shortpixel-image-optimiser');
|
@@ -212,7 +212,6 @@ class ShortPixelView {
|
|
212 |
//$this->ctrl->outputHSBeacon();
|
213 |
\ShortPixel\HelpScout::outputBeacon($this->ctrl->getApiKey());
|
214 |
|
215 |
-
|
216 |
$this->bulkType = $this->ctrl->getPrioQ()->getBulkTypeForDisplay(); // adding to the mess
|
217 |
$hider = ($this->bulkType == ShortPixelQueue::BULK_TYPE_RESTORE) ? 'sp-hidden' : '';
|
218 |
?>
|
@@ -234,6 +233,14 @@ class ShortPixelView {
|
|
234 |
<div style='width:165px; display:inline-block; padding-left: 5px'>
|
235 |
<input type='checkbox' id='thumbnails' name='thumbnails' onclick='ShortPixel.checkThumbsUpdTotal(this)' <?php echo($this->ctrl->processThumbnails() ? "checked":"");?>>
|
236 |
<?php _e('Include thumbnails','shortpixel-image-optimiser');?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
</div><br>
|
238 |
<?php if($quotaData["totalProcessedMlFiles"] > 0) { ?>
|
239 |
<div class="bulk-label bulk-total"><?php _e('Total images','shortpixel-image-optimiser');?></div>
|
@@ -266,8 +273,8 @@ class ShortPixelView {
|
|
266 |
: "onclick=\"document.getElementById('startBulk').submit();\""); ?> class='button'>
|
267 |
<div style="width: 320px">
|
268 |
<div class="bulk-btn-img" class="bulk-btn-img">
|
269 |
-
<img src='<?php echo(
|
270 |
-
srcset='<?php echo(
|
271 |
</div>
|
272 |
<div class="bulk-btn-txt">
|
273 |
<?php printf(__('<span class="label">Start Optimizing</span><br> <span class="total">%s</span> images','shortpixel-image-optimiser'),
|
@@ -276,7 +283,7 @@ class ShortPixelView {
|
|
276 |
number_format(max(0, $quotaData['mainMlFiles'] - $quotaData['mainProcessedMlFiles']) + $customCount));?>
|
277 |
</div>
|
278 |
<div class="bulk-btn-img" class="bulk-btn-img">
|
279 |
-
<img src='<?php echo(
|
280 |
</div>
|
281 |
</div>
|
282 |
</a>
|
@@ -344,8 +351,8 @@ class ShortPixelView {
|
|
344 |
<div class="sp-container">
|
345 |
<div class='sp-notice sp-notice-success sp-floating-block sp-single-width' style="height: 80px;overflow:hidden;">
|
346 |
<div style='float:left;margin:5px 20px 5px 0'>
|
347 |
-
<img src="<?php echo(
|
348 |
-
srcset='<?php echo(
|
349 |
</div>
|
350 |
<div class="sp-bulk-summary <?php echo $hider ?>">
|
351 |
<input type="text" value="<?php echo("" . round($averageCompression))?>" id="sp-total-optimization-dial" class="dial">
|
@@ -420,7 +427,7 @@ class ShortPixelView {
|
|
420 |
<a href="https://wordpress.org/support/view/plugin-reviews/shortpixel-image-optimiser?rate=5#postform" target="_blank">
|
421 |
<span>
|
422 |
<?php _e('Please rate us!','shortpixel-image-optimiser');?>
|
423 |
-
</span><br><img src="<?php echo(
|
424 |
</a>
|
425 |
</div>
|
426 |
<?php } ?>
|
@@ -556,6 +563,15 @@ class ShortPixelView {
|
|
556 |
<input type='checkbox' id='bulk-thumbnails' name='thumbnails' <?php echo($this->ctrl->processThumbnails() ? "checked":"");?>
|
557 |
onchange="ShortPixel.onBulkThumbsCheck(this)"> <?php _e('Include thumbnails','shortpixel-image-optimiser');?><br><br>
|
558 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
559 |
<a class='button' style="float: right;" href='<?php echo add_query_arg('part','bulk-restore-all'); ?> '><?php _e('Bulk Restore Images','shortpixel-image-optimiser'); ?></a>
|
560 |
|
561 |
<input type='submit' name='bulkProcess' id='bulkProcess' class='button button-primary' value='<?php _e('Restart Optimizing','shortpixel-image-optimiser');?>'
|
@@ -588,7 +604,7 @@ class ShortPixelView {
|
|
588 |
<div id="short-pixel-notice-squirrly" class="sp-notice sp-notice-info bulk-progress bulk-progress-partners sp-floating-block sp-full-width">
|
589 |
<div style="float:right"><a href="javascript:dismissShortPixelNotice('squirrly')"><?php _e('Dismiss','shortpixel-image-optimiser');?></a></div>
|
590 |
<a href="https://my.squirrly.co/go120073/squirrly.co/short-pixel-seo" target="_blank">
|
591 |
-
<img src="<?php echo(
|
592 |
<div><?php _e('While you wait for your images to optimize, check out Squirrly, a great plugin for further boosting your SEO.','shortpixel-image-optimiser');?></div>
|
593 |
</a>
|
594 |
</div>
|
@@ -597,28 +613,28 @@ class ShortPixelView {
|
|
597 |
<div class="sp-floating-block sp-notice bulk-notices-parent">
|
598 |
<div class="bulk-notice-container">
|
599 |
<div class="bulk-notice-msg bulk-lengthy">
|
600 |
-
<img src="<?php echo(
|
601 |
<?php _e('Lengthy operation in progress:','shortpixel-image-optimiser');?><br>
|
602 |
<?php _e('Optimizing image','shortpixel-image-optimiser');?> <a href="#" data-href="<?php echo(get_admin_url());?>/post.php?post=__ID__&action=edit" target="_blank">placeholder.png</a>
|
603 |
</div>
|
604 |
<div class="bulk-notice-msg bulk-maintenance">
|
605 |
-
<img src="<?php echo(
|
606 |
<?php _e("The ShortPixel API is in maintenance mode. Please don't close this window. The bulk will resume automatically as soon as the API is back online.",'shortpixel-image-optimiser');?>
|
607 |
</div>
|
608 |
<div class="bulk-notice-msg bulk-queue-full">
|
609 |
-
<img src="<?php echo(
|
610 |
<?php _e("Too many images processing simultaneously for your site, automatically retrying in 1 min. Please don't close this window.",'shortpixel-image-optimiser');?>
|
611 |
</div>
|
612 |
<div class="bulk-notice-msg bulk-error" id="bulk-error-template">
|
613 |
<div style="float: right; margin-top: -4px; margin-right: -3px;">
|
614 |
<a href="javascript:void(0);" onclick="ShortPixel.removeBulkMsg(this)" style='color: #c32525;font-size: 20px;text-decoration: none;'>×</a>
|
615 |
</div>
|
616 |
-
<img src="<?php echo(
|
617 |
<span class="sp-err-title"><?php _e('Error processing file:','shortpixel-image-optimiser');?><br></span>
|
618 |
<span class="sp-err-content"><?php echo $message; ?></span> <a class="sp-post-link" href="<?php echo(get_admin_url());?>/post.php?post=__ID__&action=edit" target="_blank">placeholder.png</a>
|
619 |
</div>
|
620 |
<div class="bulk-notice-msg bulk-searching">
|
621 |
-
<img src="<?php echo(
|
622 |
<?php _e('Please bear with me. ShortPixel is checking many already optimized images to see if they\'re OK, so the progress bar could stop for a while.','shortpixel-image-optimiser');?><br>
|
623 |
</div>
|
624 |
</div>
|
@@ -713,8 +729,8 @@ class ShortPixelView {
|
|
713 |
<?php }?>
|
714 |
<div id="bulk-progress" class="progress" >
|
715 |
<div class="progress-img" style="left: <?php echo($percent);?>%;">
|
716 |
-
<img src="<?php echo(
|
717 |
-
srcset='<?php echo(
|
718 |
<span><?php echo($percentAfter);?></span>
|
719 |
</div>
|
720 |
<div class="progress-left" style="width: <?php echo($percent);?>%"><?php echo($percentBefore);?></div>
|
@@ -794,8 +810,8 @@ class ShortPixelView {
|
|
794 |
?>
|
795 |
<br/>
|
796 |
<div class="clearfix <?php echo($extraClass);?>" style="background-color: #fff; border-left-style: solid; border-left-width: 4px; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 1px 12px;;width: 95%">
|
797 |
-
<img src="<?php echo(
|
798 |
-
srcset='<?php echo(
|
799 |
class='short-pixel-notice-icon'>
|
800 |
<p><?php echo($notice['msg']);?></p>
|
801 |
</div>
|
@@ -900,8 +916,8 @@ class ShortPixelView {
|
|
900 |
}
|
901 |
?><br><span style="position:relative;">
|
902 |
<input name="tos" type="checkbox" id="tos">
|
903 |
-
<img id="tos-robo" src="<?php echo(
|
904 |
-
<img id="tos-hand" src="<?php echo(
|
905 |
</span>
|
906 |
<?php _e('I have read and I agree to the <a href="https://shortpixel.com/tos" target="_blank">Terms of Service</a> and the <a href="https://shortpixel.com/privacy" target="_blank">Privacy Policy</a> (<a href="https://shortpixel.com/privacy#gdpr" target="_blank">GDPR compliant</a>).','shortpixel-image-optimiser');
|
907 |
?>
|
@@ -1049,12 +1065,12 @@ class ShortPixelView {
|
|
1049 |
</p>
|
1050 |
<div style="margin-top: 10px;">
|
1051 |
<input type="radio" name="resize_type" id="resize_type_outer" value="outer" <?php echo($settings->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
|
1052 |
-
<img src="<?php echo(
|
1053 |
-
srcset='<?php echo(
|
1054 |
title="<?php _e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
|
1055 |
<input type="radio" name="resize_type" id="resize_type_inner" value="inner" <?php echo($settings->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
|
1056 |
-
<img src="<?php echo(
|
1057 |
-
srcset='<?php echo(
|
1058 |
title="<?php _e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
|
1059 |
<div style="display:inline-block;margin-left: 20px;"><a href="https://blog.shortpixel.com/resize-images/" class="shortpixel-help-link" target="_blank">
|
1060 |
<span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
|
@@ -1188,7 +1204,7 @@ class ShortPixelView {
|
|
1188 |
<td>
|
1189 |
<?php if(!($st == "Empty")) { ?>
|
1190 |
<a href="javascript:none();" title="<?php echo $fullStat; ?>" style="text-decoration: none;">
|
1191 |
-
<img src='<?php echo(
|
1192 |
</a> <?php } echo($typ.$st.$err); ?>
|
1193 |
|
1194 |
</td>
|
33 |
</div>
|
34 |
</div>
|
35 |
<?php } ?>
|
36 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/robo-scared.png'));?>"
|
37 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/robo-scared.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/robo-scared@2x.png' ));?> 2x'
|
38 |
class='short-pixel-notice-icon'>
|
39 |
<h3><?php /* translators: header of the alert box */ _e('Quota Exceeded','shortpixel-image-optimiser');?></h3>
|
40 |
<p><?php /* translators: body of the alert box */
|
118 |
<?php }
|
119 |
}
|
120 |
if($icon){ ?>
|
121 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/robo-' . $icon . '.png'));?>"
|
122 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/robo-' . $icon . '.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/robo-' . $icon . '@2x.png' ));?> 2x'
|
123 |
class='short-pixel-notice-icon'>
|
124 |
<?php } ?>
|
125 |
<h3><?php _e('ShortPixel Image Optimizer','shortpixel-image-optimiser');
|
212 |
//$this->ctrl->outputHSBeacon();
|
213 |
\ShortPixel\HelpScout::outputBeacon($this->ctrl->getApiKey());
|
214 |
|
|
|
215 |
$this->bulkType = $this->ctrl->getPrioQ()->getBulkTypeForDisplay(); // adding to the mess
|
216 |
$hider = ($this->bulkType == ShortPixelQueue::BULK_TYPE_RESTORE) ? 'sp-hidden' : '';
|
217 |
?>
|
233 |
<div style='width:165px; display:inline-block; padding-left: 5px'>
|
234 |
<input type='checkbox' id='thumbnails' name='thumbnails' onclick='ShortPixel.checkThumbsUpdTotal(this)' <?php echo($this->ctrl->processThumbnails() ? "checked":"");?>>
|
235 |
<?php _e('Include thumbnails','shortpixel-image-optimiser');?>
|
236 |
+
</div><br><br>
|
237 |
+
<div>
|
238 |
+
|
239 |
+
<input name="createWebp" type="checkbox" id="createWebp" value="1" <?php checked( $settings->createWebp, "1" );?> >
|
240 |
+
<label for="createWebp">
|
241 |
+
<?php _e('Also create <a href="http://blog.shortpixel.com/how-webp-images-can-speed-up-your-site/" target="_blank">WebP versions</a> of the images, <strong>for free</strong>.','shortpixel-image-optimiser');?>
|
242 |
+
</label>
|
243 |
+
|
244 |
</div><br>
|
245 |
<?php if($quotaData["totalProcessedMlFiles"] > 0) { ?>
|
246 |
<div class="bulk-label bulk-total"><?php _e('Total images','shortpixel-image-optimiser');?></div>
|
273 |
: "onclick=\"document.getElementById('startBulk').submit();\""); ?> class='button'>
|
274 |
<div style="width: 320px">
|
275 |
<div class="bulk-btn-img" class="bulk-btn-img">
|
276 |
+
<img src='<?php echo(wpSPIO()->plugin_url('res/img/robo-slider.png' ));?>'
|
277 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/robo-slider.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/robo-slider@2x.png' ));?> 2x'/>
|
278 |
</div>
|
279 |
<div class="bulk-btn-txt">
|
280 |
<?php printf(__('<span class="label">Start Optimizing</span><br> <span class="total">%s</span> images','shortpixel-image-optimiser'),
|
283 |
number_format(max(0, $quotaData['mainMlFiles'] - $quotaData['mainProcessedMlFiles']) + $customCount));?>
|
284 |
</div>
|
285 |
<div class="bulk-btn-img" class="bulk-btn-img">
|
286 |
+
<img src='<?php echo(wpSPIO()->plugin_url('res/img/arrow.png' ));?>'/>
|
287 |
</div>
|
288 |
</div>
|
289 |
</a>
|
351 |
<div class="sp-container">
|
352 |
<div class='sp-notice sp-notice-success sp-floating-block sp-single-width' style="height: 80px;overflow:hidden;">
|
353 |
<div style='float:left;margin:5px 20px 5px 0'>
|
354 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/slider.png' ));?>"
|
355 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/slider.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/slider@2x.png' ));?> 2x'>
|
356 |
</div>
|
357 |
<div class="sp-bulk-summary <?php echo $hider ?>">
|
358 |
<input type="text" value="<?php echo("" . round($averageCompression))?>" id="sp-total-optimization-dial" class="dial">
|
427 |
<a href="https://wordpress.org/support/view/plugin-reviews/shortpixel-image-optimiser?rate=5#postform" target="_blank">
|
428 |
<span>
|
429 |
<?php _e('Please rate us!','shortpixel-image-optimiser');?>
|
430 |
+
</span><br><img src="<?php echo(wpSPIO()->plugin_url('res/img/stars.png' ));?>">
|
431 |
</a>
|
432 |
</div>
|
433 |
<?php } ?>
|
563 |
<input type='checkbox' id='bulk-thumbnails' name='thumbnails' <?php echo($this->ctrl->processThumbnails() ? "checked":"");?>
|
564 |
onchange="ShortPixel.onBulkThumbsCheck(this)"> <?php _e('Include thumbnails','shortpixel-image-optimiser');?><br><br>
|
565 |
|
566 |
+
<div>
|
567 |
+
|
568 |
+
<input name="createWebp" type="checkbox" id="createWebp" value="1" <?php checked( $settings->createWebp, "1" );?> >
|
569 |
+
<label for="createWebp">
|
570 |
+
<?php _e('Also create <a href="http://blog.shortpixel.com/how-webp-images-can-speed-up-your-site/" target="_blank">WebP versions</a> of the images, <strong>for free</strong>.','shortpixel-image-optimiser');?>
|
571 |
+
</label>
|
572 |
+
|
573 |
+
</div><br>
|
574 |
+
|
575 |
<a class='button' style="float: right;" href='<?php echo add_query_arg('part','bulk-restore-all'); ?> '><?php _e('Bulk Restore Images','shortpixel-image-optimiser'); ?></a>
|
576 |
|
577 |
<input type='submit' name='bulkProcess' id='bulkProcess' class='button button-primary' value='<?php _e('Restart Optimizing','shortpixel-image-optimiser');?>'
|
604 |
<div id="short-pixel-notice-squirrly" class="sp-notice sp-notice-info bulk-progress bulk-progress-partners sp-floating-block sp-full-width">
|
605 |
<div style="float:right"><a href="javascript:dismissShortPixelNotice('squirrly')"><?php _e('Dismiss','shortpixel-image-optimiser');?></a></div>
|
606 |
<a href="https://my.squirrly.co/go120073/squirrly.co/short-pixel-seo" target="_blank">
|
607 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/squirrly.png' ));?>" height="50">
|
608 |
<div><?php _e('While you wait for your images to optimize, check out Squirrly, a great plugin for further boosting your SEO.','shortpixel-image-optimiser');?></div>
|
609 |
</a>
|
610 |
</div>
|
613 |
<div class="sp-floating-block sp-notice bulk-notices-parent">
|
614 |
<div class="bulk-notice-container">
|
615 |
<div class="bulk-notice-msg bulk-lengthy">
|
616 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/loading-dark-big.gif' ));?>">
|
617 |
<?php _e('Lengthy operation in progress:','shortpixel-image-optimiser');?><br>
|
618 |
<?php _e('Optimizing image','shortpixel-image-optimiser');?> <a href="#" data-href="<?php echo(get_admin_url());?>/post.php?post=__ID__&action=edit" target="_blank">placeholder.png</a>
|
619 |
</div>
|
620 |
<div class="bulk-notice-msg bulk-maintenance">
|
621 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/loading-dark-big.gif' ));?>">
|
622 |
<?php _e("The ShortPixel API is in maintenance mode. Please don't close this window. The bulk will resume automatically as soon as the API is back online.",'shortpixel-image-optimiser');?>
|
623 |
</div>
|
624 |
<div class="bulk-notice-msg bulk-queue-full">
|
625 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/loading-dark-big.gif' ));?>">
|
626 |
<?php _e("Too many images processing simultaneously for your site, automatically retrying in 1 min. Please don't close this window.",'shortpixel-image-optimiser');?>
|
627 |
</div>
|
628 |
<div class="bulk-notice-msg bulk-error" id="bulk-error-template">
|
629 |
<div style="float: right; margin-top: -4px; margin-right: -3px;">
|
630 |
<a href="javascript:void(0);" onclick="ShortPixel.removeBulkMsg(this)" style='color: #c32525;font-size: 20px;text-decoration: none;'>×</a>
|
631 |
</div>
|
632 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/exclamation-big.png' ));?>">
|
633 |
<span class="sp-err-title"><?php _e('Error processing file:','shortpixel-image-optimiser');?><br></span>
|
634 |
<span class="sp-err-content"><?php echo $message; ?></span> <a class="sp-post-link" href="<?php echo(get_admin_url());?>/post.php?post=__ID__&action=edit" target="_blank">placeholder.png</a>
|
635 |
</div>
|
636 |
<div class="bulk-notice-msg bulk-searching">
|
637 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/loading-dark-big.gif' ));?>">
|
638 |
<?php _e('Please bear with me. ShortPixel is checking many already optimized images to see if they\'re OK, so the progress bar could stop for a while.','shortpixel-image-optimiser');?><br>
|
639 |
</div>
|
640 |
</div>
|
729 |
<?php }?>
|
730 |
<div id="bulk-progress" class="progress" >
|
731 |
<div class="progress-img" style="left: <?php echo($percent);?>%;">
|
732 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/slider.png' ));?>"
|
733 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/slider.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/slider@2x.png' ));?> 2x'>
|
734 |
<span><?php echo($percentAfter);?></span>
|
735 |
</div>
|
736 |
<div class="progress-left" style="width: <?php echo($percent);?>%"><?php echo($percentBefore);?></div>
|
810 |
?>
|
811 |
<br/>
|
812 |
<div class="clearfix <?php echo($extraClass);?>" style="background-color: #fff; border-left-style: solid; border-left-width: 4px; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 1px 12px;;width: 95%">
|
813 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/robo-' . $icon . '.png'));?>"
|
814 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/robo-' . $icon . '.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/robo-' . $icon . '@2x.png' ));?> 2x'
|
815 |
class='short-pixel-notice-icon'>
|
816 |
<p><?php echo($notice['msg']);?></p>
|
817 |
</div>
|
916 |
}
|
917 |
?><br><span style="position:relative;">
|
918 |
<input name="tos" type="checkbox" id="tos">
|
919 |
+
<img id="tos-robo" src="<?php echo(wpSPIO()->plugin_url('res/img/slider.png' ));?>" style="position: absolute;left: -95px;bottom: -26px;display:none;">
|
920 |
+
<img id="tos-hand" src="<?php echo(wpSPIO()->plugin_url('res/img/point.png' ));?>" style="position: absolute;left: -39px;bottom: -9px;display:none;">
|
921 |
</span>
|
922 |
<?php _e('I have read and I agree to the <a href="https://shortpixel.com/tos" target="_blank">Terms of Service</a> and the <a href="https://shortpixel.com/privacy" target="_blank">Privacy Policy</a> (<a href="https://shortpixel.com/privacy#gdpr" target="_blank">GDPR compliant</a>).','shortpixel-image-optimiser');
|
923 |
?>
|
1065 |
</p>
|
1066 |
<div style="margin-top: 10px;">
|
1067 |
<input type="radio" name="resize_type" id="resize_type_outer" value="outer" <?php echo($settings->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
|
1068 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?>"
|
1069 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/resize-outer@2x.png' ));?> 2x'
|
1070 |
title="<?php _e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
|
1071 |
<input type="radio" name="resize_type" id="resize_type_inner" value="inner" <?php echo($settings->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
|
1072 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?>"
|
1073 |
+
srcset='<?php echo(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/resize-inner@2x.png' ));?> 2x'
|
1074 |
title="<?php _e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
|
1075 |
<div style="display:inline-block;margin-left: 20px;"><a href="https://blog.shortpixel.com/resize-images/" class="shortpixel-help-link" target="_blank">
|
1076 |
<span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
|
1204 |
<td>
|
1205 |
<?php if(!($st == "Empty")) { ?>
|
1206 |
<a href="javascript:none();" title="<?php echo $fullStat; ?>" style="text-decoration: none;">
|
1207 |
+
<img src='<?php echo(wpSPIO()->plugin_url('res/img/info-icon.png' ));?>' style="margin-bottom: -2px;"/>
|
1208 |
</a> <?php } echo($typ.$st.$err); ?>
|
1209 |
|
1210 |
</td>
|
@@ -22,6 +22,8 @@ class WPShortPixel {
|
|
22 |
|
23 |
public static $PROCESSABLE_EXTENSIONS = array('jpg', 'jpeg', 'gif', 'png', 'pdf');
|
24 |
|
|
|
|
|
25 |
public function __construct() {
|
26 |
$this->timer = time();
|
27 |
|
@@ -37,11 +39,33 @@ class WPShortPixel {
|
|
37 |
$this->_settings = new WPShortPixelSettings();
|
38 |
$this->_apiInterface = new ShortPixelAPI($this->_settings);
|
39 |
$this->cloudflareApi = new ShortPixelCloudFlareApi($this->_settings->cloudflareEmail, $this->_settings->cloudflareAuthKey, $this->_settings->cloudflareZoneID);
|
40 |
-
$this->hasNextGen = ShortPixelNextGenAdapter::hasNextGen();
|
41 |
$this->spMetaDao = new ShortPixelCustomMetaDao(new WpShortPixelDb(), $this->_settings->excludePatterns);
|
42 |
$this->prioQ = (! defined('SHORTPIXEL_NOFLOCK')) ? new ShortPixelQueue($this, $this->_settings) : new ShortPixelQueueDB($this, $this->_settings);
|
43 |
$this->view = new ShortPixelView($this);
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
define('QUOTA_EXCEEDED', $this->view->getQuotaExceededHTML());
|
47 |
|
@@ -148,36 +172,18 @@ class WPShortPixel {
|
|
148 |
add_action( 'admin_footer', array($this, 'admin_footer_js') );
|
149 |
add_action( 'admin_head', array( $this, 'headCSS') );
|
150 |
|
151 |
-
if($this->_settings->frontBootstrap && shortPixelCheckQueue()) {
|
152 |
-
//only if we have something in the queue - usually we never get here if the queue is empty but for some hooks...
|
153 |
-
//also need to have it in the front footer then
|
154 |
-
add_action( 'wp_footer', array( &$this, 'shortPixelJS') );
|
155 |
-
//need to add the nopriv action for when items exist in the queue and no user is logged in
|
156 |
-
add_action( 'wp_ajax_nopriv_shortpixel_image_processing', array( &$this, 'handleImageProcessing') );
|
157 |
-
}
|
158 |
//register a method to display admin notices if necessary
|
159 |
add_action('admin_notices', array( &$this, 'displayAdminNotices'));
|
160 |
|
161 |
$this->migrateBackupFolder();
|
162 |
-
|
163 |
-
|
164 |
-
// only load backed, or when frontend processing is enabled.
|
165 |
-
if (is_admin() || $this->_settings->frontBootstrap )
|
166 |
-
{
|
167 |
-
$keyControl = new \ShortPixel\apiKeyController();
|
168 |
-
$keyControl->setShortPixel($this);
|
169 |
-
$keyControl->load();
|
170 |
-
}
|
171 |
}
|
172 |
|
173 |
-
|
174 |
-
public function WPShortPixel() {
|
175 |
-
$this->__construct();
|
176 |
-
}
|
177 |
|
178 |
// @hook admin menu
|
179 |
// @todo move to plugin class
|
180 |
function registerAdminPage( ) {
|
|
|
181 |
if($this->spMetaDao->hasFoldersTable() && count($this->spMetaDao->getFolders())) {
|
182 |
/*translators: title and menu name for the Other media page*/
|
183 |
add_media_page( __('Other Media Optimized by ShortPixel','shortpixel-image-optimiser'), __('Other Media','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-custom', array( &$this, 'listCustomMedia' ) );
|
@@ -186,7 +192,7 @@ class WPShortPixel {
|
|
186 |
add_media_page( __('ShortPixel Bulk Process','shortpixel-image-optimiser'), __('Bulk ShortPixel','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-bulk', array( &$this, 'bulkProcess' ) );
|
187 |
}
|
188 |
|
189 |
-
public static function shortPixelActivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
|
190 |
{
|
191 |
self::shortPixelDeactivatePlugin();
|
192 |
if(SHORTPIXEL_RESET_ON_ACTIVATE === true && WP_DEBUG === true) { //force reset plugin counters, only on specific occasions and on test environments
|
@@ -205,9 +211,9 @@ class WPShortPixel {
|
|
205 |
self::alterHtaccess(); //add the htaccess lines
|
206 |
}
|
207 |
WPShortPixelSettings::onActivate();
|
208 |
-
}
|
209 |
|
210 |
-
public static function shortPixelDeactivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
|
211 |
{
|
212 |
ShortPixelQueue::resetBulk();
|
213 |
(! defined('SHORTPIXEL_NOFLOCK')) ? ShortPixelQueue::resetPrio() : ShortPixelQueueDB::resetPrio();
|
@@ -220,16 +226,16 @@ class WPShortPixel {
|
|
220 |
self::alterHtaccess(true);
|
221 |
|
222 |
@unlink(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
|
223 |
-
}
|
224 |
|
225 |
-
public static function shortPixelUninstallPlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
|
226 |
{
|
227 |
$settings = new WPShortPixelSettings();
|
228 |
if($settings->removeSettingsOnDeletePlugin == 1) {
|
229 |
WPShortPixelSettings::debugResetOptions();
|
230 |
insert_with_markers( get_home_path() . '.htaccess', 'ShortPixelWebp', '');
|
231 |
}
|
232 |
-
}
|
233 |
|
234 |
public function getConflictingPlugins() {
|
235 |
$conflictPlugins = array(
|
@@ -333,6 +339,15 @@ class WPShortPixel {
|
|
333 |
)
|
334 |
));
|
335 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
336 |
$found = array();
|
337 |
foreach($conflictPlugins as $name => $path) {
|
338 |
$action = ( isset($path['action']) ) ? $path['action'] : null;
|
@@ -481,13 +496,15 @@ class WPShortPixel {
|
|
481 |
/** @todo Plugin init class. Try to get rid of inline JS. Also still loads on all WP pages, prevent that. */
|
482 |
function shortPixelJS() {
|
483 |
|
|
|
|
|
|
|
484 |
//require_once(ABSPATH . 'wp-admin/includes/screen.php');
|
485 |
if(function_exists('get_current_screen')) {
|
486 |
$screen = get_current_screen();
|
487 |
|
488 |
if(is_object($screen)) {
|
489 |
|
490 |
-
|
491 |
wp_enqueue_style('short-pixel-bar.min.css', plugins_url('/res/css/short-pixel-bar.min.css',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
|
492 |
if( in_array($screen->id, array('attachment', 'upload', 'settings_page_wp-shortpixel', 'media_page_wp-short-pixel-bulk', 'media_page_wp-short-pixel-custom'))) {
|
493 |
wp_enqueue_style('short-pixel.min.css', plugins_url('/res/css/short-pixel.min.css',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
|
@@ -580,6 +597,9 @@ class WPShortPixel {
|
|
580 |
* @todo Find a better solution for this */
|
581 |
public function admin_footer_js()
|
582 |
{
|
|
|
|
|
|
|
583 |
if(function_exists('get_current_screen')) {
|
584 |
$screen = get_current_screen();
|
585 |
if(is_object($screen)) {
|
@@ -759,8 +779,12 @@ class WPShortPixel {
|
|
759 |
return $meta;
|
760 |
}
|
761 |
|
|
|
|
|
762 |
// some plugins (e.g. WP e-Commerce) call the wp_attachment_metadata on just editing the image...
|
763 |
$dbMeta = wp_get_attachment_metadata($ID);
|
|
|
|
|
764 |
$refresh = false;
|
765 |
|
766 |
if(isset($dbMeta['ShortPixelImprovement'])) {
|
@@ -774,11 +798,11 @@ class WPShortPixel {
|
|
774 |
self::log("Handle Media Library Image Upload #{$ID}");
|
775 |
//self::log("STACK: " . json_encode(debug_backtrace()));
|
776 |
|
777 |
-
if(!$this->_settings->optimizePdfs && 'pdf' ===
|
778 |
//pdf is not optimized automatically as per the option, but can be optimized by button. Nothing to do.
|
779 |
return $meta;
|
780 |
}
|
781 |
-
elseif(!
|
782 |
//in some rare cases (images added from the front-end) it's an image but get_attached_file returns null (the record is not yet saved in the DB)
|
783 |
//in this case add it to the queue nevertheless
|
784 |
$this->prioQ->push($ID);
|
@@ -880,7 +904,8 @@ class WPShortPixel {
|
|
880 |
return $converter->checkConvertMediaPng2Jpg($itemHandler);
|
881 |
}
|
882 |
|
883 |
-
|
|
|
884 |
if(!($folder = $this->spMetaDao->getFolder(SHORTPIXEL_UPLOADS_BASE . '/gravity_forms'))) {
|
885 |
return;
|
886 |
}
|
@@ -893,7 +918,7 @@ class WPShortPixel {
|
|
893 |
$localPath = str_replace($uploadDir['baseurl'], SHORTPIXEL_UPLOADS_BASE, $value);
|
894 |
|
895 |
return $this->addPathToCustomFolder($localPath, $folder->getId(), 0);
|
896 |
-
}
|
897 |
|
898 |
/**
|
899 |
* this is hooked onto the NextGen upload
|
@@ -1093,6 +1118,7 @@ class WPShortPixel {
|
|
1093 |
$maxTime = min(SHORTPIXEL_MAX_EXECUTION_TIME, 90);
|
1094 |
$timeoutThreshold = 5; // will adapt this with the maximum time needed for one pass
|
1095 |
$passTime = time();
|
|
|
1096 |
for ($sanityCheck = 0, $crtStartQueryID = $startQueryID;
|
1097 |
($crtStartQueryID >= $endQueryID) && (count($itemList) < SHORTPIXEL_PRESEND_ITEMS) && ($sanityCheck < 150)
|
1098 |
&& (time() - $this->timer < $maxTime - $timeoutThreshold); $sanityCheck++) {
|
@@ -1195,7 +1221,7 @@ class WPShortPixel {
|
|
1195 |
)
|
1196 |
) {
|
1197 |
|
1198 |
-
$
|
1199 |
$URLsAndPATHs = $item->getURLsAndPATHs(true, true, $this->_settings->optimizeRetina, $this->_settings->excludeSizes);
|
1200 |
Log::addDebug('Gathering URLS AND PATHS', array($URLsAndPATHs));
|
1201 |
if(count($URLsAndPATHs["URLs"])) {
|
@@ -1348,7 +1374,7 @@ class WPShortPixel {
|
|
1348 |
{ //take from custom images if any left to optimize - only if bulk was ever started
|
1349 |
//but first refresh if it wasn't refreshed in the last hour
|
1350 |
if(time() - $this->_settings->hasCustomFolders > 3600) {
|
1351 |
-
$notice = null; $this->refreshCustomFolders(
|
1352 |
$this->_settings->hasCustomFolders = time();
|
1353 |
}
|
1354 |
|
@@ -1458,7 +1484,7 @@ class WPShortPixel {
|
|
1458 |
$sizes = $meta->getThumbs();
|
1459 |
if('pdf' == strtolower(pathinfo($result["Filename"], PATHINFO_EXTENSION))) {
|
1460 |
// echo($result["Filename"] . " ESTE --> "); die(var_dump(strtolower(pathinfo($result["Filename"], PATHINFO_EXTENSION))));
|
1461 |
-
$thumb =
|
1462 |
$bkThumb = '';
|
1463 |
} else {
|
1464 |
if(count($sizes)) {
|
@@ -1487,7 +1513,6 @@ class WPShortPixel {
|
|
1487 |
//$backupUrl = content_url() . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/";
|
1488 |
//or even better:
|
1489 |
$backupUrl = SHORTPIXEL_BACKUP_URL . "/";
|
1490 |
-
//$urlBkPath = $this->_apiInterface->returnSubDir(get_attached_file($ID));
|
1491 |
$urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath(), ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
|
1492 |
$bkThumb = $backupUrl . $urlBkPath . $thumb;
|
1493 |
}
|
@@ -1645,7 +1670,7 @@ class WPShortPixel {
|
|
1645 |
$meta = $itemHandler->getMeta();
|
1646 |
|
1647 |
Log::addDebug('Finding Thumbs on path' . $meta->getPath());
|
1648 |
-
|
1649 |
|
1650 |
$fs = new \ShortPixel\FileSystemController();
|
1651 |
$mainFile = $fs->getFile($meta->getPath());
|
@@ -1729,6 +1754,7 @@ class WPShortPixel {
|
|
1729 |
|
1730 |
private function sendToProcessing($itemHandler, $compressionType = false, $onlyThumbs = false) {
|
1731 |
//conversion of PNG 2 JPG for existing images
|
|
|
1732 |
if($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) { //currently only for ML
|
1733 |
$rawMeta = $this->checkConvertMediaPng2Jpg($itemHandler);
|
1734 |
|
@@ -1741,9 +1767,18 @@ class WPShortPixel {
|
|
1741 |
$URLsAndPATHs = $this->getURLsAndPATHs($itemHandler, NULL, $onlyThumbs);
|
1742 |
Log::addDebug('Send to PRocessing - URLS -', array($URLsAndPATHs) );
|
1743 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1744 |
//find thumbs that are not listed in the metadata and add them in the sizes array
|
1745 |
-
$this->addUnlistedThumbs($itemHandler);
|
1746 |
-
$meta = $itemHandler->getMeta();
|
1747 |
|
1748 |
//find any missing thumbs files and mark them as such
|
1749 |
$miss = $meta->getThumbsMissing();
|
@@ -1775,8 +1810,8 @@ class WPShortPixel {
|
|
1775 |
}
|
1776 |
}
|
1777 |
|
1778 |
-
|
1779 |
-
|
1780 |
|
1781 |
|
1782 |
$this->_apiInterface->doRequests($URLsAndPATHs['URLs'], false, $itemHandler,
|
@@ -1839,14 +1874,15 @@ class WPShortPixel {
|
|
1839 |
$this->prioQ->push($imageId);
|
1840 |
$itemHandler = new ShortPixelMetaFacade($imageId);
|
1841 |
|
1842 |
-
$
|
1843 |
-
|
|
|
1844 |
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
|
1845 |
} else {
|
1846 |
try {
|
1847 |
$this->sendToProcessing($itemHandler, false, $itemHandler->getMeta()->getThumbsTodo());
|
1848 |
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
|
1849 |
-
} catch(Exception $e) {
|
1850 |
$itemHandler->getMeta();
|
1851 |
$errCode = $e->getCode() < 0 ? $e->getCode() : ShortPixelAPI::ERR_FILE_NOT_FOUND;
|
1852 |
$itemHandler->setError($errCode, $e->getMessage());
|
@@ -2045,15 +2081,19 @@ class WPShortPixel {
|
|
2045 |
protected function doRestore($attachmentID, $rawMeta = null) {
|
2046 |
do_action("shortpixel_before_restore_image", $attachmentID);
|
2047 |
|
2048 |
-
$fs =
|
2049 |
-
$origFile = get_attached_file($attachmentID);
|
2050 |
-
// $file = get_attached_file($attachmentID);
|
2051 |
|
2052 |
// Setup Original File and Data. This is used to determine backup path.
|
2053 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2054 |
$filePath = (string) $fsFile->getFileDir();
|
2055 |
|
2056 |
-
$itemHandler = new ShortPixelMetaFacade($attachmentID);
|
2057 |
if($rawMeta) {
|
2058 |
$itemHandler->setRawMeta($rawMeta); //prevent another database trip
|
2059 |
} else {
|
@@ -2068,6 +2108,9 @@ class WPShortPixel {
|
|
2068 |
return false;
|
2069 |
}
|
2070 |
|
|
|
|
|
|
|
2071 |
// Get correct Backup Folder and file. .
|
2072 |
$sizes = isset($rawMeta["sizes"]) ? $rawMeta["sizes"] : array();
|
2073 |
$bkFolder = $fs->getDirectory($this->getBackupFolderAny($fsFile->getFullPath(), $sizes));
|
@@ -2097,14 +2140,13 @@ class WPShortPixel {
|
|
2097 |
|
2098 |
// find the jpg optimized image in backups, and mark to remove
|
2099 |
if ($bkFile->exists())
|
2100 |
-
|
2101 |
|
2102 |
// $baseUrl = ShortPixelPng2Jpg::removeUrlProtocol(trailingslashit(str_replace($image, "", $imageUrl))); //make the base url protocol agnostic if it's not already
|
2103 |
|
2104 |
// not needed, we don't do this weird remove anymore.
|
2105 |
$baseRelPath = ''; // trailingslashit(dirname($image)); // @todo Replace this (string) $fsFile->getFileDir();
|
2106 |
|
2107 |
-
|
2108 |
$toReplace[ShortPixelPng2Jpg::removeUrlProtocol($imageUrl)] = $baseUrl . $baseRelPath . wp_basename($png2jpgMain);
|
2109 |
foreach($sizes as $key => $size) {
|
2110 |
if(isset($png2jpgSizes[$key])) {
|
@@ -2112,7 +2154,7 @@ class WPShortPixel {
|
|
2112 |
}
|
2113 |
|
2114 |
$backuppedSize = $fs->getFile($backupFileDir . $size['file'] );
|
2115 |
-
Log::addDebug('
|
2116 |
if ($backuppedSize->exists())
|
2117 |
{
|
2118 |
$toUnlink['PATHs'][] = $backuppedSize ->getFullPath();
|
@@ -2164,7 +2206,9 @@ class WPShortPixel {
|
|
2164 |
return false;
|
2165 |
}
|
2166 |
$bkCount++;
|
2167 |
-
|
|
|
|
|
2168 |
}
|
2169 |
}
|
2170 |
if(!$bkCount) {
|
@@ -2183,11 +2227,22 @@ class WPShortPixel {
|
|
2183 |
if($bkCount) { // backups, if exist
|
2184 |
//main file
|
2185 |
if($main) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2186 |
//$this->renameWithRetina($bkFile, $file);
|
2187 |
if (! $bkFile->move($fsFile))
|
2188 |
{
|
2189 |
Log::addError('DoRestore failed restoring backup', array($bkFile->getFullPath(), $fsFile->getFullPath() ));
|
2190 |
}
|
|
|
2191 |
$retinaBK = $fs->getFile( $bkFile->getFileDir()->getPath() . $bkFile->getFileBase() . '@2x' . $bkFile->getExtension() );
|
2192 |
if ($retinaBK->exists())
|
2193 |
{
|
@@ -2229,7 +2284,14 @@ class WPShortPixel {
|
|
2229 |
$duplicates = ShortPixelMetaFacade::getWPMLDuplicates($attachmentID);
|
2230 |
foreach($duplicates as $ID) {
|
2231 |
//Added sanitizeMeta (improved with @unserialize) as per https://secure.helpscout.net/conversation/725053586/11656?folderId=1117588
|
2232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2233 |
if(isset($crtMeta['previous_meta'])) continue;
|
2234 |
if( isset($crtMeta["ShortPixelImprovement"]) && is_numeric($crtMeta["ShortPixelImprovement"])
|
2235 |
&& 0 + $crtMeta["ShortPixelImprovement"] < 5 && $this->_settings->under5Percent > 0) {
|
@@ -2251,36 +2313,59 @@ class WPShortPixel {
|
|
2251 |
$crtMeta['sizes'] = $png2jpgSizes;
|
2252 |
} else {
|
2253 |
//this was an image converted on upload, regenerate the thumbs using the PNG main image BUT deactivate temporarily the filter!!
|
2254 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2255 |
$crtMeta = wp_generate_attachment_metadata($ID, $png2jpgMain);
|
2256 |
-
add_filter( 'wp_generate_attachment_metadata', '
|
2257 |
}
|
2258 |
}
|
2259 |
//wp_update_attachment_metadata($ID, $crtMeta);
|
|
|
2260 |
update_post_meta($ID, '_wp_attachment_metadata', $crtMeta);
|
|
|
2261 |
if($attachmentID == $ID) { //copy back the metadata which will be returned.
|
2262 |
$rawMeta = $crtMeta;
|
2263 |
}
|
|
|
2264 |
}
|
2265 |
|
2266 |
if($png2jpgMain) {
|
2267 |
$spPng2Jpg = new ShortPixelPng2Jpg($this->_settings);
|
2268 |
$spPng2Jpg->png2JpgUpdateUrls(array(), $toReplace);
|
2269 |
}
|
2270 |
-
|
2271 |
if(isset($toUnlink['PATHs'])) foreach($toUnlink['PATHs'] as $unlink) {
|
2272 |
if($png2jpgMain) {
|
2273 |
WPShortPixel::log("PNG2JPG unlink $unlink");
|
2274 |
$unlinkFile = $fs->getFile($unlink);
|
2275 |
$unlinkFile->delete();
|
2276 |
-
|
2277 |
}
|
2278 |
//try also the .webp
|
2279 |
$unlinkWebpSymlink = trailingslashit(dirname($unlink)) . wp_basename($unlink, '.' . pathinfo($unlink, PATHINFO_EXTENSION)) . '.webp';
|
2280 |
$unlinkWebp = $unlink . '.webp';
|
2281 |
-
WPShortPixel::log("
|
2282 |
-
|
2283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2284 |
}
|
2285 |
} catch(Exception $e) {
|
2286 |
$this->throwNotice('generic-err', $e->getMessage());
|
@@ -2289,6 +2374,8 @@ class WPShortPixel {
|
|
2289 |
|
2290 |
/** It's being dumped because settings like .webp can be cached */
|
2291 |
$this->maybeDumpFromProcessedOnServer($itemHandler, $toUnlink);
|
|
|
|
|
2292 |
do_action("shortpixel_after_restore_image", $attachmentID);
|
2293 |
return $rawMeta;
|
2294 |
}
|
@@ -2383,7 +2470,7 @@ class WPShortPixel {
|
|
2383 |
$meta->setStatus(3);
|
2384 |
$this->spMetaDao->update($meta);
|
2385 |
|
2386 |
-
|
2387 |
//}
|
2388 |
|
2389 |
return $meta;
|
@@ -2467,12 +2554,14 @@ class WPShortPixel {
|
|
2467 |
public function handleOptimizeThumbs() {
|
2468 |
$ID = intval($_GET['attachment_ID']);
|
2469 |
$meta = wp_get_attachment_metadata($ID);
|
|
|
2470 |
|
2471 |
// default return;
|
2472 |
//$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "message" => (isset($meta['ShortPixelImprovement']) ? __('No thumbnails to optimize for ID: ','shortpixel-image-optimiser') : __('Please optimize image for ID: ','shortpixel-image-optimiser')) . $ID);
|
2473 |
$error = array('Status' => ShortPixelAPI::STATUS_SKIP, 'message' => __('Unspecified Error on Thumbnails for: ') . $ID);
|
2474 |
|
2475 |
-
|
|
|
2476 |
//WpShortPixelMediaLbraryAdapter::getSizesNotExcluded($meta['sizes'], $this->_settings->excludeSizes);
|
2477 |
$thumbsCount = count($includedSizes);
|
2478 |
|
@@ -2564,8 +2653,10 @@ class WPShortPixel {
|
|
2564 |
$this->getQuotaInformation();
|
2565 |
}
|
2566 |
|
|
|
2567 |
public function handleDeleteAttachmentInBackup($ID) {
|
2568 |
-
$
|
|
|
2569 |
$meta = wp_get_attachment_metadata($ID);
|
2570 |
|
2571 |
|
@@ -2574,7 +2665,8 @@ class WPShortPixel {
|
|
2574 |
try {
|
2575 |
$SubDir = ShortPixelMetaFacade::returnSubDir($file);
|
2576 |
|
2577 |
-
|
|
|
2578 |
|
2579 |
if ( !empty($meta['file']) )
|
2580 |
{
|
@@ -2582,7 +2674,8 @@ class WPShortPixel {
|
|
2582 |
//remove thumbs thumbnails
|
2583 |
if(isset($meta["sizes"])) {
|
2584 |
foreach($meta["sizes"] as $size => $imageData) {
|
2585 |
-
|
|
|
2586 |
}
|
2587 |
}
|
2588 |
}
|
@@ -2631,8 +2724,10 @@ class WPShortPixel {
|
|
2631 |
&& isset($this->_settings->currentStats['time'])
|
2632 |
&& (time() - $this->_settings->currentStats['time'] < $time))
|
2633 |
{
|
|
|
2634 |
return $this->_settings->currentStats;
|
2635 |
} else {
|
|
|
2636 |
$imageCount = WpShortPixelMediaLbraryAdapter::countAllProcessable($this->_settings);
|
2637 |
$quotaData['time'] = time();
|
2638 |
$quotaData['optimizePdfs'] = $this->_settings->optimizePdfs;
|
@@ -2694,7 +2789,7 @@ class WPShortPixel {
|
|
2694 |
}
|
2695 |
|
2696 |
/** View for Custom media
|
2697 |
-
* @todo Move this
|
2698 |
*/
|
2699 |
public function listCustomMedia() {
|
2700 |
if( ! class_exists( 'ShortPixelListTable' ) ) {
|
@@ -2702,7 +2797,7 @@ class WPShortPixel {
|
|
2702 |
}
|
2703 |
if(isset($_REQUEST['refresh']) && esc_attr($_REQUEST['refresh']) == 1) {
|
2704 |
$notice = null;
|
2705 |
-
$this->refreshCustomFolders(
|
2706 |
}
|
2707 |
if(isset($_REQUEST['action']) && esc_attr($_REQUEST['action']) == 'optimize' && isset($_REQUEST['image'])) {
|
2708 |
//die(ShortPixelMetaFacade::queuedId(ShortPixelMetaFacade::CUSTOM_TYPE, $_REQUEST['image']));
|
@@ -2796,6 +2891,12 @@ class WPShortPixel {
|
|
2796 |
} else {
|
2797 |
$this->_settings->processThumbnails = 0;
|
2798 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2799 |
//clean the custom files errors in order to process them again
|
2800 |
if($this->_settings->hasCustomFolders) {
|
2801 |
$this->spMetaDao->resetFailed();
|
@@ -2972,13 +3073,13 @@ class WPShortPixel {
|
|
2972 |
die(self::formatBytes(self::folderSize(SHORTPIXEL_BACKUP_FOLDER)));
|
2973 |
}
|
2974 |
|
|
|
2975 |
public function browseContent() {
|
2976 |
if ( !current_user_can( 'manage_options' ) ) {
|
2977 |
wp_die(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser'));
|
2978 |
}
|
2979 |
-
|
2980 |
$root = self::getCustomFolderBase();
|
2981 |
-
|
2982 |
|
2983 |
$postDir = rawurldecode($root.(isset($_POST['dir']) ? trim($_POST['dir']) : null ));
|
2984 |
// set checkbox if multiSelect set to true
|
@@ -2988,28 +3089,35 @@ class WPShortPixel {
|
|
2988 |
|
2989 |
if( file_exists($postDir) ) {
|
2990 |
|
2991 |
-
|
|
|
|
|
|
|
|
|
|
|
2992 |
$returnDir = substr($postDir, strlen($root));
|
2993 |
|
2994 |
-
natcasesort($files);
|
2995 |
|
2996 |
-
if( count($
|
2997 |
echo "<ul class='jqueryFileTree'>";
|
2998 |
-
foreach(
|
2999 |
|
3000 |
-
|
|
|
|
|
3001 |
|
3002 |
-
$htmlRel = str_replace("'", "'", $returnDir . $
|
3003 |
-
$htmlName = htmlentities($
|
3004 |
-
|
3005 |
|
3006 |
-
if(
|
3007 |
//KEEP the spaces in front of the rel values - it's a trick to make WP Hide not replace the wp-content path
|
3008 |
-
|
3009 |
echo "<li class='directory collapsed'>{$checkbox}<a rel=' " .$htmlRel. "/'>" . $htmlName . "</a></li>";
|
3010 |
-
|
3011 |
echo "<li class='file ext_{$ext}'>{$checkbox}<a rel=' " . $htmlRel . "'>" . $htmlName . "</a></li>";
|
3012 |
-
}
|
3013 |
}
|
3014 |
}
|
3015 |
|
@@ -3152,7 +3260,7 @@ class WPShortPixel {
|
|
3152 |
'filesTodo' => $stats['totalFiles'] - $stats['totalProcessedFiles'],
|
3153 |
'estimated' => $this->_settings->optimizeUnlisted || $this->_settings->optimizeRetina ? 'true' : 'false',
|
3154 |
/* */
|
3155 |
-
'iconsUrl' => base64_encode(
|
3156 |
))),
|
3157 |
'cookies' => array()
|
3158 |
));
|
@@ -3165,29 +3273,56 @@ class WPShortPixel {
|
|
3165 |
|
3166 |
// TODO - Part of the folder model.
|
3167 |
public static function getCustomFolderBase() {
|
3168 |
-
|
3169 |
-
|
3170 |
-
|
3171 |
-
|
3172 |
-
$up = wp_upload_dir();
|
3173 |
-
return realpath($up['basedir']);
|
3174 |
-
}
|
3175 |
}
|
3176 |
|
3177 |
-
// TODO - Should be part of folder model
|
|
|
3178 |
protected function fullRefreshCustomFolder($path, &$notice) {
|
3179 |
$folder = $this->spMetaDao->getFolder($path);
|
3180 |
$diff = $folder->checkFolderContents(array('ShortPixelCustomMetaDao', 'getPathFiles'));
|
3181 |
-
}
|
|
|
3182 |
|
3183 |
// @todo - Should be part of folder model
|
3184 |
-
|
|
|
3185 |
$customFolders = array();
|
|
|
|
|
3186 |
if($this->_settings->hasCustomFolders) {
|
3187 |
$customFolders = $this->spMetaDao->getFolders();
|
3188 |
foreach($customFolders as $folder) {
|
3189 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3190 |
try {
|
|
|
3191 |
$mt = $folder->getFolderContentsChangeDate();
|
3192 |
if($mt > strtotime($folder->getTsUpdated())) {
|
3193 |
$fileList = $folder->getFileList(strtotime($folder->getTsUpdated()));
|
@@ -3204,8 +3339,8 @@ class WPShortPixel {
|
|
3204 |
} else {
|
3205 |
$notice = array("status" => "error", "msg" => $ex->getMessage());
|
3206 |
}
|
3207 |
-
}
|
3208 |
-
}
|
3209 |
}
|
3210 |
return $customFolders;
|
3211 |
}
|
@@ -3215,6 +3350,13 @@ class WPShortPixel {
|
|
3215 |
*/
|
3216 |
public static function alterHtaccess( $clear = false ){
|
3217 |
// [BS] Backward compat. 11/03/2019 - remove possible settings from root .htaccess
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3218 |
$upload_dir = wp_upload_dir();
|
3219 |
$upload_base = trailingslashit($upload_dir['basedir']);
|
3220 |
|
@@ -3358,7 +3500,7 @@ class WPShortPixel {
|
|
3358 |
if($validate) {
|
3359 |
$args['body']['DomainCheck'] = get_site_url();
|
3360 |
$args['body']['Info'] = get_bloginfo('version') . '|' . phpversion();
|
3361 |
-
$imageCount = WpShortPixelMediaLbraryAdapter::
|
3362 |
$args['body']['ImagesCount'] = $imageCount['mainFiles'];
|
3363 |
$args['body']['ThumbsCount'] = $imageCount['totalFiles'] - $imageCount['mainFiles'];
|
3364 |
$argsStr .= "&DomainCheck={$args['body']['DomainCheck']}&Info={$args['body']['Info']}&ImagesCount={$imageCount['mainFiles']}&ThumbsCount={$args['body']['ThumbsCount']}";
|
@@ -3513,12 +3655,13 @@ class WPShortPixel {
|
|
3513 |
return;
|
3514 |
}
|
3515 |
|
3516 |
-
$
|
|
|
3517 |
$data = ShortPixelMetaFacade::sanitizeMeta(wp_get_attachment_metadata($id));
|
3518 |
$itemHandler = new ShortPixelMetaFacade($id);
|
3519 |
$meta = $itemHandler->getMeta();
|
3520 |
|
3521 |
-
$fileExtension = strtolower(
|
3522 |
$invalidKey = !$this->_settings->verifiedKey;
|
3523 |
$quotaExceeded = $this->_settings->quotaExceeded;
|
3524 |
$renderData = array("id" => $id, "showActions" => (current_user_can( 'manage_options' ) || current_user_can( 'upload_files' ) || current_user_can( 'edit_posts' )));
|
@@ -3550,12 +3693,12 @@ class WPShortPixel {
|
|
3550 |
&& !($data['ShortPixelImprovement'] == 0 && isset($data['ShortPixel']['WaitingProcessing'])) //for images that erroneously have ShortPixelImprovement = 0 when WaitingProcessing
|
3551 |
) { //already optimized
|
3552 |
$thumbsOptList = isset($data['ShortPixel']['thumbsOptList']) ? $data['ShortPixel']['thumbsOptList'] : array();
|
3553 |
-
list($thumbsToOptimizeList, $sizesCount) = $this->getThumbsToOptimize($data, $file);
|
3554 |
|
3555 |
$renderData['status'] = $fileExtension == "pdf" ? 'pdfOptimized' : 'imgOptimized';
|
3556 |
$renderData['percent'] = $this->optimizationPercentIfPng2Jpg($data);
|
3557 |
$renderData['bonus'] = ($data['ShortPixelImprovement'] < 5);
|
3558 |
-
$renderData['backup'] = $this->getBackupFolderAny($file, $sizesCount? $data['sizes'] : array());
|
3559 |
$renderData['type'] = isset($data['ShortPixel']['type']) ? $data['ShortPixel']['type'] : '';
|
3560 |
$renderData['invType'] = ShortPixelAPI::getCompressionTypeName($this->getOtherCompressionTypes(ShortPixelAPI::getCompressionTypeCode($renderData['type'])));
|
3561 |
$renderData['thumbsTotal'] = $sizesCount;
|
@@ -3572,14 +3715,14 @@ class WPShortPixel {
|
|
3572 |
$renderData['quotaExceeded'] = $quotaExceeded;
|
3573 |
$webP = 0;
|
3574 |
if($extended) {
|
3575 |
-
if(file_exists(dirname($file) . '/' . ShortPixelAPI::MB_basename($file, '.'.$fileExtension) . '.webp' )){
|
3576 |
$webP++;
|
3577 |
}
|
3578 |
if(isset($data['sizes'])) {
|
3579 |
foreach($data['sizes'] as $key => $size) {
|
3580 |
if (strpos($key, ShortPixelMeta::WEBP_THUMB_PREFIX) === 0) continue;
|
3581 |
$sizeName = $size['file'];
|
3582 |
-
if(file_exists(dirname($file) . '/' . ShortPixelAPI::MB_basename($sizeName, '.'.$fileExtension) . '.webp' )){
|
3583 |
$webP++;
|
3584 |
}
|
3585 |
}
|
@@ -3640,7 +3783,7 @@ class WPShortPixel {
|
|
3640 |
* @return array Array of Thumbs to Optimize - only the filename - , and count of sizes not excluded ...
|
3641 |
*/
|
3642 |
function getThumbsToOptimize($data, $filepath) {
|
3643 |
-
// This function moved, but lack of other destination.
|
3644 |
return WpShortPixelMediaLbraryAdapter::getThumbsToOptimize($data, $filepath);
|
3645 |
|
3646 |
}
|
@@ -3660,7 +3803,6 @@ class WPShortPixel {
|
|
3660 |
* @param array $columns Array of colums sortable
|
3661 |
* @todo Should be part of media library controller. ( is request best hook for this?)
|
3662 |
*/
|
3663 |
-
|
3664 |
function columnOrderFilterBy($vars) {
|
3665 |
if ( isset( $vars['orderby'] ) && 'ShortPixel Compression' == $vars['orderby'] ) {
|
3666 |
$vars = array_merge( $vars, array(
|
@@ -3668,11 +3810,35 @@ class WPShortPixel {
|
|
3668 |
'orderby' => 'meta_value_num',
|
3669 |
) );
|
3670 |
}
|
3671 |
-
if ( 'upload.php' == $GLOBALS['pagenow'] &&
|
3672 |
|
3673 |
-
$status = $_GET['shortpixel_status'];
|
3674 |
$metaKey = '_shortpixel_status';
|
3675 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3676 |
|
3677 |
$vars = array_merge( $vars, array(
|
3678 |
'meta_query' => array(
|
@@ -3684,6 +3850,7 @@ class WPShortPixel {
|
|
3684 |
)
|
3685 |
));
|
3686 |
}
|
|
|
3687 |
return $vars;
|
3688 |
}
|
3689 |
|
@@ -3696,21 +3863,36 @@ class WPShortPixel {
|
|
3696 |
if ( $scr->base !== 'upload' ) return;
|
3697 |
|
3698 |
$status = filter_input(INPUT_GET, 'shortpixel_status', FILTER_SANITIZE_STRING );
|
3699 |
-
|
3700 |
-
|
3701 |
'show_option_none' => 'ShortPixel',
|
3702 |
'name' => 'shortpixel_status',
|
3703 |
'selected' => $selected
|
3704 |
-
);
|
3705 |
// wp_dropdown_users( $args );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3706 |
|
3707 |
-
echo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3708 |
. "\t<option value='0'" . ($status == 0 ? " selected='selected'" : "") . ">All images</option>\n"
|
3709 |
. "\t<option value='2'" . ($status == 2 ? " selected='selected'" : "") . ">Optimized</option>\n"
|
3710 |
. "\t<option value='none'" . ($status == 'none' ? " selected='selected'" : "") . ">Unoptimized</option>\n"
|
3711 |
. "\t<option value='1'" . ($status == 1 ? " selected='selected'" : "") . ">Pending</option>\n"
|
3712 |
. "\t<option value='-1'" . ($status < 0 ? " selected='selected'" : "") . ">Errors</option>\n"
|
3713 |
-
. "</select>");
|
3714 |
}
|
3715 |
|
3716 |
/** Calculates Optimization if PNG2Jpg does something
|
@@ -3753,11 +3935,12 @@ class WPShortPixel {
|
|
3753 |
*/
|
3754 |
public function onDeleteImage($post_id) {
|
3755 |
$itemHandler = new ShortPixelMetaFacade($post_id);
|
3756 |
-
$urlsPaths = $itemHandler->getURLsAndPATHs(true, false, true, array(), true);
|
3757 |
if(count($urlsPaths['PATHs'])) {
|
3758 |
$this->maybeDumpFromProcessedOnServer($itemHandler, $urlsPaths);
|
3759 |
$this->deleteBackupsAndWebPs($urlsPaths['PATHs']);
|
3760 |
}
|
|
|
3761 |
return $itemHandler; //return it because we call it also on replace and on replace we need to follow this by deleting SP metadata, on delete it
|
3762 |
}
|
3763 |
|
@@ -3773,20 +3956,35 @@ class WPShortPixel {
|
|
3773 |
return;
|
3774 |
}
|
3775 |
|
|
|
|
|
|
|
3776 |
$backupFolder = trailingslashit($this->getBackupFolder($paths[0]));
|
3777 |
foreach($paths as $path) {
|
3778 |
$pos = strrpos($path, ".");
|
|
|
3779 |
if ($pos !== false) {
|
3780 |
//$webpPath = substr($path, 0, $pos) . ".webp";
|
3781 |
//echo($webpPath . "<br>");
|
3782 |
-
|
3783 |
-
|
|
|
|
|
3784 |
}
|
3785 |
//delte also the backups for image and retina correspondent
|
3786 |
-
$fileName =
|
3787 |
-
$extension =
|
3788 |
-
|
3789 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3790 |
}
|
3791 |
}
|
3792 |
//
|
@@ -3805,7 +4003,7 @@ class WPShortPixel {
|
|
3805 |
return $defaults;
|
3806 |
}
|
3807 |
|
3808 |
-
// todo move NGG specific function to own integration
|
3809 |
public function nggColumns( $defaults ) {
|
3810 |
$this->nggColumnIndex = count($defaults) + 1;
|
3811 |
add_filter( 'ngg_manage_images_column_' . $this->nggColumnIndex . '_header', array( &$this, 'nggColumnHeader' ) );
|
@@ -3865,15 +4063,8 @@ class WPShortPixel {
|
|
3865 |
|
3866 |
// @todo Should be utility function
|
3867 |
static public function formatBytes($bytes, $precision = 2) {
|
3868 |
-
|
3869 |
-
|
3870 |
-
$bytes = max($bytes, 0);
|
3871 |
-
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
3872 |
-
$pow = min($pow, count($units) - 1);
|
3873 |
|
3874 |
-
$bytes /= pow(1024, $pow);
|
3875 |
-
|
3876 |
-
return round($bytes, $precision) . ' ' . $units[$pow];
|
3877 |
}
|
3878 |
|
3879 |
/** Checks if file can be processed. Mainly against exclusion
|
@@ -3896,8 +4087,11 @@ class WPShortPixel {
|
|
3896 |
return self::_isProcessablePath($path, $excludeExtensions, $excludePatterns);
|
3897 |
}
|
3898 |
|
|
|
3899 |
static public function _isProcessable($ID, $excludeExtensions = array(), $excludePatterns = array(), $meta = false) {
|
3900 |
-
$
|
|
|
|
|
3901 |
if(isset($excludePatterns) && is_array($excludePatterns)) {
|
3902 |
foreach($excludePatterns as $excludePattern) {
|
3903 |
$type = $excludePattern["type"];
|
@@ -3986,13 +4180,30 @@ class WPShortPixel {
|
|
3986 |
*/
|
3987 |
static public function folderSize($path) {
|
3988 |
$total_size = 0;
|
3989 |
-
|
3990 |
-
|
|
|
|
|
|
|
|
|
|
|
3991 |
} else {
|
3992 |
return $total_size;
|
3993 |
}
|
3994 |
-
|
3995 |
-
foreach($files as $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3996 |
if ($t<>"." && $t<>"..")
|
3997 |
{
|
3998 |
$currentFile = $cleanPath . $t;
|
@@ -4005,7 +4216,7 @@ class WPShortPixel {
|
|
4005 |
$total_size += $size;
|
4006 |
}
|
4007 |
}
|
4008 |
-
}
|
4009 |
return $total_size;
|
4010 |
}
|
4011 |
|
@@ -4183,7 +4394,7 @@ class WPShortPixel {
|
|
4183 |
<div id="shortpixel-hs-button-blind" class="shortpixel-hs-button-blind"></div>
|
4184 |
<div id="shortpixel-hs-tools" class="shortpixel-hs-tools">
|
4185 |
<a href="javascript:shortpixelToggleHS();" class="shortpixel-hs-tools-docs" title="<?php _e('Search through our online documentation.', 'shortpixel-image-optimiser'); ?>">
|
4186 |
-
<img src="<?php echo(
|
4187 |
</a>
|
4188 |
</div>
|
4189 |
<script>
|
22 |
|
23 |
public static $PROCESSABLE_EXTENSIONS = array('jpg', 'jpeg', 'gif', 'png', 'pdf');
|
24 |
|
25 |
+
private static $first_run = false;
|
26 |
+
|
27 |
public function __construct() {
|
28 |
$this->timer = time();
|
29 |
|
39 |
$this->_settings = new WPShortPixelSettings();
|
40 |
$this->_apiInterface = new ShortPixelAPI($this->_settings);
|
41 |
$this->cloudflareApi = new ShortPixelCloudFlareApi($this->_settings->cloudflareEmail, $this->_settings->cloudflareAuthKey, $this->_settings->cloudflareZoneID);
|
42 |
+
$this->hasNextGen = wpSPIO()->env()->has_nextgen; //ShortPixelNextGenAdapter::hasNextGen();
|
43 |
$this->spMetaDao = new ShortPixelCustomMetaDao(new WpShortPixelDb(), $this->_settings->excludePatterns);
|
44 |
$this->prioQ = (! defined('SHORTPIXEL_NOFLOCK')) ? new ShortPixelQueue($this, $this->_settings) : new ShortPixelQueueDB($this, $this->_settings);
|
45 |
$this->view = new ShortPixelView($this);
|
46 |
|
47 |
+
if (self::$first_run === false)
|
48 |
+
{
|
49 |
+
$this->loadHooks();
|
50 |
+
}
|
51 |
+
|
52 |
+
// only load backed, or when frontend processing is enabled.
|
53 |
+
if (is_admin() || $this->_settings->frontBootstrap )
|
54 |
+
{
|
55 |
+
$keyControl = new \ShortPixel\apiKeyController();
|
56 |
+
$keyControl->setShortPixel($this);
|
57 |
+
$keyControl->load();
|
58 |
+
}
|
59 |
+
|
60 |
+
}
|
61 |
+
|
62 |
+
/** Fire only once hooks. In time these function mostly should be divided between controllers / hook itself moved to ShortPixel Plugin */
|
63 |
+
protected function loadHooks()
|
64 |
+
{
|
65 |
+
self::$first_run = true;
|
66 |
+
load_plugin_textdomain('shortpixel-image-optimiser', false, plugin_basename(dirname( SHORTPIXEL_PLUGIN_FILE )).'/lang');
|
67 |
+
|
68 |
+
$isAdminUser = current_user_can( 'manage_options' );
|
69 |
|
70 |
define('QUOTA_EXCEEDED', $this->view->getQuotaExceededHTML());
|
71 |
|
172 |
add_action( 'admin_footer', array($this, 'admin_footer_js') );
|
173 |
add_action( 'admin_head', array( $this, 'headCSS') );
|
174 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
//register a method to display admin notices if necessary
|
176 |
add_action('admin_notices', array( &$this, 'displayAdminNotices'));
|
177 |
|
178 |
$this->migrateBackupFolder();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
}
|
180 |
|
181 |
+
|
|
|
|
|
|
|
182 |
|
183 |
// @hook admin menu
|
184 |
// @todo move to plugin class
|
185 |
function registerAdminPage( ) {
|
186 |
+
return;
|
187 |
if($this->spMetaDao->hasFoldersTable() && count($this->spMetaDao->getFolders())) {
|
188 |
/*translators: title and menu name for the Other media page*/
|
189 |
add_media_page( __('Other Media Optimized by ShortPixel','shortpixel-image-optimiser'), __('Other Media','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-custom', array( &$this, 'listCustomMedia' ) );
|
192 |
add_media_page( __('ShortPixel Bulk Process','shortpixel-image-optimiser'), __('Bulk ShortPixel','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-bulk', array( &$this, 'bulkProcess' ) );
|
193 |
}
|
194 |
|
195 |
+
/*public static function shortPixelActivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
|
196 |
{
|
197 |
self::shortPixelDeactivatePlugin();
|
198 |
if(SHORTPIXEL_RESET_ON_ACTIVATE === true && WP_DEBUG === true) { //force reset plugin counters, only on specific occasions and on test environments
|
211 |
self::alterHtaccess(); //add the htaccess lines
|
212 |
}
|
213 |
WPShortPixelSettings::onActivate();
|
214 |
+
} */
|
215 |
|
216 |
+
/* public static function shortPixelDeactivatePlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
|
217 |
{
|
218 |
ShortPixelQueue::resetBulk();
|
219 |
(! defined('SHORTPIXEL_NOFLOCK')) ? ShortPixelQueue::resetPrio() : ShortPixelQueueDB::resetPrio();
|
226 |
self::alterHtaccess(true);
|
227 |
|
228 |
@unlink(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
|
229 |
+
} */
|
230 |
|
231 |
+
/* public static function shortPixelUninstallPlugin()//reset some params to avoid trouble for plugins that were activated/deactivated/activated
|
232 |
{
|
233 |
$settings = new WPShortPixelSettings();
|
234 |
if($settings->removeSettingsOnDeletePlugin == 1) {
|
235 |
WPShortPixelSettings::debugResetOptions();
|
236 |
insert_with_markers( get_home_path() . '.htaccess', 'ShortPixelWebp', '');
|
237 |
}
|
238 |
+
} */
|
239 |
|
240 |
public function getConflictingPlugins() {
|
241 |
$conflictPlugins = array(
|
339 |
)
|
340 |
));
|
341 |
}
|
342 |
+
if(!$this->_settings->frontBootstrap){
|
343 |
+
$conflictPlugins['Bulk Images to Posts Frontend'] = array (
|
344 |
+
'action'=>'Change Setting',
|
345 |
+
'data'=>'bulk-images-to-posts-front/bulk-images-to-posts.php',
|
346 |
+
'href'=>'options-general.php?page=wp-shortpixel-settings&part=adv-settings#siteAuthUser',
|
347 |
+
'details' => __('This plugin is uploading images in front-end so please activate the "Process in front-end" advanced option in ShortPixel in order to have your images optimized.','shortpixel-image-optimiser')
|
348 |
+
);
|
349 |
+
}
|
350 |
+
|
351 |
$found = array();
|
352 |
foreach($conflictPlugins as $name => $path) {
|
353 |
$action = ( isset($path['action']) ) ? $path['action'] : null;
|
496 |
/** @todo Plugin init class. Try to get rid of inline JS. Also still loads on all WP pages, prevent that. */
|
497 |
function shortPixelJS() {
|
498 |
|
499 |
+
if (! \wpSPIO()->env()->is_screen_to_use )
|
500 |
+
return; // not ours, don't load JS and such.
|
501 |
+
|
502 |
//require_once(ABSPATH . 'wp-admin/includes/screen.php');
|
503 |
if(function_exists('get_current_screen')) {
|
504 |
$screen = get_current_screen();
|
505 |
|
506 |
if(is_object($screen)) {
|
507 |
|
|
|
508 |
wp_enqueue_style('short-pixel-bar.min.css', plugins_url('/res/css/short-pixel-bar.min.css',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
|
509 |
if( in_array($screen->id, array('attachment', 'upload', 'settings_page_wp-shortpixel', 'media_page_wp-short-pixel-bulk', 'media_page_wp-short-pixel-custom'))) {
|
510 |
wp_enqueue_style('short-pixel.min.css', plugins_url('/res/css/short-pixel.min.css',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
|
597 |
* @todo Find a better solution for this */
|
598 |
public function admin_footer_js()
|
599 |
{
|
600 |
+
if (! \wpSPIO()->env()->is_screen_to_use )
|
601 |
+
return; // not ours, don't load JS and such.
|
602 |
+
|
603 |
if(function_exists('get_current_screen')) {
|
604 |
$screen = get_current_screen();
|
605 |
if(is_object($screen)) {
|
779 |
return $meta;
|
780 |
}
|
781 |
|
782 |
+
$fs = \wpSPIO()->filesystem();
|
783 |
+
|
784 |
// some plugins (e.g. WP e-Commerce) call the wp_attachment_metadata on just editing the image...
|
785 |
$dbMeta = wp_get_attachment_metadata($ID);
|
786 |
+
$currentFile = $fs->getAttachedFile($ID);
|
787 |
+
|
788 |
$refresh = false;
|
789 |
|
790 |
if(isset($dbMeta['ShortPixelImprovement'])) {
|
798 |
self::log("Handle Media Library Image Upload #{$ID}");
|
799 |
//self::log("STACK: " . json_encode(debug_backtrace()));
|
800 |
|
801 |
+
if(!$this->_settings->optimizePdfs && 'pdf' === $currentFile->getExtension() ) {
|
802 |
//pdf is not optimized automatically as per the option, but can be optimized by button. Nothing to do.
|
803 |
return $meta;
|
804 |
}
|
805 |
+
elseif(! $currentFile->exists() && isset($meta['file']) && in_array(strtolower(pathinfo($meta['file'], PATHINFO_EXTENSION)), self::$PROCESSABLE_EXTENSIONS)) {
|
806 |
//in some rare cases (images added from the front-end) it's an image but get_attached_file returns null (the record is not yet saved in the DB)
|
807 |
//in this case add it to the queue nevertheless
|
808 |
$this->prioQ->push($ID);
|
904 |
return $converter->checkConvertMediaPng2Jpg($itemHandler);
|
905 |
}
|
906 |
|
907 |
+
// moved to external.
|
908 |
+
/* public function handleGravityFormsImageField($value) {
|
909 |
if(!($folder = $this->spMetaDao->getFolder(SHORTPIXEL_UPLOADS_BASE . '/gravity_forms'))) {
|
910 |
return;
|
911 |
}
|
918 |
$localPath = str_replace($uploadDir['baseurl'], SHORTPIXEL_UPLOADS_BASE, $value);
|
919 |
|
920 |
return $this->addPathToCustomFolder($localPath, $folder->getId(), 0);
|
921 |
+
} */
|
922 |
|
923 |
/**
|
924 |
* this is hooked onto the NextGen upload
|
1118 |
$maxTime = min(SHORTPIXEL_MAX_EXECUTION_TIME, 90);
|
1119 |
$timeoutThreshold = 5; // will adapt this with the maximum time needed for one pass
|
1120 |
$passTime = time();
|
1121 |
+
// @todo If this fails, the bulk will since no start/stop Id's will change */
|
1122 |
for ($sanityCheck = 0, $crtStartQueryID = $startQueryID;
|
1123 |
($crtStartQueryID >= $endQueryID) && (count($itemList) < SHORTPIXEL_PRESEND_ITEMS) && ($sanityCheck < 150)
|
1124 |
&& (time() - $this->timer < $maxTime - $timeoutThreshold); $sanityCheck++) {
|
1221 |
)
|
1222 |
) {
|
1223 |
|
1224 |
+
$item->searchUnlistedFiles(); // $this->addUnlistedThumbs($item); // search for unlisted thumbs, if that is the setting.
|
1225 |
$URLsAndPATHs = $item->getURLsAndPATHs(true, true, $this->_settings->optimizeRetina, $this->_settings->excludeSizes);
|
1226 |
Log::addDebug('Gathering URLS AND PATHS', array($URLsAndPATHs));
|
1227 |
if(count($URLsAndPATHs["URLs"])) {
|
1374 |
{ //take from custom images if any left to optimize - only if bulk was ever started
|
1375 |
//but first refresh if it wasn't refreshed in the last hour
|
1376 |
if(time() - $this->_settings->hasCustomFolders > 3600) {
|
1377 |
+
$notice = null; $this->refreshCustomFolders();
|
1378 |
$this->_settings->hasCustomFolders = time();
|
1379 |
}
|
1380 |
|
1484 |
$sizes = $meta->getThumbs();
|
1485 |
if('pdf' == strtolower(pathinfo($result["Filename"], PATHINFO_EXTENSION))) {
|
1486 |
// echo($result["Filename"] . " ESTE --> "); die(var_dump(strtolower(pathinfo($result["Filename"], PATHINFO_EXTENSION))));
|
1487 |
+
$thumb = wpSPIO()->plugin_url('res/img/logo-pdf.png' );
|
1488 |
$bkThumb = '';
|
1489 |
} else {
|
1490 |
if(count($sizes)) {
|
1513 |
//$backupUrl = content_url() . "/" . SHORTPIXEL_UPLOADS_NAME . "/" . SHORTPIXEL_BACKUP . "/";
|
1514 |
//or even better:
|
1515 |
$backupUrl = SHORTPIXEL_BACKUP_URL . "/";
|
|
|
1516 |
$urlBkPath = ShortPixelMetaFacade::returnSubDir($meta->getPath(), ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE);
|
1517 |
$bkThumb = $backupUrl . $urlBkPath . $thumb;
|
1518 |
}
|
1670 |
$meta = $itemHandler->getMeta();
|
1671 |
|
1672 |
Log::addDebug('Finding Thumbs on path' . $meta->getPath());
|
1673 |
+
//$thumbs = WpShortPixelMediaLbraryAdapter::findThumbs($meta->getPath());
|
1674 |
|
1675 |
$fs = new \ShortPixel\FileSystemController();
|
1676 |
$mainFile = $fs->getFile($meta->getPath());
|
1754 |
|
1755 |
private function sendToProcessing($itemHandler, $compressionType = false, $onlyThumbs = false) {
|
1756 |
//conversion of PNG 2 JPG for existing images
|
1757 |
+
|
1758 |
if($itemHandler->getType() == ShortPixelMetaFacade::MEDIA_LIBRARY_TYPE) { //currently only for ML
|
1759 |
$rawMeta = $this->checkConvertMediaPng2Jpg($itemHandler);
|
1760 |
|
1767 |
$URLsAndPATHs = $this->getURLsAndPATHs($itemHandler, NULL, $onlyThumbs);
|
1768 |
Log::addDebug('Send to PRocessing - URLS -', array($URLsAndPATHs) );
|
1769 |
|
1770 |
+
// Limit 'send to processing' by URL, see function.
|
1771 |
+
$result = WpShortPixelMediaLbraryAdapter::checkRequestLimiter($URLsAndPATHs['URLs']);
|
1772 |
+
|
1773 |
+
if (! $result) // already passed onto the processor.
|
1774 |
+
{
|
1775 |
+
Log::addDebug('Preventing sentToProcessing. Reported as already sent');
|
1776 |
+
return $URLsAndPATHs;
|
1777 |
+
}
|
1778 |
+
|
1779 |
+
$meta = $itemHandler->getMeta();
|
1780 |
//find thumbs that are not listed in the metadata and add them in the sizes array
|
1781 |
+
$itemHandler->searchUnlistedFiles(); // $this->addUnlistedThumbs($itemHandler);
|
|
|
1782 |
|
1783 |
//find any missing thumbs files and mark them as such
|
1784 |
$miss = $meta->getThumbsMissing();
|
1810 |
}
|
1811 |
}
|
1812 |
|
1813 |
+
$thumbObtList = $meta->getThumbsOptList();
|
1814 |
+
$missing = $meta->getThumbsMissing();
|
1815 |
|
1816 |
|
1817 |
$this->_apiInterface->doRequests($URLsAndPATHs['URLs'], false, $itemHandler,
|
1874 |
$this->prioQ->push($imageId);
|
1875 |
$itemHandler = new ShortPixelMetaFacade($imageId);
|
1876 |
|
1877 |
+
$itemFile = \wpSPIO()->filesystem()->getAttachedFile($imageId);
|
1878 |
+
|
1879 |
+
if(!$manual && 'pdf' === $itemFile->getExtension() && !$this->_settings->optimizePdfs) {
|
1880 |
$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "Message" => $imageId);
|
1881 |
} else {
|
1882 |
try {
|
1883 |
$this->sendToProcessing($itemHandler, false, $itemHandler->getMeta()->getThumbsTodo());
|
1884 |
$ret = array("Status" => ShortPixelAPI::STATUS_SUCCESS, "Message" => "");
|
1885 |
+
} catch(Exception $e) { //$path Exception("Post metadata is corrupt (No attachment URL)")
|
1886 |
$itemHandler->getMeta();
|
1887 |
$errCode = $e->getCode() < 0 ? $e->getCode() : ShortPixelAPI::ERR_FILE_NOT_FOUND;
|
1888 |
$itemHandler->setError($errCode, $e->getMessage());
|
2081 |
protected function doRestore($attachmentID, $rawMeta = null) {
|
2082 |
do_action("shortpixel_before_restore_image", $attachmentID);
|
2083 |
|
2084 |
+
$fs = \wpSPIO()->filesystem();
|
|
|
|
|
2085 |
|
2086 |
// Setup Original File and Data. This is used to determine backup path.
|
2087 |
+
\wpSPIO()->loadModel('image');
|
2088 |
+
|
2089 |
+
$imageObj = new \ShortPixel\ImageModel();
|
2090 |
+
$imageObj->setbyPostID($attachmentID);
|
2091 |
+
|
2092 |
+
$fsFile = $imageObj->getFile();
|
2093 |
+
//$fsFile = $fs->getAttachedFile($attachmentID);
|
2094 |
$filePath = (string) $fsFile->getFileDir();
|
2095 |
|
2096 |
+
$itemHandler = $imageObj->getFacade(); //new ShortPixelMetaFacade($attachmentID);
|
2097 |
if($rawMeta) {
|
2098 |
$itemHandler->setRawMeta($rawMeta); //prevent another database trip
|
2099 |
} else {
|
2108 |
return false;
|
2109 |
}
|
2110 |
|
2111 |
+
// -sigh- to do something after possibly downloading and getting paths, but before any conversions.
|
2112 |
+
do_action('shortpixel_restore_after_pathget', $attachmentID);
|
2113 |
+
|
2114 |
// Get correct Backup Folder and file. .
|
2115 |
$sizes = isset($rawMeta["sizes"]) ? $rawMeta["sizes"] : array();
|
2116 |
$bkFolder = $fs->getDirectory($this->getBackupFolderAny($fsFile->getFullPath(), $sizes));
|
2140 |
|
2141 |
// find the jpg optimized image in backups, and mark to remove
|
2142 |
if ($bkFile->exists())
|
2143 |
+
$toUnlink['PATHs'][] = $bkFile->getFullPath();
|
2144 |
|
2145 |
// $baseUrl = ShortPixelPng2Jpg::removeUrlProtocol(trailingslashit(str_replace($image, "", $imageUrl))); //make the base url protocol agnostic if it's not already
|
2146 |
|
2147 |
// not needed, we don't do this weird remove anymore.
|
2148 |
$baseRelPath = ''; // trailingslashit(dirname($image)); // @todo Replace this (string) $fsFile->getFileDir();
|
2149 |
|
|
|
2150 |
$toReplace[ShortPixelPng2Jpg::removeUrlProtocol($imageUrl)] = $baseUrl . $baseRelPath . wp_basename($png2jpgMain);
|
2151 |
foreach($sizes as $key => $size) {
|
2152 |
if(isset($png2jpgSizes[$key])) {
|
2154 |
}
|
2155 |
|
2156 |
$backuppedSize = $fs->getFile($backupFileDir . $size['file'] );
|
2157 |
+
Log::addDebug('Checking for PNG Backup at - ', $backuppedSize->getFullPath() );
|
2158 |
if ($backuppedSize->exists())
|
2159 |
{
|
2160 |
$toUnlink['PATHs'][] = $backuppedSize ->getFullPath();
|
2206 |
return false;
|
2207 |
}
|
2208 |
$bkCount++;
|
2209 |
+
//$thumbsPaths[] = array('source' => $source, 'destination' => $destination);
|
2210 |
+
// This is to prevent double attempts on moving. If sizes have same definition, can have multiple same files in sizes, but they will be written to same path.
|
2211 |
+
$thumbsPaths[$destination->getFileName()] = array('source' => $source, 'destination' => $destination);
|
2212 |
}
|
2213 |
}
|
2214 |
if(!$bkCount) {
|
2227 |
if($bkCount) { // backups, if exist
|
2228 |
//main file
|
2229 |
if($main) {
|
2230 |
+
// new WP 5.3 feature when image is scaled if big.
|
2231 |
+
$origFile = $imageObj->has_original();
|
2232 |
+
if (is_object($origFile))
|
2233 |
+
{
|
2234 |
+
$bkOrigFile = $origFile->getBackUpFile();
|
2235 |
+
if ($bkOrigFile && $bkOrigFile->exists())
|
2236 |
+
$bkOrigFile->move($origFile);
|
2237 |
+
|
2238 |
+
Log::addDebug('Restore result - Backup oringal file', array($bkOrigFile, $origFile));
|
2239 |
+
}
|
2240 |
//$this->renameWithRetina($bkFile, $file);
|
2241 |
if (! $bkFile->move($fsFile))
|
2242 |
{
|
2243 |
Log::addError('DoRestore failed restoring backup', array($bkFile->getFullPath(), $fsFile->getFullPath() ));
|
2244 |
}
|
2245 |
+
|
2246 |
$retinaBK = $fs->getFile( $bkFile->getFileDir()->getPath() . $bkFile->getFileBase() . '@2x' . $bkFile->getExtension() );
|
2247 |
if ($retinaBK->exists())
|
2248 |
{
|
2284 |
$duplicates = ShortPixelMetaFacade::getWPMLDuplicates($attachmentID);
|
2285 |
foreach($duplicates as $ID) {
|
2286 |
//Added sanitizeMeta (improved with @unserialize) as per https://secure.helpscout.net/conversation/725053586/11656?folderId=1117588
|
2287 |
+
// $crtMeta = $attachmentID == $ID ? $rawMeta : ShortPixelMetaFacade::sanitizeMeta(wp_get_attachment_metadata($ID));
|
2288 |
+
$facade = new ShortPixelMetaFacade($ID);
|
2289 |
+
if ($attachmentID == $ID)
|
2290 |
+
$crtMeta = ShortPixelMetaFacade::sanitizeMeta(wp_get_attachment_metadata($ID));
|
2291 |
+
else {
|
2292 |
+
$crtMeta = $rawMeta;
|
2293 |
+
}
|
2294 |
+
|
2295 |
if(isset($crtMeta['previous_meta'])) continue;
|
2296 |
if( isset($crtMeta["ShortPixelImprovement"]) && is_numeric($crtMeta["ShortPixelImprovement"])
|
2297 |
&& 0 + $crtMeta["ShortPixelImprovement"] < 5 && $this->_settings->under5Percent > 0) {
|
2313 |
$crtMeta['sizes'] = $png2jpgSizes;
|
2314 |
} else {
|
2315 |
//this was an image converted on upload, regenerate the thumbs using the PNG main image BUT deactivate temporarily the filter!!
|
2316 |
+
$admin = \ShortPixel\adminController::getInstance();
|
2317 |
+
|
2318 |
+
//@todo Can be removed when test seems working.
|
2319 |
+
$test = remove_filter( 'wp_generate_attachment_metadata', array($admin,'handleImageUploadHook'),10);
|
2320 |
+
|
2321 |
+
if (! $test)
|
2322 |
+
Log::addWarn('Wp generate Attachment metadta filter not removed');
|
2323 |
$crtMeta = wp_generate_attachment_metadata($ID, $png2jpgMain);
|
2324 |
+
add_filter( 'wp_generate_attachment_metadata', array($admin,'handleImageUploadHook'), 10, 2 );
|
2325 |
}
|
2326 |
}
|
2327 |
//wp_update_attachment_metadata($ID, $crtMeta);
|
2328 |
+
// @todo Should call MetaFacade here!
|
2329 |
update_post_meta($ID, '_wp_attachment_metadata', $crtMeta);
|
2330 |
+
|
2331 |
if($attachmentID == $ID) { //copy back the metadata which will be returned.
|
2332 |
$rawMeta = $crtMeta;
|
2333 |
}
|
2334 |
+
|
2335 |
}
|
2336 |
|
2337 |
if($png2jpgMain) {
|
2338 |
$spPng2Jpg = new ShortPixelPng2Jpg($this->_settings);
|
2339 |
$spPng2Jpg->png2JpgUpdateUrls(array(), $toReplace);
|
2340 |
}
|
2341 |
+
|
2342 |
if(isset($toUnlink['PATHs'])) foreach($toUnlink['PATHs'] as $unlink) {
|
2343 |
if($png2jpgMain) {
|
2344 |
WPShortPixel::log("PNG2JPG unlink $unlink");
|
2345 |
$unlinkFile = $fs->getFile($unlink);
|
2346 |
$unlinkFile->delete();
|
2347 |
+
|
2348 |
}
|
2349 |
//try also the .webp
|
2350 |
$unlinkWebpSymlink = trailingslashit(dirname($unlink)) . wp_basename($unlink, '.' . pathinfo($unlink, PATHINFO_EXTENSION)) . '.webp';
|
2351 |
$unlinkWebp = $unlink . '.webp';
|
2352 |
+
WPShortPixel::log("DoRestore webp unlink $unlinkWebp");
|
2353 |
+
//@unlink($unlinkWebpSymlink);
|
2354 |
+
|
2355 |
+
$unlinkFile = $fs->getFile($unlinkWebpSymlink);
|
2356 |
+
if ($unlinkFile->exists())
|
2357 |
+
{
|
2358 |
+
Log::addDebug('DoRestore, Deleting - ', $unlinkWebpSymlink );
|
2359 |
+
$unlinkFile->delete();
|
2360 |
+
}
|
2361 |
+
|
2362 |
+
$unlinkFile = $fs->getFile($unlinkWebp);
|
2363 |
+
if ($unlinkFile->exists())
|
2364 |
+
{
|
2365 |
+
Log::addDebug('DoRestore, Deleting - ', $unlinkWebp );
|
2366 |
+
$unlinkFile->delete();
|
2367 |
+
}
|
2368 |
+
|
2369 |
}
|
2370 |
} catch(Exception $e) {
|
2371 |
$this->throwNotice('generic-err', $e->getMessage());
|
2374 |
|
2375 |
/** It's being dumped because settings like .webp can be cached */
|
2376 |
$this->maybeDumpFromProcessedOnServer($itemHandler, $toUnlink);
|
2377 |
+
$itemHandler->deleteItemCache(); // remove any cache
|
2378 |
+
$rawMeta = $itemHandler->getRawMeta();
|
2379 |
do_action("shortpixel_after_restore_image", $attachmentID);
|
2380 |
return $rawMeta;
|
2381 |
}
|
2470 |
$meta->setStatus(3);
|
2471 |
$this->spMetaDao->update($meta);
|
2472 |
|
2473 |
+
$itemHandler->deleteItemCache();
|
2474 |
//}
|
2475 |
|
2476 |
return $meta;
|
2554 |
public function handleOptimizeThumbs() {
|
2555 |
$ID = intval($_GET['attachment_ID']);
|
2556 |
$meta = wp_get_attachment_metadata($ID);
|
2557 |
+
$fs = \wpSPIO()->filesystem();
|
2558 |
|
2559 |
// default return;
|
2560 |
//$ret = array("Status" => ShortPixelAPI::STATUS_SKIP, "message" => (isset($meta['ShortPixelImprovement']) ? __('No thumbnails to optimize for ID: ','shortpixel-image-optimiser') : __('Please optimize image for ID: ','shortpixel-image-optimiser')) . $ID);
|
2561 |
$error = array('Status' => ShortPixelAPI::STATUS_SKIP, 'message' => __('Unspecified Error on Thumbnails for: ') . $ID);
|
2562 |
|
2563 |
+
$optFile = $fs->getAttachedFile($ID);
|
2564 |
+
list($includedSizes, $thumbsCount) = $this->getThumbsToOptimize($meta, $optFile->getFullPath());
|
2565 |
//WpShortPixelMediaLbraryAdapter::getSizesNotExcluded($meta['sizes'], $this->_settings->excludeSizes);
|
2566 |
$thumbsCount = count($includedSizes);
|
2567 |
|
2653 |
$this->getQuotaInformation();
|
2654 |
}
|
2655 |
|
2656 |
+
// @todo integrate this in a normal way / move @unlinks to proper fs delete.
|
2657 |
public function handleDeleteAttachmentInBackup($ID) {
|
2658 |
+
$fileObj = \wpSPIO()->filesystem()->getAttachedFile($ID);
|
2659 |
+
$file = $fileObj->getFullPath();
|
2660 |
$meta = wp_get_attachment_metadata($ID);
|
2661 |
|
2662 |
|
2665 |
try {
|
2666 |
$SubDir = ShortPixelMetaFacade::returnSubDir($file);
|
2667 |
|
2668 |
+
if (file_exists(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file)))
|
2669 |
+
@unlink(SHORTPIXEL_BACKUP_FOLDER . '/' . $SubDir . ShortPixelAPI::MB_basename($file));
|
2670 |
|
2671 |
if ( !empty($meta['file']) )
|
2672 |
{
|
2674 |
//remove thumbs thumbnails
|
2675 |
if(isset($meta["sizes"])) {
|
2676 |
foreach($meta["sizes"] as $size => $imageData) {
|
2677 |
+
if (file_exists($filesPath . ShortPixelAPI::MB_basename($imageData['file'])))
|
2678 |
+
@unlink($filesPath . ShortPixelAPI::MB_basename($imageData['file']));//remove thumbs
|
2679 |
}
|
2680 |
}
|
2681 |
}
|
2724 |
&& isset($this->_settings->currentStats['time'])
|
2725 |
&& (time() - $this->_settings->currentStats['time'] < $time))
|
2726 |
{
|
2727 |
+
Log::addDebug("CURRENT STATS FROM CACHE (not older than $time sec., currently " . (time() - $this->_settings->currentStats['time']) . ' sec. old)');
|
2728 |
return $this->_settings->currentStats;
|
2729 |
} else {
|
2730 |
+
Log::addDebug("CURRENT STATS (not older than $time) ARE BEING CALCULATED...");
|
2731 |
$imageCount = WpShortPixelMediaLbraryAdapter::countAllProcessable($this->_settings);
|
2732 |
$quotaData['time'] = time();
|
2733 |
$quotaData['optimizePdfs'] = $this->_settings->optimizePdfs;
|
2789 |
}
|
2790 |
|
2791 |
/** View for Custom media
|
2792 |
+
* @todo Move this to own view.
|
2793 |
*/
|
2794 |
public function listCustomMedia() {
|
2795 |
if( ! class_exists( 'ShortPixelListTable' ) ) {
|
2797 |
}
|
2798 |
if(isset($_REQUEST['refresh']) && esc_attr($_REQUEST['refresh']) == 1) {
|
2799 |
$notice = null;
|
2800 |
+
$this->refreshCustomFolders(true);
|
2801 |
}
|
2802 |
if(isset($_REQUEST['action']) && esc_attr($_REQUEST['action']) == 'optimize' && isset($_REQUEST['image'])) {
|
2803 |
//die(ShortPixelMetaFacade::queuedId(ShortPixelMetaFacade::CUSTOM_TYPE, $_REQUEST['image']));
|
2891 |
} else {
|
2892 |
$this->_settings->processThumbnails = 0;
|
2893 |
}
|
2894 |
+
|
2895 |
+
if ( isset($_POST['createWebp']) )
|
2896 |
+
$this->_settings->createWebp = 1;
|
2897 |
+
else
|
2898 |
+
$this->_settings->createWebp = 0;
|
2899 |
+
|
2900 |
//clean the custom files errors in order to process them again
|
2901 |
if($this->_settings->hasCustomFolders) {
|
2902 |
$this->spMetaDao->resetFailed();
|
3073 |
die(self::formatBytes(self::folderSize(SHORTPIXEL_BACKUP_FOLDER)));
|
3074 |
}
|
3075 |
|
3076 |
+
// ** Function to get filedata for a directory when adding custom media directory */
|
3077 |
public function browseContent() {
|
3078 |
if ( !current_user_can( 'manage_options' ) ) {
|
3079 |
wp_die(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser'));
|
3080 |
}
|
|
|
3081 |
$root = self::getCustomFolderBase();
|
3082 |
+
$fs = \wpSPIO()->filesystem();
|
3083 |
|
3084 |
$postDir = rawurldecode($root.(isset($_POST['dir']) ? trim($_POST['dir']) : null ));
|
3085 |
// set checkbox if multiSelect set to true
|
3089 |
|
3090 |
if( file_exists($postDir) ) {
|
3091 |
|
3092 |
+
|
3093 |
+
$dir = $fs->getDirectory($postDir);
|
3094 |
+
$files = $dir->getFiles();
|
3095 |
+
$subdirs = $fs->sortFiles($dir->getSubDirectories()); // runs through FS sort.
|
3096 |
+
|
3097 |
+
// $files = scandir($postDir);
|
3098 |
$returnDir = substr($postDir, strlen($root));
|
3099 |
|
3100 |
+
//natcasesort($files);
|
3101 |
|
3102 |
+
if( count($subdirs) > 0 ) {
|
3103 |
echo "<ul class='jqueryFileTree'>";
|
3104 |
+
foreach($subdirs as $dir ) {
|
3105 |
|
3106 |
+
$dirpath = $dir->getPath();
|
3107 |
+
$dirname = $dir->getName();
|
3108 |
+
if($dirname == 'ShortpixelBackups' || ShortPixelMetaFacade::isMediaSubfolder($dirname, false)) continue;
|
3109 |
|
3110 |
+
$htmlRel = str_replace("'", "'", $returnDir . $dirname);
|
3111 |
+
$htmlName = htmlentities($dirname);
|
3112 |
+
//$ext = preg_replace('/^.*\./', '', $file);
|
3113 |
|
3114 |
+
if( $dir->exists() ) {
|
3115 |
//KEEP the spaces in front of the rel values - it's a trick to make WP Hide not replace the wp-content path
|
3116 |
+
// if( is_dir($postDir . $file) && (!$onlyFiles || $onlyFolders) ) {
|
3117 |
echo "<li class='directory collapsed'>{$checkbox}<a rel=' " .$htmlRel. "/'>" . $htmlName . "</a></li>";
|
3118 |
+
/* } else if (!$onlyFolders || $onlyFiles) {
|
3119 |
echo "<li class='file ext_{$ext}'>{$checkbox}<a rel=' " . $htmlRel . "'>" . $htmlName . "</a></li>";
|
3120 |
+
} */
|
3121 |
}
|
3122 |
}
|
3123 |
|
3260 |
'filesTodo' => $stats['totalFiles'] - $stats['totalProcessedFiles'],
|
3261 |
'estimated' => $this->_settings->optimizeUnlisted || $this->_settings->optimizeRetina ? 'true' : 'false',
|
3262 |
/* */
|
3263 |
+
'iconsUrl' => base64_encode(wpSPIO()->plugin_url('res/img'))
|
3264 |
))),
|
3265 |
'cookies' => array()
|
3266 |
));
|
3273 |
|
3274 |
// TODO - Part of the folder model.
|
3275 |
public static function getCustomFolderBase() {
|
3276 |
+
Log::addDebug('Call to legacy function getCustomFolderBase');
|
3277 |
+
$fs = \wpSPIO()->filesystem();
|
3278 |
+
$dir = $fs->getWPFileBase();
|
3279 |
+
return $dir->getPath();
|
|
|
|
|
|
|
3280 |
}
|
3281 |
|
3282 |
+
// @TODO - Should be part of folder model
|
3283 |
+
/* Seems not in use @todo marked for removal.
|
3284 |
protected function fullRefreshCustomFolder($path, &$notice) {
|
3285 |
$folder = $this->spMetaDao->getFolder($path);
|
3286 |
$diff = $folder->checkFolderContents(array('ShortPixelCustomMetaDao', 'getPathFiles'));
|
3287 |
+
} */
|
3288 |
+
|
3289 |
|
3290 |
// @todo - Should be part of folder model
|
3291 |
+
// @param force boolean Force a recheck.
|
3292 |
+
public function refreshCustomFolders($force = false) {
|
3293 |
$customFolders = array();
|
3294 |
+
$fs = \wpSPIO()->fileSystem();
|
3295 |
+
|
3296 |
if($this->_settings->hasCustomFolders) {
|
3297 |
$customFolders = $this->spMetaDao->getFolders();
|
3298 |
foreach($customFolders as $folder) {
|
3299 |
+
|
3300 |
+
try {
|
3301 |
+
$mt = $folder->getFolderContentsChangeDate();
|
3302 |
+
}
|
3303 |
+
catch(ShortPixelFileRightsException $ex) {
|
3304 |
+
Notices::addWarning($ex->getMessage());
|
3305 |
+
}
|
3306 |
+
|
3307 |
+
if($mt > strtotime($folder->getTsUpdated()) || $force) {
|
3308 |
+
// when forcing, set to never updated.
|
3309 |
+
if ($force)
|
3310 |
+
{
|
3311 |
+
$folder->setTsUpdated(date("Y-m-d H:i:s", 0) ); //
|
3312 |
+
$this->spMetaDao->update($folder);
|
3313 |
+
}
|
3314 |
+
|
3315 |
+
$fsFolder = $fs->getDirectory($folder->getPath());
|
3316 |
+
if ($fsFolder->exists())
|
3317 |
+
$this->spMetaDao->refreshFolder($fsFolder);
|
3318 |
+
else {
|
3319 |
+
Log::addWarn('Custom folder does not exist: ' . $fsFolder->getPath() );
|
3320 |
+
}
|
3321 |
+
|
3322 |
+
}
|
3323 |
+
/* if($folder->getPath() === $ignore) continue;
|
3324 |
try {
|
3325 |
+
|
3326 |
$mt = $folder->getFolderContentsChangeDate();
|
3327 |
if($mt > strtotime($folder->getTsUpdated())) {
|
3328 |
$fileList = $folder->getFileList(strtotime($folder->getTsUpdated()));
|
3339 |
} else {
|
3340 |
$notice = array("status" => "error", "msg" => $ex->getMessage());
|
3341 |
}
|
3342 |
+
}*/
|
3343 |
+
} // folders
|
3344 |
}
|
3345 |
return $customFolders;
|
3346 |
}
|
3350 |
*/
|
3351 |
public static function alterHtaccess( $clear = false ){
|
3352 |
// [BS] Backward compat. 11/03/2019 - remove possible settings from root .htaccess
|
3353 |
+
/* Plugin init is before loading these admin scripts. So it can happen misc.php is not yet loaded */
|
3354 |
+
if (! function_exists('insert_with_markers'))
|
3355 |
+
{
|
3356 |
+
Log::addWarn('AlterHtaccess Called before WP init');
|
3357 |
+
return;
|
3358 |
+
//require_once( ABSPATH . 'wp-admin/includes/misc.php' );
|
3359 |
+
}
|
3360 |
$upload_dir = wp_upload_dir();
|
3361 |
$upload_base = trailingslashit($upload_dir['basedir']);
|
3362 |
|
3500 |
if($validate) {
|
3501 |
$args['body']['DomainCheck'] = get_site_url();
|
3502 |
$args['body']['Info'] = get_bloginfo('version') . '|' . phpversion();
|
3503 |
+
$imageCount = WpShortPixelMediaLbraryAdapter::countAllProcessable($this->_settings);
|
3504 |
$args['body']['ImagesCount'] = $imageCount['mainFiles'];
|
3505 |
$args['body']['ThumbsCount'] = $imageCount['totalFiles'] - $imageCount['mainFiles'];
|
3506 |
$argsStr .= "&DomainCheck={$args['body']['DomainCheck']}&Info={$args['body']['Info']}&ImagesCount={$imageCount['mainFiles']}&ThumbsCount={$args['body']['ThumbsCount']}";
|
3655 |
return;
|
3656 |
}
|
3657 |
|
3658 |
+
$fs = \wpSPIO()->filesystem();
|
3659 |
+
$file = $fs->getAttachedFile($id);
|
3660 |
$data = ShortPixelMetaFacade::sanitizeMeta(wp_get_attachment_metadata($id));
|
3661 |
$itemHandler = new ShortPixelMetaFacade($id);
|
3662 |
$meta = $itemHandler->getMeta();
|
3663 |
|
3664 |
+
$fileExtension = strtolower( $file->getExtension() );
|
3665 |
$invalidKey = !$this->_settings->verifiedKey;
|
3666 |
$quotaExceeded = $this->_settings->quotaExceeded;
|
3667 |
$renderData = array("id" => $id, "showActions" => (current_user_can( 'manage_options' ) || current_user_can( 'upload_files' ) || current_user_can( 'edit_posts' )));
|
3693 |
&& !($data['ShortPixelImprovement'] == 0 && isset($data['ShortPixel']['WaitingProcessing'])) //for images that erroneously have ShortPixelImprovement = 0 when WaitingProcessing
|
3694 |
) { //already optimized
|
3695 |
$thumbsOptList = isset($data['ShortPixel']['thumbsOptList']) ? $data['ShortPixel']['thumbsOptList'] : array();
|
3696 |
+
list($thumbsToOptimizeList, $sizesCount) = $this->getThumbsToOptimize($data, $file->getFullPath());
|
3697 |
|
3698 |
$renderData['status'] = $fileExtension == "pdf" ? 'pdfOptimized' : 'imgOptimized';
|
3699 |
$renderData['percent'] = $this->optimizationPercentIfPng2Jpg($data);
|
3700 |
$renderData['bonus'] = ($data['ShortPixelImprovement'] < 5);
|
3701 |
+
$renderData['backup'] = $this->getBackupFolderAny($file->getFullPath(), $sizesCount? $data['sizes'] : array());
|
3702 |
$renderData['type'] = isset($data['ShortPixel']['type']) ? $data['ShortPixel']['type'] : '';
|
3703 |
$renderData['invType'] = ShortPixelAPI::getCompressionTypeName($this->getOtherCompressionTypes(ShortPixelAPI::getCompressionTypeCode($renderData['type'])));
|
3704 |
$renderData['thumbsTotal'] = $sizesCount;
|
3715 |
$renderData['quotaExceeded'] = $quotaExceeded;
|
3716 |
$webP = 0;
|
3717 |
if($extended) {
|
3718 |
+
if(file_exists(dirname($file->getFullPath()) . '/' . ShortPixelAPI::MB_basename($file->getFullPath(), '.'.$fileExtension) . '.webp' )){
|
3719 |
$webP++;
|
3720 |
}
|
3721 |
if(isset($data['sizes'])) {
|
3722 |
foreach($data['sizes'] as $key => $size) {
|
3723 |
if (strpos($key, ShortPixelMeta::WEBP_THUMB_PREFIX) === 0) continue;
|
3724 |
$sizeName = $size['file'];
|
3725 |
+
if(file_exists(dirname($file->getFullPath()) . '/' . ShortPixelAPI::MB_basename($sizeName, '.'.$fileExtension) . '.webp' )){
|
3726 |
$webP++;
|
3727 |
}
|
3728 |
}
|
3783 |
* @return array Array of Thumbs to Optimize - only the filename - , and count of sizes not excluded ...
|
3784 |
*/
|
3785 |
function getThumbsToOptimize($data, $filepath) {
|
3786 |
+
// This function moved, but lack of other destination.
|
3787 |
return WpShortPixelMediaLbraryAdapter::getThumbsToOptimize($data, $filepath);
|
3788 |
|
3789 |
}
|
3803 |
* @param array $columns Array of colums sortable
|
3804 |
* @todo Should be part of media library controller. ( is request best hook for this?)
|
3805 |
*/
|
|
|
3806 |
function columnOrderFilterBy($vars) {
|
3807 |
if ( isset( $vars['orderby'] ) && 'ShortPixel Compression' == $vars['orderby'] ) {
|
3808 |
$vars = array_merge( $vars, array(
|
3810 |
'orderby' => 'meta_value_num',
|
3811 |
) );
|
3812 |
}
|
3813 |
+
if ( 'upload.php' == $GLOBALS['pagenow'] && isset( $_GET['shortpixel_status'] ) ) {
|
3814 |
|
3815 |
+
$status = sanitize_text_field($_GET['shortpixel_status']);
|
3816 |
$metaKey = '_shortpixel_status';
|
3817 |
+
//$metaCompare = $status == 0 ? 'NOT EXISTS' : ($status < 0 ? '<' : '=');
|
3818 |
+
|
3819 |
+
if ($status == 'all')
|
3820 |
+
return $vars; // not for us
|
3821 |
+
|
3822 |
+
switch($status)
|
3823 |
+
{
|
3824 |
+
case "opt":
|
3825 |
+
$status = ShortPixelMeta::FILE_STATUS_SUCCESS;
|
3826 |
+
$metaCompare = ">="; // somehow this meta stores optimization percentage.
|
3827 |
+
break;
|
3828 |
+
case "unopt":
|
3829 |
+
$status = ShortPixelMeta::FILE_STATUS_UNPROCESSED;
|
3830 |
+
$metaCompare = "NOT EXISTS";
|
3831 |
+
break;
|
3832 |
+
case "pending":
|
3833 |
+
$status = ShortPixelMeta::FILE_STATUS_PENDING;
|
3834 |
+
$metaCompare = "=";
|
3835 |
+
break;
|
3836 |
+
case "error":
|
3837 |
+
$status = -1;
|
3838 |
+
$metaCompare = "<=";
|
3839 |
+
break;
|
3840 |
+
|
3841 |
+
}
|
3842 |
|
3843 |
$vars = array_merge( $vars, array(
|
3844 |
'meta_query' => array(
|
3850 |
)
|
3851 |
));
|
3852 |
}
|
3853 |
+
|
3854 |
return $vars;
|
3855 |
}
|
3856 |
|
3863 |
if ( $scr->base !== 'upload' ) return;
|
3864 |
|
3865 |
$status = filter_input(INPUT_GET, 'shortpixel_status', FILTER_SANITIZE_STRING );
|
3866 |
+
// $selected = (int)$status > 0 ? $status : 0;
|
3867 |
+
/* $args = array(
|
3868 |
'show_option_none' => 'ShortPixel',
|
3869 |
'name' => 'shortpixel_status',
|
3870 |
'selected' => $selected
|
3871 |
+
); */
|
3872 |
// wp_dropdown_users( $args );
|
3873 |
+
$options = array(
|
3874 |
+
'all' => __('All Images', 'shortpixel-image-optimiser'),
|
3875 |
+
'opt' => __('Optimized', 'shortpixel-image-optimiser'),
|
3876 |
+
'unopt' => __('Unoptimized', 'shortpixel-image-optimiser'),
|
3877 |
+
// 'pending' => __('Pending', 'shortpixel-image-optimiser'),
|
3878 |
+
// 'error' => __('Errors', 'shortpixel-image-optimiser'),
|
3879 |
+
);
|
3880 |
|
3881 |
+
echo "<select name='shortpixel_status' id='shortpixel_status'>\n";
|
3882 |
+
foreach($options as $optname => $optval)
|
3883 |
+
{
|
3884 |
+
$selected = ($status == $optname) ? 'selected' : '';
|
3885 |
+
echo "<option value='". $optname . "' $selected>" . $optval . "</option>\n";
|
3886 |
+
}
|
3887 |
+
echo "</select>";
|
3888 |
+
|
3889 |
+
/*echo("<select name='shortpixel_status' id='shortpixel_status'>\n"
|
3890 |
. "\t<option value='0'" . ($status == 0 ? " selected='selected'" : "") . ">All images</option>\n"
|
3891 |
. "\t<option value='2'" . ($status == 2 ? " selected='selected'" : "") . ">Optimized</option>\n"
|
3892 |
. "\t<option value='none'" . ($status == 'none' ? " selected='selected'" : "") . ">Unoptimized</option>\n"
|
3893 |
. "\t<option value='1'" . ($status == 1 ? " selected='selected'" : "") . ">Pending</option>\n"
|
3894 |
. "\t<option value='-1'" . ($status < 0 ? " selected='selected'" : "") . ">Errors</option>\n"
|
3895 |
+
. "</select>"); */
|
3896 |
}
|
3897 |
|
3898 |
/** Calculates Optimization if PNG2Jpg does something
|
3935 |
*/
|
3936 |
public function onDeleteImage($post_id) {
|
3937 |
$itemHandler = new ShortPixelMetaFacade($post_id);
|
3938 |
+
$urlsPaths = $itemHandler->getURLsAndPATHs(true, false, true, array(), true, true);
|
3939 |
if(count($urlsPaths['PATHs'])) {
|
3940 |
$this->maybeDumpFromProcessedOnServer($itemHandler, $urlsPaths);
|
3941 |
$this->deleteBackupsAndWebPs($urlsPaths['PATHs']);
|
3942 |
}
|
3943 |
+
$itemHandler->deleteItemCache();
|
3944 |
return $itemHandler; //return it because we call it also on replace and on replace we need to follow this by deleting SP metadata, on delete it
|
3945 |
}
|
3946 |
|
3956 |
return;
|
3957 |
}
|
3958 |
|
3959 |
+
|
3960 |
+
$fs = \wpSPIO()->filesystem();
|
3961 |
+
|
3962 |
$backupFolder = trailingslashit($this->getBackupFolder($paths[0]));
|
3963 |
foreach($paths as $path) {
|
3964 |
$pos = strrpos($path, ".");
|
3965 |
+
$pathFile = $fs->getFile($path);
|
3966 |
if ($pos !== false) {
|
3967 |
//$webpPath = substr($path, 0, $pos) . ".webp";
|
3968 |
//echo($webpPath . "<br>");
|
3969 |
+
$file = $fs->getFile(substr($path, 0, $pos) . ".webp");
|
3970 |
+
$file->delete();
|
3971 |
+
$file = $fs->getFile(substr($path, 0, $pos) . "@2x.webp");
|
3972 |
+
$file->delete();
|
3973 |
}
|
3974 |
//delte also the backups for image and retina correspondent
|
3975 |
+
$fileName = $pathFile->getFileName();
|
3976 |
+
$extension = $pathFile->getExtension();
|
3977 |
+
|
3978 |
+
$backupFile = $fs->getFile($backupFolder . $fileName);
|
3979 |
+
if ($backupFile->exists())
|
3980 |
+
$backupFile->delete();
|
3981 |
+
//@unlink($backupFolder . $fileName);
|
3982 |
+
|
3983 |
+
$backupFile = $fs->getFile($backupFolder . preg_replace("/\." . $extension . "$/i", '@2x.' . $extension, $fileName));
|
3984 |
+
if ($backupFile->exists())
|
3985 |
+
$backupFile->delete();
|
3986 |
+
|
3987 |
+
// @unlink($backupFolder . preg_replace("/\." . $extension . "$/i", '@2x.' . $extension, $fileName));
|
3988 |
}
|
3989 |
}
|
3990 |
//
|
4003 |
return $defaults;
|
4004 |
}
|
4005 |
|
4006 |
+
// @todo move NGG specific function to own integration
|
4007 |
public function nggColumns( $defaults ) {
|
4008 |
$this->nggColumnIndex = count($defaults) + 1;
|
4009 |
add_filter( 'ngg_manage_images_column_' . $this->nggColumnIndex . '_header', array( &$this, 'nggColumnHeader' ) );
|
4063 |
|
4064 |
// @todo Should be utility function
|
4065 |
static public function formatBytes($bytes, $precision = 2) {
|
4066 |
+
return \ShortPixelTools::formatBytes($bytes, $precision);
|
|
|
|
|
|
|
|
|
4067 |
|
|
|
|
|
|
|
4068 |
}
|
4069 |
|
4070 |
/** Checks if file can be processed. Mainly against exclusion
|
4087 |
return self::_isProcessablePath($path, $excludeExtensions, $excludePatterns);
|
4088 |
}
|
4089 |
|
4090 |
+
/** @todo pretty much every caller of this function already has a path. Check if get/attached/file is really needed -again- */
|
4091 |
static public function _isProcessable($ID, $excludeExtensions = array(), $excludePatterns = array(), $meta = false) {
|
4092 |
+
$file = \wpSPIO()->filesystem()->getAttachedFile($ID);
|
4093 |
+
$path = $file->getFullPath(); //get the full file PATH
|
4094 |
+
|
4095 |
if(isset($excludePatterns) && is_array($excludePatterns)) {
|
4096 |
foreach($excludePatterns as $excludePattern) {
|
4097 |
$type = $excludePattern["type"];
|
4180 |
*/
|
4181 |
static public function folderSize($path) {
|
4182 |
$total_size = 0;
|
4183 |
+
$fs = wpSPIO()->filesystem();
|
4184 |
+
$dir = $fs->getDirectory($path);
|
4185 |
+
|
4186 |
+
if($dir->exists()) {
|
4187 |
+
$files = $dir->getFiles(); // @todo This gives a warning if directory is not writable.
|
4188 |
+
$subdirs = $dir->getSubDirectories();
|
4189 |
+
|
4190 |
} else {
|
4191 |
return $total_size;
|
4192 |
}
|
4193 |
+
//$cleanPath = rtrim($path, '/'). '/';
|
4194 |
+
foreach($files as $file)
|
4195 |
+
{
|
4196 |
+
$total_size += $file->getFileSize();
|
4197 |
+
}
|
4198 |
+
|
4199 |
+
foreach($subdirs as $dir)
|
4200 |
+
{
|
4201 |
+
$total_size += self::folderSize($dir->getPath());
|
4202 |
+
}
|
4203 |
+
|
4204 |
+
return $total_size;
|
4205 |
+
|
4206 |
+
/* foreach($files as $t) {
|
4207 |
if ($t<>"." && $t<>"..")
|
4208 |
{
|
4209 |
$currentFile = $cleanPath . $t;
|
4216 |
$total_size += $size;
|
4217 |
}
|
4218 |
}
|
4219 |
+
} */
|
4220 |
return $total_size;
|
4221 |
}
|
4222 |
|
4394 |
<div id="shortpixel-hs-button-blind" class="shortpixel-hs-button-blind"></div>
|
4395 |
<div id="shortpixel-hs-tools" class="shortpixel-hs-tools">
|
4396 |
<a href="javascript:shortpixelToggleHS();" class="shortpixel-hs-tools-docs" title="<?php _e('Search through our online documentation.', 'shortpixel-image-optimiser'); ?>">
|
4397 |
+
<img src="<?php echo(wpSPIO()->plugin_url('res/img/notes-sp.png'));?>" style="margin-bottom: 2px;width: 36px;">
|
4398 |
</a>
|
4399 |
</div>
|
4400 |
<script>
|
@@ -233,7 +233,15 @@ class WPShortPixelSettings extends ShortPixel\ShortPixelModel {
|
|
233 |
}
|
234 |
|
235 |
public function setOpt($key, $val) {
|
236 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
|
238 |
//hack for the situation when the option would just not update....
|
239 |
if($ret === false && !is_array($val) && $val != get_option($key)) {
|
@@ -245,7 +253,7 @@ class WPShortPixelSettings extends ShortPixel\ShortPixelModel {
|
|
245 |
wp_cache_delete( $key, 'options' );
|
246 |
}
|
247 |
delete_option($key);
|
248 |
-
add_option($key, $val, '',
|
249 |
|
250 |
// still not? try the DB way...
|
251 |
if($ret === false && $val != get_option($key)) {
|
@@ -254,7 +262,7 @@ class WPShortPixelSettings extends ShortPixel\ShortPixelModel {
|
|
254 |
$rows = $wpdb->get_results($sql);
|
255 |
if(count($rows) === 0) {
|
256 |
$wpdb->insert($wpdb->prefix.'options',
|
257 |
-
array("option_name" => $key, "option_value" => (is_array($val) ? serialize($val) : $val), "autoload" =>
|
258 |
array("option_name" => "%s", "option_value" => (is_numeric($val) ? "%d" : "%s")));
|
259 |
} else { //update
|
260 |
$sql = "update {$wpdb->prefix}options SET option_value=" .
|
@@ -268,7 +276,7 @@ class WPShortPixelSettings extends ShortPixel\ShortPixelModel {
|
|
268 |
//tough luck, gonna use the bomb...
|
269 |
wp_cache_flush();
|
270 |
delete_option($key);
|
271 |
-
add_option($key, $val, '',
|
272 |
}
|
273 |
}
|
274 |
}
|
233 |
}
|
234 |
|
235 |
public function setOpt($key, $val) {
|
236 |
+
$autoload = true;
|
237 |
+
/*if (isset(self::$_optionsMap[$key]))
|
238 |
+
{
|
239 |
+
if (self::$_optionsMap[$key]['group'] == 'options')
|
240 |
+
$autoload = true; // add most used to autoload, because performance.
|
241 |
+
|
242 |
+
} */
|
243 |
+
|
244 |
+
$ret = update_option($key, $val, $autoload);
|
245 |
|
246 |
//hack for the situation when the option would just not update....
|
247 |
if($ret === false && !is_array($val) && $val != get_option($key)) {
|
253 |
wp_cache_delete( $key, 'options' );
|
254 |
}
|
255 |
delete_option($key);
|
256 |
+
add_option($key, $val, '', $autoload);
|
257 |
|
258 |
// still not? try the DB way...
|
259 |
if($ret === false && $val != get_option($key)) {
|
262 |
$rows = $wpdb->get_results($sql);
|
263 |
if(count($rows) === 0) {
|
264 |
$wpdb->insert($wpdb->prefix.'options',
|
265 |
+
array("option_name" => $key, "option_value" => (is_array($val) ? serialize($val) : $val), "autoload" => $autoload),
|
266 |
array("option_name" => "%s", "option_value" => (is_numeric($val) ? "%d" : "%s")));
|
267 |
} else { //update
|
268 |
$sql = "update {$wpdb->prefix}options SET option_value=" .
|
276 |
//tough luck, gonna use the bomb...
|
277 |
wp_cache_flush();
|
278 |
delete_option($key);
|
279 |
+
add_option($key, $val, '', $autoload);
|
280 |
}
|
281 |
}
|
282 |
}
|
@@ -2,22 +2,22 @@
|
|
2 |
Contributors: ShortPixel
|
3 |
Tags: compressor, image, compression, optimize, image optimizer, image optimiser, image compression, resize, compress pdf, compress jpg, compress png, image compression
|
4 |
Requires at least: 3.2.0
|
5 |
-
Tested up to: 5.
|
6 |
Requires PHP: 5.3
|
7 |
-
Stable tag: 4.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
-
Speed up your website
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
**A freemium easy to use, comprehensive, stable and frequently updated image compression plugin supported by the friendly team that created it. :)**
|
16 |
|
17 |
Increase your website's SEO ranking, number of visitors and ultimately your sales by optimizing any image or PDF document on your website.
|
18 |
-
ShortPixel is an easy to use, lightweight, install-and-forget-about-it <a href="https://shortpixel.com" target="_blank">image optimization</a> plugin that can compress all your past images and PDF documents with a single click. New images are automatically resized/rescaled and optimized on the fly, in the background.
|
19 |
|
20 |
-
**Ready for a quick DEMO? Test <a href="https://sandboxwordpress.com/?htmldata=https://shortpixel.com/sp.html&slug=shortpixel-image-optimiser&redirect=plugins.php&title=Test%20SHORTPIXEL%20Now!&ga=UA-55918546-1" target="_blank">here</a
|
21 |
|
22 |
Short Pixel uses minimal resources and works well with any shared, cloud, VPS or dedicated web hosting. It can optimize any image you have on your website even the images that aren't listed in Media Library like those in galleries like <a href="https://wordpress.org/plugins/nextgen-gallery/" target="_blank">NextGEN</a>, <a href="https://wordpress.org/plugins/modula-best-grid-gallery/" target="_blank">Modula</a> or added directly via FTP!
|
23 |
|
@@ -29,7 +29,7 @@ Make an instant <a href="http://shortpixel.com/image-compression-test" target="_
|
|
29 |
|
30 |
**Why is ShortPixel the best choice when it comes to image optimization or PDF compression?**
|
31 |
|
32 |
-
* popular plugin with over
|
33 |
* compress JPG, PNG, GIF (still or animated) images and also PDF documents
|
34 |
* option to automatically convert PNG to JPG if that will result in smaller images. Ideal for large images in PNG format.
|
35 |
* no file size limit
|
@@ -71,7 +71,7 @@ Check out <a href="https://shortpixel.com/pricing" target="_blank">our prices</a
|
|
71 |
> ★★★★★ **The secret sauce for a WordPress website.** [mark1mark](https://wordpress.org/support/topic/the-secret-sauce-for-a-wordpress-website/)
|
72 |
> ★★★★★ **A must have plugin, great support!** [ElColo13](https://wordpress.org/support/topic/a-must-have-plugin-great-support/)
|
73 |
> ★★★★★ **Excellent Plugin! Even Better Customer Service!** [scaliendo](https://wordpress.org/support/topic/great-plugin-great-support-508/)
|
74 |
-
> ★★★★★ **Great image compression, solid plugin, equally great support.** [matters1959](https://wordpress.org/support/topic/support-shortpixel-image-optimiser/)
|
75 |
> [more testimonials](https://wordpress.org/support/plugin/shortpixel-image-optimiser/reviews/?filter=5)
|
76 |
|
77 |
[youtube https://www.youtube.com/watch?v=5EbX0Hsy6j4]
|
@@ -214,15 +214,30 @@ The ShortPixel team is here to help. <a href="https://shortpixel.com/contact">Co
|
|
214 |
|
215 |
The ShortPixel Image Optimiser plugin calls the following actions and filters:
|
216 |
> do_action( 'shortpixel_image_optimised', $post_id ); //upon successful optimization
|
|
|
217 |
> do_action("shortpixel_before_restore_image", $post_id); //before restoring an image from backup
|
|
|
218 |
> do_action("shortpixel_after_restore_image", $post_id); //after succesful restore
|
|
|
219 |
> apply_filters("shortpixel_backup_folder", $backup_folder, $main_file_path, $sizes); //just before returning the ShortPixel backup folder, usually /wp-content/uploads/ShortpixelBackups. The $sizes are the sizes array from metadata.
|
|
|
220 |
> apply_filters('shortpixel_image_exists', file_exists($path), $path, $post_id); //post ID is not always set, only if it's an image from Media Library
|
|
|
221 |
> apply_filters('shortpixel_image_urls', $URLs, $post_id) // filters the URLs that will be sent to optimization, $URLs is a plain array
|
222 |
|
|
|
|
|
223 |
In order to define custom thumbnails to be picked up by the optimization you have two options, both comma separated defines:
|
|
|
224 |
define('SHORTPIXEL_CUSTOM_THUMB_SUFFIXES', '_tl,_tr'); will handle custom thumbnails like image-100x100_tl.jpg
|
|
|
225 |
define('SHORTPIXEL_CUSTOM_THUMB_INFIXES', '-uae'); will handle custom thumbnails like image-uae-100x100.jpg
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
|
227 |
== Screenshots ==
|
228 |
|
@@ -246,9 +261,42 @@ define('SHORTPIXEL_CUSTOM_THUMB_INFIXES', '-uae'); will handle custom thumbnails
|
|
246 |
|
247 |
== Changelog ==
|
248 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
= 4.14.6 =
|
|
|
250 |
Release date: 9th October 2019
|
251 |
-
* Don't convert to
|
252 |
* Remove unused eval() call.
|
253 |
* Restore the validate button next to API Key but change label to "Save and validate"
|
254 |
* Fixed: PNGtoJPG issue with already uploaded images
|
@@ -263,9 +311,10 @@ Release date: 9th October 2019
|
|
263 |
* Fixed: notice in filemodel due meta-facade feeding array
|
264 |
* Fixed: bug in File2Url in filesystemcontroller
|
265 |
* Fixed: download issue in attempt to remote download
|
266 |
-
* Language – 0 new strings added,
|
267 |
|
268 |
= 4.14.5 =
|
|
|
269 |
Release date: 29th August 2019
|
270 |
* If constant SHORTPIXEL_USE_DOUBLE_WEBP_EXTENSION is defined as true, use double extension for WebP (.jpg.webp)
|
271 |
* Fixed: Javascript - String.prototype causes errors on React apps
|
@@ -276,6 +325,7 @@ Release date: 29th August 2019
|
|
276 |
* Language – 0 new strings added, 1 updated, 0 fuzzied, and 0 obsoleted
|
277 |
|
278 |
= 4.14.4 =
|
|
|
279 |
Release date: 19th August 2019
|
280 |
* Check if unlisted thumbnails present for already optimized images (in case the thumbnails were added later) in Media Library list and when doing bulk. This also integrates with the Unicode plugin.
|
281 |
* If JSON PHP module not present, add a proper error
|
@@ -345,189 +395,5 @@ Release date: 10th April 2019
|
|
345 |
* Fixed: Restoring an Other Media item and then Optimizing it again optimizes it Lossless
|
346 |
* fix generating the WebP <picture> tags when the images are either on a subdomain or on a CDN domain having the same root domain as the main site.
|
347 |
|
348 |
-
= 4.12.8 =
|
349 |
-
|
350 |
-
Release date: 25th February 2019
|
351 |
-
|
352 |
-
* fix CSS for the top bar ShortPixel icon on post pages
|
353 |
-
* i18n some text which was left out by mistake
|
354 |
-
* include the green "CAN" WebP image which shows that the .htaccess works with WebP images having extensions like .jpg.webp
|
355 |
-
* display notice if ShortPixel Adaptive Images is active and the Generate WebP markup option is checked. Do not generate the WebP markup in this case.
|
356 |
-
|
357 |
-
= 4.12.7 =
|
358 |
-
|
359 |
-
Release date: 12th February 2019
|
360 |
-
|
361 |
-
* solved conflicting WebP file names when image.jpg and image.png exist in the same folder - use image.jpg.webp filename.
|
362 |
-
* fixed .htaccess rules for some Apache versions which seemingly don't honour the RewriteRule backreferences in the RewriteCond's (Apache bug?)
|
363 |
-
* remove the WebP .htaccess rules on plugin deactivation and add them back on plugin activation
|
364 |
-
* fixed alt attribute for <picture> tags - now it is included properly only on the enclosed <img> tag.
|
365 |
-
|
366 |
-
= 4.12.6 =
|
367 |
-
|
368 |
-
Release date: 27th January 2019
|
369 |
-
|
370 |
-
* Improvements to the .htaccess WebP method
|
371 |
-
* Improve performance of backup deletion - get rid of unnecessary checks
|
372 |
-
* Fixed: wrong calculation of remaining credits
|
373 |
-
* Fixed: discrepancy between the description of the exclude size option and the behaviour for the exact size case.
|
374 |
-
|
375 |
-
= 4.12.5 =
|
376 |
-
|
377 |
-
Release date: 10th Ianuary 2019
|
378 |
-
|
379 |
-
* change the JS name in order to circumveit cache problem on many WP installs
|
380 |
-
* sorting the Media Library entries by ShortPixel optimization: also sort based on compression level
|
381 |
-
* Fixed: case sensitive search for guid duplicates of image posts (needed for finding Polylang versions)
|
382 |
-
* Fixed: the data-lazy-src/srcset detection for WebP
|
383 |
-
* Improvements to the Deliver WebP options and especially messages with caveats
|
384 |
-
* Load the ShortPixel CSS only on admin pages that need it
|
385 |
-
|
386 |
-
= 4.12.4 =
|
387 |
-
|
388 |
-
Release date: 27th December 2018
|
389 |
-
|
390 |
-
* Fixed: shortpixel-thumbnails-regenerated action when not all the thumbnails were regenerated
|
391 |
-
|
392 |
-
= 4.12.3 =
|
393 |
-
|
394 |
-
Release date: 19th December 2018
|
395 |
-
|
396 |
-
* Fixed: error in getting the lazy- attributes of <img> for WebP handling.
|
397 |
-
|
398 |
-
= 4.12.2 =
|
399 |
-
|
400 |
-
Release date: 13th December 2018
|
401 |
-
|
402 |
-
* Improved: The Webp options interface. Now the user can implement Webp images both via .htaccess and by altering the page code on the server before being sent to the browser.
|
403 |
-
* Improved: The settings data handling interface in the Plugin deactivation dialogue. Now the option to delete or keep the user settings on plugin deletion is more clear.
|
404 |
-
* Added: Option to download image with thumbnails in a single archive file, to speed-up the optimization.
|
405 |
-
* Added: A "shortpixel_get_backup" filter, which receives the local path of the media image and returns the ShortPixel backup path, if a backup image exists
|
406 |
-
* Added: The "Simple Image Sizes" plugin to the conflicting plugins list
|
407 |
-
* Added: A new compatibility check for the "Jetpack" plugin, alerting the user about potential overlapping functionality
|
408 |
-
* Added: A safety alert before switching to Code Altering mode (where IMG tgs get inserted into PICTURE tags, to better serve Webp images)
|
409 |
-
* Added: Enhanced "Envira" plugin compatibility by adding more suffixes to be looked for: _tl, _tr, _bl, _br
|
410 |
-
* Added: More customized FAQ suggestions in the HelpScout Beacon helper, to address each Plugin TAB separately
|
411 |
-
* Fixed: The post-uninstall redirect when uninstalling a plugin from within the respective plugin's Settings page
|
412 |
-
* Fixed: The credits display on the Statistics page
|
413 |
-
* Fixed: Refreshing a plugin page now loads directly in the previously selected TAB
|
414 |
-
* Fixed: Removed a stray "SP_CELL_MESSAGE" div from the interface
|
415 |
-
|
416 |
-
= 4.12.1 =
|
417 |
-
|
418 |
-
Release date: 6th November 2018
|
419 |
-
|
420 |
-
* Fix WebP replacement for lazy-loaded images
|
421 |
-
* Fix WebP replacement with output buffering on some WP installs
|
422 |
-
|
423 |
-
= 4.12.0 =
|
424 |
-
|
425 |
-
Release date: 31st October 2018
|
426 |
-
|
427 |
-
* Generate WebP <picture> tags - use the output buffer instead of the_content which is not triggered by some themes on all content.
|
428 |
-
* compatibility of the WebP <picture> tag with lazy loading plugins (that support <picture>)
|
429 |
-
* Compatibility with Polylang.
|
430 |
-
* hooks to be used by thumbnail regeneration plugins: 'shortpixel-thumbnails-before-regenerate' and 'shortpixel-thumbnails-regenerated'
|
431 |
-
* Proper error message when the custom tables cannot be created.
|
432 |
-
* exclude the PNGs from conversion to JPEG when they match the exclude patterns.
|
433 |
-
* properly warn when cURL is not enabled that Cloudflare integration won't work.
|
434 |
-
* send only one url for metadata thumbnails which correspond to the same physical file.
|
435 |
-
* JavaScript delayed init for cases when some plugins deffer the load of javascript files.
|
436 |
-
* fix identifying filenames with basename length == 3 as retina
|
437 |
-
* display improvements for the bulk errors list
|
438 |
-
|
439 |
-
= 4.11.3 =
|
440 |
-
|
441 |
-
Release date: 27th September 2018
|
442 |
-
|
443 |
-
* fix error when metadata is returned as string by wp_get_attachment_metadata (happens to PDFs when using PDF Image Generator)
|
444 |
-
* remove the configurable Affiliate code as per new WP Themes rules.
|
445 |
-
|
446 |
-
= 4.11.2 =
|
447 |
-
|
448 |
-
Release date: 30th August 2018
|
449 |
-
|
450 |
-
* Fix "Image files are missing" warning when thumbails optimization is activated but all the thumbnails are excepted from optimization and the bulk is ran a second time.
|
451 |
-
* Fix not saving properly the metadata on some situations
|
452 |
-
|
453 |
-
= 4.11.1 =
|
454 |
-
|
455 |
-
Release date: 28th August 2018
|
456 |
-
|
457 |
-
* compatibility with the MediaPress plugin
|
458 |
-
* new action to be called by when thumbnails are regenerated: shortpixel-thumbnails-regenerated
|
459 |
-
* accept '+' inside the e-mail address
|
460 |
-
* fix optimization not working on internationalized domain names
|
461 |
-
* better count of the not optimized thumbs for an image, in some circumstances
|
462 |
-
* fallback to ABSPATH when get_home_path() returns '/'
|
463 |
-
* fix settings tabs navigation when url ends with #/
|
464 |
-
* extract all release notes < 4.9 from readme.txt into changelog.txt
|
465 |
-
* display the thumbnail name for some errors which refer only to a specific thumbnail.
|
466 |
-
* use update_post_meta() instead of wp_update_attachment_metadata() for cases when other plugins cannot be concerned by the meta change (specific to ShortPixel)
|
467 |
-
* add the attributes of the original <img> to the <picture> replacement tag, in case the "Generate WebP Markup" option is active.
|
468 |
-
* fix action buttons in media edit view overflowing their box
|
469 |
-
* restore full compatibility with WP < 4.1 by checking first before using wp_json_encode
|
470 |
-
* fix admin when domain is internationalized but the setting in admin uses the punycode-encrypted version
|
471 |
-
|
472 |
-
= 4.11.0 =
|
473 |
-
|
474 |
-
Release date: 3rd July 2018
|
475 |
-
|
476 |
-
* add bulk menu options: restore, reoptimize
|
477 |
-
* filter the media list by optimization status
|
478 |
-
* sort the media list by optimization status
|
479 |
-
* do not display the Media Library (years) folders in the selection list for Other Media folders
|
480 |
-
* force PNG 2 JPG conversion option
|
481 |
-
* integrate with Gravity Forms
|
482 |
-
* integrate with WP Stateless
|
483 |
-
* add several actions and a filter (see the Actions and Filters section of the readme)
|
484 |
-
* UI improvements to the settings page
|
485 |
-
* fix the WPML compatibility when converting from PNG
|
486 |
-
* fix SELECT IN image counting bug on rare cases and when >100k records in wp_postmeta
|
487 |
-
* add option to delete ShortPixel settings and give feedback form on deactivate plugin
|
488 |
-
|
489 |
-
= 4.10.5 =
|
490 |
-
* GDPR compliance
|
491 |
-
|
492 |
-
= 4.10.4 =
|
493 |
-
* replace back the PNG links when restoring a PNG converted to JPG
|
494 |
-
* fix incompatibility with Dynamics 365 Integration plugin
|
495 |
-
* improve restore capabilities after certain types of PNG to JPG errors which left the media item in an unconsistent state.
|
496 |
-
* remove AUTH credentials on server too, if removed in plugin's settings.
|
497 |
-
* more performance improvements to PNG 2 JPG conversion
|
498 |
-
* fix replacing PNG urls having http:// instead of https:// for a SSL site. (and viceversa)
|
499 |
-
* fix string not appearing in translations
|
500 |
-
|
501 |
-
= 4.10.3 =
|
502 |
-
* improvements to context help beacon
|
503 |
-
* performance improvements to PNG to JPG conversion
|
504 |
-
|
505 |
-
= 4.10.2 =
|
506 |
-
* fix error when listing Other media in some circumstances
|
507 |
-
|
508 |
-
= 4.10.1 =
|
509 |
-
* fix missing file from commit
|
510 |
-
|
511 |
-
= 4.10.0 =
|
512 |
-
* option to exclude thumbnails from optimization
|
513 |
-
* options to delete Cloudflare cache for optimized images
|
514 |
-
* method to define affilate codes for themes
|
515 |
-
* error message when restore could not be performed
|
516 |
-
* better handling of situations with files with different owner but with write permissions for all
|
517 |
-
* fix bug for inner resize when setting and unsetting the resize parameter
|
518 |
-
* fix bug for third-party WebP thumbnails registered in the 'sizes' metadata array which were sent to optimization.
|
519 |
-
* check if function mb_convert_encoding exists before using it
|
520 |
-
|
521 |
-
= 4.9.1 =
|
522 |
-
* fix error for older WP versions which don't have wp_raise_memory_limit
|
523 |
-
|
524 |
-
= 4.9.0 =
|
525 |
-
* inline help beacon
|
526 |
-
* fix exclude patterns not working after last update
|
527 |
-
* handle situations when not enough memory to convert from PNG to JPG.
|
528 |
-
* fix particular situations where there was no 'file' property in the metadata.
|
529 |
-
* fix slider optimized percent over the bulk warning box.
|
530 |
-
* display the x close link for the bulk warning box.
|
531 |
-
|
532 |
= EARLIER VERSIONS =
|
533 |
* please refer to the changelog.txt file inside the plugin archive.
|
2 |
Contributors: ShortPixel
|
3 |
Tags: compressor, image, compression, optimize, image optimizer, image optimiser, image compression, resize, compress pdf, compress jpg, compress png, image compression
|
4 |
Requires at least: 3.2.0
|
5 |
+
Tested up to: 5.3
|
6 |
Requires PHP: 5.3
|
7 |
+
Stable tag: 4.15.0
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
+
Speed up your website & boost your SEO by compressing old & new images and PDFs. WebP convert and optimize support.
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
**A freemium easy to use, comprehensive, stable and frequently updated image compression plugin supported by the friendly team that created it. :)**
|
16 |
|
17 |
Increase your website's SEO ranking, number of visitors and ultimately your sales by optimizing any image or PDF document on your website.
|
18 |
+
ShortPixel is an easy to use, lightweight, install-and-forget-about-it <a href="https://shortpixel.com" target="_blank">image optimization</a> plugin that can compress all your past images and PDF documents with a single click. New images are automatically resized/rescaled and optimized on the fly, in the background. It's also compatible with any gallery, slider or ecommerce plugin.
|
19 |
|
20 |
+
**Ready for a quick DEMO? Test <a href="https://sandboxwordpress.com/?htmldata=https://shortpixel.com/sp.html&slug=shortpixel-image-optimiser&redirect=plugins.php&title=Test%20SHORTPIXEL%20Now!&ga=UA-55918546-1" target="_blank">here</a>.**
|
21 |
|
22 |
Short Pixel uses minimal resources and works well with any shared, cloud, VPS or dedicated web hosting. It can optimize any image you have on your website even the images that aren't listed in Media Library like those in galleries like <a href="https://wordpress.org/plugins/nextgen-gallery/" target="_blank">NextGEN</a>, <a href="https://wordpress.org/plugins/modula-best-grid-gallery/" target="_blank">Modula</a> or added directly via FTP!
|
23 |
|
29 |
|
30 |
**Why is ShortPixel the best choice when it comes to image optimization or PDF compression?**
|
31 |
|
32 |
+
* popular plugin with over 200,000 active installations according to WordPress
|
33 |
* compress JPG, PNG, GIF (still or animated) images and also PDF documents
|
34 |
* option to automatically convert PNG to JPG if that will result in smaller images. Ideal for large images in PNG format.
|
35 |
* no file size limit
|
71 |
> ★★★★★ **The secret sauce for a WordPress website.** [mark1mark](https://wordpress.org/support/topic/the-secret-sauce-for-a-wordpress-website/)
|
72 |
> ★★★★★ **A must have plugin, great support!** [ElColo13](https://wordpress.org/support/topic/a-must-have-plugin-great-support/)
|
73 |
> ★★★★★ **Excellent Plugin! Even Better Customer Service!** [scaliendo](https://wordpress.org/support/topic/great-plugin-great-support-508/)
|
74 |
+
> ★★★★★ **Great image compression, solid plugin, equally great support.** [matters1959](https://wordpress.org/support/topic/support-shortpixel-image-optimiser/)
|
75 |
> [more testimonials](https://wordpress.org/support/plugin/shortpixel-image-optimiser/reviews/?filter=5)
|
76 |
|
77 |
[youtube https://www.youtube.com/watch?v=5EbX0Hsy6j4]
|
214 |
|
215 |
The ShortPixel Image Optimiser plugin calls the following actions and filters:
|
216 |
> do_action( 'shortpixel_image_optimised', $post_id ); //upon successful optimization
|
217 |
+
|
218 |
> do_action("shortpixel_before_restore_image", $post_id); //before restoring an image from backup
|
219 |
+
|
220 |
> do_action("shortpixel_after_restore_image", $post_id); //after succesful restore
|
221 |
+
|
222 |
> apply_filters("shortpixel_backup_folder", $backup_folder, $main_file_path, $sizes); //just before returning the ShortPixel backup folder, usually /wp-content/uploads/ShortpixelBackups. The $sizes are the sizes array from metadata.
|
223 |
+
|
224 |
> apply_filters('shortpixel_image_exists', file_exists($path), $path, $post_id); //post ID is not always set, only if it's an image from Media Library
|
225 |
+
|
226 |
> apply_filters('shortpixel_image_urls', $URLs, $post_id) // filters the URLs that will be sent to optimization, $URLs is a plain array
|
227 |
|
228 |
+
> apply_filters('shortpixel/db/chunk_size', $chunk); //the $chunk is the value ShortPixel chooses to use as number of selected records in one query (based on total table size), some hosts work better with a different value
|
229 |
+
|
230 |
In order to define custom thumbnails to be picked up by the optimization you have two options, both comma separated defines:
|
231 |
+
|
232 |
define('SHORTPIXEL_CUSTOM_THUMB_SUFFIXES', '_tl,_tr'); will handle custom thumbnails like image-100x100_tl.jpg
|
233 |
+
|
234 |
define('SHORTPIXEL_CUSTOM_THUMB_INFIXES', '-uae'); will handle custom thumbnails like image-uae-100x100.jpg
|
235 |
+
define('SHORTPIXEL_USE_DOUBLE_WEBP_EXTENSION', true); will tell the plugin to create double extensions for the WebP image counterparts, for example image.jpg.webp for image.jpg
|
236 |
+
|
237 |
+
define("SHORTPIXEL_NOFLOCK", true); // don't use flock queue, only activate this when you have flock() denied errors on your installation.
|
238 |
+
.
|
239 |
+
define("SHORTPIXEL_EXPERIMENTAL_SECURICACHE", true); // adds timestamps to URLS, to prevent hitting the cache. Useful for persistent caches.
|
240 |
+
|
241 |
|
242 |
== Screenshots ==
|
243 |
|
261 |
|
262 |
== Changelog ==
|
263 |
|
264 |
+
= 4.15.0 =
|
265 |
+
|
266 |
+
Release date: 27th November 2019
|
267 |
+
* Ask if WebP files should be created before bulk optimization : checkbox added in Bulk page.
|
268 |
+
* Added filters for optimal chunk size when selecting records from wp_postmeta while bulk processing: 'shortpixel/db/chunk_size'.
|
269 |
+
* Optimize images also on edit-media screen.
|
270 |
+
* Experimental support for static cache firewalls, and sending images w/ timestamp: SHORTPIXEL_EXPERIMENTAL_SECURICACHE.
|
271 |
+
* Limit loading of JS / CSS to pages we do work on.
|
272 |
+
* Refactoring & speed optimizations: - new external class for gravity forms, nextgen and visual composer, new controller for global admin hooks, new front controller, updated plugin init, clean(ish) root file, database optimization(reduced number of queries), unlistedThumbs checker only fires when the optimize unlisted check is active, optimizations for filesystem and findFileByPattern.
|
273 |
+
* WPML Duplicates - Don't mark empty GUID's as duplicate.
|
274 |
+
* Fix broken styles on WP 5.3.
|
275 |
+
* Fix in case meta_value in processCountable has a WP_Error object instead of normal metadata.
|
276 |
+
* Fix on WP Engine when large wp_postmeta table: limit to 16K the size of the query with ID list.
|
277 |
+
* Fixed: error when log path is not writeable
|
278 |
+
* Fixed: double sends within the same images, can happen with something like WPML and it's duplicated media.
|
279 |
+
* Fixed: bug when searching unlisted images, in some circumstances.
|
280 |
+
* Fixed: max_execution_time when time is set lower than 0.
|
281 |
+
* Fixed: directories with no permission would give PHP error
|
282 |
+
* Fixed: pathToUrl now also works for paths outside wp uploads
|
283 |
+
* Fixed: check for DOING_AJAX on redirect to settings.
|
284 |
+
* Fixed: Shortpixel icon + exclamation mark in toolbar showing on every page load.
|
285 |
+
* Fixed: Add Custom media browser doesn't display files anymore
|
286 |
+
* Fixed: WebP option adds an extra border if image already has a border -> borders will not be replicated to <picture> tags.
|
287 |
+
* Fixed: Validating empty key doesn't show any message.
|
288 |
+
* Fixed: on Nginx writes .htaccess files.
|
289 |
+
* Fixed: Bug with safeGetAttachmentUrl for URLs that start with //.
|
290 |
+
* Fixed: New S3-Offload version breaks Shortpixel and offloading.
|
291 |
+
* Fixed: get_attached_file when S3-Offload is active, breaks other plugins.
|
292 |
+
* Fixed: crash when doing .htaccess files ( WP 5.3 specific ).
|
293 |
+
* Fixed: double file occurences on png2jpg in conjunction with s3offload.
|
294 |
+
* Language – 1 new strings added, 0 updated, 0 fuzzied, and 0 obsoleted
|
295 |
+
|
296 |
= 4.14.6 =
|
297 |
+
|
298 |
Release date: 9th October 2019
|
299 |
+
* Don't convert to <picture> the <img>s with backgrounds.
|
300 |
* Remove unused eval() call.
|
301 |
* Restore the validate button next to API Key but change label to "Save and validate"
|
302 |
* Fixed: PNGtoJPG issue with already uploaded images
|
311 |
* Fixed: notice in filemodel due meta-facade feeding array
|
312 |
* Fixed: bug in File2Url in filesystemcontroller
|
313 |
* Fixed: download issue in attempt to remote download
|
314 |
+
* Language – 0 new strings added, 1 updated, 0 fuzzied, and 0 obsoleted
|
315 |
|
316 |
= 4.14.5 =
|
317 |
+
|
318 |
Release date: 29th August 2019
|
319 |
* If constant SHORTPIXEL_USE_DOUBLE_WEBP_EXTENSION is defined as true, use double extension for WebP (.jpg.webp)
|
320 |
* Fixed: Javascript - String.prototype causes errors on React apps
|
325 |
* Language – 0 new strings added, 1 updated, 0 fuzzied, and 0 obsoleted
|
326 |
|
327 |
= 4.14.4 =
|
328 |
+
|
329 |
Release date: 19th August 2019
|
330 |
* Check if unlisted thumbnails present for already optimized images (in case the thumbnails were added later) in Media Library list and when doing bulk. This also integrates with the Unicode plugin.
|
331 |
* If JSON PHP module not present, add a proper error
|
395 |
* Fixed: Restoring an Other Media item and then Optimizing it again optimizes it Lossless
|
396 |
* fix generating the WebP <picture> tags when the images are either on a subdomain or on a CDN domain having the same root domain as the main site.
|
397 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
= EARLIER VERSIONS =
|
399 |
* please refer to the changelog.txt file inside the plugin archive.
|
@@ -18,6 +18,7 @@
|
|
18 |
.sp-dropbtn.button {
|
19 |
padding: 1px 24px 20px 5px;
|
20 |
font-size: 20px;
|
|
|
21 |
/*background-color: #4CAF50;
|
22 |
color: white;
|
23 |
border: none;*/
|
@@ -354,7 +355,7 @@ div.shortpixel-rate-us > a:focus {
|
|
354 |
padding:0px 5px;
|
355 |
margin-bottom: 4px;
|
356 |
height:20px;
|
357 |
-
|
358 |
float:right;
|
359 |
}
|
360 |
|
18 |
.sp-dropbtn.button {
|
19 |
padding: 1px 24px 20px 5px;
|
20 |
font-size: 20px;
|
21 |
+
line-height: 28px;
|
22 |
/*background-color: #4CAF50;
|
23 |
color: white;
|
24 |
border: none;*/
|
355 |
padding:0px 5px;
|
356 |
margin-bottom: 4px;
|
357 |
height:20px;
|
358 |
+
/* line-height:16px; */
|
359 |
float:right;
|
360 |
}
|
361 |
|
@@ -1 +1 @@
|
|
1 |
-
.reset{font-weight:normal;font-style:normal}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.clearfix{zoom:1}.resumeLabel{float:right;line-height:30px;margin-right:20px;font-size:16px}.sp-dropbtn.button{padding:1px 24px 20px 5px;font-size:20px;cursor:pointer}.sp-dropdown{position:relative;display:inline-block}.sp-dropdown-content{display:none;right:0;position:absolute;background-color:#f9f9f9;min-width:190px;box-shadow:0 8px 16px 0 rgba(0,0,0,0.2);z-index:1}.sp-dropdown-content a{color:black;padding:12px 16px;text-decoration:none;display:block}.sp-dropdown-content a:hover{background-color:#f1f1f1}.sp-dropdown.sp-show .sp-dropdown-content{display:block}div.fb-like{transform:scale(1.3);-ms-transform:scale(1.3);-webkit-transform:scale(1.3);-o-transform:scale(1.3);-moz-transform:scale(1.3);transform-origin:bottom left;-ms-transform-origin:bottom left;-webkit-transform-origin:bottom left;-moz-transform-origin:bottom left;-webkit-transform-origin:bottom left}.wp-core-ui .button.button-alert,.wp-core-ui .button.button-alert:hover{background:#f79797}.wp-core-ui .button.remove-folder-button{min-width:120px}.sp-notice{background:#fff;border-left:4px solid #fff;-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 1px 0 rgba(0,0,0,.1);padding:1px 12px}.sp-notice img{vertical-align:bottom}@media(max-width:1249px){.sp-notice{margin:5px 15px 2px}}.sp-notice-info{border-left-color:#00a0d2}.sp-notice-success{border-left-color:#46b450}.sp-notice-warning{border-left-color:#f1e02a}div.short-pixel-bulk-page input.dial{font-size:16px !important}div.short-pixel-bulk-page h1{margin-bottom:20px}div.bulk-progress div.sp-h2{margin-top:0;margin-bottom:10px;font-size:23px;font-weight:400;padding:9px 15px 4px 0;line-height:29px}div.bulk-progress-partners{margin-top:20px}div.bulk-progress.bulk-progress-partners a div{display:inline-block;vertical-align:top;line-height:50px;margin-left:30px;font-size:1.2em}div.bulk-progress .bulk-progress-indicator,div.sp-quota-exceeded-alert .bulk-progress-indicator{display:inline-block;text-align:center;padding:0 10px;margin-left:10px;float:left;height:90px;overflow:hidden;border:1px solid #1caecb}div.wrap.short-pixel-bulk-page .bulk-notice-container{margin-top:15px;position:absolute;width:500px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg{text-align:center;margin:10px 0 0 32px;overflow:hidden;border:1px solid #1caecb;background-color:#9ddbe0;border-radius:5px;padding:7px 10px 10px;display:none;max-width:600px;margin-right:20px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error{border:1px solid #b5914d;background-color:#ffe996;margin-right:20px;position:relative;z-index:10}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error.bulk-error-fatal{border:1px solid #c32525;background-color:#ff969d}div.wrap.short-pixel-bulk-page .bulk-notice-msg img{float:left;margin-top:3px;margin-right:5px}div.sp-bulk-summary{float:right;margin:8px 5px 3px 20px}.sp-notice .bulk-error-show{cursor:pointer}.sp-notice div.bulk-error-list{background-color:#f1f1f1;padding:0 10px;display:none;max-height:200px;overflow-y:scroll}.sp-notice div.bulk-error-list ul{padding:3px 0 0;margin-top:5px}.sp-notice div.bulk-error-list ul>li:not(:last-child){border-bottom:1px solid white;padding-bottom:4px}input.dial{box-shadow:none}.shortpixel-table .column-filename{max-width:32em;width:40%}.shortpixel-table .column-folder{max-width:20em;width:20%}.shortpixel-table .column-media_type{max-width:8em;width:10%}.shortpixel-table .column-status{max-width:16em;width:15%}.shortpixel-table .column-options{max-width:16em;width:15%}.form-table th{width:220px}.form-table td{position:relative}.form-table table.shortpixel-folders-list tr{background-color:#eee}.form-table table.shortpixel-folders-list td{padding:5px 10px}div.shortpixel-rate-us{display:inline-block;margin-left:10px;vertical-align:top;font-weight:bold}div.shortpixel-rate-us>a{vertical-align:middle;padding:1px 5px 0;text-align:center;display:inline-block}div.shortpixel-rate-us>a>span{display:inline-block;vertical-align:top;margin-top:5px}div.shortpixel-rate-us>a>img{padding-top:7px}div.shortpixel-rate-us>a:active,div.shortpixel-rate-us>a:hover,div.shortpixel-rate-us>a:focus{outline:0;border-style:none}.sp-loading-small{margin-top:2px;float:left;margin-right:5px}.twentytwenty-horizontal .twentytwenty-before-label:before,.twentytwenty-horizontal .twentytwenty-after-label:before{font-family:inherit;font-size:16px}.short-pixel-bulk-page p{margin:.6em 0}.short-pixel-bulk-page form.start{display:table;content:" ";width:98%;background-color:white;padding:10px 10px 0;position:relative}.bulk-stats-container{display:inline-block;min-width:450px;width:45%;float:left;padding-right:50px;font-size:1.1em;line-height:1.5em}.bulk-text-container{display:inline-block;min-width:440px;width:45%;float:left;padding-right:50px}.bulk-text-container h3{border-bottom:1px solid #a8a8a8;margin-bottom:.5em;padding-bottom:.5em}.bulk-wide{display:inline-block;width:90%;float:left;margin-top:25px}.bulk-stats-container .bulk-label{width:220px;display:inline-block}.bulk-stats-container .bulk-val{width:50px;display:inline-block;text-align:right}.bulk-stats-container .bulk-total{font-weight:bold;margin-top:10px;margin-bottom:10px}.wp-core-ui .bulk-play{display:inline;width:310px;float:left;margin-bottom:20px}.wp-core-ui .bulk-play.bulk-nothing-optimize{font-weight:bold;color:#0080b2;border:1px solid;border-radius:5px;margin-top:60px;padding:5px 12px}.wp-core-ui .bulk-play a.button{height:60px;margin-top:27px;overflow:hidden}.wp-core-ui .column-wp-shortPixel .sp-column-actions{max-width:140px;float:right;text-align:right}.wp-core-ui .column-wp-shortPixel .sp-column-actions .button.button-smaller{margin-right:0}.wp-core-ui .column-wp-shortPixel .button.button-smaller{font-size:13px;padding:0 5px;margin-bottom:4px;height:20px;line-height:16px;float:right}th.sortable.column-wp-shortPixel a,th.sorted.column-wp-shortPixel a{display:inline-block}.column-wp-shortPixel .sorting-indicator{display:inline-block}.wp-core-ui .bulk-play a.button .bulk-btn-img{display:inline-block;padding-top:6px}.wp-core-ui .bulk-play a.button .bulk-btn-txt{display:inline-block;text-align:right;line-height:1.3em;margin:11px 10px}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.label{font-size:1.6em}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.total{font-size:1.4em}.bulk-progress{padding:20px 32px 17px;background-color:#fff}.bulk-progress.bulk-stats>div{display:inline-block}.bulk-progress.bulk-stats>div.label{width:320px}.bulk-progress.bulk-stats>div.stat-value{width:80px;text-align:right}.short-pixel-bulk-page .progress{background-color:#ecedee;height:30px;position:relative;width:60%;display:inline-block;margin-right:28px;overflow:visible}.progress .progress-img{position:absolute;top:-10px;z-index:2;margin-left:-35px;line-height:48px;font-size:22px;font-weight:bold}.progress .progress-img span{vertical-align:top;margin-left:-7px}.progress .progress-left{background-color:#1cbecb;bottom:0;left:0;position:absolute;top:0;z-index:1;font-size:22px;font-weight:bold;line-height:28px;text-align:center;color:#fff}.bulk-estimate{font-size:20px;line-height:30px;vertical-align:top;display:inline-block}.wp-core-ui .button-primary.bulk-cancel{float:right;height:30px}.short-pixel-block-title{font-size:22px;font-weight:bold;text-align:center;margin-bottom:30px}.sp-floating-block.bulk-slider-container{display:none}.sp-floating-block.sp-notice.bulk-notices-parent{padding:0;margin:0;float:right;margin-right:500px !important}.bulk-slider-container{margin-top:20px;min-height:300px;overflow:hidden}.bulk-slider-container h2{margin-bottom:15px}.bulk-slider-container span.filename{font-weight:normal}.bulk-slider{display:table;margin:0 auto}.bulk-slider .bulk-slide{margin:0 auto;padding-left:120px;display:inline-block;font-weight:bold}.bulk-slider .img-original,.bulk-slider .img-optimized{display:inline-block;margin-right:20px;text-align:center}.bulk-slider .img-original div,.bulk-slider .img-optimized div{max-height:450px;overflow:hidden}.bulk-slider .img-original img,.bulk-slider .img-optimized img{max-width:300px}.bulk-slider .img-info{display:inline-block;vertical-align:top;font-size:48px;max-width:150px;padding:10px 0 0 20px}.bulk-slide-images{display:inline-block;border:1px solid #1caecb;padding:15px 0 0 20px}p.settings-info{padding-top:0;color:#818181;font-size:13px !important}p.settings-info.shortpixel-settings-error{color:#c32525}.shortpixel-key-valid{font-weight:bold}.shortpixel-key-valid .dashicons-yes:before{font-size:2em;line-height:25px;color:#3485ba;margin-left:-20px}.shortpixel-compression .shortpixel-compression-options{color:#999}.shortpixel-compression strong{line-height:22px}.shortpixel-compression .shortpixel-compression-options{display:inline-block}.shortpixel-compression label{width:158px;margin:0 -2px;background-color:#e2faff;font-weight:bold;display:inline-block}.shortpixel-compression label span{text-align:center;font-size:18px;padding:8px 0;display:block}.shortpixel-compression label input{display:none}.shortpixel-compression input:checked+span{background-color:#0085ba;color:#f7f7f7}.shortpixel-compression .shortpixel-radio-info{min-height:60px}article.sp-tabs{position:relative;display:block;width:100%;margin:2em auto}article.sp-tabs section{position:absolute;display:block;top:1.8em;left:0;width:100%;max-width:100%;box-sizing:border-box;padding:10px 20px;z-index:0}article.sp-tabs section.sel-tab{box-shadow:0 3px 3px rgba(0,0,0,0.1)}article.sp-tabs section .wp-shortpixel-tab-content{visibility:hidden}article.sp-tabs section.sel-tab .wp-shortpixel-tab-content{visibility:visible !important}article.sp-tabs section:first-child{z-index:1}article.sp-tabs section h2 a:focus,article.sp-tabs section#tab-resources a:focus{box-shadow:none;outline:0}article.sp-tabs section.sel-tab,article.sp-tabs section.sel-tab h2{color:#333;background-color:#fff;z-index:2}#tab-stats .sp-bulk-summary{position:absolute;right:0;top:0;z-index:100}.deliverWebpSettings,.deliverWebpTypes,.deliverWebpAlteringTypes{display:none}.deliverWebpTypes .sp-notice{color:red}.deliverWebpSettings{margin:16px 0}.deliverWebpSettings input:disabled+label{color:#818181}.deliverWebpTypes,.deliverWebpAlteringTypes{margin:16px 0 16px 16px}#png2jpg:not(:checked) ~ #png2jpgForce,#png2jpg:not(:checked) ~ label[for=png2jpgForce]{display:none}article.sp-tabs section #createWebp:checked ~ .deliverWebpSettings,article.sp-tabs section #deliverWebp:checked ~ .deliverWebpTypes,article.sp-tabs section #deliverWebpAltered:checked ~ .deliverWebpAlteringTypes{display:block}.shortpixel-help-link span.dashicons{text-decoration:none;margin-top:-1px}@media(min-width:1000px){section#tab-resources .col-md-6{display:inline-block;width:45%}}@media(max-width:999px){section#tab-resources .col-sm-12{display:inline-block;width:100%}}section#tab-resources .text-center{text-align:center}section#tab-resources p{font-size:16px}.wrap.short-pixel-bulk-page{margin-right:0}.sp-container{overflow:hidden;display:block;width:100%}.sp-floating-block{overflow:hidden;display:inline-block;float:left;margin-right:1.1% !important}.sp-full-width{width:98.8%;box-sizing:border-box}.sp-double-width{width:65.52%;box-sizing:border-box}.sp-single-width{width:32.23%;box-sizing:border-box}@media(max-width:1759px){.sp-floating-block{margin-right:1.3% !important}.sp-double-width,.sp-full-width{width:98.65%}.sp-single-width{width:48.7%}}@media(max-width:1249px){.sp-floating-block{margin-right:2% !important}.sp-double-width,.sp-full-width,.sp-single-width{width:97%}}.sp-tabs h2:before{content:none}.sp-column-actions-template+.sp-column-info{display:none}#wpadminbar .shortpixel-toolbar-processing .cssload-container{width:100%;height:24px;text-align:center;position:absolute;top:0;left:-1px}#wpadminbar .shortpixel-toolbar-processing.shortpixel-quota-exceeded .cssload-container,#wpadminbar .shortpixel-toolbar-processing.shortpixel-alert .cssload-container{display:none}#wpadminbar .shortpixel-toolbar-processing .cssload-speeding-wheel{width:24px;height:24px;opacity:.7;margin:0 auto;border:4px solid #1cbfcb;border-radius:50%;border-left-color:transparent;animation:cssload-spin 2000ms infinite linear;-o-animation:cssload-spin 2000ms infinite linear;-ms-animation:cssload-spin 2000ms infinite linear;-webkit-animation:cssload-spin 2000ms infinite linear;-moz-animation:cssload-spin 2000ms infinite linear}@keyframes cssload-spin{100%{transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes cssload-spin{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes cssload-spin{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes cssload-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes cssload-spin{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}
|
1 |
+
.reset{font-weight:400;font-style:normal}.clearfix:after,.clearfix:before{content:" ";display:table}.clearfix:after{clear:both}.clearfix{zoom:1}.resumeLabel{float:right;line-height:30px;margin-right:20px;font-size:16px}.sp-dropbtn.button{padding:1px 24px 20px 5px;font-size:20px;line-height:28px;cursor:pointer}.sp-dropdown{position:relative;display:inline-block}.sp-dropdown-content{display:none;right:0;position:absolute;background-color:#f9f9f9;min-width:190px;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);z-index:1}.sp-dropdown-content a{color:#000;padding:12px 16px;text-decoration:none;display:block}.sp-dropdown-content a:hover{background-color:#f1f1f1}.sp-dropdown.sp-show .sp-dropdown-content{display:block}div.fb-like{transform:scale(1.3);-ms-transform:scale(1.3);-webkit-transform:scale(1.3);-o-transform:scale(1.3);-moz-transform:scale(1.3);transform-origin:bottom left;-ms-transform-origin:bottom left;-webkit-transform-origin:bottom left;-moz-transform-origin:bottom left;-webkit-transform-origin:bottom left}.wp-core-ui .button.button-alert,.wp-core-ui .button.button-alert:hover{background:#f79797}.wp-core-ui .button.remove-folder-button{min-width:120px}.sp-notice{background:#fff;border-left:4px solid #fff;-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 1px 0 rgba(0,0,0,.1);padding:1px 12px}.sp-notice img{vertical-align:bottom}@media(max-width:1249px){.sp-notice{margin:5px 15px 2px}}.sp-notice-info{border-left-color:#00a0d2}.sp-notice-success{border-left-color:#46b450}.sp-notice-warning{border-left-color:#f1e02a}div.short-pixel-bulk-page input.dial{font-size:16px!important}div.short-pixel-bulk-page h1{margin-bottom:20px}div.bulk-progress div.sp-h2{margin-top:0;margin-bottom:10px;font-size:23px;font-weight:400;padding:9px 15px 4px 0;line-height:29px}div.bulk-progress-partners{margin-top:20px}div.bulk-progress.bulk-progress-partners a div{display:inline-block;vertical-align:top;line-height:50px;margin-left:30px;font-size:1.2em}div.bulk-progress .bulk-progress-indicator,div.sp-quota-exceeded-alert .bulk-progress-indicator{display:inline-block;text-align:center;padding:0 10px;margin-left:10px;float:left;height:90px;overflow:hidden;border:1px solid #1caecb}div.wrap.short-pixel-bulk-page .bulk-notice-container{margin-top:15px;position:absolute;width:500px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg{text-align:center;margin:10px 0 0 32px;overflow:hidden;border:1px solid #1caecb;background-color:#9ddbe0;border-radius:5px;padding:7px 10px 10px;display:none;max-width:600px;margin-right:20px}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error{border:1px solid #b5914d;background-color:#ffe996;margin-right:20px;position:relative;z-index:10}div.wrap.short-pixel-bulk-page .bulk-notice-container .bulk-notice-msg.bulk-error.bulk-error-fatal{border:1px solid #c32525;background-color:#ff969d}div.wrap.short-pixel-bulk-page .bulk-notice-msg img{float:left;margin-top:3px;margin-right:5px}div.sp-bulk-summary{float:right;margin:8px 5px 3px 20px}.sp-notice .bulk-error-show{cursor:pointer}.sp-notice div.bulk-error-list{background-color:#f1f1f1;padding:0 10px;display:none;max-height:200px;overflow-y:scroll}.sp-notice div.bulk-error-list ul{padding:3px 0 0;margin-top:5px}.sp-notice div.bulk-error-list ul>li:not(:last-child){border-bottom:1px solid #fff;padding-bottom:4px}input.dial{box-shadow:none}.shortpixel-table .column-filename{max-width:32em;width:40%}.shortpixel-table .column-folder{max-width:20em;width:20%}.shortpixel-table .column-media_type{max-width:8em;width:10%}.shortpixel-table .column-status{max-width:16em;width:15%}.shortpixel-table .column-options{max-width:16em;width:15%}.form-table th{width:220px}.form-table td{position:relative}.form-table table.shortpixel-folders-list tr{background-color:#eee}.form-table table.shortpixel-folders-list td{padding:5px 10px}div.shortpixel-rate-us{display:inline-block;margin-left:10px;vertical-align:top;font-weight:700}div.shortpixel-rate-us>a{vertical-align:middle;padding:1px 5px 0;text-align:center;display:inline-block}div.shortpixel-rate-us>a>span{display:inline-block;vertical-align:top;margin-top:5px}div.shortpixel-rate-us>a>img{padding-top:7px}div.shortpixel-rate-us>a:active,div.shortpixel-rate-us>a:focus,div.shortpixel-rate-us>a:hover{outline:0;border-style:none}.sp-loading-small{margin-top:2px;float:left;margin-right:5px}.twentytwenty-horizontal .twentytwenty-after-label:before,.twentytwenty-horizontal .twentytwenty-before-label:before{font-family:inherit;font-size:16px}.short-pixel-bulk-page p{margin:.6em 0}.short-pixel-bulk-page form.start{display:table;content:" ";width:98%;background-color:#fff;padding:10px 10px 0;position:relative}.bulk-stats-container{display:inline-block;min-width:450px;width:45%;float:left;padding-right:50px;font-size:1.1em;line-height:1.5em}.bulk-text-container{display:inline-block;min-width:440px;width:45%;float:left;padding-right:50px}.bulk-text-container h3{border-bottom:1px solid #a8a8a8;margin-bottom:.5em;padding-bottom:.5em}.bulk-wide{display:inline-block;width:90%;float:left;margin-top:25px}.bulk-stats-container .bulk-label{width:220px;display:inline-block}.bulk-stats-container .bulk-val{width:50px;display:inline-block;text-align:right}.bulk-stats-container .bulk-total{font-weight:700;margin-top:10px;margin-bottom:10px}.wp-core-ui .bulk-play{display:inline;width:310px;float:left;margin-bottom:20px}.wp-core-ui .bulk-play.bulk-nothing-optimize{font-weight:700;color:#0080b2;border:1px solid;border-radius:5px;margin-top:60px;padding:5px 12px}.wp-core-ui .bulk-play a.button{height:60px;margin-top:27px;overflow:hidden}.wp-core-ui .column-wp-shortPixel .sp-column-actions{max-width:140px;float:right;text-align:right}.wp-core-ui .column-wp-shortPixel .sp-column-actions .button.button-smaller{margin-right:0}.wp-core-ui .column-wp-shortPixel .button.button-smaller{font-size:13px;padding:0 5px;margin-bottom:4px;height:20px;float:right}th.sortable.column-wp-shortPixel a,th.sorted.column-wp-shortPixel a{display:inline-block}.column-wp-shortPixel .sorting-indicator{display:inline-block}.wp-core-ui .bulk-play a.button .bulk-btn-img{display:inline-block;padding-top:6px}.wp-core-ui .bulk-play a.button .bulk-btn-txt{display:inline-block;text-align:right;line-height:1.3em;margin:11px 10px}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.label{font-size:1.6em}.wp-core-ui .bulk-play a.button .bulk-btn-txt span.total{font-size:1.4em}.bulk-progress{padding:20px 32px 17px;background-color:#fff}.bulk-progress.bulk-stats>div{display:inline-block}.bulk-progress.bulk-stats>div.label{width:320px}.bulk-progress.bulk-stats>div.stat-value{width:80px;text-align:right}.short-pixel-bulk-page .progress{background-color:#ecedee;height:30px;position:relative;width:60%;display:inline-block;margin-right:28px;overflow:visible}.progress .progress-img{position:absolute;top:-10px;z-index:2;margin-left:-35px;line-height:48px;font-size:22px;font-weight:700}.progress .progress-img span{vertical-align:top;margin-left:-7px}.progress .progress-left{background-color:#1cbecb;bottom:0;left:0;position:absolute;top:0;z-index:1;font-size:22px;font-weight:700;line-height:28px;text-align:center;color:#fff}.bulk-estimate{font-size:20px;line-height:30px;vertical-align:top;display:inline-block}.wp-core-ui .button-primary.bulk-cancel{float:right;height:30px}.short-pixel-block-title{font-size:22px;font-weight:700;text-align:center;margin-bottom:30px}.sp-floating-block.bulk-slider-container{display:none}.sp-floating-block.sp-notice.bulk-notices-parent{padding:0;margin:0;float:right;margin-right:500px!important}.bulk-slider-container{margin-top:20px;min-height:300px;overflow:hidden}.bulk-slider-container h2{margin-bottom:15px}.bulk-slider-container span.filename{font-weight:400}.bulk-slider{display:table;margin:0 auto}.bulk-slider .bulk-slide{margin:0 auto;padding-left:120px;display:inline-block;font-weight:700}.bulk-slider .img-optimized,.bulk-slider .img-original{display:inline-block;margin-right:20px;text-align:center}.bulk-slider .img-optimized div,.bulk-slider .img-original div{max-height:450px;overflow:hidden}.bulk-slider .img-optimized img,.bulk-slider .img-original img{max-width:300px}.bulk-slider .img-info{display:inline-block;vertical-align:top;font-size:48px;max-width:150px;padding:10px 0 0 20px}.bulk-slide-images{display:inline-block;border:1px solid #1caecb;padding:15px 0 0 20px}p.settings-info{padding-top:0;color:#818181;font-size:13px!important}p.settings-info.shortpixel-settings-error{color:#c32525}.shortpixel-key-valid{font-weight:700}.shortpixel-key-valid .dashicons-yes:before{font-size:2em;line-height:25px;color:#3485ba;margin-left:-20px}.shortpixel-compression .shortpixel-compression-options{color:#999}.shortpixel-compression strong{line-height:22px}.shortpixel-compression .shortpixel-compression-options{display:inline-block}.shortpixel-compression label{width:158px;margin:0 -2px;background-color:#e2faff;font-weight:700;display:inline-block}.shortpixel-compression label span{text-align:center;font-size:18px;padding:8px 0;display:block}.shortpixel-compression label input{display:none}.shortpixel-compression input:checked+span{background-color:#0085ba;color:#f7f7f7}.shortpixel-compression .shortpixel-radio-info{min-height:60px}article.sp-tabs{position:relative;display:block;width:100%;margin:2em auto}article.sp-tabs section{position:absolute;display:block;top:1.8em;left:0;width:100%;max-width:100%;box-sizing:border-box;padding:10px 20px;z-index:0}article.sp-tabs section.sel-tab{box-shadow:0 3px 3px rgba(0,0,0,.1)}article.sp-tabs section .wp-shortpixel-tab-content{visibility:hidden}article.sp-tabs section.sel-tab .wp-shortpixel-tab-content{visibility:visible!important}article.sp-tabs section:first-child{z-index:1}article.sp-tabs section h2 a:focus,article.sp-tabs section#tab-resources a:focus{box-shadow:none;outline:0}article.sp-tabs section.sel-tab,article.sp-tabs section.sel-tab h2{color:#333;background-color:#fff;z-index:2}#tab-stats .sp-bulk-summary{position:absolute;right:0;top:0;z-index:100}.deliverWebpAlteringTypes,.deliverWebpSettings,.deliverWebpTypes{display:none}.deliverWebpTypes .sp-notice{color:red}.deliverWebpSettings{margin:16px 0}.deliverWebpSettings input:disabled+label{color:#818181}.deliverWebpAlteringTypes,.deliverWebpTypes{margin:16px 0 16px 16px}#png2jpg:not(:checked)~#png2jpgForce,#png2jpg:not(:checked)~label[for=png2jpgForce]{display:none}article.sp-tabs section #createWebp:checked~.deliverWebpSettings,article.sp-tabs section #deliverWebp:checked~.deliverWebpTypes,article.sp-tabs section #deliverWebpAltered:checked~.deliverWebpAlteringTypes{display:block}.shortpixel-help-link span.dashicons{text-decoration:none;margin-top:-1px}@media(min-width:1000px){section#tab-resources .col-md-6{display:inline-block;width:45%}}@media(max-width:999px){section#tab-resources .col-sm-12{display:inline-block;width:100%}}section#tab-resources .text-center{text-align:center}section#tab-resources p{font-size:16px}.wrap.short-pixel-bulk-page{margin-right:0}.sp-container{overflow:hidden;display:block;width:100%}.sp-floating-block{overflow:hidden;display:inline-block;float:left;margin-right:1.1%!important}.sp-full-width{width:98.8%;box-sizing:border-box}.sp-double-width{width:65.52%;box-sizing:border-box}.sp-single-width{width:32.23%;box-sizing:border-box}@media(max-width:1759px){.sp-floating-block{margin-right:1.3%!important}.sp-double-width,.sp-full-width{width:98.65%}.sp-single-width{width:48.7%}}@media(max-width:1249px){.sp-floating-block{margin-right:2%!important}.sp-double-width,.sp-full-width,.sp-single-width{width:97%}}.sp-tabs h2:before{content:none}.sp-column-actions-template+.sp-column-info{display:none}#wpadminbar .shortpixel-toolbar-processing .cssload-container{width:100%;height:24px;text-align:center;position:absolute;top:0;left:-1px}#wpadminbar .shortpixel-toolbar-processing.shortpixel-alert .cssload-container,#wpadminbar .shortpixel-toolbar-processing.shortpixel-quota-exceeded .cssload-container{display:none}#wpadminbar .shortpixel-toolbar-processing .cssload-speeding-wheel{width:24px;height:24px;opacity:.7;margin:0 auto;border:4px solid #1cbfcb;border-radius:50%;border-left-color:transparent;animation:cssload-spin 2s infinite linear;-o-animation:cssload-spin 2s infinite linear;-ms-animation:cssload-spin 2s infinite linear;-webkit-animation:cssload-spin 2s infinite linear;-moz-animation:cssload-spin 2s infinite linear}@keyframes cssload-spin{100%{transform:rotate(360deg);transform:rotate(360deg)}}@-o-keyframes cssload-spin{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes cssload-spin{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes cssload-spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes cssload-spin{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}
|
@@ -1019,7 +1019,7 @@ function checkBulkProcessingCallApi(){
|
|
1019 |
ShortPixel.otherMediaUpdateActions(id, ['quota','view']);
|
1020 |
break;
|
1021 |
case ShortPixel.STATUS_FAIL:
|
1022 |
-
setCellMessage(id, data["Message"], "<a class='button button-smaller button-primary' href=\"javascript:manualOptimization('" + id + "',
|
1023 |
+ _spTr.retry + "</a>");
|
1024 |
showToolBarAlert(ShortPixel.STATUS_FAIL, data["Message"], id);
|
1025 |
if(isBulkPage) {
|
1019 |
ShortPixel.otherMediaUpdateActions(id, ['quota','view']);
|
1020 |
break;
|
1021 |
case ShortPixel.STATUS_FAIL:
|
1022 |
+
setCellMessage(id, data["Message"], "<a class='button button-smaller button-primary' href=\"javascript:manualOptimization('" + id + "', true)\">"
|
1023 |
+ _spTr.retry + "</a>");
|
1024 |
showToolBarAlert(ShortPixel.STATUS_FAIL, data["Message"], id);
|
1025 |
if(isBulkPage) {
|
@@ -10,7 +10,9 @@ use ShortPixel\Notices\NoticeController as Notices;
|
|
10 |
*/
|
11 |
class ShortPixelPlugin
|
12 |
{
|
13 |
-
static
|
|
|
|
|
14 |
private $paths = array('class', 'class/controller', 'class/external'); // classes that are autoloaded
|
15 |
|
16 |
protected $is_noheaders = false;
|
@@ -18,17 +20,92 @@ class ShortPixelPlugin
|
|
18 |
protected $plugin_path;
|
19 |
protected $plugin_url;
|
20 |
|
|
|
|
|
|
|
|
|
|
|
21 |
public function __construct()
|
22 |
{
|
23 |
$this->plugin_path = plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
|
24 |
$this->plugin_url = plugin_dir_url(SHORTPIXEL_PLUGIN_FILE);
|
25 |
|
26 |
-
$this->initRuntime();
|
27 |
$this->initHooks();
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
if(isset($_REQUEST['noheader'])) {
|
30 |
$this->is_noheaders = true;
|
31 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
33 |
|
34 |
/** Create instance. This should not be needed to call anywhere else than main plugin file **/
|
@@ -36,9 +113,10 @@ class ShortPixelPlugin
|
|
36 |
{
|
37 |
if (is_null(self::$instance))
|
38 |
{
|
39 |
-
self::$instance = new
|
40 |
}
|
41 |
return self::$instance;
|
|
|
42 |
}
|
43 |
|
44 |
/** Init Runtime. Loads all classes. */
|
@@ -73,17 +151,26 @@ class ShortPixelPlugin
|
|
73 |
public function initHooks()
|
74 |
{
|
75 |
add_action('admin_menu', array($this,'admin_pages'));
|
76 |
-
add_action('admin_enqueue_scripts', array($this, 'admin_scripts'));
|
77 |
add_action('admin_notices', array($this, 'admin_notices')); // notices occured before page load
|
78 |
add_action('admin_footer', array($this, 'admin_notices')); // called in views.
|
79 |
-
|
80 |
}
|
81 |
|
82 |
/** Hook in our admin pages */
|
83 |
public function admin_pages()
|
84 |
{
|
|
|
85 |
// settings page
|
86 |
-
add_options_page( __('ShortPixel Settings','shortpixel-image-optimiser'), 'ShortPixel', 'manage_options', 'wp-shortpixel-settings', array($this, 'route'));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
}
|
88 |
|
89 |
/** PluginRunTime. Items that should be initialized *only* when doing our pages and territory. */
|
@@ -168,8 +255,6 @@ class ShortPixelPlugin
|
|
168 |
public function route()
|
169 |
{
|
170 |
global $plugin_page;
|
171 |
-
global $shortPixelPluginInstance; //brrr @todo Find better solution for this some day.
|
172 |
-
|
173 |
$this->initPluginRunTime();
|
174 |
|
175 |
$default_action = 'load'; // generic action on controller.
|
@@ -193,7 +278,7 @@ class ShortPixelPlugin
|
|
193 |
if ($controller !== false)
|
194 |
{
|
195 |
$c = new $controller();
|
196 |
-
$c->setShortPixel($
|
197 |
$c->setControllerURL($url);
|
198 |
if (method_exists($c, $action))
|
199 |
$c->$action();
|
@@ -205,4 +290,103 @@ class ShortPixelPlugin
|
|
205 |
}
|
206 |
}
|
207 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
} // class plugin
|
10 |
*/
|
11 |
class ShortPixelPlugin
|
12 |
{
|
13 |
+
private static $instance;
|
14 |
+
protected static $modelsLoaded = array(); // don't require twice, limit amount of require looksups..
|
15 |
+
|
16 |
private $paths = array('class', 'class/controller', 'class/external'); // classes that are autoloaded
|
17 |
|
18 |
protected $is_noheaders = false;
|
20 |
protected $plugin_path;
|
21 |
protected $plugin_url;
|
22 |
|
23 |
+
protected $shortPixel; // shortpixel megaclass
|
24 |
+
protected $settings; // settings object.
|
25 |
+
|
26 |
+
protected $admin_pages; // admin page hooks.
|
27 |
+
|
28 |
public function __construct()
|
29 |
{
|
30 |
$this->plugin_path = plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
|
31 |
$this->plugin_url = plugin_dir_url(SHORTPIXEL_PLUGIN_FILE);
|
32 |
|
33 |
+
$this->initRuntime(); // require controllers, and other needed classes
|
34 |
$this->initHooks();
|
35 |
|
36 |
+
add_action('plugins_loaded', array($this, 'init'), 5); // early as possible init.
|
37 |
+
}
|
38 |
+
|
39 |
+
/*
|
40 |
+
* Init the plugin after plugins_loaded hook. All of WP is there, all plugins.
|
41 |
+
* This can't be loaded on construct time, because of model Loaders etc, with would result in loop.
|
42 |
+
*
|
43 |
+
*/
|
44 |
+
public function init()
|
45 |
+
{
|
46 |
if(isset($_REQUEST['noheader'])) {
|
47 |
$this->is_noheaders = true;
|
48 |
}
|
49 |
+
|
50 |
+
// @todo Transitionary init for the time being, since plugin init functionality is still split between.
|
51 |
+
global $shortPixelPluginInstance;
|
52 |
+
$shortPixelPluginInstance = new \wpShortPixel();
|
53 |
+
$this->shortPixel = $shortPixelPluginInstance;
|
54 |
+
|
55 |
+
$front = new frontController();
|
56 |
+
$admin = adminController::getInstance();
|
57 |
+
|
58 |
+
|
59 |
+
if ($this->settings()->autoMediaLibrary)
|
60 |
+
{
|
61 |
+
// compat filter to shortcircuit this in cases. (see external - visualcomposer)
|
62 |
+
if (apply_filters('shortpixel/init/automedialibrary', true))
|
63 |
+
{
|
64 |
+
// $autoPng2Jpg = get_option('wp-short-pixel-png2jpg');
|
65 |
+
//$autoMediaLibrary = get_option('wp-short-pixel-auto-media-library');
|
66 |
+
|
67 |
+
if($this->settings()->autoMediaLibrary && $this->settings()->png2jpg) {
|
68 |
+
add_action( 'wp_handle_upload', array($admin,'handlePng2JpgHook'));
|
69 |
+
// @todo Document what plugin does mpp
|
70 |
+
add_action( 'mpp_handle_upload', array($admin,'handlePng2JpgHook'));
|
71 |
+
}
|
72 |
+
add_action('wp_handle_replace', array($admin,'handleReplaceHook'));
|
73 |
+
|
74 |
+
if($this->settings()->autoMediaLibrary) {
|
75 |
+
|
76 |
+
add_filter( 'wp_generate_attachment_metadata', array($admin,'handleImageUploadHook'), 10, 2 );
|
77 |
+
// @todo Document what plugin does mpp
|
78 |
+
add_filter( 'mpp_generate_metadata', array($admin,'handleImageUploadHook'), 10, 2 );
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
/** Function to get plugin settings
|
85 |
+
*
|
86 |
+
* @return SettingsModel The settings model object.
|
87 |
+
*/
|
88 |
+
public function settings()
|
89 |
+
{
|
90 |
+
if (is_null($this->settings))
|
91 |
+
$this->settings = new \WPShortPixelSettings();
|
92 |
+
|
93 |
+
return $this->settings;
|
94 |
+
}
|
95 |
+
|
96 |
+
/** Function to get all enviromental variables
|
97 |
+
*
|
98 |
+
* @return EnvironmentModel
|
99 |
+
*/
|
100 |
+
public function env()
|
101 |
+
{
|
102 |
+
$this->loadModel('environment');
|
103 |
+
return EnvironmentModel::getInstance();
|
104 |
+
}
|
105 |
+
|
106 |
+
public function fileSystem()
|
107 |
+
{
|
108 |
+
return new \ShortPixel\FileSystemController();
|
109 |
}
|
110 |
|
111 |
/** Create instance. This should not be needed to call anywhere else than main plugin file **/
|
113 |
{
|
114 |
if (is_null(self::$instance))
|
115 |
{
|
116 |
+
self::$instance = new ShortPixelPlugin();
|
117 |
}
|
118 |
return self::$instance;
|
119 |
+
|
120 |
}
|
121 |
|
122 |
/** Init Runtime. Loads all classes. */
|
151 |
public function initHooks()
|
152 |
{
|
153 |
add_action('admin_menu', array($this,'admin_pages'));
|
154 |
+
add_action('admin_enqueue_scripts', array($this, 'admin_scripts')); // admin scripts
|
155 |
add_action('admin_notices', array($this, 'admin_notices')); // notices occured before page load
|
156 |
add_action('admin_footer', array($this, 'admin_notices')); // called in views.
|
|
|
157 |
}
|
158 |
|
159 |
/** Hook in our admin pages */
|
160 |
public function admin_pages()
|
161 |
{
|
162 |
+
$admin_pages = array();
|
163 |
// settings page
|
164 |
+
$admin_pages[] = add_options_page( __('ShortPixel Settings','shortpixel-image-optimiser'), 'ShortPixel', 'manage_options', 'wp-shortpixel-settings', array($this, 'route'));
|
165 |
+
|
166 |
+
if($this->shortPixel->getSpMetaDao()->hasFoldersTable() && count($this->shortPixel->getSpMetaDao()->getFolders())) {
|
167 |
+
/*translators: title and menu name for the Other media page*/
|
168 |
+
$admin_pages[] = add_media_page( __('Other Media Optimized by ShortPixel','shortpixel-image-optimiser'), __('Other Media','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-custom', array( $this->shortPixel, 'listCustomMedia' ) );
|
169 |
+
}
|
170 |
+
/*translators: title and menu name for the Bulk Processing page*/
|
171 |
+
$admin_pages[] = add_media_page( __('ShortPixel Bulk Process','shortpixel-image-optimiser'), __('Bulk ShortPixel','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-bulk', array( $this->shortPixel, 'bulkProcess' ) );
|
172 |
+
|
173 |
+
$this->admin_pages = $admin_pages;
|
174 |
}
|
175 |
|
176 |
/** PluginRunTime. Items that should be initialized *only* when doing our pages and territory. */
|
255 |
public function route()
|
256 |
{
|
257 |
global $plugin_page;
|
|
|
|
|
258 |
$this->initPluginRunTime();
|
259 |
|
260 |
$default_action = 'load'; // generic action on controller.
|
278 |
if ($controller !== false)
|
279 |
{
|
280 |
$c = new $controller();
|
281 |
+
$c->setShortPixel($this->shortPixel);
|
282 |
$c->setControllerURL($url);
|
283 |
if (method_exists($c, $action))
|
284 |
$c->$action();
|
290 |
}
|
291 |
}
|
292 |
|
293 |
+
/** Loads the Model Data Structure upon request
|
294 |
+
*
|
295 |
+
* @param string $name Name of the model
|
296 |
+
*/
|
297 |
+
public function loadModel($name){
|
298 |
+
$path = \ShortPixelTools::getPluginPath() . 'class/model/' . $name . '_model.php';
|
299 |
+
|
300 |
+
if (! in_array($name, self::$modelsLoaded))
|
301 |
+
{
|
302 |
+
self::$modelsLoaded[] = $name;
|
303 |
+
if(file_exists($path)){
|
304 |
+
require_once($path);
|
305 |
+
}
|
306 |
+
else {
|
307 |
+
Log::addError("Model $name could not be found");
|
308 |
+
}
|
309 |
+
}
|
310 |
+
}
|
311 |
+
|
312 |
+
// Get the plugin URL, based on real URL.
|
313 |
+
public function plugin_url($urlpath = '')
|
314 |
+
{
|
315 |
+
$url = trailingslashit($this->plugin_url);
|
316 |
+
if (strlen($urlpath) > 0)
|
317 |
+
$url .= $urlpath;
|
318 |
+
return $url;
|
319 |
+
}
|
320 |
+
|
321 |
+
// Get the plugin path.
|
322 |
+
public function plugin_path($path = '')
|
323 |
+
{
|
324 |
+
$plugin_path = trailingslashit($this->plugin_path);
|
325 |
+
if (strlen($path) > 0)
|
326 |
+
$plugin_path .= $path;
|
327 |
+
|
328 |
+
return $plugin_path;
|
329 |
+
}
|
330 |
+
|
331 |
+
// Get the ShortPixel Object.
|
332 |
+
public function getShortPixel()
|
333 |
+
{
|
334 |
+
return $this->shortPixel;
|
335 |
+
}
|
336 |
+
|
337 |
+
/** Returns defined admin page hooks. Internal use - check states via environmentmodel
|
338 |
+
* @returns Array
|
339 |
+
*/
|
340 |
+
public function get_admin_pages()
|
341 |
+
{
|
342 |
+
return $this->admin_pages;
|
343 |
+
}
|
344 |
+
|
345 |
+
public static function activatePlugin()
|
346 |
+
{
|
347 |
+
self::deactivatePlugin();
|
348 |
+
if(SHORTPIXEL_RESET_ON_ACTIVATE === true && WP_DEBUG === true) { //force reset plugin counters, only on specific occasions and on test environments
|
349 |
+
\WPShortPixelSettings::debugResetOptions();
|
350 |
+
$settings = new \WPShortPixelSettings();
|
351 |
+
$spMetaDao = new \ShortPixelCustomMetaDao(new \WpShortPixelDb(), $settings->excludePatterns);
|
352 |
+
$spMetaDao->dropTables();
|
353 |
+
}
|
354 |
+
|
355 |
+
$env = wpSPIO()->env();
|
356 |
+
|
357 |
+
if(\WPShortPixelSettings::getOpt('deliverWebp') == 3 && ! $env->is_nginx) {
|
358 |
+
self::alterHtaccess(); //add the htaccess lines
|
359 |
+
}
|
360 |
+
\WPShortPixelSettings::onActivate();
|
361 |
+
}
|
362 |
+
|
363 |
+
public static function deactivatePlugin()
|
364 |
+
{
|
365 |
+
\ShortPixelQueue::resetBulk();
|
366 |
+
(! defined('SHORTPIXEL_NOFLOCK')) ? \ShortPixelQueue::resetPrio() : \ShortPixelQueueDB::resetPrio();
|
367 |
+
\WPShortPixelSettings::onDeactivate();
|
368 |
+
|
369 |
+
//$settingsControl = new \ShortPixel\SettingsController();
|
370 |
+
$env = wpSPIO()->env();
|
371 |
+
|
372 |
+
if (! $env->is_nginx)
|
373 |
+
\WpShortPixel::alterHtaccess(true);
|
374 |
+
|
375 |
+
// save remove.
|
376 |
+
$fs = new FileSystemController();
|
377 |
+
$log = $fs->getFile(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
|
378 |
+
if ($log->exists())
|
379 |
+
$log->delete();
|
380 |
+
// @unlink(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
|
381 |
+
}
|
382 |
+
|
383 |
+
public static function uninstallPlugin()
|
384 |
+
{
|
385 |
+
$settings = new \WPShortPixelSettings();
|
386 |
+
if($settings->removeSettingsOnDeletePlugin == 1) {
|
387 |
+
\WPShortPixelSettings::debugResetOptions();
|
388 |
+
insert_with_markers( get_home_path() . '.htaccess', 'ShortPixelWebp', '');
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
} // class plugin
|
@@ -113,7 +113,7 @@ class ShortPixelAPI {
|
|
113 |
}
|
114 |
|
115 |
// WpShortPixel::log("DO REQUESTS for META: " . json_encode($itemHandler->getRawMeta()) . " STACK: " . json_encode(debug_backtrace()));
|
116 |
-
|
117 |
|
118 |
$requestParameters = array(
|
119 |
'plugin_version' => SHORTPIXEL_IMAGE_OPTIMISER_VERSION,
|
@@ -135,8 +135,8 @@ class ShortPixelAPI {
|
|
135 |
}
|
136 |
|
137 |
//WpShortPixel::log("ShortPixel API Request Settings: " . json_encode($requestParameters));
|
138 |
-
//Log::addDebug('ShortPixel API Request');
|
139 |
$response = wp_remote_post($this->_apiEndPoint, $this->prepareRequest($requestParameters, $Blocking) );
|
|
|
140 |
|
141 |
//WpShortPixel::log('RESPONSE: ' . json_encode($response));
|
142 |
|
@@ -247,6 +247,7 @@ class ShortPixelAPI {
|
|
247 |
$compressionType = $meta->getCompressionType() !== null ? $meta->getCompressionType() : $this->_settings->compressionType;
|
248 |
$response = $this->doRequests($URLs, true, $itemHandler, $compressionType);//send requests to API
|
249 |
|
|
|
250 |
//die($response['body']);
|
251 |
|
252 |
if($response['response']['code'] != 200) {//response <> 200 -> there was an error apparently?
|
@@ -467,12 +468,13 @@ class ShortPixelAPI {
|
|
467 |
return array("Status" => self::STATUS_SUCCESS);
|
468 |
}
|
469 |
|
470 |
-
|
471 |
|
472 |
//$fullSubDir = str_replace(wp_normalize_path(get_home_path()), "", wp_normalize_path(dirname($itemHandler->getMeta()->getPath()))) . '/';
|
473 |
//$SubDir = ShortPixelMetaFacade::returnSubDir($itemHandler->getMeta()->getPath(), $itemHandler->getType());
|
474 |
$fullSubDir = ShortPixelMetaFacade::returnSubDir($mainPath);
|
475 |
$source = $PATHs; //array with final paths for these files
|
|
|
476 |
|
477 |
if( !file_exists(SHORTPIXEL_BACKUP_FOLDER) && ! ShortPixelFolder::createBackUpFolder() ) {//creates backup folder if it doesn't exist
|
478 |
Log::addWarn('Backup folder does not exist and it cannot be created');
|
@@ -489,16 +491,20 @@ class ShortPixelAPI {
|
|
489 |
//now that we have original files and where we should back them up we attempt to do just that
|
490 |
if(is_writable(SHORTPIXEL_BACKUP_FOLDER))
|
491 |
{
|
492 |
-
|
493 |
foreach ( $destination as $fileID => $filePATH )
|
494 |
{
|
495 |
-
|
|
|
|
|
496 |
{
|
497 |
-
|
|
|
|
|
498 |
{//file couldn't be saved in backup folder
|
499 |
$msg = sprintf(__('Cannot save file <i>%s</i> in backup directory','shortpixel-image-optimiser'),self::MB_basename($source[$fileID]));
|
500 |
return array("Status" => self::STATUS_FAIL, "Message" => $msg);
|
501 |
}
|
|
|
502 |
}
|
503 |
}
|
504 |
return array("Status" => self::STATUS_SUCCESS);
|
@@ -828,6 +834,7 @@ class ShortPixelAPI {
|
|
828 |
/**
|
829 |
* @param $archive
|
830 |
* @param $tempFiles
|
|
|
831 |
*/
|
832 |
protected static function cleanupTemporaryFiles($archive, $tempFiles)
|
833 |
{
|
@@ -835,8 +842,16 @@ class ShortPixelAPI {
|
|
835 |
ShortpixelFolder::deleteFolder($archive['Path']);
|
836 |
} else {
|
837 |
if (!empty($tempFiles) && is_array($tempFiles)) {
|
|
|
838 |
foreach ($tempFiles as $tmpFile) {
|
839 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
840 |
}
|
841 |
}
|
842 |
}
|
113 |
}
|
114 |
|
115 |
// WpShortPixel::log("DO REQUESTS for META: " . json_encode($itemHandler->getRawMeta()) . " STACK: " . json_encode(debug_backtrace()));
|
116 |
+
$URLs = apply_filters('shortpixel_image_urls', $URLs, $itemHandler->getId()) ;
|
117 |
|
118 |
$requestParameters = array(
|
119 |
'plugin_version' => SHORTPIXEL_IMAGE_OPTIMISER_VERSION,
|
135 |
}
|
136 |
|
137 |
//WpShortPixel::log("ShortPixel API Request Settings: " . json_encode($requestParameters));
|
|
|
138 |
$response = wp_remote_post($this->_apiEndPoint, $this->prepareRequest($requestParameters, $Blocking) );
|
139 |
+
Log::addDebug('ShortPixel API Request sent', $requestParameters);
|
140 |
|
141 |
//WpShortPixel::log('RESPONSE: ' . json_encode($response));
|
142 |
|
247 |
$compressionType = $meta->getCompressionType() !== null ? $meta->getCompressionType() : $this->_settings->compressionType;
|
248 |
$response = $this->doRequests($URLs, true, $itemHandler, $compressionType);//send requests to API
|
249 |
|
250 |
+
|
251 |
//die($response['body']);
|
252 |
|
253 |
if($response['response']['code'] != 200) {//response <> 200 -> there was an error apparently?
|
468 |
return array("Status" => self::STATUS_SUCCESS);
|
469 |
}
|
470 |
|
471 |
+
//Log::addDebug('Backing The Up', array($mainPath, $PATHs));
|
472 |
|
473 |
//$fullSubDir = str_replace(wp_normalize_path(get_home_path()), "", wp_normalize_path(dirname($itemHandler->getMeta()->getPath()))) . '/';
|
474 |
//$SubDir = ShortPixelMetaFacade::returnSubDir($itemHandler->getMeta()->getPath(), $itemHandler->getType());
|
475 |
$fullSubDir = ShortPixelMetaFacade::returnSubDir($mainPath);
|
476 |
$source = $PATHs; //array with final paths for these files
|
477 |
+
$fs = \wpSPIO()->filesystem();
|
478 |
|
479 |
if( !file_exists(SHORTPIXEL_BACKUP_FOLDER) && ! ShortPixelFolder::createBackUpFolder() ) {//creates backup folder if it doesn't exist
|
480 |
Log::addWarn('Backup folder does not exist and it cannot be created');
|
491 |
//now that we have original files and where we should back them up we attempt to do just that
|
492 |
if(is_writable(SHORTPIXEL_BACKUP_FOLDER))
|
493 |
{
|
|
|
494 |
foreach ( $destination as $fileID => $filePATH )
|
495 |
{
|
496 |
+
$destination_file = $fs->getFile($filePATH);
|
497 |
+
|
498 |
+
if ( ! $destination_file->exists() )
|
499 |
{
|
500 |
+
$source_file = $fs->getFile($source[$fileID]);
|
501 |
+
$result = $source_file->copy($destination_file);
|
502 |
+
if ( ! $result )
|
503 |
{//file couldn't be saved in backup folder
|
504 |
$msg = sprintf(__('Cannot save file <i>%s</i> in backup directory','shortpixel-image-optimiser'),self::MB_basename($source[$fileID]));
|
505 |
return array("Status" => self::STATUS_FAIL, "Message" => $msg);
|
506 |
}
|
507 |
+
|
508 |
}
|
509 |
}
|
510 |
return array("Status" => self::STATUS_SUCCESS);
|
834 |
/**
|
835 |
* @param $archive
|
836 |
* @param $tempFiles
|
837 |
+
* @todo Move to FS-controller
|
838 |
*/
|
839 |
protected static function cleanupTemporaryFiles($archive, $tempFiles)
|
840 |
{
|
842 |
ShortpixelFolder::deleteFolder($archive['Path']);
|
843 |
} else {
|
844 |
if (!empty($tempFiles) && is_array($tempFiles)) {
|
845 |
+
|
846 |
foreach ($tempFiles as $tmpFile) {
|
847 |
+
$filepath = isset($tmpFile['Message']) ? $tmpFile['Message'] : false;
|
848 |
+
if ($filepath)
|
849 |
+
{
|
850 |
+
$file = \wpSPIO()->filesystem()->getFile($filepath);
|
851 |
+
if ($file->exists())
|
852 |
+
$file->delete();
|
853 |
+
//@unlink($tmpFile["Message"]);
|
854 |
+
}
|
855 |
}
|
856 |
}
|
857 |
}
|
@@ -7,27 +7,24 @@ if(defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG === true) {
|
|
7 |
} */
|
8 |
|
9 |
// Debug. Hook as early as possible.
|
10 |
-
require_once('class/controller/controller.php');
|
11 |
//require_once('class/controller/debug.php');
|
12 |
//require_once('class/model/shortpixel-debug.php');
|
13 |
|
14 |
// @todo wp-shortpixel-settings which depends on this model should be called when needed; in the model/ directory. That will be some work, so for now here.
|
15 |
-
require_once('class/shortpixel-model.php');
|
16 |
|
17 |
//use ShortPixel\DebugItem as DebugItem;
|
18 |
-
use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
19 |
|
20 |
-
if (! defined('SHORTPIXEL_DEBUG'))
|
21 |
{
|
22 |
define('SHORTPIXEL_DEBUG', false);
|
23 |
-
}
|
24 |
-
|
25 |
-
Log::addDebug('Plugin Req Init');
|
26 |
-
|
27 |
|
28 |
// [BS] New plugin runtime.
|
29 |
-
require_once('shortpixel-plugin.php'); // loads runtime and needed classes.
|
30 |
-
new Shortpixel\ShortPixelPlugin();
|
31 |
|
32 |
// @todo Temporary until main plugin file will receive it's unclutter. Require the things loaded by new plugin main
|
33 |
/*if (! class_exists('ShortPixel\ShortPixelPlugin'))
|
7 |
} */
|
8 |
|
9 |
// Debug. Hook as early as possible.
|
10 |
+
//require_once('class/controller/controller.php');
|
11 |
//require_once('class/controller/debug.php');
|
12 |
//require_once('class/model/shortpixel-debug.php');
|
13 |
|
14 |
// @todo wp-shortpixel-settings which depends on this model should be called when needed; in the model/ directory. That will be some work, so for now here.
|
15 |
+
//require_once('class/shortpixel-model.php');
|
16 |
|
17 |
//use ShortPixel\DebugItem as DebugItem;
|
18 |
+
//use ShortPixel\ShortPixelLogger\ShortPixelLogger as Log;
|
19 |
|
20 |
+
/*if (! defined('SHORTPIXEL_DEBUG'))
|
21 |
{
|
22 |
define('SHORTPIXEL_DEBUG', false);
|
23 |
+
} */
|
|
|
|
|
|
|
24 |
|
25 |
// [BS] New plugin runtime.
|
26 |
+
//require_once('shortpixel-plugin.php'); // loads runtime and needed classes.
|
27 |
+
//new Shortpixel\ShortPixelPlugin();
|
28 |
|
29 |
// @todo Temporary until main plugin file will receive it's unclutter. Require the things loaded by new plugin main
|
30 |
/*if (! class_exists('ShortPixel\ShortPixelPlugin'))
|
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: ShortPixel Image Optimizer
|
4 |
* Plugin URI: https://shortpixel.com/
|
5 |
* Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel-settings" target="_blank">Settings > ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
|
6 |
-
* Version: 4.
|
7 |
* Author: ShortPixel
|
8 |
* Author URI: https://shortpixel.com
|
9 |
* Text Domain: shortpixel-image-optimiser
|
@@ -19,7 +19,7 @@ define('SHORTPIXEL_PLUGIN_DIR', __DIR__);
|
|
19 |
|
20 |
//define('SHORTPIXEL_AFFILIATE_CODE', '');
|
21 |
|
22 |
-
define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.
|
23 |
define('SHORTPIXEL_MAX_TIMEOUT', 10);
|
24 |
define('SHORTPIXEL_VALIDATE_MAX_TIMEOUT', 15);
|
25 |
define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
|
@@ -40,13 +40,14 @@ define('SHORTPIXEL_API', 'api.shortpixel.com');
|
|
40 |
$max_exec = intval(ini_get('max_execution_time'));
|
41 |
if ($max_exec === 0) // max execution time of zero means infinite. Quantify.
|
42 |
$max_exec = 60;
|
|
|
|
|
43 |
define('SHORTPIXEL_MAX_EXECUTION_TIME', $max_exec);
|
44 |
|
45 |
// ** @todo For what is this needed? */
|
46 |
//require_once(ABSPATH . 'wp-admin/includes/file.php');
|
47 |
require_once(SHORTPIXEL_PLUGIN_DIR . '/build/shortpixel/autoload.php');
|
48 |
|
49 |
-
|
50 |
$sp__uploads = wp_upload_dir();
|
51 |
define('SHORTPIXEL_UPLOADS_BASE', (file_exists($sp__uploads['basedir']) ? '' : ABSPATH) . $sp__uploads['basedir'] );
|
52 |
//define('SHORTPIXEL_UPLOADS_URL', is_main_site() ? $sp__uploads['baseurl'] : dirname(dirname($sp__uploads['baseurl'])));
|
@@ -69,203 +70,35 @@ else
|
|
69 |
define('SHORTPIXEL_MAX_EXECUTION_TIME2', 2 );
|
70 |
define("SHORTPIXEL_MAX_RESULTS_QUERY", 30);
|
71 |
//define("SHORTPIXEL_NOFLOCK", true); // don't use flock queue, can cause instability.
|
|
|
72 |
|
73 |
-
function
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
if(is_object($screen) && !in_array($screen->id, array('upload', 'edit', 'edit-tags', 'post-new', 'post'))) {
|
80 |
-
return;
|
81 |
-
}
|
82 |
-
}
|
83 |
-
$isAjaxButNotSP = false; //defined( 'DOING_AJAX' ) && DOING_AJAX && !(isset($_REQUEST['action']) && (strpos($_REQUEST['action'], 'shortpixel_') === 0));
|
84 |
-
if (!isset($shortPixelPluginInstance)
|
85 |
-
&& ( (shortPixelCheckQueue() && get_option('wp-short-pixel-front-bootstrap'))
|
86 |
-
|| is_admin() && !$isAjaxButNotSP
|
87 |
-
&& (function_exists("is_user_logged_in") && is_user_logged_in()) //is admin, is logged in - :) seems funny but it's not, ajax scripts are admin even if no admin is logged in.
|
88 |
-
&& ( current_user_can( 'manage_options' )
|
89 |
-
|| current_user_can( 'upload_files' )
|
90 |
-
|| current_user_can( 'edit_posts' )
|
91 |
-
)
|
92 |
-
)
|
93 |
-
)
|
94 |
-
{
|
95 |
-
require_once('wp-shortpixel-req.php');
|
96 |
-
|
97 |
-
$shortPixelPluginInstance = new WPShortPixel;
|
98 |
-
}
|
99 |
-
|
100 |
-
}
|
101 |
-
|
102 |
-
|
103 |
-
function shortPixelCheckQueue(){
|
104 |
-
require_once('class/shortpixel_queue.php');
|
105 |
-
require_once('class/external/shortpixel_queue_db.php');
|
106 |
-
$prio = (! defined('SHORTPIXEL_NOFLOCK')) ? ShortPixelQueue::get() : ShortPixelQueueDB::get();
|
107 |
-
return $prio && is_array($prio) && count($prio);
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* this is hooked into wp_generate_attachment_metadata
|
112 |
-
* @param $meta
|
113 |
-
* @param null $ID
|
114 |
-
* @return WPShortPixel the instance
|
115 |
-
*/
|
116 |
-
function shortPixelHandleImageUploadHook($meta, $ID = null) {
|
117 |
-
global $shortPixelPluginInstance;
|
118 |
-
if(!isset($shortPixelPluginInstance)) {
|
119 |
-
require_once('wp-shortpixel-req.php');
|
120 |
-
$shortPixelPluginInstance = new WPShortPixel;
|
121 |
-
}
|
122 |
-
return $shortPixelPluginInstance->handleMediaLibraryImageUpload($meta, $ID);
|
123 |
-
}
|
124 |
-
|
125 |
-
function shortPixelReplaceHook($params) {
|
126 |
-
if(isset($params['post_id'])) { //integration with EnableMediaReplace - that's an upload for replacing an existing ID
|
127 |
-
global $shortPixelPluginInstance;
|
128 |
-
if (!isset($shortPixelPluginInstance)) {
|
129 |
-
require_once('wp-shortpixel-req.php');
|
130 |
-
$shortPixelPluginInstance = new WPShortPixel;
|
131 |
-
}
|
132 |
-
$itemHandler = $shortPixelPluginInstance->onDeleteImage($params['post_id']);
|
133 |
-
$itemHandler->deleteAllSPMeta();
|
134 |
-
}
|
135 |
-
}
|
136 |
-
|
137 |
-
function shortPixelPng2JpgHook($params) {
|
138 |
-
global $shortPixelPluginInstance;
|
139 |
-
if(!isset($shortPixelPluginInstance)) {
|
140 |
-
require_once('wp-shortpixel-req.php');
|
141 |
-
$shortPixelPluginInstance = new WPShortPixel;
|
142 |
-
}
|
143 |
-
return $shortPixelPluginInstance->convertPng2Jpg($params);
|
144 |
-
}
|
145 |
-
|
146 |
-
function shortPixelNggAdd($image) {
|
147 |
-
global $shortPixelPluginInstance;
|
148 |
-
if(!isset($shortPixelPluginInstance)) {
|
149 |
-
require_once('wp-shortpixel-req.php');
|
150 |
-
$shortPixelPluginInstance = new WPShortPixel;
|
151 |
-
}
|
152 |
-
$shortPixelPluginInstance->handleNextGenImageUpload($image);
|
153 |
-
}
|
154 |
-
|
155 |
-
function shortPixelActivatePlugin () {
|
156 |
-
require_once('wp-shortpixel-req.php');
|
157 |
-
WPShortPixel::shortPixelActivatePlugin();
|
158 |
-
}
|
159 |
-
|
160 |
-
function shortPixelDeactivatePlugin () {
|
161 |
-
require_once('wp-shortpixel-req.php');
|
162 |
-
WPShortPixel::shortPixelDeactivatePlugin();
|
163 |
-
}
|
164 |
-
|
165 |
-
function shortPixelUninstallPlugin () {
|
166 |
-
require_once('wp-shortpixel-req.php');
|
167 |
-
WPShortPixel::shortPixelUninstallPlugin();
|
168 |
-
}
|
169 |
-
|
170 |
-
//Picture generation, hooked on the_content filter
|
171 |
-
function shortPixelConvertImgToPictureAddWebp($content) {
|
172 |
-
if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
|
173 |
-
//for AMP pages the <picture> tag is not allowed
|
174 |
-
return $content . (isset($_GET['SHORTPIXEL_DEBUG']) ? '<!-- SPDBG is AMP -->' : '');
|
175 |
-
}
|
176 |
-
require_once('wp-shortpixel-req.php');
|
177 |
-
require_once('class/front/img-to-picture-webp.php');
|
178 |
-
|
179 |
-
return ShortPixelImgToPictureWebp::convert($content);// . "<!-- PICTURE TAGS BY SHORTPIXEL -->";
|
180 |
-
}
|
181 |
-
function shortPixelAddPictureJs() {
|
182 |
-
// Don't do anything with the RSS feed.
|
183 |
-
if ( is_feed() || is_admin() ) { return; }
|
184 |
-
|
185 |
-
echo '<script>'
|
186 |
-
. 'var spPicTest = document.createElement( "picture" );'
|
187 |
-
. 'if(!window.HTMLPictureElement && document.addEventListener) {'
|
188 |
-
. 'window.addEventListener("DOMContentLoaded", function() {'
|
189 |
-
. 'var scriptTag = document.createElement("script");'
|
190 |
-
. 'scriptTag.src = "' . plugins_url('/res/js/picturefill.min.js', __FILE__) . '";'
|
191 |
-
. 'document.body.appendChild(scriptTag);'
|
192 |
-
. '});'
|
193 |
-
. '}'
|
194 |
-
. '</script>';
|
195 |
-
}
|
196 |
-
|
197 |
-
add_filter( 'gform_save_field_value', 'shortPixelGravityForms', 10, 5 );
|
198 |
-
|
199 |
-
function shortPixelGravityForms( $value, $lead, $field, $form ) {
|
200 |
-
global $shortPixelPluginInstance;
|
201 |
-
if($field->type == 'post_image') {
|
202 |
-
require_once('wp-shortpixel-req.php');
|
203 |
-
$shortPixelPluginInstance = new WPShortPixel;
|
204 |
-
$shortPixelPluginInstance->handleGravityFormsImageField($value);
|
205 |
-
}
|
206 |
-
return $value;
|
207 |
}
|
208 |
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
$activePlugins = array_merge($activePlugins, get_site_option( 'active_sitewide_plugins'));
|
219 |
-
}
|
220 |
-
return in_array( $plugin, $activePlugins);
|
221 |
}
|
222 |
-
|
223 |
-
// [BS] Start runtime here
|
224 |
$log = ShortPixel\ShortPixelLogger\ShortPixelLogger::getInstance();
|
225 |
$log->setLogPath(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
|
226 |
|
227 |
// Pre-Runtime Checks
|
228 |
// @todo Better solution for pre-runtime inclusions of externals.
|
229 |
-
|
230 |
-
require_once('class/external/wp-offload-media.php');
|
231 |
|
|
|
232 |
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
set_transient("shortpixel_thrown_notice", array('when' => 'spai', 'extra' => __('Please deactivate the ShortPixel Image Optimizer\'s
|
237 |
-
<a href="options-general.php?page=wp-shortpixel-settings&part=adv-settings">Deliver WebP using PICTURE tag</a>
|
238 |
-
option when the ShortPixel Adaptive Images plugin is active.','shortpixel-image-optimiser')), 1800);
|
239 |
-
}
|
240 |
-
elseif( $option == 1 ){
|
241 |
-
add_action( 'wp_head', 'shortPixelAddPictureJs'); // adds polyfill JS to the header
|
242 |
-
add_action( 'init', 'shortPixelInitOB', 1 ); // start output buffer to capture content
|
243 |
-
} elseif ($option == 2){
|
244 |
-
add_filter( 'the_content', 'shortPixelConvertImgToPictureAddWebp', 10000 ); // priority big, so it will be executed last
|
245 |
-
add_filter( 'the_excerpt', 'shortPixelConvertImgToPictureAddWebp', 10000 );
|
246 |
-
add_filter( 'post_thumbnail_html', 'shortPixelConvertImgToPictureAddWebp');
|
247 |
-
}
|
248 |
-
// add_action( 'wp_enqueue_scripts', 'spAddPicturefillJs' );
|
249 |
-
}
|
250 |
-
|
251 |
-
if ( !function_exists( 'vc_action' ) || vc_action() !== 'vc_inline' ) { //handle incompatibility with Visual Composer
|
252 |
-
add_action( 'init', 'shortpixelInit');
|
253 |
-
add_action('ngg_added_new_image', 'shortPixelNggAdd');
|
254 |
-
|
255 |
-
$autoPng2Jpg = get_option('wp-short-pixel-png2jpg');
|
256 |
-
$autoMediaLibrary = get_option('wp-short-pixel-auto-media-library');
|
257 |
-
if($autoPng2Jpg && $autoMediaLibrary) {
|
258 |
-
add_action( 'wp_handle_upload', 'shortPixelPng2JpgHook');
|
259 |
-
add_action( 'mpp_handle_upload', 'shortPixelPng2JpgHook');
|
260 |
-
}
|
261 |
-
add_action('wp_handle_replace', 'shortPixelReplaceHook');
|
262 |
-
if($autoMediaLibrary) {
|
263 |
-
add_filter( 'wp_generate_attachment_metadata', 'shortPixelHandleImageUploadHook', 10, 2 );
|
264 |
-
add_filter( 'mpp_generate_metadata', 'shortPixelHandleImageUploadHook', 10, 2 );
|
265 |
-
}
|
266 |
-
|
267 |
-
register_activation_hook( __FILE__, 'shortPixelActivatePlugin' );
|
268 |
-
register_deactivation_hook( __FILE__, 'shortPixelDeactivatePlugin' );
|
269 |
-
register_uninstall_hook(__FILE__, 'shortPixelUninstallPlugin');
|
270 |
-
}
|
271 |
-
?>
|
3 |
* Plugin Name: ShortPixel Image Optimizer
|
4 |
* Plugin URI: https://shortpixel.com/
|
5 |
* Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="options-general.php?page=wp-shortpixel-settings" target="_blank">Settings > ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
|
6 |
+
* Version: 4.15.0
|
7 |
* Author: ShortPixel
|
8 |
* Author URI: https://shortpixel.com
|
9 |
* Text Domain: shortpixel-image-optimiser
|
19 |
|
20 |
//define('SHORTPIXEL_AFFILIATE_CODE', '');
|
21 |
|
22 |
+
define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "4.15.0");
|
23 |
define('SHORTPIXEL_MAX_TIMEOUT', 10);
|
24 |
define('SHORTPIXEL_VALIDATE_MAX_TIMEOUT', 15);
|
25 |
define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
|
40 |
$max_exec = intval(ini_get('max_execution_time'));
|
41 |
if ($max_exec === 0) // max execution time of zero means infinite. Quantify.
|
42 |
$max_exec = 60;
|
43 |
+
elseif($max_exec < 0) // some hosts like to set negative figures on this. Ignore that.
|
44 |
+
$max_exec = 30;
|
45 |
define('SHORTPIXEL_MAX_EXECUTION_TIME', $max_exec);
|
46 |
|
47 |
// ** @todo For what is this needed? */
|
48 |
//require_once(ABSPATH . 'wp-admin/includes/file.php');
|
49 |
require_once(SHORTPIXEL_PLUGIN_DIR . '/build/shortpixel/autoload.php');
|
50 |
|
|
|
51 |
$sp__uploads = wp_upload_dir();
|
52 |
define('SHORTPIXEL_UPLOADS_BASE', (file_exists($sp__uploads['basedir']) ? '' : ABSPATH) . $sp__uploads['basedir'] );
|
53 |
//define('SHORTPIXEL_UPLOADS_URL', is_main_site() ? $sp__uploads['baseurl'] : dirname(dirname($sp__uploads['baseurl'])));
|
70 |
define('SHORTPIXEL_MAX_EXECUTION_TIME2', 2 );
|
71 |
define("SHORTPIXEL_MAX_RESULTS_QUERY", 30);
|
72 |
//define("SHORTPIXEL_NOFLOCK", true); // don't use flock queue, can cause instability.
|
73 |
+
//define("SHORTPIXEL_EXPERIMENTAL_SECURICACHE", true); // tries to add timestamps to URLS, to prevent hitting the cache.
|
74 |
|
75 |
+
/* Function to reach core function of ShortPixel
|
76 |
+
* Use to get plugin url, plugin path, or certain core controllers
|
77 |
+
*/
|
78 |
+
function wpSPIO()
|
79 |
+
{
|
80 |
+
return \ShortPixel\ShortPixelPlugin::getInstance();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
|
83 |
+
// [BS] Start runtime here
|
84 |
+
require_once(SHORTPIXEL_PLUGIN_DIR . '/wp-shortpixel-req.php'); // @todo should be incorporated here.
|
85 |
+
require_once(SHORTPIXEL_PLUGIN_DIR . '/class/controller/controller.php');
|
86 |
+
require_once(SHORTPIXEL_PLUGIN_DIR . '/class/shortpixel-model.php');
|
87 |
+
require_once(SHORTPIXEL_PLUGIN_DIR . '/shortpixel-plugin.php'); // loads runtime and needed classes.
|
88 |
|
89 |
+
if (! defined('SHORTPIXEL_DEBUG'))
|
90 |
+
{
|
91 |
+
define('SHORTPIXEL_DEBUG', false);
|
|
|
|
|
|
|
92 |
}
|
|
|
|
|
93 |
$log = ShortPixel\ShortPixelLogger\ShortPixelLogger::getInstance();
|
94 |
$log->setLogPath(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log");
|
95 |
|
96 |
// Pre-Runtime Checks
|
97 |
// @todo Better solution for pre-runtime inclusions of externals.
|
98 |
+
// Should not be required here. wpspio initruntime loads externals
|
|
|
99 |
|
100 |
+
wpSPIO(); // let's go!
|
101 |
|
102 |
+
register_activation_hook( __FILE__, array('\ShortPixel\ShortPixelPlugin','activatePlugin') );
|
103 |
+
register_deactivation_hook( __FILE__, array('\ShortPixel\ShortPixelPlugin','deactivatePlugin') );
|
104 |
+
register_uninstall_hook(__FILE__, array('\ShortPixel\ShortPixelPlugin','uninstallPlugin') );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|