Version Description
- 2018/06/19 =
- New: you can now optimize pdf files.
- Improvement: custom folders, you can now optimize files located in the uploads folder.
- Improvement: support for thumbnails dynamically generated by NextGen Gallery plugin.
- Bug Fix: revamped support for WP Retina 2x plugin.
Download this release
Release Info
Developer | wp_media |
Plugin | Imagify Image Optimizer |
Version | 1.8 |
Comparing to | |
See all releases |
Code changes from version 1.7.1.3 to 1.8
- assets/css/files-list.css +0 -0
- assets/css/files-list.min.css +0 -0
- assets/images/big-blue-check.png +0 -0
- assets/images/icon-alert.svg +0 -0
- assets/images/icon-arrow-choice.png +0 -0
- assets/images/icon-arrow-choice.svg +0 -0
- assets/images/icon-doc-image.svg +0 -0
- assets/images/icon-external.svg +0 -0
- assets/images/icon-level.svg +0 -0
- assets/images/icon-load.svg +0 -0
- assets/images/icon-lock.png +0 -0
- assets/images/icon-lock.svg +0 -0
- assets/images/icon-pack.png +0 -0
- assets/images/icon-pack.svg +0 -0
- assets/images/icon-time.svg +0 -0
- assets/images/imagify-logo.png +0 -0
- assets/images/imagify-menu-bar.jpg +0 -0
- assets/images/lazyload.png +0 -0
- assets/images/logo-wprocket.png +0 -0
- assets/images/logo-wprocket.svg +0 -0
- assets/images/logo-wprocket@2x.png +0 -0
- assets/images/pic-ericwaltr.jpg +0 -0
- assets/images/pic-srhdesign.jpg +0 -0
- assets/images/spinner.gif +0 -0
- assets/images/upload-image.png +0 -0
- assets/js/chart.js +0 -0
- assets/js/chart.min.js +0 -0
- assets/js/files-list.js +0 -0
- assets/js/files-list.min.js +0 -0
- assets/js/formdata-polyfill.js +390 -0
- assets/js/formdata-polyfill.min.js +16 -0
- assets/js/imagify-gulp.js +0 -0
- assets/js/imagify-gulp.min.js +0 -0
- assets/js/imagify-wp-retina-2x.js +87 -0
- assets/js/imagify-wp-retina-2x.min.js +1 -0
- assets/js/options.js +1 -1
- assets/js/options.min.js +1 -1
- assets/js/weakmap-polyfill.js +144 -0
- assets/js/weakmap-polyfill.min.js +7 -0
- imagify.php +2 -2
- inc/3rd-party/3rd-party.php +1 -1
- inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf-attachment.php +46 -24
- inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf.php +0 -2
- inc/3rd-party/hosting/siteground.php +0 -0
- inc/3rd-party/hosting/wpengine.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/admin/ajax.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/admin/bulk.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/admin/enqueue.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/admin/gallery.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/admin/heartbeat.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/admin/menu.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-attachment.php +300 -121
- inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-db.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-dynamic-thumbnails-background-process.php +162 -0
- inc/3rd-party/nextgen-gallery/inc/common/attachments.php +58 -1
- inc/3rd-party/nextgen-gallery/inc/functions/admin-stats.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/functions/attachments.php +0 -0
- inc/3rd-party/nextgen-gallery/inc/functions/common.php +0 -0
- inc/3rd-party/nextgen-gallery/nextgen-gallery.php +1 -0
- inc/3rd-party/regenerate-thumbnails/inc/classes/class-imagify-regenerate-thumbnails.php +6 -2
- inc/3rd-party/wp-retina-2x.php +0 -87
- inc/3rd-party/wp-retina-2x/inc/classes/class-imagify-wp-retina-2x-core.php +1684 -0
- inc/3rd-party/wp-retina-2x/inc/classes/class-imagify-wp-retina-2x.php +680 -0
- inc/3rd-party/wp-retina-2x/wp-retina-2x.php +8 -0
- inc/3rd-party/wp-rocket.php +0 -0
- inc/admin/custom-folders.php +0 -0
- inc/admin/media.php +1 -1
- inc/admin/upload.php +4 -4
- inc/classes/class-imagify-abstract-attachment.php +134 -31
- inc/classes/class-imagify-abstract-cron.php +0 -0
- inc/classes/class-imagify-abstract-db.php +0 -0
- inc/classes/class-imagify-abstract-options.php +0 -0
- inc/classes/class-imagify-admin-ajax-post.php +14 -7
- inc/classes/class-imagify-attachment.php +77 -48
- inc/classes/class-imagify-cron-library-size.php +0 -0
- inc/classes/class-imagify-cron-rating.php +0 -0
- inc/classes/class-imagify-cron-sync-files.php +0 -0
- inc/classes/class-imagify-custom-folders.php +3 -3
- inc/classes/class-imagify-data.php +0 -0
- inc/classes/class-imagify-db.php +0 -0
- inc/classes/class-imagify-file-attachment.php +5 -5
- inc/classes/class-imagify-files-db.php +0 -0
- inc/classes/class-imagify-files-iterator.php +7 -2
- inc/classes/class-imagify-files-list-table.php +28 -20
- inc/classes/class-imagify-files-recursive-iterator.php +5 -1
- inc/classes/class-imagify-files-scan.php +232 -74
- inc/classes/class-imagify-files-stats.php +0 -0
- inc/classes/class-imagify-filesystem.php +244 -20
- inc/classes/class-imagify-folders-db.php +0 -0
- inc/classes/class-imagify-options.php +0 -0
- inc/classes/class-imagify-requirements.php +0 -0
- inc/classes/class-imagify-settings.php +0 -0
- inc/classes/class-imagify-views.php +3 -3
- inc/classes/class-imagify.php +0 -0
- inc/classes/class-wp-async-request.php +163 -0
- inc/classes/class-wp-background-process.php +506 -0
- inc/functions/admin-stats.php +12 -8
- inc/functions/admin-ui.php +18 -10
- inc/functions/api.php +3 -3
- inc/functions/attachments.php +19 -8
- inc/functions/common.php +14 -9
- inc/functions/deprecated.php +78 -0
- inc/functions/i18n.php +16 -12
- inc/functions/process.php +15 -15
- readme.txt +8 -2
- uninstall.php +6 -5
- views/part-settings-custom-folders.php +14 -0
assets/css/files-list.css
CHANGED
File without changes
|
assets/css/files-list.min.css
CHANGED
File without changes
|
assets/images/big-blue-check.png
CHANGED
File without changes
|
assets/images/icon-alert.svg
CHANGED
File without changes
|
assets/images/icon-arrow-choice.png
CHANGED
File without changes
|
assets/images/icon-arrow-choice.svg
CHANGED
File without changes
|
assets/images/icon-doc-image.svg
CHANGED
File without changes
|
assets/images/icon-external.svg
CHANGED
File without changes
|
assets/images/icon-level.svg
CHANGED
File without changes
|
assets/images/icon-load.svg
CHANGED
File without changes
|
assets/images/icon-lock.png
CHANGED
File without changes
|
assets/images/icon-lock.svg
CHANGED
File without changes
|
assets/images/icon-pack.png
CHANGED
File without changes
|
assets/images/icon-pack.svg
CHANGED
File without changes
|
assets/images/icon-time.svg
CHANGED
File without changes
|
assets/images/imagify-logo.png
CHANGED
File without changes
|
assets/images/imagify-menu-bar.jpg
CHANGED
File without changes
|
assets/images/lazyload.png
CHANGED
File without changes
|
assets/images/logo-wprocket.png
CHANGED
File without changes
|
assets/images/logo-wprocket.svg
CHANGED
File without changes
|
assets/images/logo-wprocket@2x.png
CHANGED
File without changes
|
assets/images/pic-ericwaltr.jpg
CHANGED
File without changes
|
assets/images/pic-srhdesign.jpg
CHANGED
File without changes
|
assets/images/spinner.gif
CHANGED
File without changes
|
assets/images/upload-image.png
CHANGED
File without changes
|
assets/js/chart.js
CHANGED
File without changes
|
assets/js/chart.min.js
CHANGED
File without changes
|
assets/js/files-list.js
CHANGED
File without changes
|
assets/js/files-list.min.js
CHANGED
File without changes
|
assets/js/formdata-polyfill.js
ADDED
@@ -0,0 +1,390 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
if (typeof FormData === 'undefined' || !FormData.prototype.keys) {
|
2 |
+
const global = typeof window === 'object'
|
3 |
+
? window : typeof self === 'object'
|
4 |
+
? self : this
|
5 |
+
|
6 |
+
// keep a reference to native implementation
|
7 |
+
const _FormData = global.FormData
|
8 |
+
|
9 |
+
// To be monkey patched
|
10 |
+
const _send = global.XMLHttpRequest && global.XMLHttpRequest.prototype.send
|
11 |
+
const _fetch = global.Request && global.fetch
|
12 |
+
|
13 |
+
// Unable to patch Request constructor correctly
|
14 |
+
// const _Request = global.Request
|
15 |
+
// only way is to use ES6 class extend
|
16 |
+
// https://github.com/babel/babel/issues/1966
|
17 |
+
|
18 |
+
const stringTag = global.Symbol && Symbol.toStringTag
|
19 |
+
const map = new WeakMap
|
20 |
+
const wm = o => map.get(o)
|
21 |
+
const arrayFrom = Array.from || (obj => [].slice.call(obj))
|
22 |
+
|
23 |
+
// Add missing stringTags to blob and files
|
24 |
+
if (stringTag) {
|
25 |
+
if (!Blob.prototype[stringTag]) {
|
26 |
+
Blob.prototype[stringTag] = 'Blob'
|
27 |
+
}
|
28 |
+
|
29 |
+
if ('File' in global && !File.prototype[stringTag]) {
|
30 |
+
File.prototype[stringTag] = 'File'
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
// Fix so you can construct your own File
|
35 |
+
try {
|
36 |
+
new File([], '')
|
37 |
+
} catch (a) {
|
38 |
+
global.File = function(b, d, c) {
|
39 |
+
const blob = new Blob(b, c)
|
40 |
+
const t = c && void 0 !== c.lastModified ? new Date(c.lastModified) : new Date
|
41 |
+
|
42 |
+
Object.defineProperties(blob, {
|
43 |
+
name: {
|
44 |
+
value: d
|
45 |
+
},
|
46 |
+
lastModifiedDate: {
|
47 |
+
value: t
|
48 |
+
},
|
49 |
+
lastModified: {
|
50 |
+
value: +t
|
51 |
+
},
|
52 |
+
toString: {
|
53 |
+
value() {
|
54 |
+
return '[object File]'
|
55 |
+
}
|
56 |
+
}
|
57 |
+
})
|
58 |
+
|
59 |
+
if (stringTag) {
|
60 |
+
Object.defineProperty(blob, stringTag, {
|
61 |
+
value: 'File'
|
62 |
+
})
|
63 |
+
}
|
64 |
+
|
65 |
+
return blob
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
function normalizeValue([value, filename]) {
|
70 |
+
if (value instanceof Blob)
|
71 |
+
// Should always returns a new File instance
|
72 |
+
// console.assert(fd.get(x) !== fd.get(x))
|
73 |
+
value = new File([value], filename, {
|
74 |
+
type: value.type,
|
75 |
+
lastModified: value.lastModified
|
76 |
+
})
|
77 |
+
|
78 |
+
return value
|
79 |
+
}
|
80 |
+
|
81 |
+
function stringify(name) {
|
82 |
+
if (!arguments.length)
|
83 |
+
throw new TypeError('1 argument required, but only 0 present.')
|
84 |
+
|
85 |
+
return [name + '']
|
86 |
+
}
|
87 |
+
|
88 |
+
function normalizeArgs(name, value, filename) {
|
89 |
+
if (arguments.length < 2)
|
90 |
+
throw new TypeError(
|
91 |
+
`2 arguments required, but only ${arguments.length} present.`
|
92 |
+
)
|
93 |
+
|
94 |
+
return value instanceof Blob
|
95 |
+
// normalize name and filename if adding an attachment
|
96 |
+
? [name + '', value, filename !== undefined
|
97 |
+
? filename + '' // Cast filename to string if 3th arg isn't undefined
|
98 |
+
: typeof value.name === 'string' // if name prop exist
|
99 |
+
? value.name // Use File.name
|
100 |
+
: 'Blob'] // otherwise fallback to Blob
|
101 |
+
|
102 |
+
// If no attachment, just cast the args to strings
|
103 |
+
: [name + '', value + '']
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* @implements {Iterable}
|
108 |
+
*/
|
109 |
+
class FormDataPolyfill {
|
110 |
+
|
111 |
+
/**
|
112 |
+
* FormData class
|
113 |
+
*
|
114 |
+
* @param {HTMLElement=} form
|
115 |
+
*/
|
116 |
+
constructor(form) {
|
117 |
+
map.set(this, Object.create(null))
|
118 |
+
|
119 |
+
if (!form)
|
120 |
+
return this
|
121 |
+
|
122 |
+
for (let elm of arrayFrom(form.elements)) {
|
123 |
+
if (!elm.name || elm.disabled) continue
|
124 |
+
|
125 |
+
if (elm.type === 'file')
|
126 |
+
for (let file of elm.files)
|
127 |
+
this.append(elm.name, file)
|
128 |
+
else if (elm.type === 'select-multiple' || elm.type === 'select-one')
|
129 |
+
for (let opt of arrayFrom(elm.options))
|
130 |
+
opt.selected && this.append(elm.name, opt.value)
|
131 |
+
else if (elm.type === 'checkbox' || elm.type === 'radio') {
|
132 |
+
if (elm.checked) this.append(elm.name, elm.value)
|
133 |
+
} else
|
134 |
+
this.append(elm.name, elm.value)
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Append a field
|
141 |
+
*
|
142 |
+
* @param {String} name field name
|
143 |
+
* @param {String|Blob|File} value string / blob / file
|
144 |
+
* @param {String=} filename filename to use with blob
|
145 |
+
* @return {Undefined}
|
146 |
+
*/
|
147 |
+
append(name, value, filename) {
|
148 |
+
const map = wm(this)
|
149 |
+
|
150 |
+
if (!map[name])
|
151 |
+
map[name] = []
|
152 |
+
|
153 |
+
map[name].push([value, filename])
|
154 |
+
}
|
155 |
+
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Delete all fields values given name
|
159 |
+
*
|
160 |
+
* @param {String} name Field name
|
161 |
+
* @return {Undefined}
|
162 |
+
*/
|
163 |
+
delete(name) {
|
164 |
+
delete wm(this)[name]
|
165 |
+
}
|
166 |
+
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Iterate over all fields as [name, value]
|
170 |
+
*
|
171 |
+
* @return {Iterator}
|
172 |
+
*/
|
173 |
+
*entries() {
|
174 |
+
const map = wm(this)
|
175 |
+
|
176 |
+
for (let name in map)
|
177 |
+
for (let value of map[name])
|
178 |
+
yield [name, normalizeValue(value)]
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Iterate over all fields
|
183 |
+
*
|
184 |
+
* @param {Function} callback Executed for each item with parameters (value, name, thisArg)
|
185 |
+
* @param {Object=} thisArg `this` context for callback function
|
186 |
+
* @return {Undefined}
|
187 |
+
*/
|
188 |
+
forEach(callback, thisArg) {
|
189 |
+
for (let [name, value] of this)
|
190 |
+
callback.call(thisArg, value, name, this)
|
191 |
+
}
|
192 |
+
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Return first field value given name
|
196 |
+
* or null if non existen
|
197 |
+
*
|
198 |
+
* @param {String} name Field name
|
199 |
+
* @return {String|File|null} value Fields value
|
200 |
+
*/
|
201 |
+
get(name) {
|
202 |
+
const map = wm(this)
|
203 |
+
return map[name] ? normalizeValue(map[name][0]) : null
|
204 |
+
}
|
205 |
+
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Return all fields values given name
|
209 |
+
*
|
210 |
+
* @param {String} name Fields name
|
211 |
+
* @return {Array} [{String|File}]
|
212 |
+
*/
|
213 |
+
getAll(name) {
|
214 |
+
return (wm(this)[name] || []).map(normalizeValue)
|
215 |
+
}
|
216 |
+
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Check for field name existence
|
220 |
+
*
|
221 |
+
* @param {String} name Field name
|
222 |
+
* @return {boolean}
|
223 |
+
*/
|
224 |
+
has(name) {
|
225 |
+
return name in wm(this)
|
226 |
+
}
|
227 |
+
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Iterate over all fields name
|
231 |
+
*
|
232 |
+
* @return {Iterator}
|
233 |
+
*/
|
234 |
+
*keys() {
|
235 |
+
for (let [name] of this)
|
236 |
+
yield name
|
237 |
+
}
|
238 |
+
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Overwrite all values given name
|
242 |
+
*
|
243 |
+
* @param {String} name Filed name
|
244 |
+
* @param {String} value Field value
|
245 |
+
* @param {String=} filename Filename (optional)
|
246 |
+
* @return {Undefined}
|
247 |
+
*/
|
248 |
+
set(name, value, filename) {
|
249 |
+
wm(this)[name] = [[value, filename]]
|
250 |
+
}
|
251 |
+
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Iterate over all fields
|
255 |
+
*
|
256 |
+
* @return {Iterator}
|
257 |
+
*/
|
258 |
+
*values() {
|
259 |
+
for (let [name, value] of this)
|
260 |
+
yield value
|
261 |
+
}
|
262 |
+
|
263 |
+
|
264 |
+
/**
|
265 |
+
* Return a native (perhaps degraded) FormData with only a `append` method
|
266 |
+
* Can throw if it's not supported
|
267 |
+
*
|
268 |
+
* @return {FormData}
|
269 |
+
*/
|
270 |
+
['_asNative']() {
|
271 |
+
const fd = new _FormData
|
272 |
+
|
273 |
+
for (let [name, value] of this)
|
274 |
+
fd.append(name, value)
|
275 |
+
|
276 |
+
return fd
|
277 |
+
}
|
278 |
+
|
279 |
+
|
280 |
+
/**
|
281 |
+
* [_blob description]
|
282 |
+
*
|
283 |
+
* @return {Blob} [description]
|
284 |
+
*/
|
285 |
+
['_blob']() {
|
286 |
+
const boundary = '----formdata-polyfill-' + Math.random()
|
287 |
+
const chunks = []
|
288 |
+
|
289 |
+
for (let [name, value] of this) {
|
290 |
+
chunks.push(`--${boundary}\r\n`)
|
291 |
+
|
292 |
+
if (value instanceof Blob) {
|
293 |
+
chunks.push(
|
294 |
+
`Content-Disposition: form-data; name="${name}"; filename="${value.name}"\r\n`,
|
295 |
+
`Content-Type: ${value.type || 'application/octet-stream'}\r\n\r\n`,
|
296 |
+
value,
|
297 |
+
'\r\n'
|
298 |
+
)
|
299 |
+
} else {
|
300 |
+
chunks.push(
|
301 |
+
`Content-Disposition: form-data; name="${name}"\r\n\r\n${value}\r\n`
|
302 |
+
)
|
303 |
+
}
|
304 |
+
}
|
305 |
+
|
306 |
+
chunks.push(`--${boundary}--`)
|
307 |
+
|
308 |
+
return new Blob(chunks, {type: 'multipart/form-data; boundary=' + boundary})
|
309 |
+
}
|
310 |
+
|
311 |
+
|
312 |
+
/**
|
313 |
+
* The class itself is iterable
|
314 |
+
* alias for formdata.entries()
|
315 |
+
*
|
316 |
+
* @return {Iterator}
|
317 |
+
*/
|
318 |
+
[Symbol.iterator]() {
|
319 |
+
return this.entries()
|
320 |
+
}
|
321 |
+
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Create the default string description.
|
325 |
+
*
|
326 |
+
* @return {String} [object FormData]
|
327 |
+
*/
|
328 |
+
toString() {
|
329 |
+
return '[object FormData]'
|
330 |
+
}
|
331 |
+
}
|
332 |
+
|
333 |
+
|
334 |
+
if (stringTag) {
|
335 |
+
/**
|
336 |
+
* Create the default string description.
|
337 |
+
* It is accessed internally by the Object.prototype.toString().
|
338 |
+
*
|
339 |
+
* @return {String} FormData
|
340 |
+
*/
|
341 |
+
FormDataPolyfill.prototype[stringTag] = 'FormData'
|
342 |
+
}
|
343 |
+
|
344 |
+
const decorations = [
|
345 |
+
['append', normalizeArgs],
|
346 |
+
['delete', stringify],
|
347 |
+
['get', stringify],
|
348 |
+
['getAll', stringify],
|
349 |
+
['has', stringify],
|
350 |
+
['set', normalizeArgs]
|
351 |
+
]
|
352 |
+
|
353 |
+
decorations.forEach(arr => {
|
354 |
+
const orig = FormDataPolyfill.prototype[arr[0]]
|
355 |
+
FormDataPolyfill.prototype[arr[0]] = function() {
|
356 |
+
return orig.apply(this, arr[1].apply(this, arrayFrom(arguments)))
|
357 |
+
}
|
358 |
+
})
|
359 |
+
|
360 |
+
// Patch xhr's send method to call _blob transparently
|
361 |
+
if (_send) {
|
362 |
+
XMLHttpRequest.prototype.send = function(data) {
|
363 |
+
// I would check if Content-Type isn't already set
|
364 |
+
// But xhr lacks getRequestHeaders functionallity
|
365 |
+
// https://github.com/jimmywarting/FormData/issues/44
|
366 |
+
if (data instanceof FormDataPolyfill) {
|
367 |
+
const blob = data['_blob']()
|
368 |
+
this.setRequestHeader('Content-Type', blob.type)
|
369 |
+
_send.call(this, blob)
|
370 |
+
} else {
|
371 |
+
_send.call(this, data)
|
372 |
+
}
|
373 |
+
}
|
374 |
+
}
|
375 |
+
|
376 |
+
// Patch fetch's function to call _blob transparently
|
377 |
+
if (_fetch) {
|
378 |
+
const _fetch = global.fetch
|
379 |
+
|
380 |
+
global.fetch = function(input, init) {
|
381 |
+
if (init && init.body && init.body instanceof FormDataPolyfill) {
|
382 |
+
init.body = init.body['_blob']()
|
383 |
+
}
|
384 |
+
|
385 |
+
return _fetch(input, init)
|
386 |
+
}
|
387 |
+
}
|
388 |
+
|
389 |
+
global['FormData'] = FormDataPolyfill
|
390 |
+
}
|
assets/js/formdata-polyfill.min.js
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
;(function(){var k,l="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,e){a!=Array.prototype&&a!=Object.prototype&&(a[b]=e.value)},m="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this;function n(){n=function(){};m.Symbol||(m.Symbol=p)}var p=function(){var a=0;return function(b){return"jscomp_symbol_"+(b||"")+a++}}();
|
2 |
+
function r(){n();var a=m.Symbol.iterator;a||(a=m.Symbol.iterator=m.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&l(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return u(this)}});r=function(){}}function u(a){var b=0;return v(function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}})}function v(a){r();a={next:a};a[m.Symbol.iterator]=function(){return this};return a}function w(a){r();n();r();var b=a[Symbol.iterator];return b?b.call(a):u(a)}
|
3 |
+
function x(){this.g=!1;this.c=null;this.m=void 0;this.b=1;this.l=this.o=0;this.f=null}function z(a){if(a.g)throw new TypeError("Generator is already running");a.g=!0}x.prototype.h=function(a){this.m=a};x.prototype.i=function(a){this.f={s:a,u:!0};this.b=this.o||this.l};x.prototype["return"]=function(a){this.f={"return":a};this.b=this.l};function A(a,b,e){a.b=e;return{value:b}}function B(a){this.v=a;this.j=[];for(var b in a)this.j.push(b);this.j.reverse()}function C(a){this.a=new x;this.w=a}
|
4 |
+
C.prototype.h=function(a){z(this.a);if(this.a.c)return D(this,this.a.c.next,a,this.a.h);this.a.h(a);return E(this)};function F(a,b){z(a.a);var e=a.a.c;if(e)return D(a,"return"in e?e["return"]:function(a){return{value:a,done:!0}},b,a.a["return"]);a.a["return"](b);return E(a)}C.prototype.i=function(a){z(this.a);if(this.a.c)return D(this,this.a.c["throw"],a,this.a.h);this.a.i(a);return E(this)};
|
5 |
+
function D(a,b,e,c){try{var d=b.call(a.a.c,e);if(!(d instanceof Object))throw new TypeError("Iterator result "+d+" is not an object");if(!d.done)return a.a.g=!1,d;var f=d.value}catch(g){return a.a.c=null,a.a.i(g),E(a)}a.a.c=null;c.call(a.a,f);return E(a)}function E(a){for(;a.a.b;)try{var b=a.w(a.a);if(b)return a.a.g=!1,{value:b.value,done:!1}}catch(e){a.a.m=void 0,a.a.i(e)}a.a.g=!1;if(a.a.f){b=a.a.f;a.a.f=null;if(b.u)throw b.s;return{value:b["return"],done:!0}}return{value:void 0,done:!0}}
|
6 |
+
function G(a){this.next=function(b){return a.h(b)};this["throw"]=function(b){return a.i(b)};this["return"]=function(b){return F(a,b)};r();this[Symbol.iterator]=function(){return this}}function H(a,b){G.prototype=a.prototype;return new G(new C(b))}
|
7 |
+
if("undefined"===typeof FormData||!FormData.prototype.keys){var I=function(a,b,e){if(2>arguments.length)throw new TypeError("2 arguments required, but only "+arguments.length+" present.");return b instanceof Blob?[a+"",b,void 0!==e?e+"":"string"===typeof b.name?b.name:"Blob"]:[a+"",b+""]},J=function(a){if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");return[a+""]},K=function(a){var b=w(a);a=b.next().value;b=b.next().value;a instanceof Blob&&(a=new File([a],b,{type:a.type,
|
8 |
+
lastModified:a.lastModified}));return a},L="object"===typeof window?window:"object"===typeof self?self:this,M=L.FormData,N=L.XMLHttpRequest&&L.XMLHttpRequest.prototype.send,O=L.Request&&L.fetch;n();var P=L.Symbol&&Symbol.toStringTag,Q=new WeakMap,R=Array.from||function(a){return[].slice.call(a)};P&&(Blob.prototype[P]||(Blob.prototype[P]="Blob"),"File"in L&&!File.prototype[P]&&(File.prototype[P]="File"));try{new File([],"")}catch(a){L.File=function(b,e,c){b=new Blob(b,c);c=c&&void 0!==c.lastModified?
|
9 |
+
new Date(c.lastModified):new Date;Object.defineProperties(b,{name:{value:e},lastModifiedDate:{value:c},lastModified:{value:+c},toString:{value:function(){return"[object File]"}}});P&&Object.defineProperty(b,P,{value:"File"});return b}}var S=function(a){Q.set(this,Object.create(null));if(!a)return this;a=w(R(a.elements));for(var b=a.next();!b.done;b=a.next())if(b=b.value,b.name&&!b.disabled)if("file"===b.type)for(var e=w(b.files),c=e.next();!c.done;c=e.next())this.append(b.name,c.value);else if("select-multiple"===
|
10 |
+
b.type||"select-one"===b.type)for(e=w(R(b.options)),c=e.next();!c.done;c=e.next())c=c.value,c.selected&&this.append(b.name,c.value);else"checkbox"===b.type||"radio"===b.type?b.checked&&this.append(b.name,b.value):this.append(b.name,b.value)};k=S.prototype;k.append=function(a,b,e){var c=Q.get(this);c[a]||(c[a]=[]);c[a].push([b,e])};k["delete"]=function(a){delete Q.get(this)[a]};k.entries=function b(){var e=this,c,d,f,g,h,q;return H(b,function(b){switch(b.b){case 1:c=Q.get(e),f=new B(c);case 2:var t;
|
11 |
+
a:{for(t=f;0<t.j.length;){var y=t.j.pop();if(y in t.v){t=y;break a}}t=null}if(null==(d=t)){b.b=0;break}g=w(c[d]);h=g.next();case 5:if(h.done){b.b=2;break}q=h.value;return A(b,[d,K(q)],6);case 6:h=g.next(),b.b=5}})};k.forEach=function(b,e){for(var c=w(this),d=c.next();!d.done;d=c.next()){var f=w(d.value);d=f.next().value;f=f.next().value;b.call(e,f,d,this)}};k.get=function(b){var e=Q.get(this);return e[b]?K(e[b][0]):null};k.getAll=function(b){return(Q.get(this)[b]||[]).map(K)};k.has=function(b){return b in
|
12 |
+
Q.get(this)};k.keys=function e(){var c=this,d,f,g,h,q;return H(e,function(e){switch(e.b){case 1:d=w(c),f=d.next();case 2:if(f.done){e.b=0;break}g=f.value;h=w(g);q=h.next().value;return A(e,q,3);case 3:f=d.next(),e.b=2}})};k.set=function(e,c,d){Q.get(this)[e]=[[c,d]]};k.values=function c(){var d=this,f,g,h,q,y;return H(c,function(c){switch(c.b){case 1:f=w(d),g=f.next();case 2:if(g.done){c.b=0;break}h=g.value;q=w(h);q.next();y=q.next().value;return A(c,y,3);case 3:g=f.next(),c.b=2}})};S.prototype._asNative=
|
13 |
+
function(){for(var c=new M,d=w(this),f=d.next();!f.done;f=d.next()){var g=w(f.value);f=g.next().value;g=g.next().value;c.append(f,g)}return c};S.prototype._blob=function(){for(var c="----formdata-polyfill-"+Math.random(),d=[],f=w(this),g=f.next();!g.done;g=f.next()){var h=w(g.value);g=h.next().value;h=h.next().value;d.push("--"+c+"\r\n");h instanceof Blob?d.push('Content-Disposition: form-data; name="'+g+'"; filename="'+h.name+'"\r\n',"Content-Type: "+(h.type||"application/octet-stream")+"\r\n\r\n",
|
14 |
+
h,"\r\n"):d.push('Content-Disposition: form-data; name="'+g+'"\r\n\r\n'+h+"\r\n")}d.push("--"+c+"--");return new Blob(d,{type:"multipart/form-data; boundary="+c})};n();r();S.prototype[Symbol.iterator]=function(){return this.entries()};S.prototype.toString=function(){return"[object FormData]"};P&&(S.prototype[P]="FormData");[["append",I],["delete",J],["get",J],["getAll",J],["has",J],["set",I]].forEach(function(c){var d=S.prototype[c[0]];S.prototype[c[0]]=function(){return d.apply(this,c[1].apply(this,
|
15 |
+
R(arguments)))}});N&&(XMLHttpRequest.prototype.send=function(c){c instanceof S?(c=c._blob(),this.setRequestHeader("Content-Type",c.type),N.call(this,c)):N.call(this,c)});if(O){var T=L.fetch;L.fetch=function(c,d){d&&d.body&&d.body instanceof S&&(d.body=d.body._blob());return T(c,d)}}L.FormData=S};
|
16 |
+
})();
|
assets/js/imagify-gulp.js
CHANGED
File without changes
|
assets/js/imagify-gulp.min.js
CHANGED
File without changes
|
assets/js/imagify-wp-retina-2x.js
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
window.imagify = window.imagify || {};
|
2 |
+
|
3 |
+
jQuery.extend( window.imagify, {
|
4 |
+
retina2x: {
|
5 |
+
hookAjax: function() {
|
6 |
+
jQuery( document ).ajaxSend( this.addData ).ajaxSuccess( this.updateInfo );
|
7 |
+
},
|
8 |
+
addData: function( e, jqXHR, settings ) {
|
9 |
+
var isString, isFormData, actions, action, id;
|
10 |
+
|
11 |
+
if ( ! settings.data ) {
|
12 |
+
return;
|
13 |
+
}
|
14 |
+
|
15 |
+
isString = typeof settings.data === 'string';
|
16 |
+
isFormData = settings.data instanceof FormData;
|
17 |
+
actions = window.imagifyRetina2x;
|
18 |
+
|
19 |
+
if ( isString ) {
|
20 |
+
action = settings.data.match( /(?:^|&)action=([^&]+)/ );
|
21 |
+
action = action ? action[1] : false;
|
22 |
+
id = settings.data.match( /(?:^|&)attachmentId=([^&]+)/ );
|
23 |
+
id = id ? parseInt( id[1], 10 ) : 0;
|
24 |
+
} else if ( isFormData ) {
|
25 |
+
action = settings.data.get( 'action' );
|
26 |
+
id = settings.data.get( 'attachmentId' );
|
27 |
+
} else {
|
28 |
+
action = settings.data.action;
|
29 |
+
id = settings.data.id;
|
30 |
+
}
|
31 |
+
|
32 |
+
if ( ! action || ! actions[ action ] ) {
|
33 |
+
return;
|
34 |
+
}
|
35 |
+
|
36 |
+
if ( ! jQuery( '.imagify_optimized_file' ).length ) {
|
37 |
+
id = 0;
|
38 |
+
}
|
39 |
+
|
40 |
+
if ( isString ) {
|
41 |
+
settings.data += '&imagify_nonce=' + actions[ action ];
|
42 |
+
|
43 |
+
if ( id > 0 ) {
|
44 |
+
settings.data += '&imagify_info=1';
|
45 |
+
}
|
46 |
+
} else if ( isFormData ) {
|
47 |
+
settings.data.append( 'imagify_nonce', actions[ action ] );
|
48 |
+
|
49 |
+
if ( id > 0 ) {
|
50 |
+
settings.data.append( 'imagify_info', 1 );
|
51 |
+
}
|
52 |
+
} else {
|
53 |
+
settings.data = jQuery.extend( settings.data, { 'imagify_nonce': actions[ action ] } );
|
54 |
+
|
55 |
+
if ( id > 0 ) {
|
56 |
+
settings.data = jQuery.extend( settings.data, { 'imagify_info': 1 } );
|
57 |
+
}
|
58 |
+
}
|
59 |
+
},
|
60 |
+
updateInfo: function( e, jqXHR, settings, data ) {
|
61 |
+
if ( typeof settings.data !== 'string' ) {
|
62 |
+
return;
|
63 |
+
}
|
64 |
+
|
65 |
+
try {
|
66 |
+
data = jQuery.parseJSON( data );
|
67 |
+
}
|
68 |
+
catch ( error ) {
|
69 |
+
return;
|
70 |
+
}
|
71 |
+
|
72 |
+
if ( 'imagify' !== data.source || 'wr2x' !== data.context || ! data.imagify_info ) {
|
73 |
+
return;
|
74 |
+
}
|
75 |
+
|
76 |
+
jQuery.each( data.imagify_info, function ( id, html ) {
|
77 |
+
var $wrapper = jQuery( '#post-' + id ).children( '.imagify_optimized_file' );
|
78 |
+
|
79 |
+
if ( $wrapper.length ) {
|
80 |
+
$wrapper.html( html );
|
81 |
+
}
|
82 |
+
} );
|
83 |
+
}
|
84 |
+
}
|
85 |
+
} );
|
86 |
+
|
87 |
+
window.imagify.retina2x.hookAjax();
|
assets/js/imagify-wp-retina-2x.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
window.imagify=window.imagify||{},jQuery.extend(window.imagify,{retina2x:{hookAjax:function(){jQuery(document).ajaxSend(this.addData).ajaxSuccess(this.updateInfo)},addData:function(a,b,c){var d,e,f,g,h;c.data&&(d="string"==typeof c.data,e=c.data instanceof FormData,f=window.imagifyRetina2x,d?(g=c.data.match(/(?:^|&)action=([^&]+)/),g=!!g&&g[1],h=c.data.match(/(?:^|&)attachmentId=([^&]+)/),h=h?parseInt(h[1],10):0):e?(g=c.data.get("action"),h=c.data.get("attachmentId")):(g=c.data.action,h=c.data.id),g&&f[g]&&(jQuery(".imagify_optimized_file").length||(h=0),d?(c.data+="&imagify_nonce="+f[g],h>0&&(c.data+="&imagify_info=1")):e?(c.data.append("imagify_nonce",f[g]),h>0&&c.data.append("imagify_info",1)):(c.data=jQuery.extend(c.data,{imagify_nonce:f[g]}),h>0&&(c.data=jQuery.extend(c.data,{imagify_info:1})))))},updateInfo:function(a,b,c,d){if("string"==typeof c.data){try{d=jQuery.parseJSON(d)}catch(a){return}"imagify"===d.source&&"wr2x"===d.context&&d.imagify_info&&jQuery.each(d.imagify_info,function(a,b){var c=jQuery("#post-"+a).children(".imagify_optimized_file");c.length&&c.html(b)})}}}}),window.imagify.retina2x.hookAjax();
|
assets/js/options.js
CHANGED
@@ -383,7 +383,7 @@
|
|
383 |
w.setTimeout( function() {
|
384 |
$row.remove();
|
385 |
// Display a message.
|
386 |
-
$( '#imagify-custom-folders-selected' ).
|
387 |
}, 750 );
|
388 |
} );
|
389 |
|
383 |
w.setTimeout( function() {
|
384 |
$row.remove();
|
385 |
// Display a message.
|
386 |
+
$( '#imagify-custom-folders-selected' ).siblings( '.imagify-success.hidden' ).removeClass( 'hidden' );
|
387 |
}, 750 );
|
388 |
} );
|
389 |
|
assets/js/options.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
!function(a,b,c,d){var e=!1,f=!1;a("#imagify-settings #api_key").on("blur",function(){var b=a(this),d=b.val();return""!==a.trim(d)&&(a("#check_api_key").val()===d?(a("#imagify-check-api-container").html('<span class="dashicons dashicons-yes"></span> '+imagifyOptions.labels.ValidApiKeyText),!1):(!0===e?f.abort():(a("#imagify-check-api-container").remove(),b.after('<span id="imagify-check-api-container"><span class="imagify-spinner"></span>'+imagifyOptions.labels.waitApiKeyCheckText+"</span>")),e=!0,void(f=a.get(ajaxurl+c.imagify.concat+"action=imagify_check_api_key_validity&api_key="+b.val()+"&imagifycheckapikeynonce="+a("#imagifycheckapikeynonce").val()).done(function(b){b.success?(a("#imagify-check-api-container").remove(),swal({title:imagifyOptions.labels.ApiKeyCheckSuccessTitle,html:imagifyOptions.labels.ApiKeyCheckSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"}).then(function(){location.reload()})):a("#imagify-check-api-container").html('<span class="dashicons dashicons-no"></span> '+b.data),e=!1}))))}),a(".imagify-options-line").css("cursor","pointer").on("click",function(b){if("INPUT"!==b.target.nodeName)return a('input[aria-describedby="'+a(this).attr("id")+'"]').trigger("click"),!1}),a(".imagify-settings th span").on("click",function(){var b=a(this).parent().next("td").find("input:checkbox");1===b.length&&b.trigger("click")}),a(".imagify-options-line").find("input").on("change focus",function(){var b=a(this).closest(".imagify-options-line").prev("label").prev("input");b[0].checked||b.prop("checked",!0)}),a(".imagify-settings-section").find("#imagify_backup").on("change",function(){var b=a(this),c=b.siblings("#backup-dir-is-writable"),d={action:"imagify_check_backup_dir_is_writable",_wpnonce:c.data("nonce")};if(b.is(":checked"))return void a.getJSON(ajaxurl,d).done(function(b){a.isPlainObject(b)&&b.success&&(b.data.is_writable?c.addClass("hidden"):c.removeClass("hidden"))});swal({title:imagifyOptions.labels.noBackupTitle,html:imagifyOptions.labels.noBackupText,type:"warning",customClass:"imagify-sweet-alert",padding:0,showCancelButton:!0,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){c.addClass("hidden")},function(){b.prop("checked",!0)})})}(jQuery,document,window),function(a,b,c,d){a.imagifyUser&&c.getJSON(ajaxurl,a.imagifyUser).done(function(a){c.isPlainObject(a)&&a.success&&(a.data.id=null,a.data.plan_id=null,a.data.is=[],c.each(a.data,function(b,d){var e=".imagify-user-"+b.replace(/_/g,"-");0===b.indexOf("is_")?d&&a.data.is.push(e):"is"!==b&&c(e).text(d)}),a.data.is.push("best-plan"),c(a.data.is.join(",")).removeClass("hidden"))})}(window,document,jQuery),function(a,b,c,d){function e(b){var d,e,f,g,h,i=!1,j=null;b&&(f=c("#imagify-custom-folders-selected"),g=f.find(".imagify-custom-folder-line"),h=g.find('[value="'+b+'"]'),h.length||(b=b.split("#///#"),d=b[1].replace(/\/+$/,"").toLowerCase(),e=a.imagify.template("imagify-custom-folder"),g.each(function(){var a=c(this),h=a.data("path").replace(/\/+$/,"").toLowerCase();return""!==h&&0===d.indexOf(h)?(i=!0,!1):d<h?(a.before(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line"),i=!0,!1):void 0}),i||(f.append(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line")),""!==d&&g.each(function(){var a=c(this),b=a.data("path").toLowerCase();null!==j&&0===b.indexOf(j)?a.find(".imagify-custom-folders-remove").trigger("click.imagify"):j=b}),f.next(".hidden").removeClass("hidden")))}imagifyOptions.getFilesTree&&(c("#imagify-add-custom-folder").on("click.imagify",function(){var a,b=c(this),d=[];b.attr("disabled")||(b.attr("disabled","disabled").next("img").attr("aria-hidden","false"),a=c("#imagify-custom-folders-selected"),a.find("input").each(function(){d.push(this.value)}),c.post({url:imagifyOptions.getFilesTree,dataType:"json",data:{folder:"/",selected:d}}).done(function(a){if(!a.success)return void swal({title:imagifyOptions.labels.error,html:a.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});swal({title:imagifyOptions.labels.filesTreeTitle,html:'<div class="imagify-swal-subtitle">'+imagifyOptions.labels.filesTreeSubTitle+'</div><div class="imagify-swal-content"><p class="imagify-folders-information"><i class="dashicons dashicons-info" aria-hidden="true"></i>'+imagifyOptions.labels.cleaningInfo+'</p><ul id="imagify-folders-tree" class="imagify-folders-tree">'+a.data+"</ul></div>",type:"",customClass:"imagify-sweet-alert imagify-swal-has-subtitle imagify-folders-selection",showCancelButton:!0,padding:0,confirmButtonText:imagifyOptions.labels.confirmFilesTreeBtn,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){var a=c("#imagify-folders-tree input").serializeArray();a.length&&c.each(a,function(a,b){e(b.value)})}).catch(swal.noop)}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",customClass:"imagify-sweet-alert",padding:0})}).always(function(){b.removeAttr("disabled").next("img").attr("aria-hidden","true")}))}),c(b).on("click.imagify","#imagify-folders-tree [data-folder]",function(){var a=c(this),b=a.nextAll(".imagify-folders-sub-tree"),d=[];if(!a.attr("disabled")&&!a.siblings(":checkbox").is(":checked")){if(a.attr("disabled","disabled"),b.length)return a.hasClass("imagify-is-open")?(b.addClass("hidden"),a.removeClass(" imagify-is-open")):(b.removeClass("hidden"),a.addClass(" imagify-is-open")),void a.removeAttr("disabled");c("#imagify-custom-folders-selected").find("input").each(function(){d.push(this.value)}),c.post({url:imagifyOptions.getFilesTree,dataType:"json",data:{folder:a.data("folder"),selected:d}}).done(function(b){if(!b.success)return void swal({title:imagifyOptions.labels.error,html:b.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});a.addClass("imagify-is-open").parent().append('<ul class="imagify-folders-sub-tree">'+b.data+"</ul>")}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",padding:0,customClass:"imagify-sweet-alert"})}).always(function(){a.removeAttr("disabled")})}}),c("#imagify-custom-folders").on("click.imagify",".imagify-custom-folders-remove",function(){var b=c(this).closest(".imagify-custom-folder-line").addClass("imagify-will-remove");a.setTimeout(function(){b.remove(),c("#imagify-custom-folders-selected").
|
1 |
+
!function(a,b,c,d){var e=!1,f=!1;a("#imagify-settings #api_key").on("blur",function(){var b=a(this),d=b.val();return""!==a.trim(d)&&(a("#check_api_key").val()===d?(a("#imagify-check-api-container").html('<span class="dashicons dashicons-yes"></span> '+imagifyOptions.labels.ValidApiKeyText),!1):(!0===e?f.abort():(a("#imagify-check-api-container").remove(),b.after('<span id="imagify-check-api-container"><span class="imagify-spinner"></span>'+imagifyOptions.labels.waitApiKeyCheckText+"</span>")),e=!0,void(f=a.get(ajaxurl+c.imagify.concat+"action=imagify_check_api_key_validity&api_key="+b.val()+"&imagifycheckapikeynonce="+a("#imagifycheckapikeynonce").val()).done(function(b){b.success?(a("#imagify-check-api-container").remove(),swal({title:imagifyOptions.labels.ApiKeyCheckSuccessTitle,html:imagifyOptions.labels.ApiKeyCheckSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"}).then(function(){location.reload()})):a("#imagify-check-api-container").html('<span class="dashicons dashicons-no"></span> '+b.data),e=!1}))))}),a(".imagify-options-line").css("cursor","pointer").on("click",function(b){if("INPUT"!==b.target.nodeName)return a('input[aria-describedby="'+a(this).attr("id")+'"]').trigger("click"),!1}),a(".imagify-settings th span").on("click",function(){var b=a(this).parent().next("td").find("input:checkbox");1===b.length&&b.trigger("click")}),a(".imagify-options-line").find("input").on("change focus",function(){var b=a(this).closest(".imagify-options-line").prev("label").prev("input");b[0].checked||b.prop("checked",!0)}),a(".imagify-settings-section").find("#imagify_backup").on("change",function(){var b=a(this),c=b.siblings("#backup-dir-is-writable"),d={action:"imagify_check_backup_dir_is_writable",_wpnonce:c.data("nonce")};if(b.is(":checked"))return void a.getJSON(ajaxurl,d).done(function(b){a.isPlainObject(b)&&b.success&&(b.data.is_writable?c.addClass("hidden"):c.removeClass("hidden"))});swal({title:imagifyOptions.labels.noBackupTitle,html:imagifyOptions.labels.noBackupText,type:"warning",customClass:"imagify-sweet-alert",padding:0,showCancelButton:!0,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){c.addClass("hidden")},function(){b.prop("checked",!0)})})}(jQuery,document,window),function(a,b,c,d){a.imagifyUser&&c.getJSON(ajaxurl,a.imagifyUser).done(function(a){c.isPlainObject(a)&&a.success&&(a.data.id=null,a.data.plan_id=null,a.data.is=[],c.each(a.data,function(b,d){var e=".imagify-user-"+b.replace(/_/g,"-");0===b.indexOf("is_")?d&&a.data.is.push(e):"is"!==b&&c(e).text(d)}),a.data.is.push("best-plan"),c(a.data.is.join(",")).removeClass("hidden"))})}(window,document,jQuery),function(a,b,c,d){function e(b){var d,e,f,g,h,i=!1,j=null;b&&(f=c("#imagify-custom-folders-selected"),g=f.find(".imagify-custom-folder-line"),h=g.find('[value="'+b+'"]'),h.length||(b=b.split("#///#"),d=b[1].replace(/\/+$/,"").toLowerCase(),e=a.imagify.template("imagify-custom-folder"),g.each(function(){var a=c(this),h=a.data("path").replace(/\/+$/,"").toLowerCase();return""!==h&&0===d.indexOf(h)?(i=!0,!1):d<h?(a.before(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line"),i=!0,!1):void 0}),i||(f.append(e({value:b[0],label:b[1]})),g=f.find(".imagify-custom-folder-line")),""!==d&&g.each(function(){var a=c(this),b=a.data("path").toLowerCase();null!==j&&0===b.indexOf(j)?a.find(".imagify-custom-folders-remove").trigger("click.imagify"):j=b}),f.next(".hidden").removeClass("hidden")))}imagifyOptions.getFilesTree&&(c("#imagify-add-custom-folder").on("click.imagify",function(){var a,b=c(this),d=[];b.attr("disabled")||(b.attr("disabled","disabled").next("img").attr("aria-hidden","false"),a=c("#imagify-custom-folders-selected"),a.find("input").each(function(){d.push(this.value)}),c.post({url:imagifyOptions.getFilesTree,dataType:"json",data:{folder:"/",selected:d}}).done(function(a){if(!a.success)return void swal({title:imagifyOptions.labels.error,html:a.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});swal({title:imagifyOptions.labels.filesTreeTitle,html:'<div class="imagify-swal-subtitle">'+imagifyOptions.labels.filesTreeSubTitle+'</div><div class="imagify-swal-content"><p class="imagify-folders-information"><i class="dashicons dashicons-info" aria-hidden="true"></i>'+imagifyOptions.labels.cleaningInfo+'</p><ul id="imagify-folders-tree" class="imagify-folders-tree">'+a.data+"</ul></div>",type:"",customClass:"imagify-sweet-alert imagify-swal-has-subtitle imagify-folders-selection",showCancelButton:!0,padding:0,confirmButtonText:imagifyOptions.labels.confirmFilesTreeBtn,cancelButtonText:imagifySwal.labels.cancelButtonText,reverseButtons:!0}).then(function(){var a=c("#imagify-folders-tree input").serializeArray();a.length&&c.each(a,function(a,b){e(b.value)})}).catch(swal.noop)}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",customClass:"imagify-sweet-alert",padding:0})}).always(function(){b.removeAttr("disabled").next("img").attr("aria-hidden","true")}))}),c(b).on("click.imagify","#imagify-folders-tree [data-folder]",function(){var a=c(this),b=a.nextAll(".imagify-folders-sub-tree"),d=[];if(!a.attr("disabled")&&!a.siblings(":checkbox").is(":checked")){if(a.attr("disabled","disabled"),b.length)return a.hasClass("imagify-is-open")?(b.addClass("hidden"),a.removeClass(" imagify-is-open")):(b.removeClass("hidden"),a.addClass(" imagify-is-open")),void a.removeAttr("disabled");c("#imagify-custom-folders-selected").find("input").each(function(){d.push(this.value)}),c.post({url:imagifyOptions.getFilesTree,dataType:"json",data:{folder:a.data("folder"),selected:d}}).done(function(b){if(!b.success)return void swal({title:imagifyOptions.labels.error,html:b.data||"",type:"error",padding:0,customClass:"imagify-sweet-alert"});a.addClass("imagify-is-open").parent().append('<ul class="imagify-folders-sub-tree">'+b.data+"</ul>")}).fail(function(){swal({title:imagifyOptions.labels.error,type:"error",padding:0,customClass:"imagify-sweet-alert"})}).always(function(){a.removeAttr("disabled")})}}),c("#imagify-custom-folders").on("click.imagify",".imagify-custom-folders-remove",function(){var b=c(this).closest(".imagify-custom-folder-line").addClass("imagify-will-remove");a.setTimeout(function(){b.remove(),c("#imagify-custom-folders-selected").siblings(".imagify-success.hidden").removeClass("hidden")},750)}),c("#imagify-add-themes-to-custom-folder").on("click.imagify",function(){var a=c(this);e(a.data("theme")),e(a.data("theme-parent")),a.replaceWith("<p>"+imagifyOptions.labels.themesAdded+"</p>")}))}(window,document,jQuery),function(a,b,c,d){var e=c.propHooks.checked;c.propHooks.checked={set:function(a,b,d){var f;return f=void 0===e?a[d]=b:e(a,b,d),c(a).trigger("change.imagify"),f}},c(".imagify-select-all").on("click.imagify",function(){var a=c(this),b=a.data("action"),d=a.closest(".imagify-select-all-buttons"),e=d.prev(".imagify-check-group"),f="imagify-is-inactive";if(a.hasClass(f))return!1;d.find(".imagify-select-all").removeClass(f).attr("aria-disabled","false"),a.addClass(f).attr("aria-disabled","true"),e.find(".imagify-row-check").prop("checked",function(){return!c(this).is(":hidden,:disabled")&&"select"===b})}),c(".imagify-check-group .imagify-row-check").on("change.imagify",function(){var a=c(this).closest(".imagify-check-group"),b=a.find(".imagify-row-check"),d=b.filter(":visible:enabled").length,e=b.filter(":visible:enabled:checked").length,f=a.next(".imagify-select-all-buttons"),g="imagify-is-inactive";0===e&&f.find('[data-action="unselect"]').addClass(g).attr("aria-disabled","true"),e===d&&f.find('[data-action="select"]').addClass(g).attr("aria-disabled","true"),e!==d&&e>0&&f.find(".imagify-select-all").removeClass(g).attr("aria-disabled","false")})}(window,document,jQuery);
|
assets/js/weakmap-polyfill.js
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* weakmap-polyfill v2.0.0 - ECMAScript6 WeakMap polyfill
|
3 |
+
* https://github.com/polygonplanet/weakmap-polyfill
|
4 |
+
* Copyright (c) 2015-2016 polygon planet <polygon.planet.aqua@gmail.com>
|
5 |
+
* @license MIT
|
6 |
+
*/
|
7 |
+
|
8 |
+
(function(self) {
|
9 |
+
'use strict';
|
10 |
+
|
11 |
+
if (self.WeakMap) {
|
12 |
+
return;
|
13 |
+
}
|
14 |
+
|
15 |
+
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
16 |
+
var defineProperty = function(object, name, value) {
|
17 |
+
if (Object.defineProperty) {
|
18 |
+
Object.defineProperty(object, name, {
|
19 |
+
configurable: true,
|
20 |
+
writable: true,
|
21 |
+
value: value
|
22 |
+
});
|
23 |
+
} else {
|
24 |
+
object[name] = value;
|
25 |
+
}
|
26 |
+
};
|
27 |
+
|
28 |
+
self.WeakMap = (function() {
|
29 |
+
|
30 |
+
// ECMA-262 23.3 WeakMap Objects
|
31 |
+
function WeakMap() {
|
32 |
+
if (this === void 0) {
|
33 |
+
throw new TypeError("Constructor WeakMap requires 'new'");
|
34 |
+
}
|
35 |
+
|
36 |
+
defineProperty(this, '_id', genId('_WeakMap'));
|
37 |
+
|
38 |
+
// ECMA-262 23.3.1.1 WeakMap([iterable])
|
39 |
+
if (arguments.length > 0) {
|
40 |
+
// Currently, WeakMap `iterable` argument is not supported
|
41 |
+
throw new TypeError('WeakMap iterable is not supported');
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
// ECMA-262 23.3.3.2 WeakMap.prototype.delete(key)
|
46 |
+
defineProperty(WeakMap.prototype, 'delete', function(key) {
|
47 |
+
checkInstance(this, 'delete');
|
48 |
+
|
49 |
+
if (!isObject(key)) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
+
var entry = key[this._id];
|
54 |
+
if (entry && entry[0] === key) {
|
55 |
+
delete key[this._id];
|
56 |
+
return true;
|
57 |
+
}
|
58 |
+
|
59 |
+
return false;
|
60 |
+
});
|
61 |
+
|
62 |
+
// ECMA-262 23.3.3.3 WeakMap.prototype.get(key)
|
63 |
+
defineProperty(WeakMap.prototype, 'get', function(key) {
|
64 |
+
checkInstance(this, 'get');
|
65 |
+
|
66 |
+
if (!isObject(key)) {
|
67 |
+
return void 0;
|
68 |
+
}
|
69 |
+
|
70 |
+
var entry = key[this._id];
|
71 |
+
if (entry && entry[0] === key) {
|
72 |
+
return entry[1];
|
73 |
+
}
|
74 |
+
|
75 |
+
return void 0;
|
76 |
+
});
|
77 |
+
|
78 |
+
// ECMA-262 23.3.3.4 WeakMap.prototype.has(key)
|
79 |
+
defineProperty(WeakMap.prototype, 'has', function(key) {
|
80 |
+
checkInstance(this, 'has');
|
81 |
+
|
82 |
+
if (!isObject(key)) {
|
83 |
+
return false;
|
84 |
+
}
|
85 |
+
|
86 |
+
var entry = key[this._id];
|
87 |
+
if (entry && entry[0] === key) {
|
88 |
+
return true;
|
89 |
+
}
|
90 |
+
|
91 |
+
return false;
|
92 |
+
});
|
93 |
+
|
94 |
+
// ECMA-262 23.3.3.5 WeakMap.prototype.set(key, value)
|
95 |
+
defineProperty(WeakMap.prototype, 'set', function(key, value) {
|
96 |
+
checkInstance(this, 'set');
|
97 |
+
|
98 |
+
if (!isObject(key)) {
|
99 |
+
throw new TypeError('Invalid value used as weak map key');
|
100 |
+
}
|
101 |
+
|
102 |
+
var entry = key[this._id];
|
103 |
+
if (entry && entry[0] === key) {
|
104 |
+
entry[1] = value;
|
105 |
+
return this;
|
106 |
+
}
|
107 |
+
|
108 |
+
defineProperty(key, this._id, [key, value]);
|
109 |
+
return this;
|
110 |
+
});
|
111 |
+
|
112 |
+
|
113 |
+
function checkInstance(x, methodName) {
|
114 |
+
if (!isObject(x) || !hasOwnProperty.call(x, '_id')) {
|
115 |
+
throw new TypeError(
|
116 |
+
methodName + ' method called on incompatible receiver ' +
|
117 |
+
typeof x
|
118 |
+
);
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
function genId(prefix) {
|
123 |
+
return prefix + '_' + rand() + '.' + rand();
|
124 |
+
}
|
125 |
+
|
126 |
+
function rand() {
|
127 |
+
return Math.random().toString().substring(2);
|
128 |
+
}
|
129 |
+
|
130 |
+
|
131 |
+
defineProperty(WeakMap, '_polyfill', true);
|
132 |
+
return WeakMap;
|
133 |
+
})();
|
134 |
+
|
135 |
+
|
136 |
+
function isObject(x) {
|
137 |
+
return Object(x) === x;
|
138 |
+
}
|
139 |
+
|
140 |
+
})(
|
141 |
+
typeof self !== 'undefined' ? self :
|
142 |
+
typeof window !== 'undefined' ? window :
|
143 |
+
typeof global !== 'undefined' ? global : this
|
144 |
+
);
|
assets/js/weakmap-polyfill.min.js
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
* weakmap-polyfill v2.0.0 - ECMAScript6 WeakMap polyfill
|
3 |
+
* https://github.com/polygonplanet/weakmap-polyfill
|
4 |
+
* Copyright (c) 2015-2016 polygon planet <polygon.planet.aqua@gmail.com>
|
5 |
+
* @license MIT
|
6 |
+
*/
|
7 |
+
(function(e){"use strict";if(e.WeakMap){return}var t=Object.prototype.hasOwnProperty;var r=function(e,t,r){if(Object.defineProperty){Object.defineProperty(e,t,{configurable:true,writable:true,value:r})}else{e[t]=r}};e.WeakMap=function(){function WeakMap(){if(this===void 0){throw new TypeError("Constructor WeakMap requires 'new'")}r(this,"_id",genId("_WeakMap"));if(arguments.length>0){throw new TypeError("WeakMap iterable is not supported")}}r(WeakMap.prototype,"delete",function(e){checkInstance(this,"delete");if(!isObject(e)){return false}var t=e[this._id];if(t&&t[0]===e){delete e[this._id];return true}return false});r(WeakMap.prototype,"get",function(e){checkInstance(this,"get");if(!isObject(e)){return void 0}var t=e[this._id];if(t&&t[0]===e){return t[1]}return void 0});r(WeakMap.prototype,"has",function(e){checkInstance(this,"has");if(!isObject(e)){return false}var t=e[this._id];if(t&&t[0]===e){return true}return false});r(WeakMap.prototype,"set",function(e,t){checkInstance(this,"set");if(!isObject(e)){throw new TypeError("Invalid value used as weak map key")}var n=e[this._id];if(n&&n[0]===e){n[1]=t;return this}r(e,this._id,[e,t]);return this});function checkInstance(e,r){if(!isObject(e)||!t.call(e,"_id")){throw new TypeError(r+" method called on incompatible receiver "+typeof e)}}function genId(e){return e+"_"+rand()+"."+rand()}function rand(){return Math.random().toString().substring(2)}r(WeakMap,"_polyfill",true);return WeakMap}();function isObject(e){return Object(e)===e}})(typeof self!=="undefined"?self:typeof window!=="undefined"?window:typeof global!=="undefined"?global:this);
|
imagify.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: Imagify
|
4 |
* Plugin URI: https://wordpress.org/plugins/imagify/
|
5 |
* Description: Dramaticaly reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
|
6 |
-
* Version: 1.
|
7 |
* Author: WP Media
|
8 |
* Author URI: https://wp-media.me/
|
9 |
* Licence: GPLv2
|
@@ -17,7 +17,7 @@
|
|
17 |
defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
18 |
|
19 |
// Imagify defines.
|
20 |
-
define( 'IMAGIFY_VERSION' , '1.
|
21 |
define( 'IMAGIFY_SLUG' , 'imagify' );
|
22 |
define( 'IMAGIFY_FILE' , __FILE__ );
|
23 |
define( 'IMAGIFY_PATH' , realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
|
3 |
* Plugin Name: Imagify
|
4 |
* Plugin URI: https://wordpress.org/plugins/imagify/
|
5 |
* Description: Dramaticaly reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
|
6 |
+
* Version: 1.8
|
7 |
* Author: WP Media
|
8 |
* Author URI: https://wp-media.me/
|
9 |
* Licence: GPLv2
|
17 |
defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
18 |
|
19 |
// Imagify defines.
|
20 |
+
define( 'IMAGIFY_VERSION' , '1.8' );
|
21 |
define( 'IMAGIFY_SLUG' , 'imagify' );
|
22 |
define( 'IMAGIFY_FILE' , __FILE__ );
|
23 |
define( 'IMAGIFY_PATH' , realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
|
inc/3rd-party/3rd-party.php
CHANGED
@@ -9,9 +9,9 @@ require( IMAGIFY_3RD_PARTY_PATH . 'enable-media-replace/enable-media-replace.php
|
|
9 |
require( IMAGIFY_3RD_PARTY_PATH . 'formidable-pro/formidable-pro.php' );
|
10 |
require( IMAGIFY_3RD_PARTY_PATH . 'nextgen-gallery/nextgen-gallery.php' );
|
11 |
require( IMAGIFY_3RD_PARTY_PATH . 'regenerate-thumbnails/regenerate-thumbnails.php' );
|
|
|
12 |
require( IMAGIFY_3RD_PARTY_PATH . 'screets-lc.php' );
|
13 |
require( IMAGIFY_3RD_PARTY_PATH . 'wp-real-media-library.php' );
|
14 |
-
require( IMAGIFY_3RD_PARTY_PATH . 'wp-retina-2x.php' );
|
15 |
require( IMAGIFY_3RD_PARTY_PATH . 'wp-rocket.php' );
|
16 |
require( IMAGIFY_3RD_PARTY_PATH . 'yoast-seo.php' );
|
17 |
|
9 |
require( IMAGIFY_3RD_PARTY_PATH . 'formidable-pro/formidable-pro.php' );
|
10 |
require( IMAGIFY_3RD_PARTY_PATH . 'nextgen-gallery/nextgen-gallery.php' );
|
11 |
require( IMAGIFY_3RD_PARTY_PATH . 'regenerate-thumbnails/regenerate-thumbnails.php' );
|
12 |
+
require( IMAGIFY_3RD_PARTY_PATH . 'wp-retina-2x/wp-retina-2x.php' );
|
13 |
require( IMAGIFY_3RD_PARTY_PATH . 'screets-lc.php' );
|
14 |
require( IMAGIFY_3RD_PARTY_PATH . 'wp-real-media-library.php' );
|
|
|
15 |
require( IMAGIFY_3RD_PARTY_PATH . 'wp-rocket.php' );
|
16 |
require( IMAGIFY_3RD_PARTY_PATH . 'yoast-seo.php' );
|
17 |
|
inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf-attachment.php
CHANGED
@@ -148,6 +148,7 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
148 |
|
149 |
// Get file path of the full size.
|
150 |
$attachment_path = $this->get_original_path();
|
|
|
151 |
|
152 |
if ( ! $attachment_path ) {
|
153 |
// We're in deep sh**.
|
@@ -174,7 +175,7 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
174 |
$filesize_total = 0;
|
175 |
|
176 |
// Maybe resize (and backup) the image.
|
177 |
-
$resized = $this->maybe_resize( $attachment_path );
|
178 |
|
179 |
if ( $resized ) {
|
180 |
$size = $this->filesystem->get_image_size( $attachment_path );
|
@@ -210,6 +211,9 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
210 |
}
|
211 |
}
|
212 |
|
|
|
|
|
|
|
213 |
// Save the optimization level.
|
214 |
update_post_meta( $this->id, '_imagify_optimization_level', $optimization_level );
|
215 |
|
@@ -227,11 +231,12 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
227 |
|
228 |
foreach ( $metadata['sizes'] as $size_key => $size_data ) {
|
229 |
$thumbnail_path = $this->get_thumbnail_path( $size_data['file'] );
|
|
|
230 |
|
231 |
if ( $this->delete_files ) {
|
232 |
$to_delete[] = $thumbnail_path;
|
233 |
|
234 |
-
// Even if this size must not be optimized ($disallowed_sizes), we must fetch the file from S3 to get its size
|
235 |
if ( ! $this->filesystem->exists( $thumbnail_path ) && ! $this->get_file_from_s3( $thumbnail_path ) ) {
|
236 |
// Doesn't exist and couldn't be retrieved from S3.
|
237 |
$data['sizes'][ $size_key ] = array(
|
@@ -250,11 +255,14 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
250 |
}
|
251 |
|
252 |
// Check if this size has to be optimized.
|
253 |
-
if ( isset( $disallowed_sizes[ $size_key ] ) &&
|
254 |
$data['sizes'][ $size_key ] = array(
|
255 |
'success' => false,
|
256 |
'error' => __( 'This size isn\'t authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' ),
|
257 |
);
|
|
|
|
|
|
|
258 |
continue;
|
259 |
}
|
260 |
|
@@ -267,7 +275,9 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
267 |
continue;
|
268 |
}
|
269 |
|
270 |
-
|
|
|
|
|
271 |
|
272 |
// Optimize the thumbnail size.
|
273 |
$response = do_imagify( $thumbnail_path, array(
|
@@ -279,7 +289,7 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
279 |
$data = $this->fill_data( $data, $response, $size_key );
|
280 |
|
281 |
/** This filter is documented in /inc/classes/class-imagify-attachment.php. */
|
282 |
-
$data = apply_filters( 'imagify_fill_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level );
|
283 |
} // End foreach().
|
284 |
} // End if().
|
285 |
|
@@ -321,7 +331,7 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
321 |
*/
|
322 |
public function optimize_missing_thumbnails( $optimization_level = null ) {
|
323 |
// Check if the attachment extension is allowed.
|
324 |
-
if ( ! $this->is_extension_supported() ) {
|
325 |
return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
|
326 |
}
|
327 |
|
@@ -529,26 +539,39 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
529 |
return false;
|
530 |
}
|
531 |
|
532 |
-
|
533 |
-
require_once( ABSPATH . 'wp-admin/includes/image.php' );
|
534 |
-
}
|
535 |
|
536 |
// Remove old optimization data.
|
537 |
$this->delete_imagify_data();
|
538 |
|
539 |
-
|
540 |
-
|
|
|
541 |
|
542 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
543 |
|
544 |
-
// If the files must be deleted, we need to store the file sizes.
|
545 |
-
$filesize_total = 0;
|
546 |
// Generate new thumbnails and new metadata.
|
547 |
-
$metadata
|
|
|
548 |
// Send to S3.
|
549 |
$sent = $this->maybe_send_attachment_to_s3( $metadata, $attachment_path );
|
550 |
// Files restored (and maybe to delete).
|
551 |
$files = array();
|
|
|
|
|
552 |
|
553 |
if ( $sent ) {
|
554 |
$files[] = $attachment_path;
|
@@ -590,6 +613,9 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
590 |
update_post_meta( $this->id, 'wpos3_filesize_total', $filesize_total );
|
591 |
}
|
592 |
|
|
|
|
|
|
|
593 |
$to_delete = $this->delete_files ? $files : array();
|
594 |
|
595 |
$this->cleanup( $metadata, $to_delete );
|
@@ -664,6 +690,10 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
664 |
* @return bool True on success. False on failure.
|
665 |
*/
|
666 |
protected function maybe_resize( $attachment_path ) {
|
|
|
|
|
|
|
|
|
667 |
$do_resize = get_imagify_option( 'resize_larger' );
|
668 |
$resize_width = get_imagify_option( 'resize_larger_w' );
|
669 |
$attachment_size = $this->filesystem->get_image_size( $attachment_path );
|
@@ -684,15 +714,7 @@ class Imagify_AS3CF_Attachment extends Imagify_Attachment {
|
|
684 |
return false;
|
685 |
}
|
686 |
|
687 |
-
$this->filesystem->move( $resized_attachment_path, $attachment_path, true );
|
688 |
-
$this->filesystem->chmod_file( $attachment_path );
|
689 |
-
|
690 |
-
// If resized temp file still exists, delete it.
|
691 |
-
if ( $this->filesystem->exists( $resized_attachment_path ) ) {
|
692 |
-
$this->filesystem->delete( $resized_attachment_path );
|
693 |
-
}
|
694 |
-
|
695 |
-
return $this->filesystem->exists( $attachment_path );
|
696 |
}
|
697 |
|
698 |
/**
|
148 |
|
149 |
// Get file path of the full size.
|
150 |
$attachment_path = $this->get_original_path();
|
151 |
+
$attachment_url = $this->get_original_url();
|
152 |
|
153 |
if ( ! $attachment_path ) {
|
154 |
// We're in deep sh**.
|
175 |
$filesize_total = 0;
|
176 |
|
177 |
// Maybe resize (and backup) the image.
|
178 |
+
$resized = $this->is_image() && $this->maybe_resize( $attachment_path );
|
179 |
|
180 |
if ( $resized ) {
|
181 |
$size = $this->filesystem->get_image_size( $attachment_path );
|
211 |
}
|
212 |
}
|
213 |
|
214 |
+
/** This filter is documented in /inc/classes/class-imagify-attachment.php. */
|
215 |
+
$data = apply_filters( 'imagify_fill_full_size_data', $data, $response, $this->id, $attachment_path, $attachment_url, 'full', $optimization_level, $metadata );
|
216 |
+
|
217 |
// Save the optimization level.
|
218 |
update_post_meta( $this->id, '_imagify_optimization_level', $optimization_level );
|
219 |
|
231 |
|
232 |
foreach ( $metadata['sizes'] as $size_key => $size_data ) {
|
233 |
$thumbnail_path = $this->get_thumbnail_path( $size_data['file'] );
|
234 |
+
$thumbnail_url = $this->get_thumbnail_url( $size_data['file'] );
|
235 |
|
236 |
if ( $this->delete_files ) {
|
237 |
$to_delete[] = $thumbnail_path;
|
238 |
|
239 |
+
// Even if this size must not be optimized ($disallowed_sizes), we must fetch the file from S3 to get its size, and not to trigger a `WP_Error` in `upload_attachment_to_s3()`.
|
240 |
if ( ! $this->filesystem->exists( $thumbnail_path ) && ! $this->get_file_from_s3( $thumbnail_path ) ) {
|
241 |
// Doesn't exist and couldn't be retrieved from S3.
|
242 |
$data['sizes'][ $size_key ] = array(
|
255 |
}
|
256 |
|
257 |
// Check if this size has to be optimized.
|
258 |
+
if ( ! $is_active_for_network && isset( $disallowed_sizes[ $size_key ] ) && $this->is_image() ) {
|
259 |
$data['sizes'][ $size_key ] = array(
|
260 |
'success' => false,
|
261 |
'error' => __( 'This size isn\'t authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' ),
|
262 |
);
|
263 |
+
|
264 |
+
/** This filter is documented in /inc/classes/class-imagify-attachment.php. */
|
265 |
+
$data = apply_filters( 'imagify_fill_unauthorized_thumbnail_data', $data, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level, $metadata );
|
266 |
continue;
|
267 |
}
|
268 |
|
275 |
continue;
|
276 |
}
|
277 |
|
278 |
+
if ( ! $this->is_image() ) {
|
279 |
+
continue;
|
280 |
+
}
|
281 |
|
282 |
// Optimize the thumbnail size.
|
283 |
$response = do_imagify( $thumbnail_path, array(
|
289 |
$data = $this->fill_data( $data, $response, $size_key );
|
290 |
|
291 |
/** This filter is documented in /inc/classes/class-imagify-attachment.php. */
|
292 |
+
$data = apply_filters( 'imagify_fill_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level, $metadata );
|
293 |
} // End foreach().
|
294 |
} // End if().
|
295 |
|
331 |
*/
|
332 |
public function optimize_missing_thumbnails( $optimization_level = null ) {
|
333 |
// Check if the attachment extension is allowed.
|
334 |
+
if ( ! $this->is_extension_supported() || ! $this->is_image() ) {
|
335 |
return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
|
336 |
}
|
337 |
|
539 |
return false;
|
540 |
}
|
541 |
|
542 |
+
$this->set_deletion_status();
|
|
|
|
|
543 |
|
544 |
// Remove old optimization data.
|
545 |
$this->delete_imagify_data();
|
546 |
|
547 |
+
if ( ! $this->is_image() ) {
|
548 |
+
// We need to delete the thumbnails for pdf, or new ones will be generated with new unique file names.
|
549 |
+
$metadata = wp_get_attachment_metadata( $this->id );
|
550 |
|
551 |
+
if ( ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ) {
|
552 |
+
foreach ( $metadata['sizes'] as $size_key => $size_data ) {
|
553 |
+
$thumbnail_path = $this->get_thumbnail_path( $size_data['file'] );
|
554 |
+
|
555 |
+
if ( $this->filesystem->exists( $thumbnail_path ) ) {
|
556 |
+
$this->filesystem->delete( $thumbnail_path );
|
557 |
+
}
|
558 |
+
}
|
559 |
+
}
|
560 |
+
}
|
561 |
+
|
562 |
+
if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
|
563 |
+
require_once( ABSPATH . 'wp-admin/includes/image.php' );
|
564 |
+
}
|
565 |
|
|
|
|
|
566 |
// Generate new thumbnails and new metadata.
|
567 |
+
$metadata = wp_generate_attachment_metadata( $this->id, $attachment_path );
|
568 |
+
|
569 |
// Send to S3.
|
570 |
$sent = $this->maybe_send_attachment_to_s3( $metadata, $attachment_path );
|
571 |
// Files restored (and maybe to delete).
|
572 |
$files = array();
|
573 |
+
// If the files must be deleted, we need to store the file sizes.
|
574 |
+
$filesize_total = 0;
|
575 |
|
576 |
if ( $sent ) {
|
577 |
$files[] = $attachment_path;
|
613 |
update_post_meta( $this->id, 'wpos3_filesize_total', $filesize_total );
|
614 |
}
|
615 |
|
616 |
+
/** This hook is documented in /inc/classes/class-imagify-attachment.php. */
|
617 |
+
do_action( 'after_imagify_restore_attachment', $this->id );
|
618 |
+
|
619 |
$to_delete = $this->delete_files ? $files : array();
|
620 |
|
621 |
$this->cleanup( $metadata, $to_delete );
|
690 |
* @return bool True on success. False on failure.
|
691 |
*/
|
692 |
protected function maybe_resize( $attachment_path ) {
|
693 |
+
if ( ! $this->is_image() ) {
|
694 |
+
return false;
|
695 |
+
}
|
696 |
+
|
697 |
$do_resize = get_imagify_option( 'resize_larger' );
|
698 |
$resize_width = get_imagify_option( 'resize_larger_w' );
|
699 |
$attachment_size = $this->filesystem->get_image_size( $attachment_path );
|
714 |
return false;
|
715 |
}
|
716 |
|
717 |
+
return $this->filesystem->move( $resized_attachment_path, $attachment_path, true );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
718 |
}
|
719 |
|
720 |
/**
|
inc/3rd-party/amazon-s3-and-cloudfront/inc/classes/class-imagify-as3cf.php
CHANGED
@@ -406,8 +406,6 @@ class Imagify_AS3CF extends Imagify_AS3CF_Deprecated {
|
|
406 |
* @author Grégory Viguier
|
407 |
*/
|
408 |
public function optimize() {
|
409 |
-
global $as3cf;
|
410 |
-
|
411 |
check_ajax_referer( 'imagify_async_optimize_as3cf' );
|
412 |
|
413 |
if ( empty( $_POST['post_id'] ) || ! imagify_current_user_can( 'auto-optimize' ) ) {
|
406 |
* @author Grégory Viguier
|
407 |
*/
|
408 |
public function optimize() {
|
|
|
|
|
409 |
check_ajax_referer( 'imagify_async_optimize_as3cf' );
|
410 |
|
411 |
if ( empty( $_POST['post_id'] ) || ! imagify_current_user_can( 'auto-optimize' ) ) {
|
inc/3rd-party/hosting/siteground.php
CHANGED
File without changes
|
inc/3rd-party/hosting/wpengine.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/admin/ajax.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/admin/bulk.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/admin/enqueue.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/admin/gallery.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/admin/heartbeat.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/admin/menu.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-attachment.php
CHANGED
@@ -14,7 +14,7 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
14 |
*
|
15 |
* @var string
|
16 |
*/
|
17 |
-
const VERSION = '1.
|
18 |
|
19 |
/**
|
20 |
* The attachment SQL DB class.
|
@@ -31,10 +31,19 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
31 |
* @var object A nggImage object.
|
32 |
* @since 1.5
|
33 |
* @since 1.7 Not public anymore.
|
34 |
-
* @access
|
35 |
*/
|
36 |
protected $image;
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
/**
|
39 |
* Tell if the file mime type can be optimized by Imagify.
|
40 |
*
|
@@ -56,8 +65,13 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
56 |
*/
|
57 |
public function __construct( $id ) {
|
58 |
if ( is_object( $id ) ) {
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
61 |
} else {
|
62 |
$this->image = nggdb::find_image( absint( $id ) );
|
63 |
$this->id = ! empty( $this->image->pid ) ? (int) $this->image->pid : 0;
|
@@ -65,6 +79,12 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
65 |
|
66 |
$this->get_row();
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
$this->filesystem = Imagify_Filesystem::get_instance();
|
69 |
$this->optimization_state_transient = 'imagify-ngg-async-in-progress-' . $this->id;
|
70 |
|
@@ -72,7 +92,7 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
72 |
$ngg_admin_functions_path = WP_PLUGIN_DIR . '/' . NGGFOLDER . '/products/photocrati_nextgen/modules/ngglegacy/admin/functions.php';
|
73 |
|
74 |
if ( ! class_exists( 'nggAdmin' ) && $this->filesystem->exists( $ngg_admin_functions_path ) ) {
|
75 |
-
require_once
|
76 |
}
|
77 |
}
|
78 |
|
@@ -185,6 +205,21 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
185 |
return isset( $row['status'] ) ? $row['status'] : false;
|
186 |
}
|
187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
/**
|
189 |
* Get width and height of the original image.
|
190 |
*
|
@@ -202,45 +237,28 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
202 |
}
|
203 |
|
204 |
/**
|
205 |
-
*
|
206 |
*
|
207 |
-
* @since 1.
|
208 |
* @access public
|
209 |
-
* @
|
210 |
-
*/
|
211 |
-
public function delete_imagify_data() {
|
212 |
-
if ( ! $this->get_row() ) {
|
213 |
-
return;
|
214 |
-
}
|
215 |
-
|
216 |
-
$this->delete_row();
|
217 |
-
}
|
218 |
-
|
219 |
-
/**
|
220 |
-
* Tell if the current file mime type is supported.
|
221 |
-
*
|
222 |
-
* @since 1.6.9
|
223 |
* @author Grégory Viguier
|
224 |
*
|
225 |
-
* @return
|
226 |
*/
|
227 |
-
public function
|
228 |
-
if ( isset( $this->
|
229 |
-
return $this->
|
230 |
}
|
231 |
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
$this->is_mime_type_supported = false;
|
236 |
-
return $this->is_mime_type_supported;
|
237 |
}
|
238 |
|
239 |
-
$
|
240 |
-
$mime_types = array_flip( $mime_types );
|
241 |
|
242 |
-
$this->
|
243 |
-
return $this->is_mime_type_supported;
|
244 |
}
|
245 |
|
246 |
/**
|
@@ -255,7 +273,7 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
255 |
static $sizes;
|
256 |
|
257 |
if ( ! isset( $sizes ) ) {
|
258 |
-
$sizes =
|
259 |
}
|
260 |
|
261 |
return $sizes && $this->get_original_path();
|
@@ -272,14 +290,16 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
272 |
public function update_metadata_size() {
|
273 |
$size = $this->filesystem->get_image_size( $this->get_original_path() );
|
274 |
|
275 |
-
if ( $size ) {
|
276 |
-
|
277 |
-
$this->image->meta_data['height'] = $size['height'];
|
278 |
-
$this->image->meta_data['full']['width'] = $size['width'];
|
279 |
-
$this->image->meta_data['full']['height'] = $size['height'];
|
280 |
-
|
281 |
-
nggdb::update_image_meta( $this->id, $this->image->meta_data );
|
282 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
}
|
284 |
|
285 |
/**
|
@@ -413,14 +433,16 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
413 |
|
414 |
// Get file path for original image.
|
415 |
$attachment_path = $this->get_original_path();
|
|
|
416 |
|
417 |
/**
|
418 |
* Fires before optimizing an attachment.
|
419 |
*
|
420 |
-
* @since
|
|
|
421 |
*
|
422 |
-
* @param int $id The
|
423 |
-
|
424 |
do_action( 'before_imagify_ngg_optimize_attachment', $this->id );
|
425 |
|
426 |
$this->set_running_status();
|
@@ -436,6 +458,22 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
436 |
|
437 |
$data = $this->fill_data( null, $response );
|
438 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
439 |
// Save the optimization level.
|
440 |
$this->update_row( array(
|
441 |
// The pid column is needed in case the row doesn't exist yet.
|
@@ -444,7 +482,7 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
444 |
) );
|
445 |
|
446 |
if ( ! $data ) {
|
447 |
-
//
|
448 |
$this->delete_running_status();
|
449 |
return;
|
450 |
}
|
@@ -457,6 +495,39 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
457 |
'status' => 'success',
|
458 |
) );
|
459 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
460 |
/**
|
461 |
* Fires after optimizing an attachment.
|
462 |
*
|
@@ -467,39 +538,6 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
467 |
*/
|
468 |
do_action( 'after_imagify_ngg_optimize_attachment', $this->id, $data );
|
469 |
|
470 |
-
/**
|
471 |
-
* Update NGG meta data.
|
472 |
-
*/
|
473 |
-
$storage = C_Gallery_Storage::get_instance()->object;
|
474 |
-
$image = $storage->_image_mapper->find( $this->id );
|
475 |
-
|
476 |
-
if ( $image ) {
|
477 |
-
$dimensions = $this->filesystem->get_image_size( $attachment_path );
|
478 |
-
$md5 = md5_file( $attachment_path );
|
479 |
-
|
480 |
-
if ( ( $dimensions || $md5 ) && ( empty( $image->meta_data['full'] ) || ! is_array( $image->meta_data['full'] ) ) ) {
|
481 |
-
$image->meta_data['full'] = array(
|
482 |
-
'width' => 0,
|
483 |
-
'height' => 0,
|
484 |
-
'md5' => '',
|
485 |
-
);
|
486 |
-
}
|
487 |
-
|
488 |
-
if ( $dimensions ) {
|
489 |
-
$image->meta_data['width'] = $dimensions['width'];
|
490 |
-
$image->meta_data['height'] = $dimensions['height'];
|
491 |
-
$image->meta_data['full']['width'] = $dimensions['width'];
|
492 |
-
$image->meta_data['full']['height'] = $dimensions['height'];
|
493 |
-
}
|
494 |
-
|
495 |
-
if ( $md5 ) {
|
496 |
-
$image->meta_data['md5'] = $md5;
|
497 |
-
$image->meta_data['full']['md5'] = $md5;
|
498 |
-
}
|
499 |
-
|
500 |
-
$storage->_image_mapper->save( $image );
|
501 |
-
}
|
502 |
-
|
503 |
$this->delete_running_status();
|
504 |
|
505 |
return $data;
|
@@ -517,9 +555,8 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
517 |
* @return array $data The optimization data.
|
518 |
*/
|
519 |
public function optimize_thumbnails( $optimization_level = null, $data = array() ) {
|
520 |
-
$
|
521 |
-
$
|
522 |
-
$data = $data ? $data : $this->get_data();
|
523 |
|
524 |
// Stop if the original image has an error.
|
525 |
if ( $this->has_error() ) {
|
@@ -531,20 +568,23 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
531 |
/**
|
532 |
* Fires before optimizing all thumbnails.
|
533 |
*
|
534 |
-
* @since
|
|
|
535 |
*
|
536 |
* @param int $id The image ID.
|
537 |
-
|
538 |
do_action( 'before_imagify_ngg_optimize_thumbnails', $this->id );
|
539 |
|
540 |
if ( $sizes ) {
|
|
|
|
|
541 |
foreach ( $sizes as $size_key ) {
|
542 |
if ( 'full' === $size_key || isset( $data['sizes'][ $size_key ]['success'] ) ) {
|
543 |
continue;
|
544 |
}
|
545 |
|
546 |
-
$thumbnail_path = $storage->get_image_abspath( $
|
547 |
-
$thumbnail_url = $storage->get_image_url( $
|
548 |
|
549 |
// Optimize the thumbnail size.
|
550 |
$response = do_imagify( $thumbnail_path, array(
|
@@ -557,19 +597,20 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
557 |
$data = $this->fill_data( $data, $response, $size_key );
|
558 |
|
559 |
/**
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
|
|
573 |
$data = apply_filters( 'imagify_fill_ngg_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level );
|
574 |
}
|
575 |
|
@@ -581,16 +622,100 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
581 |
/**
|
582 |
* Fires after optimizing all thumbnails.
|
583 |
*
|
584 |
-
* @since
|
|
|
585 |
*
|
586 |
* @param int $id The image ID.
|
587 |
* @param array $data The optimization data.
|
588 |
-
|
589 |
do_action( 'after_imagify_ngg_optimize_thumbnails', $this->id, $data );
|
590 |
|
591 |
return $data;
|
592 |
}
|
593 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
/**
|
595 |
* Re-optimize the given thumbnail sizes to the same level.
|
596 |
* This is not used in this context.
|
@@ -626,18 +751,17 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
626 |
return new WP_Error( 'no_backup', __( 'Backup image not found.', 'imagify' ) );
|
627 |
}
|
628 |
|
629 |
-
$
|
630 |
-
$image = $storage->_image_mapper->find( $this->id );
|
631 |
|
632 |
-
if ( ! $
|
633 |
return new WP_Error( 'no_image', __( 'Image not found in NextGen Gallery data.', 'imagify' ) );
|
634 |
}
|
635 |
|
636 |
/**
|
637 |
* Make some more tests before restoring the backup.
|
638 |
*/
|
639 |
-
$full_abspath = $storage->get_image_abspath( $
|
640 |
-
$backup_abspath = $storage->get_image_abspath( $
|
641 |
|
642 |
if ( $backup_abspath === $full_abspath ) {
|
643 |
return new WP_Error( 'same_path', __( 'Image path and backup path are identical.', 'imagify' ) );
|
@@ -650,10 +774,11 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
650 |
/**
|
651 |
* Fires before restoring an attachment.
|
652 |
*
|
653 |
-
* @since
|
|
|
654 |
*
|
655 |
* @param int $id The attachment ID.
|
656 |
-
|
657 |
do_action( 'before_imagify_ngg_restore_attachment', $this->id );
|
658 |
|
659 |
if ( ! $this->filesystem->copy( $backup_abspath, $full_abspath, true, FS_CHMOD_FILE ) ) {
|
@@ -717,7 +842,7 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
717 |
|
718 |
// 4- Common meta data.
|
719 |
require_once( NGGALLERY_ABSPATH . '/lib/meta.php' );
|
720 |
-
$meta_obj = new nggMeta( $
|
721 |
$common_data = $meta_obj->get_common_meta();
|
722 |
|
723 |
if ( $common_data ) {
|
@@ -738,9 +863,9 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
738 |
'keywords' => '',
|
739 |
);
|
740 |
|
741 |
-
if ( ! empty( $
|
742 |
-
$
|
743 |
-
$common_data
|
744 |
}
|
745 |
}
|
746 |
|
@@ -751,15 +876,15 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
751 |
*/
|
752 |
$failed = array();
|
753 |
|
754 |
-
foreach ( $
|
755 |
if ( 'full' === $named_size ) {
|
756 |
continue;
|
757 |
}
|
758 |
|
759 |
-
$params = $storage->get_image_size_params( $
|
760 |
-
$thumbnail = $storage->generate_image_clone(
|
761 |
$backup_abspath,
|
762 |
-
$storage->get_image_abspath( $
|
763 |
$params
|
764 |
);
|
765 |
|
@@ -790,14 +915,18 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
790 |
$thumbnails_data[ $named_size ] = $size_meta;
|
791 |
} // End foreach().
|
792 |
|
793 |
-
do_action( 'ngg_recovered_image', $
|
794 |
|
795 |
/**
|
796 |
* Save the meta data.
|
797 |
*/
|
798 |
-
$
|
|
|
|
|
|
|
|
|
799 |
|
800 |
-
$post_id = $storage->_image_mapper->save( $
|
801 |
|
802 |
if ( ! $post_id ) {
|
803 |
return new WP_Error( 'meta_data_not_saved', __( 'Related data could not be saved.', 'imagify' ) );
|
@@ -814,12 +943,62 @@ class Imagify_NGG_Attachment extends Imagify_Attachment {
|
|
814 |
/**
|
815 |
* Fires after restoring an attachment.
|
816 |
*
|
817 |
-
* @since
|
|
|
818 |
*
|
819 |
* @param int $id The attachment ID.
|
820 |
-
|
821 |
do_action( 'after_imagify_ngg_restore_attachment', $this->id );
|
822 |
|
823 |
return true;
|
824 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
825 |
}
|
14 |
*
|
15 |
* @var string
|
16 |
*/
|
17 |
+
const VERSION = '1.4';
|
18 |
|
19 |
/**
|
20 |
* The attachment SQL DB class.
|
31 |
* @var object A nggImage object.
|
32 |
* @since 1.5
|
33 |
* @since 1.7 Not public anymore.
|
34 |
+
* @access protected
|
35 |
*/
|
36 |
protected $image;
|
37 |
|
38 |
+
/**
|
39 |
+
* The storage object used by NGG.
|
40 |
+
*
|
41 |
+
* @var object A C_Gallery_Storage object (by default).
|
42 |
+
* @since 1.8.
|
43 |
+
* @access protected
|
44 |
+
*/
|
45 |
+
protected $storage;
|
46 |
+
|
47 |
/**
|
48 |
* Tell if the file mime type can be optimized by Imagify.
|
49 |
*
|
65 |
*/
|
66 |
public function __construct( $id ) {
|
67 |
if ( is_object( $id ) ) {
|
68 |
+
if ( $id instanceof nggImage ) {
|
69 |
+
$this->image = $id;
|
70 |
+
$this->id = (int) $id->pid;
|
71 |
+
} else {
|
72 |
+
$this->image = nggdb::find_image( (int) $id->pid );
|
73 |
+
$this->id = ! empty( $this->image->pid ) ? (int) $this->image->pid : 0;
|
74 |
+
}
|
75 |
} else {
|
76 |
$this->image = nggdb::find_image( absint( $id ) );
|
77 |
$this->id = ! empty( $this->image->pid ) ? (int) $this->image->pid : 0;
|
79 |
|
80 |
$this->get_row();
|
81 |
|
82 |
+
if ( ! empty( $this->image->_ngiw ) ) {
|
83 |
+
$this->storage = $this->image->_ngiw->get_storage()->object;
|
84 |
+
} else {
|
85 |
+
$this->storage = C_Gallery_Storage::get_instance()->object;
|
86 |
+
}
|
87 |
+
|
88 |
$this->filesystem = Imagify_Filesystem::get_instance();
|
89 |
$this->optimization_state_transient = 'imagify-ngg-async-in-progress-' . $this->id;
|
90 |
|
92 |
$ngg_admin_functions_path = WP_PLUGIN_DIR . '/' . NGGFOLDER . '/products/photocrati_nextgen/modules/ngglegacy/admin/functions.php';
|
93 |
|
94 |
if ( ! class_exists( 'nggAdmin' ) && $this->filesystem->exists( $ngg_admin_functions_path ) ) {
|
95 |
+
require_once $ngg_admin_functions_path;
|
96 |
}
|
97 |
}
|
98 |
|
205 |
return isset( $row['status'] ) ? $row['status'] : false;
|
206 |
}
|
207 |
|
208 |
+
/**
|
209 |
+
* Delete the data related to optimization.
|
210 |
+
*
|
211 |
+
* @since 1.7
|
212 |
+
* @access public
|
213 |
+
* @author Grégory Viguier
|
214 |
+
*/
|
215 |
+
public function delete_imagify_data() {
|
216 |
+
if ( ! $this->get_row() ) {
|
217 |
+
return;
|
218 |
+
}
|
219 |
+
|
220 |
+
$this->delete_row();
|
221 |
+
}
|
222 |
+
|
223 |
/**
|
224 |
* Get width and height of the original image.
|
225 |
*
|
237 |
}
|
238 |
|
239 |
/**
|
240 |
+
* Get the file mime type + file extension (if the file is supported).
|
241 |
*
|
242 |
+
* @since 1.8
|
243 |
* @access public
|
244 |
+
* @see wp_check_filetype()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
* @author Grégory Viguier
|
246 |
*
|
247 |
+
* @return object
|
248 |
*/
|
249 |
+
public function get_file_type() {
|
250 |
+
if ( isset( $this->file_type ) ) {
|
251 |
+
return $this->file_type;
|
252 |
}
|
253 |
|
254 |
+
if ( ! $this->is_valid() ) {
|
255 |
+
$this->file_type = (object) array( 'ext' => '', 'type' => '' );
|
256 |
+
return $this->file_type;
|
|
|
|
|
257 |
}
|
258 |
|
259 |
+
$this->file_type = (object) wp_check_filetype( $this->get_original_path(), imagify_get_mime_types( 'image' ) );
|
|
|
260 |
|
261 |
+
return $this->file_type;
|
|
|
262 |
}
|
263 |
|
264 |
/**
|
273 |
static $sizes;
|
274 |
|
275 |
if ( ! isset( $sizes ) ) {
|
276 |
+
$sizes = $this->get_image_sizes();
|
277 |
}
|
278 |
|
279 |
return $sizes && $this->get_original_path();
|
290 |
public function update_metadata_size() {
|
291 |
$size = $this->filesystem->get_image_size( $this->get_original_path() );
|
292 |
|
293 |
+
if ( ! $size ) {
|
294 |
+
return;
|
|
|
|
|
|
|
|
|
|
|
295 |
}
|
296 |
+
|
297 |
+
$this->image->meta_data['width'] = $size['width'];
|
298 |
+
$this->image->meta_data['height'] = $size['height'];
|
299 |
+
$this->image->meta_data['full']['width'] = $size['width'];
|
300 |
+
$this->image->meta_data['full']['height'] = $size['height'];
|
301 |
+
|
302 |
+
nggdb::update_image_meta( $this->id, $this->image->meta_data );
|
303 |
}
|
304 |
|
305 |
/**
|
433 |
|
434 |
// Get file path for original image.
|
435 |
$attachment_path = $this->get_original_path();
|
436 |
+
$attachment_url = $this->get_original_url();
|
437 |
|
438 |
/**
|
439 |
* Fires before optimizing an attachment.
|
440 |
*
|
441 |
+
* @since 1.5
|
442 |
+
* @author Jonathan Buttigieg
|
443 |
*
|
444 |
+
* @param int $id The image ID
|
445 |
+
*/
|
446 |
do_action( 'before_imagify_ngg_optimize_attachment', $this->id );
|
447 |
|
448 |
$this->set_running_status();
|
458 |
|
459 |
$data = $this->fill_data( null, $response );
|
460 |
|
461 |
+
/**
|
462 |
+
* Filter the optimization data of the full size.
|
463 |
+
*
|
464 |
+
* @since 1.8
|
465 |
+
* @author Grégory Viguier
|
466 |
+
*
|
467 |
+
* @param array $data The statistics data.
|
468 |
+
* @param object $response The API response.
|
469 |
+
* @param int $id The attachment ID.
|
470 |
+
* @param string $attachment_path The attachment path.
|
471 |
+
* @param string $attachment_url The attachment URL.
|
472 |
+
* @param string $size_key The attachment size key. The value is obviously 'full' but it's kept for concistancy with other filters.
|
473 |
+
* @param int $optimization_level The optimization level.
|
474 |
+
*/
|
475 |
+
$data = apply_filters( 'imagify_fill_ngg_full_size_data', $data, $response, $this->id, $attachment_path, $attachment_url, 'full', $optimization_level );
|
476 |
+
|
477 |
// Save the optimization level.
|
478 |
$this->update_row( array(
|
479 |
// The pid column is needed in case the row doesn't exist yet.
|
482 |
) );
|
483 |
|
484 |
if ( ! $data ) {
|
485 |
+
// Error or already optimized.
|
486 |
$this->delete_running_status();
|
487 |
return;
|
488 |
}
|
495 |
'status' => 'success',
|
496 |
) );
|
497 |
|
498 |
+
/**
|
499 |
+
* Update NGG meta data.
|
500 |
+
*/
|
501 |
+
$image_data = $this->storage->_image_mapper->find( $this->id );
|
502 |
+
|
503 |
+
if ( ! $image_data ) {
|
504 |
+
$this->delete_running_status();
|
505 |
+
return $data;
|
506 |
+
}
|
507 |
+
|
508 |
+
$dimensions = $this->filesystem->get_image_size( $attachment_path );
|
509 |
+
$md5 = md5_file( $attachment_path );
|
510 |
+
|
511 |
+
if ( ( $dimensions || $md5 ) && ( empty( $image_data->meta_data['full'] ) || ! is_array( $image_data->meta_data['full'] ) ) ) {
|
512 |
+
$image_data->meta_data['full'] = array(
|
513 |
+
'width' => 0,
|
514 |
+
'height' => 0,
|
515 |
+
'md5' => '',
|
516 |
+
);
|
517 |
+
}
|
518 |
+
|
519 |
+
if ( $dimensions ) {
|
520 |
+
$image_data->meta_data['width'] = $dimensions['width'];
|
521 |
+
$image_data->meta_data['height'] = $dimensions['height'];
|
522 |
+
$image_data->meta_data['full']['width'] = $dimensions['width'];
|
523 |
+
$image_data->meta_data['full']['height'] = $dimensions['height'];
|
524 |
+
}
|
525 |
+
|
526 |
+
if ( $md5 ) {
|
527 |
+
$image_data->meta_data['md5'] = $md5;
|
528 |
+
$image_data->meta_data['full']['md5'] = $md5;
|
529 |
+
}
|
530 |
+
|
531 |
/**
|
532 |
* Fires after optimizing an attachment.
|
533 |
*
|
538 |
*/
|
539 |
do_action( 'after_imagify_ngg_optimize_attachment', $this->id, $data );
|
540 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
$this->delete_running_status();
|
542 |
|
543 |
return $data;
|
555 |
* @return array $data The optimization data.
|
556 |
*/
|
557 |
public function optimize_thumbnails( $optimization_level = null, $data = array() ) {
|
558 |
+
$sizes = $this->get_image_sizes();
|
559 |
+
$data = $data ? $data : $this->get_data();
|
|
|
560 |
|
561 |
// Stop if the original image has an error.
|
562 |
if ( $this->has_error() ) {
|
568 |
/**
|
569 |
* Fires before optimizing all thumbnails.
|
570 |
*
|
571 |
+
* @since 1.5
|
572 |
+
* @author Jonathan Buttigieg
|
573 |
*
|
574 |
* @param int $id The image ID.
|
575 |
+
*/
|
576 |
do_action( 'before_imagify_ngg_optimize_thumbnails', $this->id );
|
577 |
|
578 |
if ( $sizes ) {
|
579 |
+
$image_data = $this->storage->_image_mapper->find( $this->id );
|
580 |
+
|
581 |
foreach ( $sizes as $size_key ) {
|
582 |
if ( 'full' === $size_key || isset( $data['sizes'][ $size_key ]['success'] ) ) {
|
583 |
continue;
|
584 |
}
|
585 |
|
586 |
+
$thumbnail_path = $this->storage->get_image_abspath( $image_data, $size_key );
|
587 |
+
$thumbnail_url = $this->storage->get_image_url( $image_data, $size_key );
|
588 |
|
589 |
// Optimize the thumbnail size.
|
590 |
$response = do_imagify( $thumbnail_path, array(
|
597 |
$data = $this->fill_data( $data, $response, $size_key );
|
598 |
|
599 |
/**
|
600 |
+
* Filter the optimization data of a specific thumbnail.
|
601 |
+
*
|
602 |
+
* @since 1.5
|
603 |
+
* @author Jonathan Buttigieg
|
604 |
+
*
|
605 |
+
* @param array $data The statistics data.
|
606 |
+
* @param object $response The API response.
|
607 |
+
* @param int $id The image ID.
|
608 |
+
* @param string $thumbnail_path The image path.
|
609 |
+
* @param string $thumbnail_url The image URL.
|
610 |
+
* @param string $size_key The image size key.
|
611 |
+
* @param bool $is_aggressive The optimization level.
|
612 |
+
* @return array $data The new optimization data.
|
613 |
+
*/
|
614 |
$data = apply_filters( 'imagify_fill_ngg_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level );
|
615 |
}
|
616 |
|
622 |
/**
|
623 |
* Fires after optimizing all thumbnails.
|
624 |
*
|
625 |
+
* @since 1.5
|
626 |
+
* @author Jonathan Buttigieg
|
627 |
*
|
628 |
* @param int $id The image ID.
|
629 |
* @param array $data The optimization data.
|
630 |
+
*/
|
631 |
do_action( 'after_imagify_ngg_optimize_thumbnails', $this->id, $data );
|
632 |
|
633 |
return $data;
|
634 |
}
|
635 |
|
636 |
+
/**
|
637 |
+
* Optimize one size.
|
638 |
+
*
|
639 |
+
* @since 1.8
|
640 |
+
* @access public
|
641 |
+
* @author Grégory Viguier
|
642 |
+
*
|
643 |
+
* @param string $size The thumbnail size.
|
644 |
+
*/
|
645 |
+
public function optimize_new_thumbnail( $size ) {
|
646 |
+
// Check if the attachment extension is allowed.
|
647 |
+
if ( ! $this->is_extension_supported() ) {
|
648 |
+
return;
|
649 |
+
}
|
650 |
+
|
651 |
+
if ( ! $this->is_optimized() ) {
|
652 |
+
// The main image is not optimized.
|
653 |
+
return;
|
654 |
+
}
|
655 |
+
|
656 |
+
$data = $this->get_data();
|
657 |
+
|
658 |
+
if ( isset( $data['sizes'][ $size ]['success'] ) ) {
|
659 |
+
// This thumbnail has already been processed.
|
660 |
+
return;
|
661 |
+
}
|
662 |
+
|
663 |
+
$sizes = $this->get_image_sizes();
|
664 |
+
$sizes = array_flip( $sizes );
|
665 |
+
|
666 |
+
if ( ! isset( $sizes[ $size ] ) ) {
|
667 |
+
// This size doesn't exist.
|
668 |
+
return;
|
669 |
+
}
|
670 |
+
|
671 |
+
/**
|
672 |
+
* Fires before optimizing a thumbnail.
|
673 |
+
*
|
674 |
+
* @since 1.8
|
675 |
+
* @author Grégory Viguier
|
676 |
+
*
|
677 |
+
* @param int $id The image ID.
|
678 |
+
*/
|
679 |
+
do_action( 'before_imagify_ngg_optimize_new_thumbnail', $this->id );
|
680 |
+
|
681 |
+
$this->set_running_status();
|
682 |
+
|
683 |
+
$image_data = $this->storage->_image_mapper->find( $this->id );
|
684 |
+
$thumbnail_path = $this->storage->get_image_abspath( $image_data, $size );
|
685 |
+
$thumbnail_url = $this->storage->get_image_url( $image_data, $size );
|
686 |
+
$optimization_level = $this->get_optimization_level();
|
687 |
+
|
688 |
+
// Optimize the thumbnail size.
|
689 |
+
$response = do_imagify( $thumbnail_path, array(
|
690 |
+
'optimization_level' => $optimization_level,
|
691 |
+
'context' => 'NGG',
|
692 |
+
'keep_exif' => true,
|
693 |
+
'backup' => false,
|
694 |
+
) );
|
695 |
+
|
696 |
+
$data = $this->fill_data( $data, $response, $size );
|
697 |
+
|
698 |
+
/** This filter is documented in inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-attachment.php. */
|
699 |
+
$data = apply_filters( 'imagify_fill_ngg_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size, $optimization_level );
|
700 |
+
|
701 |
+
$this->update_row( array(
|
702 |
+
'data' => $data,
|
703 |
+
) );
|
704 |
+
|
705 |
+
/**
|
706 |
+
* Fires after optimizing a thumbnail.
|
707 |
+
*
|
708 |
+
* @since 1.8
|
709 |
+
* @author Grégory Viguier
|
710 |
+
*
|
711 |
+
* @param int $id The image ID.
|
712 |
+
* @param array $data The optimization data.
|
713 |
+
*/
|
714 |
+
do_action( 'after_imagify_ngg_optimize_new_thumbnail', $this->id, $data );
|
715 |
+
|
716 |
+
$this->delete_running_status();
|
717 |
+
}
|
718 |
+
|
719 |
/**
|
720 |
* Re-optimize the given thumbnail sizes to the same level.
|
721 |
* This is not used in this context.
|
751 |
return new WP_Error( 'no_backup', __( 'Backup image not found.', 'imagify' ) );
|
752 |
}
|
753 |
|
754 |
+
$image_data = $this->storage->_image_mapper->find( $this->id );
|
|
|
755 |
|
756 |
+
if ( ! $image_data ) {
|
757 |
return new WP_Error( 'no_image', __( 'Image not found in NextGen Gallery data.', 'imagify' ) );
|
758 |
}
|
759 |
|
760 |
/**
|
761 |
* Make some more tests before restoring the backup.
|
762 |
*/
|
763 |
+
$full_abspath = $this->storage->get_image_abspath( $image_data );
|
764 |
+
$backup_abspath = $this->storage->get_image_abspath( $image_data, 'backup' );
|
765 |
|
766 |
if ( $backup_abspath === $full_abspath ) {
|
767 |
return new WP_Error( 'same_path', __( 'Image path and backup path are identical.', 'imagify' ) );
|
774 |
/**
|
775 |
* Fires before restoring an attachment.
|
776 |
*
|
777 |
+
* @since 1.5
|
778 |
+
* @author Jonathan Buttigieg
|
779 |
*
|
780 |
* @param int $id The attachment ID.
|
781 |
+
*/
|
782 |
do_action( 'before_imagify_ngg_restore_attachment', $this->id );
|
783 |
|
784 |
if ( ! $this->filesystem->copy( $backup_abspath, $full_abspath, true, FS_CHMOD_FILE ) ) {
|
842 |
|
843 |
// 4- Common meta data.
|
844 |
require_once( NGGALLERY_ABSPATH . '/lib/meta.php' );
|
845 |
+
$meta_obj = new nggMeta( $image_data );
|
846 |
$common_data = $meta_obj->get_common_meta();
|
847 |
|
848 |
if ( $common_data ) {
|
863 |
'keywords' => '',
|
864 |
);
|
865 |
|
866 |
+
if ( ! empty( $image_data->meta_data ) && is_array( $image_data->meta_data ) ) {
|
867 |
+
$image_data->meta_data = array_merge( $common_data, $image_data->meta_data );
|
868 |
+
$common_data = array_intersect_key( $image_data->meta_data, $common_data );
|
869 |
}
|
870 |
}
|
871 |
|
876 |
*/
|
877 |
$failed = array();
|
878 |
|
879 |
+
foreach ( $this->get_image_sizes() as $named_size ) {
|
880 |
if ( 'full' === $named_size ) {
|
881 |
continue;
|
882 |
}
|
883 |
|
884 |
+
$params = $this->storage->get_image_size_params( $image_data, $named_size );
|
885 |
+
$thumbnail = $this->storage->generate_image_clone(
|
886 |
$backup_abspath,
|
887 |
+
$this->storage->get_image_abspath( $image_data, $named_size ),
|
888 |
$params
|
889 |
);
|
890 |
|
915 |
$thumbnails_data[ $named_size ] = $size_meta;
|
916 |
} // End foreach().
|
917 |
|
918 |
+
do_action( 'ngg_recovered_image', $image_data );
|
919 |
|
920 |
/**
|
921 |
* Save the meta data.
|
922 |
*/
|
923 |
+
$image_data->meta_data = array_merge( $backup_data, $full_data, $thumbnails_data, $common_data );
|
924 |
+
|
925 |
+
// Keep our property up to date.
|
926 |
+
$this->image->_ngiw->_cache['meta_data'] = $image_data->meta_data;
|
927 |
+
$this->image->_ngiw->_orig_image = $image_data;
|
928 |
|
929 |
+
$post_id = $this->storage->_image_mapper->save( $image_data );
|
930 |
|
931 |
if ( ! $post_id ) {
|
932 |
return new WP_Error( 'meta_data_not_saved', __( 'Related data could not be saved.', 'imagify' ) );
|
943 |
/**
|
944 |
* Fires after restoring an attachment.
|
945 |
*
|
946 |
+
* @since 1.5
|
947 |
+
* @author Jonathan Buttigieg
|
948 |
*
|
949 |
* @param int $id The attachment ID.
|
950 |
+
*/
|
951 |
do_action( 'after_imagify_ngg_restore_attachment', $this->id );
|
952 |
|
953 |
return true;
|
954 |
}
|
955 |
+
|
956 |
+
/**
|
957 |
+
* Get the image sizes.
|
958 |
+
*
|
959 |
+
* @since 1.8
|
960 |
+
* @access public
|
961 |
+
* @author Grégory Viguier
|
962 |
+
*
|
963 |
+
* @return array
|
964 |
+
*/
|
965 |
+
public function get_image_sizes() {
|
966 |
+
$sizes = array(
|
967 |
+
'full',
|
968 |
+
);
|
969 |
+
|
970 |
+
// Remove common values (that have no value for us here, lol).
|
971 |
+
$image_data = array_diff_key( $this->image->meta_data, array(
|
972 |
+
'backup' => 1,
|
973 |
+
'width' => 1,
|
974 |
+
'height' => 1,
|
975 |
+
'md5' => 1,
|
976 |
+
'full' => 1,
|
977 |
+
'aperture' => 1,
|
978 |
+
'credit' => 1,
|
979 |
+
'camera' => 1,
|
980 |
+
'caption' => 1,
|
981 |
+
'created_timestamp' => 1,
|
982 |
+
'copyright' => 1,
|
983 |
+
'focal_length' => 1,
|
984 |
+
'iso' => 1,
|
985 |
+
'shutter_speed' => 1,
|
986 |
+
'flash' => 1,
|
987 |
+
'title' => 1,
|
988 |
+
'keywords' => 1,
|
989 |
+
'saved' => 1,
|
990 |
+
) );
|
991 |
+
|
992 |
+
if ( ! $image_data ) {
|
993 |
+
return $sizes;
|
994 |
+
}
|
995 |
+
|
996 |
+
foreach ( $image_data as $size_name => $size_data ) {
|
997 |
+
if ( isset( $size_data['width'], $size_data['height'], $size_data['filename'], $size_data['generated'] ) ) {
|
998 |
+
$sizes[] = $size_name;
|
999 |
+
}
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
return $sizes;
|
1003 |
+
}
|
1004 |
}
|
inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-db.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/classes/class-imagify-ngg-dynamic-thumbnails-background-process.php
ADDED
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class that handles background processing of thumbnails dynamically generated.
|
6 |
+
*
|
7 |
+
* @since 1.8
|
8 |
+
* @author Grégory Viguier
|
9 |
+
*/
|
10 |
+
class Imagify_NGG_Dynamic_Thumbnails_Background_Process extends WP_Background_Process {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class version.
|
14 |
+
*
|
15 |
+
* @var string
|
16 |
+
* @since 1.8
|
17 |
+
* @author Grégory Viguier
|
18 |
+
*/
|
19 |
+
const VERSION = '1.0';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Prefix used to build the global process identifier.
|
23 |
+
*
|
24 |
+
* @var string
|
25 |
+
* @since 1.8
|
26 |
+
* @access protected
|
27 |
+
* @author Grégory Viguier
|
28 |
+
*/
|
29 |
+
protected $prefix = 'imagify';
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Action.
|
33 |
+
*
|
34 |
+
* @var string
|
35 |
+
* @since 1.8
|
36 |
+
* @access protected
|
37 |
+
* @author Grégory Viguier
|
38 |
+
*/
|
39 |
+
protected $action = 'ngg_dynamic_thumbnails';
|
40 |
+
|
41 |
+
/**
|
42 |
+
* The single instance of the class.
|
43 |
+
*
|
44 |
+
* @var object
|
45 |
+
* @since 1.8
|
46 |
+
* @access protected
|
47 |
+
* @author Grégory Viguier
|
48 |
+
*/
|
49 |
+
protected static $_instance;
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Get the main Instance.
|
54 |
+
*
|
55 |
+
* @since 1.8
|
56 |
+
* @access public
|
57 |
+
* @author Grégory Viguier
|
58 |
+
*
|
59 |
+
* @return object Main instance.
|
60 |
+
*/
|
61 |
+
public static function get_instance() {
|
62 |
+
if ( ! isset( self::$_instance ) ) {
|
63 |
+
self::$_instance = new self();
|
64 |
+
}
|
65 |
+
|
66 |
+
return self::$_instance;
|
67 |
+
}
|
68 |
+
|
69 |
+
|
70 |
+
/** ----------------------------------------------------------------------------------------- */
|
71 |
+
/** BACKGROUND PROCESS ====================================================================== */
|
72 |
+
/** ----------------------------------------------------------------------------------------- */
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Push to queue.
|
76 |
+
*
|
77 |
+
* @since 1.8
|
78 |
+
* @access public
|
79 |
+
* @author Grégory Viguier
|
80 |
+
*
|
81 |
+
* @param array $data {
|
82 |
+
* The data to push in queue.
|
83 |
+
*
|
84 |
+
* @type int $id The image ID. Required.
|
85 |
+
* @type string $size The thumbnail size. Required.
|
86 |
+
* }
|
87 |
+
* @return object Class instance.
|
88 |
+
*/
|
89 |
+
public function push_to_queue( $data ) {
|
90 |
+
$key = $data['id'] . '|' . $data['size'];
|
91 |
+
|
92 |
+
$this->data[ $key ] = $data;
|
93 |
+
|
94 |
+
return $this;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Dispatch.
|
99 |
+
*
|
100 |
+
* @since 1.8
|
101 |
+
* @access public
|
102 |
+
* @author Grégory Viguier
|
103 |
+
*
|
104 |
+
* @return array|WP_Error
|
105 |
+
*/
|
106 |
+
public function dispatch() {
|
107 |
+
if ( ! empty( $this->data ) ) {
|
108 |
+
return parent::dispatch();
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Tell if a task is already in the queue.
|
114 |
+
*
|
115 |
+
* @since 1.8
|
116 |
+
* @access public
|
117 |
+
* @author Grégory Viguier
|
118 |
+
*
|
119 |
+
* @param array $data {
|
120 |
+
* The data to test against the queue.
|
121 |
+
*
|
122 |
+
* @type int $id The image ID. Required.
|
123 |
+
* @type string $size The thumbnail size. Required.
|
124 |
+
* }
|
125 |
+
* @return bool
|
126 |
+
*/
|
127 |
+
public function is_in_queue( $data ) {
|
128 |
+
$key = $data['id'] . '|' . $data['size'];
|
129 |
+
|
130 |
+
return isset( $this->data[ $key ] );
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Task: optimize the thumbnail.
|
135 |
+
*
|
136 |
+
* @since 1.8
|
137 |
+
* @access public
|
138 |
+
* @author Grégory Viguier
|
139 |
+
*
|
140 |
+
* @param array $item {
|
141 |
+
* The data to test against the queue.
|
142 |
+
*
|
143 |
+
* @type int $id The image ID. Required.
|
144 |
+
* @type string $size The thumbnail size. Required.
|
145 |
+
* }
|
146 |
+
* @return bool False to remove the item from the queue.
|
147 |
+
*/
|
148 |
+
protected function task( $item ) {
|
149 |
+
$attachment_id = absint( $item['id'] );
|
150 |
+
$size = sanitize_text_field( $item['size'] );
|
151 |
+
|
152 |
+
if ( ! $attachment_id || ! $size ) {
|
153 |
+
return false;
|
154 |
+
}
|
155 |
+
|
156 |
+
$attachment = get_imagify_attachment( 'NGG', $attachment_id, 'ngg_optimize_dynamic_thumbnail' );
|
157 |
+
|
158 |
+
$attachment->optimize_new_thumbnail( $size );
|
159 |
+
|
160 |
+
return false;
|
161 |
+
}
|
162 |
+
}
|
inc/3rd-party/nextgen-gallery/inc/common/attachments.php
CHANGED
@@ -66,7 +66,7 @@ add_filter( 'ngg_medialibrary_imported_image', '_imagify_ngg_media_library_impor
|
|
66 |
function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
|
67 |
$attachment = get_imagify_attachment( 'wp', $attachment->ID, 'ngg_medialibrary_imported_image' );
|
68 |
|
69 |
-
if ( ! $attachment->
|
70 |
// The image is not optimized.
|
71 |
return $image;
|
72 |
}
|
@@ -108,6 +108,63 @@ function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
|
|
108 |
return $image;
|
109 |
}
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
/**
|
112 |
* Delete the Imagify data when an image is deleted.
|
113 |
*
|
66 |
function _imagify_ngg_media_library_imported_image_data( $image, $attachment ) {
|
67 |
$attachment = get_imagify_attachment( 'wp', $attachment->ID, 'ngg_medialibrary_imported_image' );
|
68 |
|
69 |
+
if ( ! $attachment->is_optimized() ) {
|
70 |
// The image is not optimized.
|
71 |
return $image;
|
72 |
}
|
108 |
return $image;
|
109 |
}
|
110 |
|
111 |
+
add_action( 'ngg_generated_image', 'imagify_ngg_maybe_add_dynamic_thumbnail_to_background_process', IMAGIFY_INT_MAX, 2 );
|
112 |
+
/**
|
113 |
+
* Add a dynamically generated thumbnail to the background process queue.
|
114 |
+
*
|
115 |
+
* @since 1.8
|
116 |
+
* @author Grégory Viguier
|
117 |
+
*
|
118 |
+
* @param object $image A NGG image object.
|
119 |
+
* @param string $size The thumbnail size name.
|
120 |
+
*/
|
121 |
+
function imagify_ngg_maybe_add_dynamic_thumbnail_to_background_process( $image, $size ) {
|
122 |
+
static $done = false;
|
123 |
+
|
124 |
+
$attachment = get_imagify_attachment( 'NGG', $image, 'ngg_maybe_add_dynamic_thumbnail_to_background_process' );
|
125 |
+
|
126 |
+
if ( ! $attachment->is_optimized() ) {
|
127 |
+
// The main image is not optimized.
|
128 |
+
return;
|
129 |
+
}
|
130 |
+
|
131 |
+
$data = $attachment->get_data();
|
132 |
+
|
133 |
+
if ( isset( $data['sizes'][ $size ]['success'] ) ) {
|
134 |
+
// This thumbnail has already been processed.
|
135 |
+
return;
|
136 |
+
}
|
137 |
+
|
138 |
+
$process = Imagify_NGG_Dynamic_Thumbnails_Background_Process::get_instance();
|
139 |
+
$data = array(
|
140 |
+
'id' => $attachment->get_id(),
|
141 |
+
'size' => $size,
|
142 |
+
);
|
143 |
+
|
144 |
+
if ( $process->is_in_queue( $data ) ) {
|
145 |
+
// Duplicate.
|
146 |
+
return;
|
147 |
+
}
|
148 |
+
|
149 |
+
// Do the optimization asynchroniously.
|
150 |
+
$process->push_to_queue( $data );
|
151 |
+
|
152 |
+
if ( ! $done ) {
|
153 |
+
$done = true;
|
154 |
+
add_action( 'shutdown', 'imagify_ngg_dispatch_dynamic_thumbnail_background_process' );
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Dispatch the optimization process.
|
160 |
+
*
|
161 |
+
* @since 1.8
|
162 |
+
* @author Grégory Viguier
|
163 |
+
*/
|
164 |
+
function imagify_ngg_dispatch_dynamic_thumbnail_background_process() {
|
165 |
+
Imagify_NGG_Dynamic_Thumbnails_Background_Process::get_instance()->save()->dispatch();
|
166 |
+
}
|
167 |
+
|
168 |
/**
|
169 |
* Delete the Imagify data when an image is deleted.
|
170 |
*
|
inc/3rd-party/nextgen-gallery/inc/functions/admin-stats.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/functions/attachments.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/inc/functions/common.php
CHANGED
File without changes
|
inc/3rd-party/nextgen-gallery/nextgen-gallery.php
CHANGED
@@ -19,6 +19,7 @@ require( IMAGIFY_NGG_COMMON_PATH . 'attachments.php' );
|
|
19 |
|
20 |
Imagify_NGG::get_instance()->init();
|
21 |
Imagify_NGG_DB::get_instance()->init();
|
|
|
22 |
|
23 |
if ( is_admin() ) {
|
24 |
require( IMAGIFY_NGG_ADMIN_PATH . 'enqueue.php' );
|
19 |
|
20 |
Imagify_NGG::get_instance()->init();
|
21 |
Imagify_NGG_DB::get_instance()->init();
|
22 |
+
Imagify_NGG_Dynamic_Thumbnails_Background_Process::get_instance();
|
23 |
|
24 |
if ( is_admin() ) {
|
25 |
require( IMAGIFY_NGG_ADMIN_PATH . 'enqueue.php' );
|
inc/3rd-party/regenerate-thumbnails/inc/classes/class-imagify-regenerate-thumbnails.php
CHANGED
@@ -185,6 +185,10 @@ class Imagify_Regenerate_Thumbnails {
|
|
185 |
|
186 |
$attachment = get_imagify_attachment( $context, $attachment_id, self::ACTION );
|
187 |
|
|
|
|
|
|
|
|
|
188 |
// Optimize.
|
189 |
$attachment->reoptimize_thumbnails( $_POST['sizes'] );
|
190 |
|
@@ -216,7 +220,7 @@ class Imagify_Regenerate_Thumbnails {
|
|
216 |
|
217 |
$attachment = get_imagify_attachment( 'wp', $attachment_id, 'regenerate_thumbnails' );
|
218 |
|
219 |
-
if ( ! $attachment->is_valid() || ! $attachment->
|
220 |
return false;
|
221 |
}
|
222 |
|
@@ -285,7 +289,7 @@ class Imagify_Regenerate_Thumbnails {
|
|
285 |
}
|
286 |
|
287 |
/**
|
288 |
-
*
|
289 |
*
|
290 |
* @since 1.7.1
|
291 |
* @access protected
|
185 |
|
186 |
$attachment = get_imagify_attachment( $context, $attachment_id, self::ACTION );
|
187 |
|
188 |
+
if ( ! $attachment->is_valid() || ! $attachment->is_image() ) {
|
189 |
+
wp_send_json_error();
|
190 |
+
}
|
191 |
+
|
192 |
// Optimize.
|
193 |
$attachment->reoptimize_thumbnails( $_POST['sizes'] );
|
194 |
|
220 |
|
221 |
$attachment = get_imagify_attachment( 'wp', $attachment_id, 'regenerate_thumbnails' );
|
222 |
|
223 |
+
if ( ! $attachment->is_valid() || ! $attachment->is_image() || ! $attachment->is_optimized() ) {
|
224 |
return false;
|
225 |
}
|
226 |
|
289 |
}
|
290 |
|
291 |
/**
|
292 |
+
* Put the optimized full-sized file back.
|
293 |
*
|
294 |
* @since 1.7.1
|
295 |
* @access protected
|
inc/3rd-party/wp-retina-2x.php
DELETED
@@ -1,87 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
3 |
-
|
4 |
-
if ( function_exists( 'wr2x_delete_attachment' ) && function_exists( 'wr2x_generate_images' ) ) :
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Process to restore all retina versions for an attachment.
|
8 |
-
*
|
9 |
-
* @since 1.0
|
10 |
-
*/
|
11 |
-
|
12 |
-
add_action( 'before_imagify_restore_attachment', '_imagify_wr2x_delete_attachment_on_restore' );
|
13 |
-
/**
|
14 |
-
* Remove all retina versions if exists.
|
15 |
-
*
|
16 |
-
* @since 1.0
|
17 |
-
*
|
18 |
-
* @param int $attachment_id An attachment ID.
|
19 |
-
*/
|
20 |
-
function _imagify_wr2x_delete_attachment_on_restore( $attachment_id ) {
|
21 |
-
wr2x_delete_attachment( $attachment_id );
|
22 |
-
}
|
23 |
-
|
24 |
-
add_action( 'after_imagify_restore_attachment', '_imagify_wr2x_generate_images_on_restore' );
|
25 |
-
/**
|
26 |
-
* Regenerate all retina versions.
|
27 |
-
*
|
28 |
-
* @since 1.0
|
29 |
-
*
|
30 |
-
* @param int $attachment_id An attachment ID.
|
31 |
-
*/
|
32 |
-
function _imagify_wr2x_generate_images_on_restore( $attachment_id ) {
|
33 |
-
$metadata = wp_get_attachment_metadata( $attachment_id );
|
34 |
-
wr2x_generate_images( $metadata );
|
35 |
-
}
|
36 |
-
|
37 |
-
endif;
|
38 |
-
|
39 |
-
if ( function_exists( 'wr2x_get_retina' ) ) :
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Process to generate the retina version of a thumbnail.
|
43 |
-
*
|
44 |
-
* @since 1.0
|
45 |
-
*/
|
46 |
-
|
47 |
-
add_filter( 'imagify_fill_thumbnail_data', '_imagify_optimize_wr2x', 10, 7 );
|
48 |
-
/**
|
49 |
-
* Filter the optimization data of each thumbnail.
|
50 |
-
*
|
51 |
-
* @since 1.0
|
52 |
-
*
|
53 |
-
* @param array $data The statistics data.
|
54 |
-
* @param object $response The API response.
|
55 |
-
* @param int $id The attachment ID.
|
56 |
-
* @param string $path The attachment path.
|
57 |
-
* @param string $url The attachment URL.
|
58 |
-
* @param string $size_key The attachment size key.
|
59 |
-
* @param bool $optimization_level The optimization level.
|
60 |
-
* @return array $data The new optimization data.
|
61 |
-
*/
|
62 |
-
function _imagify_optimize_wr2x( $data, $response, $id, $path, $url, $size_key, $optimization_level ) {
|
63 |
-
/**
|
64 |
-
* Allow to optimize the retina version generated by WP Retina x2.
|
65 |
-
*
|
66 |
-
* @since 1.0
|
67 |
-
*
|
68 |
-
* @param bool $do_retina True will force the optimization.
|
69 |
-
*/
|
70 |
-
$do_retina = apply_filters( 'do_imagify_optimize_retina', true );
|
71 |
-
$retina_path = wr2x_get_retina( $path );
|
72 |
-
|
73 |
-
if ( empty( $retina_path ) || ! $do_retina ) {
|
74 |
-
return $data;
|
75 |
-
}
|
76 |
-
|
77 |
-
$response = do_imagify( $retina_path, array(
|
78 |
-
'backup' => false,
|
79 |
-
'optimization_level' => $optimization_level,
|
80 |
-
'context' => 'wp-retina',
|
81 |
-
) );
|
82 |
-
$attachment = get_imagify_attachment( 'wp', $id, 'imagify_fill_thumbnail_data' );
|
83 |
-
|
84 |
-
return $attachment->fill_data( $data, $response, $size_key . '@2x' );
|
85 |
-
}
|
86 |
-
|
87 |
-
endif;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/3rd-party/wp-retina-2x/inc/classes/class-imagify-wp-retina-2x-core.php
ADDED
@@ -0,0 +1,1684 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class that handles all the main tools for compatibility with WP Retina 2x plugin.
|
6 |
+
*
|
7 |
+
* @since 1.8
|
8 |
+
* @author Grégory Viguier
|
9 |
+
*/
|
10 |
+
class Imagify_WP_Retina_2x_Core {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class version.
|
14 |
+
*
|
15 |
+
* @var string
|
16 |
+
* @since 1.8
|
17 |
+
* @author Grégory Viguier
|
18 |
+
*/
|
19 |
+
const VERSION = '1.0';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Filesystem object.
|
23 |
+
*
|
24 |
+
* @var object Imagify_Filesystem
|
25 |
+
* @since 1.8
|
26 |
+
* @access protected
|
27 |
+
* @author Grégory Viguier
|
28 |
+
*/
|
29 |
+
protected $filesystem;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Used to store methods that should not run for a time being.
|
33 |
+
*
|
34 |
+
* @var array
|
35 |
+
* @since 1.8
|
36 |
+
* @access protected
|
37 |
+
* @author Grégory Viguier
|
38 |
+
*/
|
39 |
+
protected static $prevented = array();
|
40 |
+
|
41 |
+
/**
|
42 |
+
* The constructor.
|
43 |
+
*
|
44 |
+
* @since 1.8
|
45 |
+
* @access public
|
46 |
+
* @author Grégory Viguier
|
47 |
+
*/
|
48 |
+
public function __construct() {
|
49 |
+
$this->filesystem = Imagify_Filesystem::get_instance();
|
50 |
+
}
|
51 |
+
|
52 |
+
|
53 |
+
/** ----------------------------------------------------------------------------------------- */
|
54 |
+
/** GENERATE RETINA IMAGES ================================================================== */
|
55 |
+
/** ----------------------------------------------------------------------------------------- */
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Generate retina images (except full size), and optimize them if the non-retina images are.
|
59 |
+
*
|
60 |
+
* @since 1.8
|
61 |
+
* @access public
|
62 |
+
* @author Grégory Viguier
|
63 |
+
*
|
64 |
+
* @param object $attachment An Imagify attachment.
|
65 |
+
* @return bool|object True on success, false if prevented, a WP_Error object on failure.
|
66 |
+
*/
|
67 |
+
public function generate_retina_images( $attachment ) {
|
68 |
+
$tests = $this->validate( __FUNCTION__, $attachment );
|
69 |
+
|
70 |
+
if ( true !== $tests ) {
|
71 |
+
return $tests;
|
72 |
+
}
|
73 |
+
|
74 |
+
// Backup the optimized full-sized image and replace it by the original backup file, so it can be used to create new retina images.
|
75 |
+
$this->backup_optimized_file( $attachment );
|
76 |
+
|
77 |
+
if ( ! $this->filesystem->exists( $attachment->get_original_path() ) ) {
|
78 |
+
return new WP_Error( 'file_missing', 'The main file does not exist.' );
|
79 |
+
}
|
80 |
+
|
81 |
+
// Create retina images.
|
82 |
+
wr2x_generate_images( wp_get_attachment_metadata( $attachment->get_id() ) );
|
83 |
+
|
84 |
+
// Put the optimized full-sized file back.
|
85 |
+
$this->put_optimized_file_back( $attachment );
|
86 |
+
|
87 |
+
/**
|
88 |
+
* If the non-retina images are optimized by Imagify (or at least the user wanted it to be optimized at some point, and now has a "already optimized" or "error" status), optimize newly created retina files.
|
89 |
+
* If the retina version of the full size exists and is not optimized yet, it will be processed as well.
|
90 |
+
*/
|
91 |
+
if ( $attachment->is_optimized() && $this->can_auto_optimize() ) {
|
92 |
+
$this->optimize_retina_images( $attachment );
|
93 |
+
}
|
94 |
+
|
95 |
+
return true;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Delete previous retina images and recreate them (except full size), and optimize them if they previously were.
|
100 |
+
*
|
101 |
+
* @since 1.8
|
102 |
+
* @access public
|
103 |
+
* @author Grégory Viguier
|
104 |
+
*
|
105 |
+
* @param object $attachment An Imagify attachment.
|
106 |
+
* @return bool|object True on success, false if prevented, a WP_Error object on failure.
|
107 |
+
*/
|
108 |
+
public function regenerate_retina_images( $attachment ) {
|
109 |
+
$tests = $this->validate( __FUNCTION__, $attachment );
|
110 |
+
|
111 |
+
if ( true !== $tests ) {
|
112 |
+
return $tests;
|
113 |
+
}
|
114 |
+
|
115 |
+
// Delete the retina files and remove retina sizes from Imagify data.
|
116 |
+
$result = $this->delete_retina_images( $attachment );
|
117 |
+
|
118 |
+
if ( is_wp_error( $result ) ) {
|
119 |
+
return $result;
|
120 |
+
}
|
121 |
+
|
122 |
+
// Create new retina files (and optimize them if they previously were).
|
123 |
+
return $this->generate_retina_images( $attachment );
|
124 |
+
}
|
125 |
+
|
126 |
+
|
127 |
+
/** ----------------------------------------------------------------------------------------- */
|
128 |
+
/** DELETE RETINA IMAGES ==================================================================== */
|
129 |
+
/** ----------------------------------------------------------------------------------------- */
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Delete the retina images. Also removes the related Imagify data.
|
133 |
+
*
|
134 |
+
* @since 1.8
|
135 |
+
* @access public
|
136 |
+
* @author Grégory Viguier
|
137 |
+
*
|
138 |
+
* @param object $attachment An Imagify attachment.
|
139 |
+
* @param bool $delete_full_image True to also delete the retina version of the full size.
|
140 |
+
* @return bool|object True on success, false if prevented, a WP_Error object on failure.
|
141 |
+
*/
|
142 |
+
public function delete_retina_images( $attachment, $delete_full_image = false ) {
|
143 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
144 |
+
'metadata_dimensions' => 'error',
|
145 |
+
) );
|
146 |
+
|
147 |
+
if ( true !== $tests ) {
|
148 |
+
return $tests;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* To be a bit faster we update the data at once at the end.
|
153 |
+
*
|
154 |
+
* @see Imagify_WP_Retina_2x::remove_retina_thumbnail_data_hook().
|
155 |
+
*/
|
156 |
+
$this->prevent( 'remove_retina_image_data_by_filename' );
|
157 |
+
|
158 |
+
// Delete the retina thumbnails.
|
159 |
+
wr2x_delete_attachment( $attachment->get_id(), $delete_full_image );
|
160 |
+
|
161 |
+
$this->allow( 'remove_retina_image_data_by_filename' );
|
162 |
+
|
163 |
+
// Remove retina sizes from Imagify data.
|
164 |
+
$this->remove_retina_images_data( $attachment, $delete_full_image );
|
165 |
+
|
166 |
+
return true;
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Delete the retina version of the full size.
|
171 |
+
*
|
172 |
+
* @since 1.8
|
173 |
+
* @access public
|
174 |
+
* @author Grégory Viguier
|
175 |
+
*
|
176 |
+
* @param object $attachment An Imagify attachment.
|
177 |
+
* @return bool|object True on success, false if prevented, a WP_Error object on failure.
|
178 |
+
*/
|
179 |
+
public function delete_full_retina_image( $attachment ) {
|
180 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
181 |
+
'metadata_file' => false,
|
182 |
+
'metadata_sizes' => false,
|
183 |
+
) );
|
184 |
+
|
185 |
+
if ( true !== $tests ) {
|
186 |
+
return $tests;
|
187 |
+
}
|
188 |
+
|
189 |
+
$retina_path = wr2x_get_retina( $attachment->get_original_path() );
|
190 |
+
|
191 |
+
if ( $retina_path ) {
|
192 |
+
// The file exists.
|
193 |
+
$this->filesystem->delete( $retina_path );
|
194 |
+
}
|
195 |
+
|
196 |
+
// Delete related Imagify data.
|
197 |
+
return $this->remove_size_from_imagify_data( $attachment, 'full@2x' );
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
/** ----------------------------------------------------------------------------------------- */
|
202 |
+
/** REPLACE IMAGES ========================================================================== */
|
203 |
+
/** ----------------------------------------------------------------------------------------- */
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Replace an attachment (except the retina version of the full size).
|
207 |
+
*
|
208 |
+
* @since 1.8
|
209 |
+
* @access public
|
210 |
+
* @author Grégory Viguier
|
211 |
+
*
|
212 |
+
* @param object $attachment An Imagify attachment.
|
213 |
+
* @param string $file_path Path to the new file.
|
214 |
+
* @return bool|object True on success, false if prevented, a WP_Error object on failure.
|
215 |
+
*/
|
216 |
+
public function replace_attachment( $attachment, $file_path ) {
|
217 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
218 |
+
'metadata_sizes' => false,
|
219 |
+
) );
|
220 |
+
|
221 |
+
if ( true !== $tests ) {
|
222 |
+
return $tests;
|
223 |
+
}
|
224 |
+
|
225 |
+
$attachment_id = $attachment->get_id();
|
226 |
+
$sizes = $this->get_attachment_sizes( $attachment );
|
227 |
+
$original_path = $attachment->get_original_path();
|
228 |
+
$dir_path = $this->filesystem->path_info( $original_path, 'dir_path' );
|
229 |
+
|
230 |
+
// Insert the new file (and overwrite the full size).
|
231 |
+
$moved = $this->filesystem->move( $file_path, $original_path, true );
|
232 |
+
|
233 |
+
if ( ! $moved ) {
|
234 |
+
return new WP_Error( 'not_writable', __( 'Replacement failed.', 'imagify' ) );
|
235 |
+
}
|
236 |
+
|
237 |
+
// Delete retina images.
|
238 |
+
$this->delete_retina_images( $attachment );
|
239 |
+
|
240 |
+
// Delete the non-retina images.
|
241 |
+
if ( $sizes ) {
|
242 |
+
foreach ( $sizes as $name => $attr ) {
|
243 |
+
$size_path = $dir_path . $attr['file'];
|
244 |
+
|
245 |
+
if ( $this->filesystem->exists( $size_path ) && $this->filesystem->is_file( $size_path ) ) {
|
246 |
+
// If the deletion fails, we're screwed anyway since the main file has been deleted, so no need to return an error here.
|
247 |
+
$this->filesystem->delete( $size_path );
|
248 |
+
}
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
// Get some Imagify data before deleting everything.
|
253 |
+
$optimization_level = $this->get_optimization_level( $attachment );
|
254 |
+
$full_retina_data = $attachment->get_data();
|
255 |
+
$full_retina_data = ! empty( $full_retina_data['sizes']['full@2x'] ) ? $full_retina_data['sizes']['full@2x'] : false;
|
256 |
+
$full_retina_optimized = $full_retina_data && ! empty( $full_retina_data['success'] );
|
257 |
+
|
258 |
+
// Delete the Imagify data.
|
259 |
+
$attachment->delete_imagify_data();
|
260 |
+
|
261 |
+
// Delete the backup file.
|
262 |
+
$attachment->delete_backup();
|
263 |
+
|
264 |
+
// Prevent auto-optimization.
|
265 |
+
add_filter( 'imagify_auto_optimize_attachment', '__return_false', 442 );
|
266 |
+
|
267 |
+
// Generate the non-retina images and the related WP metadata.
|
268 |
+
wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $original_path ) );
|
269 |
+
|
270 |
+
// Allow auto-optimization back.
|
271 |
+
remove_filter( 'imagify_auto_optimize_attachment', '__return_false', 442 );
|
272 |
+
|
273 |
+
// Generate retina images (since the Imagify data has been deleted, the images won't be optimized here).
|
274 |
+
$result = $this->generate_retina_images( $attachment );
|
275 |
+
|
276 |
+
if ( is_wp_error( $result ) ) {
|
277 |
+
if ( $full_retina_optimized ) {
|
278 |
+
// The retina version of the full size is optimized: restore it overwise the user may optimize it again some day.
|
279 |
+
$this->restore_full_retina_file( $attachment );
|
280 |
+
}
|
281 |
+
|
282 |
+
return $result;
|
283 |
+
}
|
284 |
+
|
285 |
+
if ( $this->can_auto_optimize() ) {
|
286 |
+
if ( $full_retina_optimized ) {
|
287 |
+
// Don't optimize the retina full size, it already is.
|
288 |
+
remove_filter( 'imagify_fill_full_size_data', array( Imagify_WP_Retina_2x::get_instance(), 'optimize_full_retina_version_hook' ) );
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Optimize everyone.
|
293 |
+
*
|
294 |
+
* @see Imagify_WP_Retina_2x::optimize_full_retina_version_hook()
|
295 |
+
* @see Imagify_WP_Retina_2x::optimize_retina_version_hook()
|
296 |
+
* @see Imagify_WP_Retina_2x::maybe_optimize_unauthorized_retina_version_hook().
|
297 |
+
*/
|
298 |
+
$attachment->optimize( $optimization_level );
|
299 |
+
|
300 |
+
if ( $full_retina_optimized ) {
|
301 |
+
add_filter( 'imagify_fill_full_size_data', array( Imagify_WP_Retina_2x::get_instance(), 'optimize_full_retina_version_hook' ), 10, 8 );
|
302 |
+
|
303 |
+
if ( $attachment->is_optimized() ) {
|
304 |
+
// Put data back.
|
305 |
+
$data = $attachment->get_data();
|
306 |
+
$data['sizes']['full@2x'] = $full_retina_data;
|
307 |
+
update_post_meta( $attachment_id, '_imagify_data', $data );
|
308 |
+
} else {
|
309 |
+
$this->restore_full_retina_file( $attachment );
|
310 |
+
}
|
311 |
+
}
|
312 |
+
} elseif ( $full_retina_optimized ) {
|
313 |
+
// The retina version of the full size is optimized: restore it overwise the user may optimize it again some day.
|
314 |
+
$this->restore_full_retina_file( $attachment );
|
315 |
+
}
|
316 |
+
|
317 |
+
return true;
|
318 |
+
}
|
319 |
+
|
320 |
+
/**
|
321 |
+
* Replace an attachment (except the retina version of the full size).
|
322 |
+
*
|
323 |
+
* @since 1.8
|
324 |
+
* @access public
|
325 |
+
* @author Grégory Viguier
|
326 |
+
*
|
327 |
+
* @param object $attachment An Imagify attachment.
|
328 |
+
* @param string $file_path Path to the new file.
|
329 |
+
* @return bool|object True on success, false if prevented, a WP_Error object on failure.
|
330 |
+
*/
|
331 |
+
public function replace_full_retina_image( $attachment, $file_path ) {
|
332 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
333 |
+
'metadata_file' => false,
|
334 |
+
'metadata_sizes' => false,
|
335 |
+
) );
|
336 |
+
|
337 |
+
if ( true !== $tests ) {
|
338 |
+
return $tests;
|
339 |
+
}
|
340 |
+
|
341 |
+
// Replace the file.
|
342 |
+
$retina_path = $this->get_retina_path( $attachment->get_original_path() );
|
343 |
+
$moved = $this->filesystem->move( $file_path, $retina_path, true );
|
344 |
+
|
345 |
+
if ( ! $moved ) {
|
346 |
+
return new WP_Error( 'not_writable', __( 'Replacement failed.', 'imagify' ) );
|
347 |
+
}
|
348 |
+
|
349 |
+
// Delete related Imagify data.
|
350 |
+
$this->remove_size_from_imagify_data( $attachment, 'full@2x' );
|
351 |
+
|
352 |
+
// Delete previous backup file.
|
353 |
+
$result = $this->delete_file_backup( $retina_path );
|
354 |
+
|
355 |
+
if ( is_wp_error( $result ) ) {
|
356 |
+
$this->filesystem->delete( $file_path );
|
357 |
+
return $result;
|
358 |
+
}
|
359 |
+
|
360 |
+
// Optimize.
|
361 |
+
if ( $attachment->is_optimized() && $this->can_auto_optimize() ) {
|
362 |
+
return $this->optimize_full_retina_image( $attachment );
|
363 |
+
}
|
364 |
+
}
|
365 |
+
|
366 |
+
|
367 |
+
/** ----------------------------------------------------------------------------------------- */
|
368 |
+
/** OPTIMIZE RETINA IMAGES ================================================================== */
|
369 |
+
/** ----------------------------------------------------------------------------------------- */
|
370 |
+
|
371 |
+
/**
|
372 |
+
* Optimize retina images.
|
373 |
+
*
|
374 |
+
* @since 1.8
|
375 |
+
* @access public
|
376 |
+
* @author Grégory Viguier
|
377 |
+
*
|
378 |
+
* @param object $attachment An Imagify attachment.
|
379 |
+
* @param bool $optimize_full_size False to not optimize the retina version of the full size.
|
380 |
+
* @return bool|object True on success, false if prevented or not supported or no sizes, a WP_Error object on failure.
|
381 |
+
*/
|
382 |
+
public function optimize_retina_images( $attachment, $optimize_full_size = true ) {
|
383 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
384 |
+
'supported' => true,
|
385 |
+
'can_optimize' => 'error',
|
386 |
+
'metadata_dimensions' => 'error',
|
387 |
+
) );
|
388 |
+
|
389 |
+
if ( true !== $tests ) {
|
390 |
+
return $tests;
|
391 |
+
}
|
392 |
+
|
393 |
+
$metadata = wp_get_attachment_metadata( $attachment->get_id() );
|
394 |
+
|
395 |
+
if ( $optimize_full_size ) {
|
396 |
+
$metadata['sizes']['full'] = array(
|
397 |
+
'file' => $this->filesystem->file_name( $metadata['file'] ),
|
398 |
+
'width' => (int) $metadata['width'],
|
399 |
+
'height' => (int) $metadata['height'],
|
400 |
+
'mime-type' => get_post_mime_type( $attachment->get_id() ),
|
401 |
+
);
|
402 |
+
}
|
403 |
+
|
404 |
+
return $this->optimize_retina_sizes( $attachment, $metadata['sizes'] );
|
405 |
+
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* Optimize the full size retina image.
|
409 |
+
*
|
410 |
+
* @since 1.8
|
411 |
+
* @access public
|
412 |
+
* @author Grégory Viguier
|
413 |
+
*
|
414 |
+
* @param object $attachment An Imagify attachment.
|
415 |
+
* @return bool|object True on success, false if prevented or not supported or no sizes, a WP_Error object on failure.
|
416 |
+
*/
|
417 |
+
public function optimize_full_retina_image( $attachment ) {
|
418 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
419 |
+
'supported' => true,
|
420 |
+
'can_optimize' => 'error',
|
421 |
+
'metadata_dimensions' => 'error',
|
422 |
+
) );
|
423 |
+
|
424 |
+
if ( true !== $tests ) {
|
425 |
+
return $tests;
|
426 |
+
}
|
427 |
+
|
428 |
+
$metadata = wp_get_attachment_metadata( $attachment->get_id() );
|
429 |
+
|
430 |
+
$sizes = array(
|
431 |
+
'full' => array(
|
432 |
+
'file' => $this->filesystem->file_name( $metadata['file'] ),
|
433 |
+
'width' => (int) $metadata['width'],
|
434 |
+
'height' => (int) $metadata['height'],
|
435 |
+
'mime-type' => get_post_mime_type( $attachment->get_id() ),
|
436 |
+
),
|
437 |
+
);
|
438 |
+
|
439 |
+
return $this->optimize_retina_sizes( $attachment, $sizes );
|
440 |
+
}
|
441 |
+
|
442 |
+
/**
|
443 |
+
* Optimize the given retina images.
|
444 |
+
*
|
445 |
+
* @since 1.8
|
446 |
+
* @access public
|
447 |
+
* @author Grégory Viguier
|
448 |
+
*
|
449 |
+
* @param object $attachment An Imagify attachment.
|
450 |
+
* @param array $sizes A list of non-retina sizes, formatted like in wp_get_attachment_metadata().
|
451 |
+
* @return bool|object True on success, false if prevented or not supported or no sizes, a WP_Error object on failure.
|
452 |
+
*/
|
453 |
+
public function optimize_retina_sizes( $attachment, $sizes ) {
|
454 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
455 |
+
'supported' => true,
|
456 |
+
'can_optimize' => 'error',
|
457 |
+
'metadata_dimensions' => 'error',
|
458 |
+
) );
|
459 |
+
|
460 |
+
if ( true !== $tests ) {
|
461 |
+
return $tests;
|
462 |
+
}
|
463 |
+
|
464 |
+
$attachment_id = $attachment->get_id();
|
465 |
+
$optimization_level = $this->get_optimization_level( $attachment );
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Filter the retina thumbnail sizes to optimize for a given attachment. This includes the sizes disabled in Imagify’ settings.
|
469 |
+
*
|
470 |
+
* @since 1.8
|
471 |
+
* @author Grégory Viguier
|
472 |
+
*
|
473 |
+
* @param array $sizes An array of non-retina thumbnail sizes.
|
474 |
+
* @param int $attachment_id The attachment ID.
|
475 |
+
* @param int $optimization_level The optimization level.
|
476 |
+
*/
|
477 |
+
$sizes = apply_filters( 'imagify_attachment_retina_sizes', $sizes, $attachment_id, $optimization_level );
|
478 |
+
|
479 |
+
if ( ! $sizes || ! is_array( $sizes ) ) {
|
480 |
+
return false;
|
481 |
+
}
|
482 |
+
|
483 |
+
$original_dirpath = $this->filesystem->dir_path( $attachment->get_original_path() );
|
484 |
+
|
485 |
+
foreach ( $sizes as $size_key => $image_data ) {
|
486 |
+
$retina_path = wr2x_get_retina( $original_dirpath . $image_data['file'] );
|
487 |
+
|
488 |
+
if ( ! $retina_path ) {
|
489 |
+
unset( $sizes[ $size_key ] );
|
490 |
+
continue;
|
491 |
+
}
|
492 |
+
|
493 |
+
// The file exists.
|
494 |
+
$sizes[ $size_key ]['retina-path'] = $retina_path;
|
495 |
+
}
|
496 |
+
|
497 |
+
if ( ! $sizes ) {
|
498 |
+
return false;
|
499 |
+
}
|
500 |
+
|
501 |
+
$attachment->set_running_status();
|
502 |
+
|
503 |
+
/**
|
504 |
+
* Fires before optimizing the retina images.
|
505 |
+
*
|
506 |
+
* @since 1.8
|
507 |
+
* @author Grégory Viguier
|
508 |
+
*
|
509 |
+
* @param int $attachment_id The attachment ID.
|
510 |
+
* @param array $sizes An array of non-retina thumbnail sizes.
|
511 |
+
* @param int $optimization_level The optimization level.
|
512 |
+
*/
|
513 |
+
do_action( 'before_imagify_optimize_retina_images', $attachment_id, $sizes, $optimization_level );
|
514 |
+
|
515 |
+
$imagify_data = $attachment->get_data();
|
516 |
+
|
517 |
+
foreach ( $sizes as $size_key => $image_data ) {
|
518 |
+
$imagify_data = $this->optimize_retina_image( array(
|
519 |
+
'data' => $imagify_data,
|
520 |
+
'attachment' => $attachment,
|
521 |
+
'retina_path' => $image_data['retina-path'],
|
522 |
+
'size_key' => $size_key,
|
523 |
+
'optimization_level' => $optimization_level,
|
524 |
+
) );
|
525 |
+
}
|
526 |
+
|
527 |
+
$this->update_imagify_data( $attachment, $imagify_data );
|
528 |
+
|
529 |
+
/**
|
530 |
+
* Fires after optimizing the retina images.
|
531 |
+
*
|
532 |
+
* @since 1.8
|
533 |
+
* @author Grégory Viguier
|
534 |
+
*
|
535 |
+
* @param int $attachment_id The attachment ID.
|
536 |
+
* @param array $sizes An array of non-retina thumbnail sizes.
|
537 |
+
* @param int $optimization_level The optimization level.
|
538 |
+
*/
|
539 |
+
do_action( 'after_imagify_optimize_retina_images', $attachment_id, $sizes, $optimization_level );
|
540 |
+
|
541 |
+
$attachment->delete_running_status();
|
542 |
+
|
543 |
+
return true;
|
544 |
+
}
|
545 |
+
|
546 |
+
/**
|
547 |
+
* Optimize the retina version of an image.
|
548 |
+
*
|
549 |
+
* @since 1.8
|
550 |
+
* @access public
|
551 |
+
* @author Grégory Viguier
|
552 |
+
*
|
553 |
+
* @param array $args {
|
554 |
+
* An array of required arguments.
|
555 |
+
*
|
556 |
+
* @type array $data The statistics data.
|
557 |
+
* @type object $attachment An Imagify attachment.
|
558 |
+
* @type string $retina_path The path to the retina file.
|
559 |
+
* @type string $size_key The attachment size key (without '@2x').
|
560 |
+
* @type int $optimization_level The optimization level. Optionnal.
|
561 |
+
* @type array $metadata WP metadata. If omitted, wp_get_attachment_metadata() will be used.
|
562 |
+
* }
|
563 |
+
* @return array The new optimization data.
|
564 |
+
*/
|
565 |
+
public function optimize_retina_image( $args ) {
|
566 |
+
static $backup;
|
567 |
+
|
568 |
+
$args = array_merge( array(
|
569 |
+
'data' => array(),
|
570 |
+
'attachment' => false,
|
571 |
+
'retina_path' => '',
|
572 |
+
'size_key' => '',
|
573 |
+
'optimization_level' => false,
|
574 |
+
'metadata' => array(),
|
575 |
+
), $args );
|
576 |
+
|
577 |
+
if ( $this->is_prevented( __FUNCTION__ ) || ! $args['retina_path'] || $this->has_filesystem_error() ) {
|
578 |
+
return $args['data'];
|
579 |
+
}
|
580 |
+
|
581 |
+
$retina_key = $args['size_key'] . '@2x';
|
582 |
+
|
583 |
+
if ( isset( $args['data'][ $retina_key ] ) ) {
|
584 |
+
// Don't optimize something that already is.
|
585 |
+
return $args['data'];
|
586 |
+
}
|
587 |
+
|
588 |
+
$disallowed = $this->size_is_disallowed( $args['size_key'] );
|
589 |
+
$do_retina = ! $disallowed;
|
590 |
+
/**
|
591 |
+
* Allow to optimize the retina version generated by WP Retina x2.
|
592 |
+
*
|
593 |
+
* @since 1.0
|
594 |
+
* @since 1.8 Added $args parameter.
|
595 |
+
*
|
596 |
+
* @param bool $do_retina True will allow the optimization. False to prevent it.
|
597 |
+
* @param string $args The arguments passed to the method.
|
598 |
+
*/
|
599 |
+
$do_retina = apply_filters( 'do_imagify_optimize_retina', $do_retina, $args );
|
600 |
+
|
601 |
+
if ( ! $do_retina ) {
|
602 |
+
if ( $disallowed ) {
|
603 |
+
$message = __( 'This size is not authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' );
|
604 |
+
} else {
|
605 |
+
$message = __( 'This size optimization has been prevented by a filter.', 'imagify' );
|
606 |
+
}
|
607 |
+
|
608 |
+
$args['data']['sizes'][ $retina_key ] = array(
|
609 |
+
'success' => false,
|
610 |
+
'error' => $message,
|
611 |
+
);
|
612 |
+
return $args['data'];
|
613 |
+
}
|
614 |
+
|
615 |
+
if ( ! $args['metadata'] || ! is_array( $args['metadata'] ) ) {
|
616 |
+
$args['metadata'] = wp_get_attachment_metadata( $args['attachment']->get_id() );
|
617 |
+
}
|
618 |
+
|
619 |
+
$is_a_copy = $this->size_is_a_full_copy( array(
|
620 |
+
'size_name' => $args['size_key'],
|
621 |
+
'metadata' => $args['metadata'],
|
622 |
+
'imagify_data' => $args['data'],
|
623 |
+
'retina_path' => $args['retina_path'],
|
624 |
+
) );
|
625 |
+
|
626 |
+
if ( $is_a_copy ) {
|
627 |
+
// This thumbnail is a copy of the full size image, which is already optimized.
|
628 |
+
$args['data']['sizes'][ $retina_key ] = $args['data']['sizes']['full'];
|
629 |
+
|
630 |
+
if ( isset( $args['data']['sizes']['full']['original_size'], $args['data']['sizes']['full']['optimized_size'] ) ) {
|
631 |
+
// Concistancy only.
|
632 |
+
$args['data']['stats']['original_size'] += $args['data']['sizes']['full']['original_size'];
|
633 |
+
$args['data']['stats']['optimized_size'] += $args['data']['sizes']['full']['optimized_size'];
|
634 |
+
}
|
635 |
+
|
636 |
+
return $args['data'];
|
637 |
+
}
|
638 |
+
|
639 |
+
if ( ! is_int( $args['optimization_level'] ) ) {
|
640 |
+
$args['optimization_level'] = get_imagify_option( 'optimization_level' );
|
641 |
+
}
|
642 |
+
|
643 |
+
// Hammer time.
|
644 |
+
$response = do_imagify( $args['retina_path'], array(
|
645 |
+
// Backup only if it's the full size.
|
646 |
+
'backup' => 'full' === $args['size_key'],
|
647 |
+
'optimization_level' => $args['optimization_level'],
|
648 |
+
'context' => 'wp-retina',
|
649 |
+
) );
|
650 |
+
|
651 |
+
return $args['attachment']->fill_data( $args['data'], $response, $retina_key );
|
652 |
+
}
|
653 |
+
|
654 |
+
|
655 |
+
/** ----------------------------------------------------------------------------------------- */
|
656 |
+
/** HANDLE BACKUPS ========================================================================== */
|
657 |
+
/** ----------------------------------------------------------------------------------------- */
|
658 |
+
|
659 |
+
/**
|
660 |
+
* Backup a retina file.
|
661 |
+
*
|
662 |
+
* @since 1.8
|
663 |
+
* @access public
|
664 |
+
* @author Grégory Viguier
|
665 |
+
*
|
666 |
+
* @param string $file_path Path to the file.
|
667 |
+
* @return bool|object True on success, false if prevented or no need for backup, a WP_Error object on failure.
|
668 |
+
*/
|
669 |
+
public function backup_file( $file_path ) {
|
670 |
+
static $backup;
|
671 |
+
|
672 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
673 |
+
return false;
|
674 |
+
}
|
675 |
+
|
676 |
+
if ( ! isset( $backup ) ) {
|
677 |
+
$backup = get_imagify_option( 'backup' );
|
678 |
+
}
|
679 |
+
|
680 |
+
if ( ! $backup ) {
|
681 |
+
return false;
|
682 |
+
}
|
683 |
+
|
684 |
+
if ( $this->has_filesystem_error() ) {
|
685 |
+
return new WP_Error( 'filesystem', __( 'Filesystem error.', 'imagify' ) );
|
686 |
+
}
|
687 |
+
|
688 |
+
$upload_basedir = get_imagify_upload_basedir();
|
689 |
+
|
690 |
+
if ( ! $upload_basedir ) {
|
691 |
+
$file_path = make_path_relative( $file_path );
|
692 |
+
|
693 |
+
/* translators: %s is a file path. */
|
694 |
+
return new WP_Error( 'upload_basedir', sprintf( __( 'The file %s could not be backed up. Image optimization aborted.', 'imagify' ), '<code>' . esc_html( $file_path ) . '</code>' ) );
|
695 |
+
}
|
696 |
+
|
697 |
+
$file_path = wp_normalize_path( $file_path );
|
698 |
+
$backup_dir = get_imagify_backup_dir_path();
|
699 |
+
$backup_path = str_replace( $upload_basedir, $backup_dir, $file_path );
|
700 |
+
|
701 |
+
if ( $this->filesystem->exists( $backup_path ) ) {
|
702 |
+
$this->filesystem->delete( $backup_path );
|
703 |
+
}
|
704 |
+
|
705 |
+
$backup_result = imagify_backup_file( $file_path, $backup_path );
|
706 |
+
|
707 |
+
if ( is_wp_error( $backup_result ) ) {
|
708 |
+
return $backup_result;
|
709 |
+
}
|
710 |
+
|
711 |
+
return true;
|
712 |
+
}
|
713 |
+
|
714 |
+
/**
|
715 |
+
* Delete a retina file backup.
|
716 |
+
*
|
717 |
+
* @since 1.8
|
718 |
+
* @access public
|
719 |
+
* @author Grégory Viguier
|
720 |
+
*
|
721 |
+
* @param string $file_path Path to the file.
|
722 |
+
* @return bool|object True on success, false if the file doesn't exist, a WP_Error object on failure.
|
723 |
+
*/
|
724 |
+
public function delete_file_backup( $file_path ) {
|
725 |
+
$tests = $this->validate( __FUNCTION__ );
|
726 |
+
|
727 |
+
if ( true !== $tests ) {
|
728 |
+
return $tests;
|
729 |
+
}
|
730 |
+
|
731 |
+
$upload_basedir = get_imagify_upload_basedir();
|
732 |
+
|
733 |
+
if ( ! $upload_basedir ) {
|
734 |
+
$file_path = make_path_relative( $file_path );
|
735 |
+
|
736 |
+
/* translators: %s is a file path. */
|
737 |
+
return new WP_Error( 'upload_basedir', sprintf( __( 'Previous backup file for %s could not be deleted.', 'imagify' ), '<code>' . esc_html( $file_path ) . '</code>' ) );
|
738 |
+
}
|
739 |
+
|
740 |
+
$file_path = wp_normalize_path( $file_path );
|
741 |
+
$backup_dir = get_imagify_backup_dir_path();
|
742 |
+
$backup_path = str_replace( $upload_basedir, $backup_dir, $file_path );
|
743 |
+
|
744 |
+
if ( ! $this->filesystem->exists( $backup_path ) ) {
|
745 |
+
return false;
|
746 |
+
}
|
747 |
+
|
748 |
+
$result = $this->filesystem->delete( $backup_path );
|
749 |
+
|
750 |
+
if ( ! $result ) {
|
751 |
+
$file_path = make_path_relative( $file_path );
|
752 |
+
|
753 |
+
/* translators: %s is a file path. */
|
754 |
+
return new WP_Error( 'not_deleted', sprintf( __( 'Previous backup file for %s could not be deleted.', 'imagify' ), '<code>' . esc_html( $file_path ) . '</code>' ) );
|
755 |
+
}
|
756 |
+
|
757 |
+
return true;
|
758 |
+
}
|
759 |
+
|
760 |
+
/**
|
761 |
+
* Restore the retina version of the full size.
|
762 |
+
* This doesn't remove the Imagify data.
|
763 |
+
*
|
764 |
+
* @since 1.8
|
765 |
+
* @access public
|
766 |
+
* @author Grégory Viguier
|
767 |
+
*
|
768 |
+
* @param object $attachment An Imagify attachment.
|
769 |
+
* @return bool|object True on success, false if prevented or backup doesn't exist, a WP_Error object on failure.
|
770 |
+
*/
|
771 |
+
public function restore_full_retina_file( $attachment ) {
|
772 |
+
$tests = $this->validate( __FUNCTION__, $attachment, array(
|
773 |
+
'metadata_file' => false,
|
774 |
+
'metadata_sizes' => false,
|
775 |
+
) );
|
776 |
+
|
777 |
+
if ( true !== $tests ) {
|
778 |
+
return $tests;
|
779 |
+
}
|
780 |
+
|
781 |
+
$has_backup = $this->full_retina_has_backup( $attachment );
|
782 |
+
|
783 |
+
if ( is_wp_error( $has_backup ) ) {
|
784 |
+
return $has_backup;
|
785 |
+
}
|
786 |
+
|
787 |
+
if ( ! $has_backup ) {
|
788 |
+
return new WP_Error( 'no_backup', __( 'The retina version of the full size of this image does not have backup.', 'imagify' ) );
|
789 |
+
}
|
790 |
+
|
791 |
+
$file_path = $this->get_retina_path( $attachment->get_original_path() );
|
792 |
+
$backup_path = $this->get_full_retina_backup_path( $attachment );
|
793 |
+
|
794 |
+
/**
|
795 |
+
* Fires before restoring the retina version of the full size.
|
796 |
+
*
|
797 |
+
* @since 1.8
|
798 |
+
* @author Grégory Viguier
|
799 |
+
*
|
800 |
+
* @param string $backup_path Path to the backup file.
|
801 |
+
* @param string $file_path Path to the source file.
|
802 |
+
*/
|
803 |
+
do_action( 'before_imagify_restore_full_retina_file', $backup_path, $file_path );
|
804 |
+
|
805 |
+
// Save disc space by moving it instead of copying it.
|
806 |
+
$moved = $this->filesystem->move( $backup_path, $file_path, true );
|
807 |
+
|
808 |
+
/**
|
809 |
+
* Fires after restoring the retina version of the full size.
|
810 |
+
*
|
811 |
+
* @since 1.8
|
812 |
+
* @author Grégory Viguier
|
813 |
+
*
|
814 |
+
* @param string $backup_path Path to the backup file.
|
815 |
+
* @param string $file_path Path to the source file.
|
816 |
+
* @param bool $moved Restore success.
|
817 |
+
*/
|
818 |
+
do_action( 'after_imagify_restore_full_retina_file', $backup_path, $file_path, $moved );
|
819 |
+
|
820 |
+
if ( ! $moved ) {
|
821 |
+
return new WP_Error( 'upload_basedir', __( 'Backup of the retina version of the full size image could not be restored.', 'imagify' ) );
|
822 |
+
}
|
823 |
+
|
824 |
+
return true;
|
825 |
+
}
|
826 |
+
|
827 |
+
/**
|
828 |
+
* Get the path to the retina version of the full size.
|
829 |
+
*
|
830 |
+
* @since 1.8
|
831 |
+
* @access public
|
832 |
+
* @author Grégory Viguier
|
833 |
+
*
|
834 |
+
* @param object $attachment An Imagify attachment.
|
835 |
+
* @return string|object The path on success, a WP_Error object on failure.
|
836 |
+
*/
|
837 |
+
public function get_full_retina_backup_path( $attachment ) {
|
838 |
+
$file_path = $this->get_retina_path( $attachment->get_original_path() );
|
839 |
+
$backup_path = get_imagify_attachment_backup_path( $file_path );
|
840 |
+
|
841 |
+
if ( ! $backup_path ) {
|
842 |
+
return new WP_Error( 'upload_basedir', __( 'Could not retrieve the path to the backup of the retina version of the full size image.', 'imagify' ) );
|
843 |
+
}
|
844 |
+
|
845 |
+
return $backup_path;
|
846 |
+
}
|
847 |
+
|
848 |
+
/**
|
849 |
+
* Tell if the retina version of the full size has a backup.
|
850 |
+
*
|
851 |
+
* @since 1.8
|
852 |
+
* @access public
|
853 |
+
* @author Grégory Viguier
|
854 |
+
*
|
855 |
+
* @param object $attachment An Imagify attachment.
|
856 |
+
* @return bool|object A WP_Error object on failure.
|
857 |
+
*/
|
858 |
+
public function full_retina_has_backup( $attachment ) {
|
859 |
+
$backup_path = $this->get_full_retina_backup_path( $attachment );
|
860 |
+
|
861 |
+
if ( is_wp_error( $backup_path ) ) {
|
862 |
+
return $backup_path;
|
863 |
+
}
|
864 |
+
|
865 |
+
return $this->filesystem->exists( $backup_path );
|
866 |
+
}
|
867 |
+
|
868 |
+
|
869 |
+
/** ----------------------------------------------------------------------------------------- */
|
870 |
+
/** HANDLE IMAGIFY DATA ===================================================================== */
|
871 |
+
/** ----------------------------------------------------------------------------------------- */
|
872 |
+
|
873 |
+
/**
|
874 |
+
* Remove retina versions from Imagify data.
|
875 |
+
* It also rebuilds the attachment stats.
|
876 |
+
*
|
877 |
+
* @since 1.8
|
878 |
+
* @access public
|
879 |
+
* @author Grégory Viguier
|
880 |
+
*
|
881 |
+
* @param object $attachment An Imagify attachment.
|
882 |
+
* @param bool $remove_full_size True to also remove the full size data.
|
883 |
+
*/
|
884 |
+
public function remove_retina_images_data( $attachment, $remove_full_size = false ) {
|
885 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
886 |
+
return;
|
887 |
+
}
|
888 |
+
|
889 |
+
$imagify_data = $attachment->get_data();
|
890 |
+
|
891 |
+
if ( empty( $imagify_data['sizes'] ) || ! is_array( $imagify_data['sizes'] ) ) {
|
892 |
+
return;
|
893 |
+
}
|
894 |
+
|
895 |
+
$sizes = $this->get_attachment_sizes( $attachment );
|
896 |
+
|
897 |
+
if ( ! $sizes ) {
|
898 |
+
return;
|
899 |
+
}
|
900 |
+
|
901 |
+
$update = false;
|
902 |
+
|
903 |
+
if ( $remove_full_size && isset( $imagify_data['sizes']['full@2x'] ) ) {
|
904 |
+
unset( $imagify_data['sizes']['full@2x'] );
|
905 |
+
$update = true;
|
906 |
+
}
|
907 |
+
|
908 |
+
foreach ( $sizes as $size => $attr ) {
|
909 |
+
$size .= '@2x';
|
910 |
+
|
911 |
+
if ( isset( $imagify_data['sizes'][ $size ] ) ) {
|
912 |
+
unset( $imagify_data['sizes'][ $size ] );
|
913 |
+
$update = true;
|
914 |
+
}
|
915 |
+
}
|
916 |
+
|
917 |
+
if ( ! $update ) {
|
918 |
+
return;
|
919 |
+
}
|
920 |
+
|
921 |
+
$this->update_imagify_data( $attachment, $imagify_data );
|
922 |
+
}
|
923 |
+
|
924 |
+
/**
|
925 |
+
* Remove a retina thumbnail from attachment's Imagify data, given the retina file name.
|
926 |
+
*
|
927 |
+
* @since 1.8
|
928 |
+
* @access public
|
929 |
+
* @author Grégory Viguier
|
930 |
+
*
|
931 |
+
* @param object $attachment An Imagify attachment.
|
932 |
+
* @param string $retina_filename Retina thumbnail file name.
|
933 |
+
*/
|
934 |
+
public function remove_retina_image_data_by_filename( $attachment, $retina_filename ) {
|
935 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
936 |
+
return;
|
937 |
+
}
|
938 |
+
|
939 |
+
$imagify_data = $attachment->get_data();
|
940 |
+
|
941 |
+
if ( empty( $imagify_data['sizes'] ) || ! is_array( $imagify_data['sizes'] ) ) {
|
942 |
+
return;
|
943 |
+
}
|
944 |
+
|
945 |
+
$sizes = $this->get_attachment_sizes( $attachment );
|
946 |
+
|
947 |
+
if ( ! $sizes ) {
|
948 |
+
return;
|
949 |
+
}
|
950 |
+
|
951 |
+
$image_filename = str_replace( $this->get_suffix(), '.', $retina_filename );
|
952 |
+
$size = false;
|
953 |
+
|
954 |
+
foreach ( $sizes as $name => $attr ) {
|
955 |
+
if ( $image_filename === $attr['file'] ) {
|
956 |
+
$size = $name;
|
957 |
+
break;
|
958 |
+
}
|
959 |
+
}
|
960 |
+
|
961 |
+
if ( ! $size || ! isset( $imagify_data['sizes'][ $size ] ) ) {
|
962 |
+
return;
|
963 |
+
}
|
964 |
+
|
965 |
+
unset( $imagify_data['sizes'][ $size ] );
|
966 |
+
|
967 |
+
$this->update_imagify_data( $attachment, $imagify_data );
|
968 |
+
}
|
969 |
+
|
970 |
+
/**
|
971 |
+
* Rebuild the attachment stats and store the data.
|
972 |
+
* Delete all Imagify data if the sizes are empty.
|
973 |
+
*
|
974 |
+
* @since 1.8
|
975 |
+
* @access public
|
976 |
+
* @author Grégory Viguier
|
977 |
+
*
|
978 |
+
* @param object $attachment An Imagify attachment.
|
979 |
+
* @param array $imagify_data Imagify data.
|
980 |
+
* @return bool True on update, false on delete or prevented.
|
981 |
+
*/
|
982 |
+
public function update_imagify_data( $attachment, $imagify_data ) {
|
983 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
984 |
+
return false;
|
985 |
+
}
|
986 |
+
|
987 |
+
if ( empty( $imagify_data['sizes'] ) || ! is_array( $imagify_data['sizes'] ) ) {
|
988 |
+
// No new sizes.
|
989 |
+
$attachment->delete_imagify_data();
|
990 |
+
return false;
|
991 |
+
}
|
992 |
+
|
993 |
+
$imagify_data['stats'] = array(
|
994 |
+
'original_size' => 0,
|
995 |
+
'optimized_size' => 0,
|
996 |
+
'percent' => 0,
|
997 |
+
);
|
998 |
+
|
999 |
+
foreach ( $imagify_data['sizes'] as $size_data ) {
|
1000 |
+
$imagify_data['stats']['original_size'] += ! empty( $size_data['original_size'] ) ? $size_data['original_size'] : 0;
|
1001 |
+
$imagify_data['stats']['optimized_size'] += ! empty( $size_data['optimized_size'] ) ? $size_data['optimized_size'] : 0;
|
1002 |
+
}
|
1003 |
+
|
1004 |
+
if ( $imagify_data['stats']['original_size'] && $imagify_data['stats']['optimized_size'] ) {
|
1005 |
+
$imagify_data['stats']['percent'] = round( ( ( $imagify_data['stats']['original_size'] - $imagify_data['stats']['optimized_size'] ) / $imagify_data['stats']['original_size'] ) * 100, 2 );
|
1006 |
+
}
|
1007 |
+
|
1008 |
+
update_post_meta( $attachment->get_id(), '_imagify_data', $imagify_data );
|
1009 |
+
|
1010 |
+
return true;
|
1011 |
+
}
|
1012 |
+
|
1013 |
+
/**
|
1014 |
+
* Remove a size from Imagify data.
|
1015 |
+
*
|
1016 |
+
* @since 1.8
|
1017 |
+
* @access public
|
1018 |
+
* @author Grégory Viguier
|
1019 |
+
*
|
1020 |
+
* @param object $attachment An Imagify attachment.
|
1021 |
+
* @param string $size_name Name of the size.
|
1022 |
+
*/
|
1023 |
+
public function remove_size_from_imagify_data( $attachment, $size_name ) {
|
1024 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
1025 |
+
return;
|
1026 |
+
}
|
1027 |
+
|
1028 |
+
$imagify_data = $attachment->get_data();
|
1029 |
+
|
1030 |
+
if ( ! isset( $imagify_data['sizes'][ $size_name ] ) ) {
|
1031 |
+
return;
|
1032 |
+
}
|
1033 |
+
|
1034 |
+
unset( $imagify_data['sizes'][ $size_name ] );
|
1035 |
+
|
1036 |
+
$this->update_imagify_data( $attachment, $imagify_data );
|
1037 |
+
}
|
1038 |
+
|
1039 |
+
|
1040 |
+
/** ----------------------------------------------------------------------------------------- */
|
1041 |
+
/** INTERNAL TOOLS ========================================================================== */
|
1042 |
+
/** ----------------------------------------------------------------------------------------- */
|
1043 |
+
|
1044 |
+
/**
|
1045 |
+
* Tell if a file extension is supported by WP Retina 2x.
|
1046 |
+
* It uses $wr2x_core->is_supported_image() if available.
|
1047 |
+
*
|
1048 |
+
* @since 1.8
|
1049 |
+
* @access public
|
1050 |
+
* @see $wr2x_core->is_supported_image()
|
1051 |
+
* @author Grégory Viguier
|
1052 |
+
*
|
1053 |
+
* @param string|int $file_path Path to the file or attachment ID.
|
1054 |
+
* @return bool
|
1055 |
+
*/
|
1056 |
+
public function is_supported_format( $file_path ) {
|
1057 |
+
global $wr2x_core;
|
1058 |
+
static $method;
|
1059 |
+
static $results = array();
|
1060 |
+
|
1061 |
+
if ( ! $file_path ) {
|
1062 |
+
return false;
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
if ( isset( $results[ $file_path ] ) ) {
|
1066 |
+
// $file_path can be a path or an attachment ID.
|
1067 |
+
return $results[ $file_path ];
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
if ( is_int( $file_path ) ) {
|
1071 |
+
$attachment_id = $file_path;
|
1072 |
+
$file_path = get_attached_file( $attachment_id );
|
1073 |
+
|
1074 |
+
if ( ! $file_path ) {
|
1075 |
+
$results[ $attachment_id ] = false;
|
1076 |
+
return false;
|
1077 |
+
}
|
1078 |
+
|
1079 |
+
if ( isset( $results[ $file_path ] ) ) {
|
1080 |
+
// $file_path is now a path for sure.
|
1081 |
+
$results[ $attachment_id ] = $results[ $file_path ];
|
1082 |
+
return $results[ $file_path ];
|
1083 |
+
}
|
1084 |
+
}
|
1085 |
+
|
1086 |
+
if ( ! isset( $method ) ) {
|
1087 |
+
if ( $wr2x_core && is_object( $wr2x_core ) && method_exists( $wr2x_core, 'is_supported_image' ) ) {
|
1088 |
+
$method = array( $wr2x_core, 'is_supported_image' );
|
1089 |
+
} else {
|
1090 |
+
$method = array( $this, 'is_supported_extension' );
|
1091 |
+
}
|
1092 |
+
}
|
1093 |
+
|
1094 |
+
$results[ $file_path ] = call_user_func( $method, $file_path );
|
1095 |
+
$results[ $attachment_id ] = $results[ $file_path ];
|
1096 |
+
|
1097 |
+
return $results[ $file_path ];
|
1098 |
+
}
|
1099 |
+
|
1100 |
+
/**
|
1101 |
+
* Tell if a file extension is supported by WP Retina 2x.
|
1102 |
+
* Internal version of $wr2x_core->is_supported_image().
|
1103 |
+
*
|
1104 |
+
* @since 1.8
|
1105 |
+
* @access public
|
1106 |
+
* @see $this->is_supported_format()
|
1107 |
+
* @author Grégory Viguier
|
1108 |
+
*
|
1109 |
+
* @param string $file_path Path to a file.
|
1110 |
+
* @return bool
|
1111 |
+
*/
|
1112 |
+
protected function is_supported_extension( $file_path ) {
|
1113 |
+
$extension = strtolower( $this->filesystem->path_info( $file_path, 'extension' ) );
|
1114 |
+
$extensions = array(
|
1115 |
+
'jpg' => 1,
|
1116 |
+
'jpeg' => 1,
|
1117 |
+
'png' => 1,
|
1118 |
+
'gif' => 1,
|
1119 |
+
);
|
1120 |
+
|
1121 |
+
return isset( $extensions[ $extension ] );
|
1122 |
+
}
|
1123 |
+
|
1124 |
+
/**
|
1125 |
+
* Get the path to the retina version of an image.
|
1126 |
+
*
|
1127 |
+
* @since 1.8
|
1128 |
+
* @access public
|
1129 |
+
* @author Grégory Viguier
|
1130 |
+
*
|
1131 |
+
* @param string $file_path Path to the non-retina image.
|
1132 |
+
* @return string
|
1133 |
+
*/
|
1134 |
+
public function get_retina_path( $file_path ) {
|
1135 |
+
$path_info = $this->filesystem->path_info( $file_path );
|
1136 |
+
$suffix = rtrim( $this->get_suffix(), '.' );
|
1137 |
+
$extension = isset( $path_info['extension'] ) ? '.' . $path_info['extension'] : '';
|
1138 |
+
|
1139 |
+
return $path_info['dir_path'] . $path_info['file_base'] . $suffix . $extension;
|
1140 |
+
}
|
1141 |
+
|
1142 |
+
/**
|
1143 |
+
* Tell if the attchment has at least one retina image.
|
1144 |
+
*
|
1145 |
+
* @since 1.8
|
1146 |
+
* @access public
|
1147 |
+
* @author Grégory Viguier
|
1148 |
+
*
|
1149 |
+
* @param object $attachment An Imagify attachment.
|
1150 |
+
* @return bool
|
1151 |
+
*/
|
1152 |
+
public function has_retina_images( $attachment ) {
|
1153 |
+
$dir_path = $this->filesystem->path_info( $attachment->get_original_path(), 'dir_path' );
|
1154 |
+
$metadata = wp_get_attachment_metadata( $attachment->get_id() );
|
1155 |
+
$sizes = ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : array();
|
1156 |
+
$sizes['full'] = array(
|
1157 |
+
'file' => $this->filesystem->file_name( $metadata['file'] ),
|
1158 |
+
);
|
1159 |
+
|
1160 |
+
foreach ( $sizes as $name => $attr ) {
|
1161 |
+
$size_path = $this->get_retina_path( $dir_path . $attr['file'] );
|
1162 |
+
|
1163 |
+
if ( $this->filesystem->exists( $size_path ) ) {
|
1164 |
+
return true;
|
1165 |
+
}
|
1166 |
+
}
|
1167 |
+
|
1168 |
+
return false;
|
1169 |
+
}
|
1170 |
+
|
1171 |
+
/**
|
1172 |
+
* Prevent a method to do its job.
|
1173 |
+
*
|
1174 |
+
* @since 1.8
|
1175 |
+
* @access public
|
1176 |
+
* @author Grégory Viguier
|
1177 |
+
*
|
1178 |
+
* @param string $method_name Name of the method to prevent.
|
1179 |
+
*/
|
1180 |
+
public function prevent( $method_name ) {
|
1181 |
+
if ( empty( self::$prevented[ $method_name ] ) || self::$prevented[ $method_name ] < 1 ) {
|
1182 |
+
self::$prevented[ $method_name ] = 1;
|
1183 |
+
} else {
|
1184 |
+
++self::$prevented[ $method_name ];
|
1185 |
+
}
|
1186 |
+
}
|
1187 |
+
|
1188 |
+
/**
|
1189 |
+
* Allow a method to do its job.
|
1190 |
+
*
|
1191 |
+
* @since 1.8
|
1192 |
+
* @access public
|
1193 |
+
* @author Grégory Viguier
|
1194 |
+
*
|
1195 |
+
* @param string $method_name Name of the method to allow.
|
1196 |
+
*/
|
1197 |
+
public function allow( $method_name ) {
|
1198 |
+
if ( empty( self::$prevented[ $method_name ] ) || self::$prevented[ $method_name ] <= 1 ) {
|
1199 |
+
unset( self::$prevented[ $method_name ] );
|
1200 |
+
} else {
|
1201 |
+
--self::$prevented[ $method_name ];
|
1202 |
+
}
|
1203 |
+
}
|
1204 |
+
|
1205 |
+
/**
|
1206 |
+
* Tell if a method is prevented to do its job.
|
1207 |
+
*
|
1208 |
+
* @since 1.8
|
1209 |
+
* @access public
|
1210 |
+
* @author Grégory Viguier
|
1211 |
+
*
|
1212 |
+
* @param string $method_name Name of the method.
|
1213 |
+
* @return bool
|
1214 |
+
*/
|
1215 |
+
public function is_prevented( $method_name ) {
|
1216 |
+
return ! empty( self::$prevented[ $method_name ] );
|
1217 |
+
}
|
1218 |
+
|
1219 |
+
/**
|
1220 |
+
* Tell if a thumbnail size is disallowed for optimization..
|
1221 |
+
*
|
1222 |
+
* @since 1.8
|
1223 |
+
* @access public
|
1224 |
+
* @author Grégory Viguier
|
1225 |
+
*
|
1226 |
+
* @param string $size_name The size name.
|
1227 |
+
* @return bool
|
1228 |
+
*/
|
1229 |
+
public function size_is_disallowed( $size_name ) {
|
1230 |
+
static $disallowed_sizes;
|
1231 |
+
|
1232 |
+
if ( imagify_is_active_for_network() ) {
|
1233 |
+
return false;
|
1234 |
+
}
|
1235 |
+
|
1236 |
+
if ( ! isset( $disallowed_sizes ) ) {
|
1237 |
+
$disallowed_sizes = get_imagify_option( 'disallowed-sizes' );
|
1238 |
+
}
|
1239 |
+
|
1240 |
+
return isset( $disallowed_sizes[ $size_name ] );
|
1241 |
+
}
|
1242 |
+
|
1243 |
+
/**
|
1244 |
+
* Tell if a thumbnail file is a copy of the full size image. Will return false if the full size is not optimized.
|
1245 |
+
* Make sure both files exist before using this.
|
1246 |
+
*
|
1247 |
+
* @since 1.8
|
1248 |
+
* @access public
|
1249 |
+
* @author Grégory Viguier
|
1250 |
+
*
|
1251 |
+
* @param array $args {
|
1252 |
+
* An array of arguments.
|
1253 |
+
*
|
1254 |
+
* @type string $size_name The size name. Required.
|
1255 |
+
* @type array $metadata WP metadata. Required.
|
1256 |
+
* @type array $imagify_data Imagify data. Required.
|
1257 |
+
* @type string $retina_path Path to the image we're testing. Required.
|
1258 |
+
* @type string $full_path Path to the full size image. Optional but should be provided.
|
1259 |
+
* }
|
1260 |
+
* @return bool
|
1261 |
+
*/
|
1262 |
+
public function size_is_a_full_copy( $args ) {
|
1263 |
+
$size_name = $args['size_name'];
|
1264 |
+
$metadata = $args['metadata'];
|
1265 |
+
$imagify_data = $args['imagify_data'];
|
1266 |
+
|
1267 |
+
if ( empty( $imagify_data['sizes']['full'] ) ) {
|
1268 |
+
// The full size is not optimized, so there is no point in checking if the given file is a copy.
|
1269 |
+
return false;
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
if ( ! isset( $metadata['width'], $metadata['height'], $metadata['file'] ) ) {
|
1273 |
+
return false;
|
1274 |
+
}
|
1275 |
+
|
1276 |
+
if ( ! isset( $metadata['sizes'][ $size_name ]['width'], $metadata['sizes'][ $size_name ]['height'] ) ) {
|
1277 |
+
return false;
|
1278 |
+
}
|
1279 |
+
|
1280 |
+
$size = $metadata['sizes'][ $size_name ];
|
1281 |
+
|
1282 |
+
if ( $size['width'] * 2 !== $metadata['width'] || $size['height'] * 2 !== $metadata['height'] ) {
|
1283 |
+
// The full size image doesn't have the right dimensions.
|
1284 |
+
return false;
|
1285 |
+
}
|
1286 |
+
|
1287 |
+
if ( empty( $args['full_path'] ) ) {
|
1288 |
+
$dir_path = $this->filesystem->path_info( $args['retina_path'], 'dir_path' );
|
1289 |
+
$args['full_path'] = $dir_path . $metadata['file'];
|
1290 |
+
}
|
1291 |
+
|
1292 |
+
$full_hash = md5_file( $args['full_path'] );
|
1293 |
+
$retina_hash = md5_file( $args['retina_path'] );
|
1294 |
+
|
1295 |
+
return hash_equals( $full_hash, $retina_hash );
|
1296 |
+
}
|
1297 |
+
|
1298 |
+
/**
|
1299 |
+
* Tell if there is a filesystem error.
|
1300 |
+
*
|
1301 |
+
* @since 1.8
|
1302 |
+
* @access public
|
1303 |
+
* @author Grégory Viguier
|
1304 |
+
*
|
1305 |
+
* @return bool
|
1306 |
+
*/
|
1307 |
+
public function has_filesystem_error() {
|
1308 |
+
return ! empty( $this->filesystem->errors->errors );
|
1309 |
+
}
|
1310 |
+
|
1311 |
+
/**
|
1312 |
+
* Do few tests: method is not prevented, attachment is valid, filesystem has no error.
|
1313 |
+
*
|
1314 |
+
* @since 1.8
|
1315 |
+
* @access public
|
1316 |
+
* @author Grégory Viguier
|
1317 |
+
*
|
1318 |
+
* @param string $method The name of the method using this.
|
1319 |
+
* @param object $attachment An Imagify attachment.
|
1320 |
+
* @param array $args A list of additional tests.
|
1321 |
+
* @return bool|object True if ok, false if prevented, a WP_Error object on failure.
|
1322 |
+
*/
|
1323 |
+
public function validate( $method, $attachment = false, $args = array() ) {
|
1324 |
+
$args = array_merge( array(
|
1325 |
+
'supported' => false,
|
1326 |
+
'can_optimize' => false,
|
1327 |
+
'metadata_dimensions' => false,
|
1328 |
+
'metadata_file' => $attachment ? 'error' : false,
|
1329 |
+
'metadata_sizes' => $attachment ? 'error' : false,
|
1330 |
+
), $args );
|
1331 |
+
|
1332 |
+
if ( $this->is_prevented( $method ) ) {
|
1333 |
+
return false;
|
1334 |
+
}
|
1335 |
+
|
1336 |
+
if ( $attachment && ! $attachment->is_valid() ) {
|
1337 |
+
return new WP_Error( 'invalid_attachment', __( 'Invalid attachment.', 'imagify' ) );
|
1338 |
+
}
|
1339 |
+
|
1340 |
+
if ( $args['supported'] && ! $attachment->is_extension_supported() ) {
|
1341 |
+
if ( 'error' !== $args['supported'] ) {
|
1342 |
+
return false;
|
1343 |
+
}
|
1344 |
+
|
1345 |
+
return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
|
1346 |
+
}
|
1347 |
+
|
1348 |
+
if ( $args['can_optimize'] ) {
|
1349 |
+
if ( 'error' !== $args['can_optimize'] ) {
|
1350 |
+
if ( ! Imagify_Requirements::is_api_key_valid() || Imagify_Requirements::is_over_quota() ) {
|
1351 |
+
return false;
|
1352 |
+
}
|
1353 |
+
} else {
|
1354 |
+
if ( ! Imagify_Requirements::is_api_key_valid() ) {
|
1355 |
+
return new WP_Error( 'invalid_api_key', __( 'Your API key is not valid!', 'imagify' ) );
|
1356 |
+
}
|
1357 |
+
if ( Imagify_Requirements::is_over_quota() ) {
|
1358 |
+
return new WP_Error( 'over_quota', __( 'You have used all your credits!', 'imagify' ) );
|
1359 |
+
}
|
1360 |
+
}
|
1361 |
+
}
|
1362 |
+
|
1363 |
+
if ( $this->has_filesystem_error() ) {
|
1364 |
+
return new WP_Error( 'filesystem', __( 'Filesystem error.', 'imagify' ) );
|
1365 |
+
}
|
1366 |
+
|
1367 |
+
if ( $args['metadata_dimensions'] ) {
|
1368 |
+
$metadata = wp_get_attachment_metadata( $attachment->get_id() );
|
1369 |
+
|
1370 |
+
if ( empty( $metadata['width'] ) || empty( $metadata['height'] ) ) {
|
1371 |
+
if ( 'error' !== $args['metadata_sizes'] ) {
|
1372 |
+
return false;
|
1373 |
+
}
|
1374 |
+
|
1375 |
+
return new WP_Error( 'metadata_dimensions', __( 'This attachment lacks the required metadata.', 'imagify' ) );
|
1376 |
+
}
|
1377 |
+
}
|
1378 |
+
|
1379 |
+
if ( $args['metadata_file'] ) {
|
1380 |
+
$metadata = isset( $metadata ) ? $metadata : wp_get_attachment_metadata( $attachment->get_id() );
|
1381 |
+
|
1382 |
+
if ( empty( $metadata['file'] ) ) {
|
1383 |
+
if ( 'error' !== $args['metadata_file'] ) {
|
1384 |
+
return false;
|
1385 |
+
}
|
1386 |
+
|
1387 |
+
return new WP_Error( 'metadata_file', __( 'This attachment lacks the required metadata.', 'imagify' ) );
|
1388 |
+
}
|
1389 |
+
}
|
1390 |
+
|
1391 |
+
if ( $args['metadata_sizes'] ) {
|
1392 |
+
$metadata = isset( $metadata ) ? $metadata : wp_get_attachment_metadata( $attachment->get_id() );
|
1393 |
+
|
1394 |
+
if ( empty( $metadata['sizes'] ) || ! is_array( $metadata['sizes'] ) ) {
|
1395 |
+
if ( 'error' !== $args['metadata_sizes'] ) {
|
1396 |
+
return false;
|
1397 |
+
}
|
1398 |
+
|
1399 |
+
return new WP_Error( 'metadata_sizes', __( 'This attachment has no registered thumbnail sizes.', 'imagify' ) );
|
1400 |
+
}
|
1401 |
+
}
|
1402 |
+
|
1403 |
+
return true;
|
1404 |
+
}
|
1405 |
+
|
1406 |
+
/**
|
1407 |
+
* Tell if Imagify can optimize the files.
|
1408 |
+
*
|
1409 |
+
* @since 1.8
|
1410 |
+
* @access public
|
1411 |
+
* @author Grégory Viguier
|
1412 |
+
*
|
1413 |
+
* @return bool
|
1414 |
+
*/
|
1415 |
+
public function can_optimize() {
|
1416 |
+
return ! $this->has_filesystem_error() && Imagify_Requirements::is_api_key_valid() && ! Imagify_Requirements::is_over_quota();
|
1417 |
+
}
|
1418 |
+
|
1419 |
+
/**
|
1420 |
+
* Tell if Imagify can auto-optimize the files.
|
1421 |
+
*
|
1422 |
+
* @since 1.8
|
1423 |
+
* @access public
|
1424 |
+
* @author Grégory Viguier
|
1425 |
+
*
|
1426 |
+
* @return bool
|
1427 |
+
*/
|
1428 |
+
public function can_auto_optimize() {
|
1429 |
+
return $this->can_optimize() && get_imagify_option( 'auto_optimize' );
|
1430 |
+
}
|
1431 |
+
|
1432 |
+
/**
|
1433 |
+
* Get thumbnail sizes from an attachment.
|
1434 |
+
*
|
1435 |
+
* @since 1.8
|
1436 |
+
* @access public
|
1437 |
+
* @author Grégory Viguier
|
1438 |
+
*
|
1439 |
+
* @param object $attachment An Imagify attachment.
|
1440 |
+
* @return array
|
1441 |
+
*/
|
1442 |
+
public function get_attachment_sizes( $attachment ) {
|
1443 |
+
$metadata = wp_get_attachment_metadata( $attachment->get_id() );
|
1444 |
+
return ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ? $metadata['sizes'] : array();
|
1445 |
+
}
|
1446 |
+
|
1447 |
+
/**
|
1448 |
+
* Get the optimization level used to optimize the given attachment.
|
1449 |
+
*
|
1450 |
+
* @since 1.8
|
1451 |
+
* @access public
|
1452 |
+
* @author Grégory Viguier
|
1453 |
+
*
|
1454 |
+
* @param object $attachment An Imagify attachment.
|
1455 |
+
* @return int The attachment optimization level. The default level if not optimized.
|
1456 |
+
*/
|
1457 |
+
public function get_optimization_level( $attachment ) {
|
1458 |
+
static $default;
|
1459 |
+
|
1460 |
+
if ( $attachment->get_status() ) {
|
1461 |
+
$level = $attachment->get_optimization_level();
|
1462 |
+
|
1463 |
+
if ( is_int( $level ) ) {
|
1464 |
+
return $level;
|
1465 |
+
}
|
1466 |
+
}
|
1467 |
+
|
1468 |
+
if ( ! isset( $default ) ) {
|
1469 |
+
$default = get_imagify_option( 'optimization_level' );
|
1470 |
+
}
|
1471 |
+
|
1472 |
+
return $default;
|
1473 |
+
}
|
1474 |
+
|
1475 |
+
/**
|
1476 |
+
* Get the path to the temporary file.
|
1477 |
+
*
|
1478 |
+
* @since 1.8
|
1479 |
+
* @access public
|
1480 |
+
* @author Grégory Viguier
|
1481 |
+
*
|
1482 |
+
* @param string $file_path The optimized full-sized file path.
|
1483 |
+
* @return string
|
1484 |
+
*/
|
1485 |
+
public function get_temporary_file_path( $file_path ) {
|
1486 |
+
return $file_path . '_backup';
|
1487 |
+
}
|
1488 |
+
|
1489 |
+
/**
|
1490 |
+
* Backup the optimized full-sized file and replace it by the original backup file.
|
1491 |
+
*
|
1492 |
+
* @since 1.8
|
1493 |
+
* @access public
|
1494 |
+
* @author Grégory Viguier
|
1495 |
+
*
|
1496 |
+
* @param object $attachment An Imagify attachment.
|
1497 |
+
*/
|
1498 |
+
public function backup_optimized_file( $attachment ) {
|
1499 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
1500 |
+
return;
|
1501 |
+
}
|
1502 |
+
|
1503 |
+
$backup_path = $attachment->get_backup_path();
|
1504 |
+
|
1505 |
+
if ( ! $backup_path || ! $attachment->is_optimized() ) {
|
1506 |
+
return;
|
1507 |
+
}
|
1508 |
+
|
1509 |
+
/**
|
1510 |
+
* Replace the optimized full-sized file by the backup, so any optimization will not use an optimized file, but the original one.
|
1511 |
+
* The optimized full-sized file is kept and renamed, and will be put back in place at the end of the optimization process.
|
1512 |
+
*/
|
1513 |
+
$file_path = $attachment->get_original_path();
|
1514 |
+
$tmp_file_path = $this->get_temporary_file_path( $file_path );
|
1515 |
+
|
1516 |
+
if ( $this->filesystem->exists( $file_path ) ) {
|
1517 |
+
$this->filesystem->move( $file_path, $tmp_file_path, true );
|
1518 |
+
}
|
1519 |
+
|
1520 |
+
$copied = $this->filesystem->copy( $backup_path, $file_path );
|
1521 |
+
|
1522 |
+
if ( ! $copied ) {
|
1523 |
+
// Uh ho...
|
1524 |
+
$this->filesystem->move( $tmp_file_path, $file_path, true );
|
1525 |
+
return;
|
1526 |
+
}
|
1527 |
+
|
1528 |
+
// Make sure the dimensions are in sync in post meta.
|
1529 |
+
$this->maybe_update_image_dimensions( $attachment, $file_path );
|
1530 |
+
}
|
1531 |
+
|
1532 |
+
/**
|
1533 |
+
* Put the optimized full-sized file back.
|
1534 |
+
*
|
1535 |
+
* @since 1.8
|
1536 |
+
* @access public
|
1537 |
+
* @author Grégory Viguier
|
1538 |
+
*
|
1539 |
+
* @param object $attachment An Imagify attachment.
|
1540 |
+
*/
|
1541 |
+
public function put_optimized_file_back( $attachment ) {
|
1542 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
1543 |
+
return;
|
1544 |
+
}
|
1545 |
+
|
1546 |
+
$file_path = $attachment->get_original_path();
|
1547 |
+
$tmp_file_path = $this->get_temporary_file_path( $file_path );
|
1548 |
+
|
1549 |
+
if ( ! $this->filesystem->exists( $tmp_file_path ) ) {
|
1550 |
+
return;
|
1551 |
+
}
|
1552 |
+
|
1553 |
+
$moved = $this->filesystem->move( $tmp_file_path, $file_path, true );
|
1554 |
+
|
1555 |
+
if ( ! $moved ) {
|
1556 |
+
// Uh ho...
|
1557 |
+
return;
|
1558 |
+
}
|
1559 |
+
|
1560 |
+
// Make sure the dimensions are in sync in post meta.
|
1561 |
+
$this->maybe_update_image_dimensions( $attachment, $file_path );
|
1562 |
+
}
|
1563 |
+
|
1564 |
+
/**
|
1565 |
+
* Make sure the dimensions are in sync in post meta.
|
1566 |
+
*
|
1567 |
+
* @since 1.8
|
1568 |
+
* @access public
|
1569 |
+
* @author Grégory Viguier
|
1570 |
+
*
|
1571 |
+
* @param object $attachment An Imagify attachment.
|
1572 |
+
* @param string $file_path Path to the file.
|
1573 |
+
* @return bool True when updated.
|
1574 |
+
*/
|
1575 |
+
public function maybe_update_image_dimensions( $attachment, $file_path ) {
|
1576 |
+
if ( $this->is_prevented( __FUNCTION__ ) ) {
|
1577 |
+
return false;
|
1578 |
+
}
|
1579 |
+
|
1580 |
+
$metadata = wp_get_attachment_metadata( $attachment->get_id() );
|
1581 |
+
$width = ! empty( $metadata['width'] ) ? (int) $metadata['width'] : 0;
|
1582 |
+
$height = ! empty( $metadata['height'] ) ? (int) $metadata['height'] : 0;
|
1583 |
+
$dimensions = $this->filesystem->get_image_size( $file_path );
|
1584 |
+
|
1585 |
+
if ( ! $dimensions ) {
|
1586 |
+
return false;
|
1587 |
+
}
|
1588 |
+
|
1589 |
+
if ( $width === $dimensions['width'] && $height === $dimensions['height'] ) {
|
1590 |
+
return false;
|
1591 |
+
}
|
1592 |
+
|
1593 |
+
$metadata['width'] = $dimensions['width'];
|
1594 |
+
$metadata['height'] = $dimensions['height'];
|
1595 |
+
|
1596 |
+
wp_update_attachment_metadata( $attachment->get_id(), $metadata );
|
1597 |
+
return true;
|
1598 |
+
}
|
1599 |
+
|
1600 |
+
|
1601 |
+
/** ----------------------------------------------------------------------------------------- */
|
1602 |
+
/** WR2X COMPAT' TOOLS ====================================================================== */
|
1603 |
+
/** ----------------------------------------------------------------------------------------- */
|
1604 |
+
|
1605 |
+
/**
|
1606 |
+
* Get the suffix added to the file name, with a trailing dot.
|
1607 |
+
* Don't use it for the size name.
|
1608 |
+
*
|
1609 |
+
* @since 1.8
|
1610 |
+
* @access public
|
1611 |
+
* @author Grégory Viguier
|
1612 |
+
*
|
1613 |
+
* @return string
|
1614 |
+
*/
|
1615 |
+
public function get_suffix() {
|
1616 |
+
global $wr2x_core;
|
1617 |
+
static $suffix;
|
1618 |
+
|
1619 |
+
if ( ! isset( $suffix ) ) {
|
1620 |
+
$suffix = $wr2x_core && is_object( $wr2x_core ) && method_exists( $wr2x_core, 'retina_extension' ) ? $wr2x_core->retina_extension() : '@2x.';
|
1621 |
+
}
|
1622 |
+
|
1623 |
+
return $suffix;
|
1624 |
+
}
|
1625 |
+
|
1626 |
+
/**
|
1627 |
+
* Get info about retina version.
|
1628 |
+
*
|
1629 |
+
* @since 1.8
|
1630 |
+
* @access public
|
1631 |
+
* @author Grégory Viguier
|
1632 |
+
*
|
1633 |
+
* @param object $attachment An Imagify attachment.
|
1634 |
+
* @param string $type The type of info. Possible values are 'basic' and 'full' (for the full size).
|
1635 |
+
* @return array An array containing some HTML, indexed by the attachment ID.
|
1636 |
+
*/
|
1637 |
+
public function get_retina_info( $attachment, $type = 'basic' ) {
|
1638 |
+
global $wr2x_core;
|
1639 |
+
static $can_get_info;
|
1640 |
+
|
1641 |
+
if ( ! isset( $can_get_info ) ) {
|
1642 |
+
$can_get_info = $wr2x_core && is_object( $wr2x_core ) && method_exists( $wr2x_core, 'retina_info' ) && method_exists( $wr2x_core, 'html_get_basic_retina_info_full' ) && method_exists( $wr2x_core, 'html_get_basic_retina_info' );
|
1643 |
+
}
|
1644 |
+
|
1645 |
+
if ( ! $can_get_info ) {
|
1646 |
+
return '';
|
1647 |
+
}
|
1648 |
+
|
1649 |
+
$attachment_id = $attachment->get_id();
|
1650 |
+
$info = $wr2x_core->retina_info( $attachment_id );
|
1651 |
+
|
1652 |
+
if ( 'full' === $type ) {
|
1653 |
+
return array(
|
1654 |
+
$attachment_id => $wr2x_core->html_get_basic_retina_info_full( $attachment_id, $info ),
|
1655 |
+
);
|
1656 |
+
}
|
1657 |
+
|
1658 |
+
return array(
|
1659 |
+
$attachment_id => $wr2x_core->html_get_basic_retina_info( $attachment_id, $info ),
|
1660 |
+
);
|
1661 |
+
}
|
1662 |
+
|
1663 |
+
/**
|
1664 |
+
* Log.
|
1665 |
+
*
|
1666 |
+
* @since 1.8
|
1667 |
+
* @access public
|
1668 |
+
* @author Grégory Viguier
|
1669 |
+
*
|
1670 |
+
* @param string $text Text to log.
|
1671 |
+
*/
|
1672 |
+
public function log( $text ) {
|
1673 |
+
global $wr2x_core;
|
1674 |
+
static $can_log;
|
1675 |
+
|
1676 |
+
if ( ! isset( $can_log ) ) {
|
1677 |
+
$can_log = $wr2x_core && is_object( $wr2x_core ) && method_exists( $wr2x_core, 'log' );
|
1678 |
+
}
|
1679 |
+
|
1680 |
+
if ( $can_log ) {
|
1681 |
+
$wr2x_core->log( $text );
|
1682 |
+
}
|
1683 |
+
}
|
1684 |
+
}
|
inc/3rd-party/wp-retina-2x/inc/classes/class-imagify-wp-retina-2x.php
ADDED
@@ -0,0 +1,680 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class that handles compatibility with WP Retina 2x plugin.
|
6 |
+
*
|
7 |
+
* @since 1.8
|
8 |
+
* @author Grégory Viguier
|
9 |
+
*/
|
10 |
+
class Imagify_WP_Retina_2x {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class version.
|
14 |
+
*
|
15 |
+
* @var string
|
16 |
+
* @since 1.8
|
17 |
+
* @author Grégory Viguier
|
18 |
+
*/
|
19 |
+
const VERSION = '1.0';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Core instance.
|
23 |
+
*
|
24 |
+
* @var object Imagify_WP_Retina_2x_Core
|
25 |
+
* @since 1.8
|
26 |
+
* @access protected
|
27 |
+
* @author Grégory Viguier
|
28 |
+
*/
|
29 |
+
protected $core;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The single instance of the class.
|
33 |
+
*
|
34 |
+
* @var object Imagify_WP_Retina_2x
|
35 |
+
* @since 1.8
|
36 |
+
* @access protected
|
37 |
+
* @author Grégory Viguier
|
38 |
+
*/
|
39 |
+
protected static $_instance;
|
40 |
+
|
41 |
+
|
42 |
+
/** ----------------------------------------------------------------------------------------- */
|
43 |
+
/** INSTANCE ================================================================================ */
|
44 |
+
/** ----------------------------------------------------------------------------------------- */
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Get the main Instance.
|
48 |
+
*
|
49 |
+
* @since 1.8
|
50 |
+
* @access public
|
51 |
+
* @author Grégory Viguier
|
52 |
+
*
|
53 |
+
* @return object Main instance.
|
54 |
+
*/
|
55 |
+
public static function get_instance() {
|
56 |
+
if ( ! isset( self::$_instance ) ) {
|
57 |
+
self::$_instance = new self();
|
58 |
+
}
|
59 |
+
|
60 |
+
return self::$_instance;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* The constructor.
|
65 |
+
*
|
66 |
+
* @since 1.8
|
67 |
+
* @access protected
|
68 |
+
* @author Grégory Viguier
|
69 |
+
*/
|
70 |
+
protected function __construct() {}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get the core Instance.
|
74 |
+
*
|
75 |
+
* @since 1.8
|
76 |
+
* @access public
|
77 |
+
* @author Grégory Viguier
|
78 |
+
*
|
79 |
+
* @return object Imagify_WP_Retina_2x_Core instance.
|
80 |
+
*/
|
81 |
+
public function get_core() {
|
82 |
+
if ( ! isset( $this->core ) ) {
|
83 |
+
$this->core = new Imagify_WP_Retina_2x_Core();
|
84 |
+
}
|
85 |
+
|
86 |
+
return $this->core;
|
87 |
+
}
|
88 |
+
|
89 |
+
|
90 |
+
/** ----------------------------------------------------------------------------------------- */
|
91 |
+
/** INIT ==================================================================================== */
|
92 |
+
/** ----------------------------------------------------------------------------------------- */
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Launch the hooks.
|
96 |
+
*
|
97 |
+
* @since 1.8
|
98 |
+
* @access public
|
99 |
+
* @author Grégory Viguier
|
100 |
+
*/
|
101 |
+
public function init() {
|
102 |
+
// Deal with Imagify when WPR2X is working.
|
103 |
+
add_action( 'wp_ajax_wr2x_generate', array( $this, 'wr2x_generate_ajax_cb' ), 5 );
|
104 |
+
add_action( 'wp_ajax_wr2x_delete', array( $this, 'wr2x_delete_all_retina_ajax_cb' ), 5 );
|
105 |
+
add_action( 'wp_ajax_wr2x_delete_full', array( $this, 'wr2x_delete_full_retina_ajax_cb' ), 5 );
|
106 |
+
add_action( 'wp_ajax_wr2x_replace', array( $this, 'wr2x_replace_all_ajax_cb' ), 5 );
|
107 |
+
add_action( 'wp_ajax_wr2x_upload', array( $this, 'wr2x_replace_full_retina_ajax_cb' ), 5 );
|
108 |
+
add_action( 'imagify_assets_enqueued', array( $this, 'enqueue_scripts' ) );
|
109 |
+
add_action( 'wr2x_retina_file_removed', array( $this, 'remove_retina_thumbnail_data_hook' ), 10, 2 );
|
110 |
+
// Deal with Imagify when WP is working.
|
111 |
+
add_action( 'delete_attachment', array( $this, 'delete_full_retina_backup_file_hook' ) );
|
112 |
+
// Deal with retina thumbnails when Imagify processes the "normal" images.
|
113 |
+
add_filter( 'imagify_fill_full_size_data', array( $this, 'optimize_full_retina_version_hook' ), 10, 8 );
|
114 |
+
add_filter( 'imagify_fill_thumbnail_data', array( $this, 'optimize_retina_version_hook' ), 10, 8 );
|
115 |
+
add_filter( 'imagify_fill_unauthorized_thumbnail_data', array( $this, 'maybe_optimize_unauthorized_retina_version_hook' ), 10, 7 );
|
116 |
+
add_action( 'after_imagify_restore_attachment', array( $this, 'restore_retina_images_hook' ) );
|
117 |
+
}
|
118 |
+
|
119 |
+
|
120 |
+
/** ----------------------------------------------------------------------------------------- */
|
121 |
+
/** AJAX CALLBACKS ========================================================================== */
|
122 |
+
/** ----------------------------------------------------------------------------------------- */
|
123 |
+
|
124 |
+
/**
|
125 |
+
* (Re)generate the retina thumbnails (except the full size).
|
126 |
+
*
|
127 |
+
* @since 1.8
|
128 |
+
* @access public
|
129 |
+
* @author Grégory Viguier
|
130 |
+
*/
|
131 |
+
public function wr2x_generate_ajax_cb() {
|
132 |
+
$this->check_nonce( 'imagify_wr2x_generate' );
|
133 |
+
$this->check_user_capacity();
|
134 |
+
|
135 |
+
$attachment = $this->get_requested_attachment( 'wr2x_generate' );
|
136 |
+
|
137 |
+
// Delete previous retina images and recreate them.
|
138 |
+
$result = $this->get_core()->regenerate_retina_images( $attachment );
|
139 |
+
|
140 |
+
// Send results.
|
141 |
+
$this->maybe_send_json_error( $result );
|
142 |
+
|
143 |
+
$this->send_json( array(
|
144 |
+
'results' => $this->get_core()->get_retina_info( $attachment ),
|
145 |
+
'message' => __( 'Retina files generated.', 'imagify' ),
|
146 |
+
'imagify_info' => $this->get_imagify_info( $attachment ),
|
147 |
+
) );
|
148 |
+
}
|
149 |
+
|
150 |
+
/**
|
151 |
+
* Delete all retina images, including the one for the full size.
|
152 |
+
*
|
153 |
+
* @since 1.8
|
154 |
+
* @access public
|
155 |
+
* @author Grégory Viguier
|
156 |
+
*/
|
157 |
+
public function wr2x_delete_all_retina_ajax_cb() {
|
158 |
+
$this->check_nonce( 'imagify_wr2x_delete' );
|
159 |
+
$this->check_user_capacity();
|
160 |
+
|
161 |
+
$attachment = $this->get_requested_attachment( 'wr2x_delete_all' );
|
162 |
+
|
163 |
+
// Delete the retina versions, including the full size.
|
164 |
+
$result = $this->get_core()->delete_retina_images( $attachment, true );
|
165 |
+
|
166 |
+
// Send results.
|
167 |
+
$this->maybe_send_json_error( $result );
|
168 |
+
|
169 |
+
$this->send_json( array(
|
170 |
+
'results' => $this->get_core()->get_retina_info( $attachment ),
|
171 |
+
'results_full' => $this->get_core()->get_retina_info( $attachment, 'full' ),
|
172 |
+
'message' => __( 'Retina files deleted.', 'imagify' ),
|
173 |
+
) );
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Delete the retina version of the full size.
|
178 |
+
*
|
179 |
+
* @since 1.8
|
180 |
+
* @access public
|
181 |
+
* @author Grégory Viguier
|
182 |
+
*/
|
183 |
+
public function wr2x_delete_full_retina_ajax_cb() {
|
184 |
+
$this->check_nonce( 'imagify_wr2x_delete_full' );
|
185 |
+
$this->check_user_capacity();
|
186 |
+
|
187 |
+
$attachment = $this->get_requested_attachment( 'wr2x_delete_full' );
|
188 |
+
|
189 |
+
$result = $this->get_core()->delete_full_retina_image( $attachment );
|
190 |
+
|
191 |
+
// Send results.
|
192 |
+
$this->maybe_send_json_error( $result );
|
193 |
+
|
194 |
+
$this->send_json( array(
|
195 |
+
'results' => $this->get_core()->get_retina_info( $attachment, 'full' ),
|
196 |
+
'message' => __( 'Full retina file deleted.', 'imagify' ),
|
197 |
+
) );
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Replace an attachment (except the retina version of the full size).
|
202 |
+
*
|
203 |
+
* @since 1.8
|
204 |
+
* @access public
|
205 |
+
* @author Grégory Viguier
|
206 |
+
*/
|
207 |
+
public function wr2x_replace_all_ajax_cb() {
|
208 |
+
$this->check_nonce( 'imagify_wr2x_replace' );
|
209 |
+
$this->check_user_capacity();
|
210 |
+
|
211 |
+
$attachment = $this->get_requested_attachment( 'wr2x_replace_all' );
|
212 |
+
$tmp_file_path = $this->get_uploaded_file_path();
|
213 |
+
|
214 |
+
$result = $this->get_core()->replace_attachment( $attachment, $tmp_file_path );
|
215 |
+
|
216 |
+
// Send results.
|
217 |
+
$this->maybe_send_json_error( $result );
|
218 |
+
|
219 |
+
$this->send_json( array(
|
220 |
+
'results' => $this->get_core()->get_retina_info( $attachment ),
|
221 |
+
'message' => __( 'Images replaced successfully.', 'imagify' ),
|
222 |
+
) );
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Upload a new retina version for the full size.
|
227 |
+
*
|
228 |
+
* @since 1.8
|
229 |
+
* @access public
|
230 |
+
* @author Grégory Viguier
|
231 |
+
*/
|
232 |
+
public function wr2x_replace_full_retina_ajax_cb() {
|
233 |
+
$this->check_nonce( 'imagify_wr2x_upload' );
|
234 |
+
$this->check_user_capacity();
|
235 |
+
|
236 |
+
$attachment = $this->get_requested_attachment( 'wr2x_replace_full' );
|
237 |
+
$tmp_file_path = $this->get_uploaded_file_path();
|
238 |
+
|
239 |
+
$result = $this->get_core()->replace_full_retina_image( $attachment, $tmp_file_path );
|
240 |
+
|
241 |
+
// Send results.
|
242 |
+
$this->maybe_send_json_error( $result );
|
243 |
+
|
244 |
+
$this->send_json( array(
|
245 |
+
'results' => $this->get_core()->get_retina_info( $attachment ),
|
246 |
+
'message' => __( 'Image replaced successfully.', 'imagify' ),
|
247 |
+
) );
|
248 |
+
}
|
249 |
+
|
250 |
+
|
251 |
+
/** ----------------------------------------------------------------------------------------- */
|
252 |
+
/** OTHER HOOKS ============================================================================= */
|
253 |
+
/** ----------------------------------------------------------------------------------------- */
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Queue some JS to add our nonce parameter to all WR2X jQuery ajax requests.
|
257 |
+
*
|
258 |
+
* @since 1.8
|
259 |
+
* @access public
|
260 |
+
* @author Grégory Viguier
|
261 |
+
*/
|
262 |
+
public function enqueue_scripts() {
|
263 |
+
if ( ! $this->user_can() ) {
|
264 |
+
return;
|
265 |
+
}
|
266 |
+
|
267 |
+
$assets = Imagify_Assets::get_instance();
|
268 |
+
|
269 |
+
$assets->register_script( 'weakmap-polyfill', 'weakmap-polyfill', array(), '2.0.0' );
|
270 |
+
$assets->register_script( 'formdata-polyfill', 'formdata-polyfill', array( 'weakmap-polyfill' ), '3.0.10-beta' );
|
271 |
+
$assets->register_script( 'wp-retina-2x', 'imagify-wp-retina-2x', array( 'formdata-polyfill', 'jquery' ) );
|
272 |
+
|
273 |
+
if ( imagify_is_screen( 'library' ) || imagify_is_screen( 'media_page_wp-retina-2x' ) ) {
|
274 |
+
$assets->localize_script( 'wp-retina-2x', 'imagifyRetina2x', array(
|
275 |
+
'wr2x_generate' => wp_create_nonce( 'imagify_wr2x_generate' ),
|
276 |
+
'wr2x_delete' => wp_create_nonce( 'imagify_wr2x_delete' ),
|
277 |
+
'wr2x_delete_full' => wp_create_nonce( 'imagify_wr2x_delete_full' ),
|
278 |
+
'wr2x_replace' => wp_create_nonce( 'imagify_wr2x_replace' ),
|
279 |
+
'wr2x_upload' => wp_create_nonce( 'imagify_wr2x_upload' ),
|
280 |
+
) );
|
281 |
+
$assets->enqueue( 'wp-retina-2x' );
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* After a retina thumbnail is deleted, remove its Imagify data.
|
287 |
+
* This should be useless since we replaced every AJAX callbacks.
|
288 |
+
*
|
289 |
+
* @since 1.8
|
290 |
+
* @access public
|
291 |
+
* @see wr2x_delete_attachment()
|
292 |
+
* @author Grégory Viguier
|
293 |
+
*
|
294 |
+
* @param int $attachment_id An attachment ID.
|
295 |
+
* @param string $retina_filename The retina thumbnail file name.
|
296 |
+
*/
|
297 |
+
public function remove_retina_thumbnail_data_hook( $attachment_id, $retina_filename ) {
|
298 |
+
$attachment = get_imagify_attachment( 'wp', $attachment_id, 'wr2x_delete' );
|
299 |
+
|
300 |
+
$this->get_core()->remove_retina_image_data_by_filename( $attachment, $retina_filename );
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
* Delete the backup of the retina version of the full size file when an attachement is deleted.
|
305 |
+
*
|
306 |
+
* @since 1.8
|
307 |
+
* @access public
|
308 |
+
* @author Grégory Viguier
|
309 |
+
*
|
310 |
+
* @param int $attachment_id An attachment ID.
|
311 |
+
*/
|
312 |
+
public function delete_full_retina_backup_file_hook( $attachment_id ) {
|
313 |
+
if ( ! $this->get_core()->is_supported_format( $attachment_id ) ) {
|
314 |
+
return;
|
315 |
+
}
|
316 |
+
|
317 |
+
$attachment = get_imagify_attachment( 'wp', $attachment_id, 'delete_attachment' );
|
318 |
+
$retina_path = $this->get_core()->get_retina_path( $attachment->get_original_path() );
|
319 |
+
|
320 |
+
if ( $retina_path ) {
|
321 |
+
$this->get_core()->delete_file_backup( $retina_path );
|
322 |
+
}
|
323 |
+
}
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Filter the optimization data of the full size.
|
327 |
+
*
|
328 |
+
* @since 1.8
|
329 |
+
* @access public
|
330 |
+
* @author Grégory Viguier
|
331 |
+
*
|
332 |
+
* @param array $data The statistics data.
|
333 |
+
* @param object $response The API response.
|
334 |
+
* @param int $attachment_id The attachment ID.
|
335 |
+
* @param string $path The attachment path.
|
336 |
+
* @param string $url The attachment URL.
|
337 |
+
* @param string $size_key The attachment size key. The value is obviously 'full' but it's kept for oncistancy with other filters.
|
338 |
+
* @param int $optimization_level The optimization level.
|
339 |
+
* @param array $metadata WP metadata.
|
340 |
+
* @return array $data The new optimization data.
|
341 |
+
*/
|
342 |
+
public function optimize_full_retina_version_hook( $data, $response, $attachment_id, $path, $url, $size_key, $optimization_level, $metadata ) {
|
343 |
+
if ( ! $this->get_core()->is_supported_format( $attachment_id ) ) {
|
344 |
+
return $data;
|
345 |
+
}
|
346 |
+
|
347 |
+
$attachment = get_imagify_attachment( 'wp', $attachment_id, 'optimize_full_retina_version_hook' );
|
348 |
+
|
349 |
+
return $this->get_core()->optimize_retina_image( array(
|
350 |
+
'data' => $data,
|
351 |
+
'attachment' => get_imagify_attachment( 'wp', $attachment_id, 'optimize_full_retina_version_hook' ),
|
352 |
+
'retina_path' => wr2x_get_retina( $path ),
|
353 |
+
'size_key' => $size_key,
|
354 |
+
'optimization_level' => $optimization_level,
|
355 |
+
'metadata' => $metadata,
|
356 |
+
) );
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* Filter the optimization data of each thumbnail.
|
361 |
+
*
|
362 |
+
* @since 1.8
|
363 |
+
* @access public
|
364 |
+
* @author Grégory Viguier
|
365 |
+
*
|
366 |
+
* @param array $data The statistics data.
|
367 |
+
* @param object $response The API response.
|
368 |
+
* @param int $attachment_id The attachment ID.
|
369 |
+
* @param string $path The thumbnail path.
|
370 |
+
* @param string $url The thumbnail URL.
|
371 |
+
* @param string $size_key The thumbnail size key.
|
372 |
+
* @param int $optimization_level The optimization level.
|
373 |
+
* @param array $metadata WP metadata.
|
374 |
+
* @return array $data The new optimization data.
|
375 |
+
*/
|
376 |
+
public function optimize_retina_version_hook( $data, $response, $attachment_id, $path, $url, $size_key, $optimization_level, $metadata ) {
|
377 |
+
if ( ! $this->get_core()->is_supported_format( $attachment_id ) ) {
|
378 |
+
return $data;
|
379 |
+
}
|
380 |
+
|
381 |
+
return $this->get_core()->optimize_retina_image( array(
|
382 |
+
'data' => $data,
|
383 |
+
'attachment' => get_imagify_attachment( 'wp', $attachment_id, 'optimize_retina_version_hook' ),
|
384 |
+
'retina_path' => wr2x_get_retina( $path ),
|
385 |
+
'size_key' => $size_key,
|
386 |
+
'optimization_level' => $optimization_level,
|
387 |
+
'metadata' => $metadata,
|
388 |
+
) );
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* If a thumbnail size is disallowed in Imagify' settings, we can still try to optimize its "@2x" version.
|
393 |
+
*
|
394 |
+
* @since 1.8
|
395 |
+
* @access public
|
396 |
+
* @author Grégory Viguier
|
397 |
+
*
|
398 |
+
* @param array $data The statistics data.
|
399 |
+
* @param int $attachment_id The attachment ID.
|
400 |
+
* @param string $path The thumbnail path.
|
401 |
+
* @param string $url The thumbnail URL.
|
402 |
+
* @param string $size_key The thumbnail size key.
|
403 |
+
* @param int $optimization_level The optimization level.
|
404 |
+
* @param array $metadata WP metadata.
|
405 |
+
* @return array $data The new optimization data.
|
406 |
+
*/
|
407 |
+
public function maybe_optimize_unauthorized_retina_version_hook( $data, $attachment_id, $path, $url, $size_key, $optimization_level, $metadata ) {
|
408 |
+
if ( ! $this->get_core()->is_supported_format( $attachment_id ) ) {
|
409 |
+
return $data;
|
410 |
+
}
|
411 |
+
|
412 |
+
return $this->get_core()->optimize_retina_image( array(
|
413 |
+
'data' => $data,
|
414 |
+
'attachment' => get_imagify_attachment( 'wp', $attachment_id, 'maybe_optimize_unauthorized_retina_version_hook' ),
|
415 |
+
'retina_path' => wr2x_get_retina( $path ),
|
416 |
+
'size_key' => $size_key,
|
417 |
+
'optimization_level' => $optimization_level,
|
418 |
+
'metadata' => $metadata,
|
419 |
+
) );
|
420 |
+
}
|
421 |
+
|
422 |
+
/**
|
423 |
+
* Delete previous retina images and recreate them.
|
424 |
+
*
|
425 |
+
* @since 1.8
|
426 |
+
* @access public
|
427 |
+
* @author Grégory Viguier
|
428 |
+
*
|
429 |
+
* @param int $attachment_id An attachment ID.
|
430 |
+
*/
|
431 |
+
public function restore_retina_images_hook( $attachment_id ) {
|
432 |
+
if ( ! $this->get_core()->is_supported_format( $attachment_id ) ) {
|
433 |
+
return;
|
434 |
+
}
|
435 |
+
|
436 |
+
$attachment = get_imagify_attachment( 'wp', $attachment_id, 'restore_retina_images_hook' );
|
437 |
+
|
438 |
+
if ( ! $this->get_core()->has_retina_images( $attachment ) ) {
|
439 |
+
return;
|
440 |
+
}
|
441 |
+
|
442 |
+
// At this point, previous Imagify data has been removed.
|
443 |
+
$this->get_core()->regenerate_retina_images( $attachment );
|
444 |
+
$this->get_core()->restore_full_retina_file( $attachment );
|
445 |
+
}
|
446 |
+
|
447 |
+
|
448 |
+
/** ----------------------------------------------------------------------------------------- */
|
449 |
+
/** INTERNAL TOOLS ========================================================================== */
|
450 |
+
/** ----------------------------------------------------------------------------------------- */
|
451 |
+
|
452 |
+
/**
|
453 |
+
* Check for nonce.
|
454 |
+
*
|
455 |
+
* @since 1.8
|
456 |
+
* @access public
|
457 |
+
* @author Grégory Viguier
|
458 |
+
*
|
459 |
+
* @param string $action Action nonce.
|
460 |
+
* @param string|bool $query_arg Optional. Key to check for the nonce in `$_REQUEST`. If false, `$_REQUEST` values will be evaluated for '_ajax_nonce', and '_wpnonce' (in that order). Default false.
|
461 |
+
*/
|
462 |
+
public function check_nonce( $action, $query_arg = 'imagify_nonce' ) {
|
463 |
+
if ( ! check_ajax_referer( $action, $query_arg, false ) ) {
|
464 |
+
$this->send_json( array(
|
465 |
+
'success' => false,
|
466 |
+
'message' => __( 'Sorry, you are not allowed to do that.', 'imagify' ),
|
467 |
+
) );
|
468 |
+
}
|
469 |
+
}
|
470 |
+
|
471 |
+
/**
|
472 |
+
* Check for user capacity.
|
473 |
+
*
|
474 |
+
* @since 1.8
|
475 |
+
* @access public
|
476 |
+
* @author Grégory Viguier
|
477 |
+
*/
|
478 |
+
public function check_user_capacity() {
|
479 |
+
if ( ! $this->user_can() ) {
|
480 |
+
$this->send_json( array(
|
481 |
+
'success' => false,
|
482 |
+
'message' => __( 'Sorry, you are not allowed to do that.', 'imagify' ),
|
483 |
+
) );
|
484 |
+
}
|
485 |
+
}
|
486 |
+
|
487 |
+
/**
|
488 |
+
* Tell if the current user can re-optimize files.
|
489 |
+
*
|
490 |
+
* @since 1.8
|
491 |
+
* @access public
|
492 |
+
* @author Grégory Viguier
|
493 |
+
*/
|
494 |
+
public function user_can() {
|
495 |
+
return imagify_current_user_can( 'auto-optimize' );
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Shorthand to get the attachment ID sent via $_POST.
|
500 |
+
*
|
501 |
+
* @since 1.8
|
502 |
+
* @access public
|
503 |
+
* @author Grégory Viguier
|
504 |
+
*
|
505 |
+
* @param string $context The context to use in get_imagify_attachment().
|
506 |
+
* @param string $key The $_POST key.
|
507 |
+
* @return int $attachment_id
|
508 |
+
*/
|
509 |
+
public function get_requested_attachment( $context, $key = 'attachmentId' ) {
|
510 |
+
$attachment_id = filter_input( INPUT_POST, $key, FILTER_VALIDATE_INT );
|
511 |
+
|
512 |
+
if ( $attachment_id <= 0 ) {
|
513 |
+
$this->send_json( array(
|
514 |
+
'success' => false,
|
515 |
+
'message' => __( 'The attachment ID is missing.', 'imagify' ),
|
516 |
+
) );
|
517 |
+
}
|
518 |
+
|
519 |
+
if ( ! $this->get_core()->is_supported_format( $attachment_id ) ) {
|
520 |
+
$this->send_json( array(
|
521 |
+
'success' => false,
|
522 |
+
'message' => __( 'This format is not supported.', 'imagify' ),
|
523 |
+
) );
|
524 |
+
}
|
525 |
+
|
526 |
+
$attachment = get_imagify_attachment( 'wp', $attachment_id, $context );
|
527 |
+
|
528 |
+
if ( ! $this->has_required_metadata( $attachment ) ) {
|
529 |
+
$this->send_json( array(
|
530 |
+
'success' => false,
|
531 |
+
'message' => __( 'This attachment lacks the required metadata.', 'imagify' ),
|
532 |
+
) );
|
533 |
+
}
|
534 |
+
|
535 |
+
return $attachment;
|
536 |
+
}
|
537 |
+
|
538 |
+
/**
|
539 |
+
* Shorthand to get the path to the uploaded file.
|
540 |
+
*
|
541 |
+
* @since 1.8
|
542 |
+
* @access public
|
543 |
+
* @author Grégory Viguier
|
544 |
+
*
|
545 |
+
* @return string Path to the temporary file.
|
546 |
+
*/
|
547 |
+
public function get_uploaded_file_path() {
|
548 |
+
$tmp_file_path = ! empty( $_FILES['file']['tmp_name'] ) && is_uploaded_file( $_FILES['file']['tmp_name'] ) ? $_FILES['file']['tmp_name'] : '';
|
549 |
+
$filesystem = Imagify_Filesystem::get_instance();
|
550 |
+
|
551 |
+
if ( ! $tmp_file_path || ! $filesystem->is_image( $tmp_file_path ) ) {
|
552 |
+
$this->get_core()->log( 'The file is not an image or the upload went wrong.' );
|
553 |
+
$filesystem->delete( $tmp_file_path );
|
554 |
+
|
555 |
+
$this->send_json_string( array(
|
556 |
+
'success' => false,
|
557 |
+
'message' => __( 'The file is not an image or the upload went wrong.', 'imagify' ),
|
558 |
+
) );
|
559 |
+
}
|
560 |
+
|
561 |
+
$file_name = filter_input( INPUT_POST, 'filename', FILTER_SANITIZE_STRING );
|
562 |
+
$file_data = wp_check_filetype_and_ext( $tmp_file_path, $file_name );
|
563 |
+
|
564 |
+
if ( empty( $file_data['ext'] ) ) {
|
565 |
+
$this->get_core()->log( 'You cannot use this file (wrong extension? wrong type?).' );
|
566 |
+
$filesystem->delete( $tmp_file_path );
|
567 |
+
|
568 |
+
$this->send_json_string( array(
|
569 |
+
'success' => false,
|
570 |
+
'message' => __( 'You cannot use this file (wrong extension? wrong type?).', 'imagify' ),
|
571 |
+
) );
|
572 |
+
}
|
573 |
+
|
574 |
+
$this->get_core()->log( 'The temporary file was written successfully.' );
|
575 |
+
|
576 |
+
return $tmp_file_path;
|
577 |
+
}
|
578 |
+
|
579 |
+
/**
|
580 |
+
* Tell if Imagify's column content has been requested.
|
581 |
+
*
|
582 |
+
* @since 1.8
|
583 |
+
* @access public
|
584 |
+
* @author Grégory Viguier
|
585 |
+
*
|
586 |
+
* @return bool
|
587 |
+
*/
|
588 |
+
public function needs_info() {
|
589 |
+
return filter_input( INPUT_POST, 'imagify_info', FILTER_VALIDATE_INT ) === 1;
|
590 |
+
}
|
591 |
+
|
592 |
+
/**
|
593 |
+
* Tell if the attachment has the required WP metadata.
|
594 |
+
*
|
595 |
+
* @since 1.8
|
596 |
+
* @access public
|
597 |
+
* @see $wr2x_core->is_image_meta()
|
598 |
+
* @author Grégory Viguier
|
599 |
+
*
|
600 |
+
* @param object $attachment An Imagify attachment.
|
601 |
+
* @return bool
|
602 |
+
*/
|
603 |
+
public function has_required_metadata( $attachment ) {
|
604 |
+
if ( ! $attachment->has_required_metadata() ) {
|
605 |
+
return false;
|
606 |
+
}
|
607 |
+
|
608 |
+
$metadata = wp_get_attachment_metadata( $attachment->get_id() );
|
609 |
+
|
610 |
+
if ( ! isset( $metadata['sizes'], $metadata['width'], $metadata['height'] ) ) {
|
611 |
+
return false;
|
612 |
+
}
|
613 |
+
|
614 |
+
return is_array( $metadata['sizes'] );
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Get info about Imagify.
|
619 |
+
*
|
620 |
+
* @since 1.8
|
621 |
+
* @access public
|
622 |
+
* @author Grégory Viguier
|
623 |
+
*
|
624 |
+
* @param object $attachment An Imagify attachment.
|
625 |
+
* @return array An array containing some HTML, indexed by the attachment ID.
|
626 |
+
*/
|
627 |
+
public function get_imagify_info( $attachment ) {
|
628 |
+
if ( ! $this->needs_info() ) {
|
629 |
+
return array();
|
630 |
+
}
|
631 |
+
|
632 |
+
return array(
|
633 |
+
$attachment->get_id() => get_imagify_media_column_content( $attachment ),
|
634 |
+
);
|
635 |
+
}
|
636 |
+
|
637 |
+
/**
|
638 |
+
* Send a JSON response back to an Ajax request.
|
639 |
+
* It sends a "success" by default.
|
640 |
+
*
|
641 |
+
* @since 1.8
|
642 |
+
* @access public
|
643 |
+
* @author Grégory Viguier
|
644 |
+
*
|
645 |
+
* @param array $data An array of data to print and die.
|
646 |
+
*/
|
647 |
+
public function send_json( $data ) {
|
648 |
+
// Use the same JSON format than WPR2X.
|
649 |
+
$data = array_merge( array(
|
650 |
+
'success' => true,
|
651 |
+
'message' => '',
|
652 |
+
'source' => 'imagify',
|
653 |
+
'context' => 'wr2x',
|
654 |
+
), $data );
|
655 |
+
|
656 |
+
echo wp_json_encode( $data );
|
657 |
+
die;
|
658 |
+
}
|
659 |
+
|
660 |
+
/**
|
661 |
+
* Send a JSON error response if the given argument is a WP_Error object.
|
662 |
+
*
|
663 |
+
* @since 1.8
|
664 |
+
* @access public
|
665 |
+
* @author Grégory Viguier
|
666 |
+
*
|
667 |
+
* @param mixed $result Result of an operation.
|
668 |
+
*/
|
669 |
+
public function maybe_send_json_error( $result ) {
|
670 |
+
if ( ! is_wp_error( $result ) ) {
|
671 |
+
return;
|
672 |
+
}
|
673 |
+
|
674 |
+
// Oh no.
|
675 |
+
$this->send_json( array(
|
676 |
+
'success' => false,
|
677 |
+
'message' => $result->get_error_message(),
|
678 |
+
) );
|
679 |
+
}
|
680 |
+
}
|
inc/3rd-party/wp-retina-2x/wp-retina-2x.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
3 |
+
|
4 |
+
if ( ! class_exists( 'Meow_WR2X_Core' ) ) {
|
5 |
+
return;
|
6 |
+
}
|
7 |
+
|
8 |
+
Imagify_WP_Retina_2x::get_instance()->init();
|
inc/3rd-party/wp-rocket.php
CHANGED
File without changes
|
inc/admin/custom-folders.php
CHANGED
File without changes
|
inc/admin/media.php
CHANGED
@@ -55,7 +55,7 @@ function _imagify_add_actions_to_media_list_row( $actions, $post ) {
|
|
55 |
$attachment = get_imagify_attachment( 'wp', $post->ID, 'media_row_actions' );
|
56 |
|
57 |
// If this attachment is not an image, do nothing.
|
58 |
-
if ( ! $attachment->is_extension_supported() ) {
|
59 |
return $actions;
|
60 |
}
|
61 |
|
55 |
$attachment = get_imagify_attachment( 'wp', $post->ID, 'media_row_actions' );
|
56 |
|
57 |
// If this attachment is not an image, do nothing.
|
58 |
+
if ( ! $attachment->is_extension_supported() || ! $attachment->is_image() ) {
|
59 |
return $actions;
|
60 |
}
|
61 |
|
inc/admin/upload.php
CHANGED
@@ -56,14 +56,14 @@ function _imagify_attachments_filter_dropdown() {
|
|
56 |
$errors = imagify_count_error_attachments();
|
57 |
$status = isset( $_GET['imagify-status'] ) ? $_GET['imagify-status'] : 0; // WPCS: CSRF ok.
|
58 |
$options = array(
|
59 |
-
'optimized' =>
|
60 |
-
'unoptimized' =>
|
61 |
-
'errors' =>
|
62 |
);
|
63 |
|
64 |
echo '<label class="screen-reader-text" for="filter-by-optimization-status">' . __( 'Filter by status','imagify' ) . '</label>';
|
65 |
echo '<select id="filter-by-optimization-status" name="imagify-status">';
|
66 |
-
echo '<option value="0" selected="selected">' . __( 'All
|
67 |
|
68 |
foreach ( $options as $value => $label ) {
|
69 |
echo '<option value="' . $value . '" ' . selected( $status, $value, false ) . '>' . $label . ' (' . ${$value} . ')</option>';
|
56 |
$errors = imagify_count_error_attachments();
|
57 |
$status = isset( $_GET['imagify-status'] ) ? $_GET['imagify-status'] : 0; // WPCS: CSRF ok.
|
58 |
$options = array(
|
59 |
+
'optimized' => _x( 'Optimized', 'Media Files','imagify' ),
|
60 |
+
'unoptimized' => _x( 'Unoptimized', 'Media Files','imagify' ),
|
61 |
+
'errors' => _x( 'Errors', 'Media Files','imagify' ),
|
62 |
);
|
63 |
|
64 |
echo '<label class="screen-reader-text" for="filter-by-optimization-status">' . __( 'Filter by status','imagify' ) . '</label>';
|
65 |
echo '<select id="filter-by-optimization-status" name="imagify-status">';
|
66 |
+
echo '<option value="0" selected="selected">' . __( 'All Media Files','imagify' ) . '</option>';
|
67 |
|
68 |
foreach ( $options as $value => $label ) {
|
69 |
echo '<option value="' . $value . '" ' . selected( $status, $value, false ) . '>' . $label . ' (' . ${$value} . ')</option>';
|
inc/classes/class-imagify-abstract-attachment.php
CHANGED
@@ -50,18 +50,47 @@ abstract class Imagify_Abstract_Attachment extends Imagify_Abstract_Attachment_D
|
|
50 |
* @since 1.7
|
51 |
* @access protected
|
52 |
*/
|
53 |
-
protected $row
|
54 |
|
55 |
/**
|
56 |
-
* Tell if the file
|
57 |
-
* This is used to cache the result of $this->is_extension_supported().
|
58 |
*
|
59 |
* @var bool
|
60 |
-
* @since 1.
|
61 |
* @access protected
|
62 |
-
* @see $this->
|
63 |
*/
|
64 |
-
protected $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
/**
|
67 |
* Filesystem object.
|
@@ -116,12 +145,12 @@ abstract class Imagify_Abstract_Attachment extends Imagify_Abstract_Attachment_D
|
|
116 |
global $post;
|
117 |
|
118 |
if ( $id ) {
|
119 |
-
if (
|
120 |
$this->id = $id->ID;
|
121 |
} elseif ( is_numeric( $id ) ) {
|
122 |
$this->id = $id;
|
123 |
}
|
124 |
-
} elseif ( $post &&
|
125 |
$this->id = $post->ID;
|
126 |
}
|
127 |
|
@@ -356,6 +385,89 @@ abstract class Imagify_Abstract_Attachment extends Imagify_Abstract_Attachment_D
|
|
356 |
);
|
357 |
}
|
358 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
/**
|
360 |
* Get the attachment extension.
|
361 |
*
|
@@ -365,11 +477,18 @@ abstract class Imagify_Abstract_Attachment extends Imagify_Abstract_Attachment_D
|
|
365 |
* @return string|null
|
366 |
*/
|
367 |
public function get_extension() {
|
|
|
|
|
|
|
|
|
368 |
if ( ! $this->is_valid() ) {
|
369 |
-
|
|
|
370 |
}
|
371 |
|
372 |
-
|
|
|
|
|
373 |
}
|
374 |
|
375 |
/**
|
@@ -382,37 +501,21 @@ abstract class Imagify_Abstract_Attachment extends Imagify_Abstract_Attachment_D
|
|
382 |
* @return bool
|
383 |
*/
|
384 |
public function is_extension_supported() {
|
385 |
-
|
386 |
-
return $this->is_extension_supported;
|
387 |
-
}
|
388 |
-
|
389 |
-
if ( ! $this->is_valid() ) {
|
390 |
-
$this->is_extension_supported = false;
|
391 |
-
return $this->is_extension_supported;
|
392 |
-
}
|
393 |
-
|
394 |
-
$file_type = wp_check_filetype( $this->get_original_path(), imagify_get_mime_types() );
|
395 |
-
|
396 |
-
$this->is_extension_supported = (bool) $file_type['ext'];
|
397 |
-
|
398 |
-
return $this->is_extension_supported;
|
399 |
}
|
400 |
|
401 |
/**
|
402 |
* Tell if the current file mime type is supported.
|
403 |
*
|
404 |
* @since 1.6.9
|
|
|
405 |
* @access public
|
406 |
* @author Grégory Viguier
|
407 |
*
|
408 |
* @return bool
|
409 |
*/
|
410 |
public function is_mime_type_supported() {
|
411 |
-
|
412 |
-
return false;
|
413 |
-
}
|
414 |
-
|
415 |
-
return imagify_is_attachment_mime_type_supported( $this->id );
|
416 |
}
|
417 |
|
418 |
/**
|
@@ -778,7 +881,7 @@ abstract class Imagify_Abstract_Attachment extends Imagify_Abstract_Attachment_D
|
|
778 |
*/
|
779 |
public function get_unoptimized_sizes() {
|
780 |
// The attachment must have been optimized once and have a backup.
|
781 |
-
if ( ! $this->is_valid() || ! $this->is_optimized() || ! $this->has_backup() ) {
|
782 |
return array();
|
783 |
}
|
784 |
|
@@ -917,7 +1020,7 @@ abstract class Imagify_Abstract_Attachment extends Imagify_Abstract_Attachment_D
|
|
917 |
* @return string Path the the resized image or the original image if the resize failed.
|
918 |
*/
|
919 |
public function resize( $attachment_path, $attachment_sizes, $max_width ) {
|
920 |
-
if ( ! $this->is_valid() ) {
|
921 |
return '';
|
922 |
}
|
923 |
|
50 |
* @since 1.7
|
51 |
* @access protected
|
52 |
*/
|
53 |
+
protected $row;
|
54 |
|
55 |
/**
|
56 |
+
* Tell if the file is an image.
|
|
|
57 |
*
|
58 |
* @var bool
|
59 |
+
* @since 1.8
|
60 |
* @access protected
|
61 |
+
* @see $this->is_image()
|
62 |
*/
|
63 |
+
protected $is_image;
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Tell if the file is a pdf.
|
67 |
+
*
|
68 |
+
* @var bool
|
69 |
+
* @since 1.8
|
70 |
+
* @access protected
|
71 |
+
* @see $this->is_pdf()
|
72 |
+
*/
|
73 |
+
protected $is_pdf;
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Stores the file extension (even if the extension is not supported by Imagify).
|
77 |
+
*
|
78 |
+
* @var string|null
|
79 |
+
* @since 1.8
|
80 |
+
* @access protected
|
81 |
+
* @see $this->get_extension()
|
82 |
+
*/
|
83 |
+
protected $extension = false;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Stores the file mime type + file extension (if the file is supported).
|
87 |
+
*
|
88 |
+
* @var array
|
89 |
+
* @since 1.8
|
90 |
+
* @access protected
|
91 |
+
* @see $this->get_file_type()
|
92 |
+
*/
|
93 |
+
protected $file_type;
|
94 |
|
95 |
/**
|
96 |
* Filesystem object.
|
145 |
global $post;
|
146 |
|
147 |
if ( $id ) {
|
148 |
+
if ( $id instanceof WP_Post ) {
|
149 |
$this->id = $id->ID;
|
150 |
} elseif ( is_numeric( $id ) ) {
|
151 |
$this->id = $id;
|
152 |
}
|
153 |
+
} elseif ( $post && $id instanceof WP_Post ) {
|
154 |
$this->id = $post->ID;
|
155 |
}
|
156 |
|
385 |
);
|
386 |
}
|
387 |
|
388 |
+
/**
|
389 |
+
* Tell if the current item refers to an image, based on file extension.
|
390 |
+
*
|
391 |
+
* @since 1.8
|
392 |
+
* @access public
|
393 |
+
* @author Grégory Viguier
|
394 |
+
*
|
395 |
+
* @return bool Returns false in case it's an image but not in a supported format (bmp for example).
|
396 |
+
*/
|
397 |
+
public function is_image() {
|
398 |
+
if ( isset( $this->is_image ) ) {
|
399 |
+
return $this->is_image;
|
400 |
+
}
|
401 |
+
|
402 |
+
$this->is_image = strpos( (string) $this->get_mime_type(), 'image/' ) === 0;
|
403 |
+
|
404 |
+
return $this->is_image;
|
405 |
+
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* Tell if the current item refers to a pdf, based on file extension.
|
409 |
+
*
|
410 |
+
* @since 1.8
|
411 |
+
* @access public
|
412 |
+
* @author Grégory Viguier
|
413 |
+
*
|
414 |
+
* @return bool
|
415 |
+
*/
|
416 |
+
public function is_pdf() {
|
417 |
+
if ( isset( $this->is_pdf ) ) {
|
418 |
+
return $this->is_pdf;
|
419 |
+
}
|
420 |
+
|
421 |
+
$this->is_pdf = 'application/pdf' === $this->get_mime_type();
|
422 |
+
|
423 |
+
return $this->is_pdf;
|
424 |
+
}
|
425 |
+
|
426 |
+
/**
|
427 |
+
* Get the file mime type.
|
428 |
+
*
|
429 |
+
* @since 1.8
|
430 |
+
* @access public
|
431 |
+
* @author Grégory Viguier
|
432 |
+
*
|
433 |
+
* @return bool
|
434 |
+
*/
|
435 |
+
public function get_mime_type() {
|
436 |
+
return $this->get_file_type()->type;
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* Get the file mime type + file extension (if the file is supported).
|
441 |
+
*
|
442 |
+
* @since 1.8
|
443 |
+
* @access public
|
444 |
+
* @see wp_check_filetype()
|
445 |
+
* @author Grégory Viguier
|
446 |
+
*
|
447 |
+
* @return object
|
448 |
+
*/
|
449 |
+
public function get_file_type() {
|
450 |
+
if ( isset( $this->file_type ) ) {
|
451 |
+
return $this->file_type;
|
452 |
+
}
|
453 |
+
|
454 |
+
if ( ! $this->is_valid() ) {
|
455 |
+
$this->file_type = (object) array( 'ext' => '', 'type' => '' );
|
456 |
+
return $this->file_type;
|
457 |
+
}
|
458 |
+
|
459 |
+
$path = $this->get_original_path();
|
460 |
+
|
461 |
+
if ( ! $path ) {
|
462 |
+
$this->file_type = (object) array( 'ext' => '', 'type' => '' );
|
463 |
+
return $this->file_type;
|
464 |
+
}
|
465 |
+
|
466 |
+
$this->file_type = (object) wp_check_filetype( $path, imagify_get_mime_types() );
|
467 |
+
|
468 |
+
return $this->file_type;
|
469 |
+
}
|
470 |
+
|
471 |
/**
|
472 |
* Get the attachment extension.
|
473 |
*
|
477 |
* @return string|null
|
478 |
*/
|
479 |
public function get_extension() {
|
480 |
+
if ( false !== $this->extension ) {
|
481 |
+
return $this->extension;
|
482 |
+
}
|
483 |
+
|
484 |
if ( ! $this->is_valid() ) {
|
485 |
+
$this->extension = null;
|
486 |
+
return $this->extension;
|
487 |
}
|
488 |
|
489 |
+
$this->extension = $this->filesystem->path_info( $this->get_original_path(), 'extension' );
|
490 |
+
|
491 |
+
return $this->extension;
|
492 |
}
|
493 |
|
494 |
/**
|
501 |
* @return bool
|
502 |
*/
|
503 |
public function is_extension_supported() {
|
504 |
+
return (bool) $this->get_file_type()->ext;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
}
|
506 |
|
507 |
/**
|
508 |
* Tell if the current file mime type is supported.
|
509 |
*
|
510 |
* @since 1.6.9
|
511 |
+
* @since 1.8 Does the same has this->is_extension_supported().
|
512 |
* @access public
|
513 |
* @author Grégory Viguier
|
514 |
*
|
515 |
* @return bool
|
516 |
*/
|
517 |
public function is_mime_type_supported() {
|
518 |
+
return (bool) $this->get_mime_type();
|
|
|
|
|
|
|
|
|
519 |
}
|
520 |
|
521 |
/**
|
881 |
*/
|
882 |
public function get_unoptimized_sizes() {
|
883 |
// The attachment must have been optimized once and have a backup.
|
884 |
+
if ( ! $this->is_valid() || ! $this->is_optimized() || ! $this->has_backup() || ! $this->is_image() ) {
|
885 |
return array();
|
886 |
}
|
887 |
|
1020 |
* @return string Path the the resized image or the original image if the resize failed.
|
1021 |
*/
|
1022 |
public function resize( $attachment_path, $attachment_sizes, $max_width ) {
|
1023 |
+
if ( ! $this->is_valid() || ! $this->is_image() ) {
|
1024 |
return '';
|
1025 |
}
|
1026 |
|
inc/classes/class-imagify-abstract-cron.php
CHANGED
File without changes
|
inc/classes/class-imagify-abstract-db.php
CHANGED
File without changes
|
inc/classes/class-imagify-abstract-options.php
CHANGED
File without changes
|
inc/classes/class-imagify-admin-ajax-post.php
CHANGED
@@ -16,7 +16,7 @@ class Imagify_Admin_Ajax_Post {
|
|
16 |
* @since 1.6.11
|
17 |
* @author Grégory Viguier
|
18 |
*/
|
19 |
-
const VERSION = '1.0.
|
20 |
|
21 |
/**
|
22 |
* Actions to be triggered on admin ajax and admin post.
|
@@ -244,6 +244,12 @@ class Imagify_Admin_Ajax_Post {
|
|
244 |
imagify_check_user_capacity( 'manual-optimize', $attachment_id );
|
245 |
|
246 |
$attachment = get_imagify_attachment( $context, $attachment_id, 'imagify_optimize_missing_sizes' );
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
|
248 |
// Optimize the missing thumbnails.
|
249 |
$attachment->optimize_missing_thumbnails();
|
@@ -1359,13 +1365,14 @@ class Imagify_Admin_Ajax_Post {
|
|
1359 |
imagify_die( __( 'This file is not a folder.', 'imagify' ) );
|
1360 |
}
|
1361 |
|
|
|
|
|
1362 |
if ( Imagify_Files_Scan::is_path_forbidden( $folder ) ) {
|
1363 |
imagify_die( __( 'This folder is not allowed.', 'imagify' ) );
|
1364 |
}
|
1365 |
|
1366 |
// Finally we made all our validations.
|
1367 |
$selected = ! empty( $_POST['selected'] ) && is_array( $_POST['selected'] ) ? array_flip( $_POST['selected'] ) : array();
|
1368 |
-
$folder = $this->filesystem->normalize_dir_path( $folder );
|
1369 |
$views = Imagify_Views::get_instance();
|
1370 |
$output = '';
|
1371 |
|
@@ -1381,9 +1388,9 @@ class Imagify_Admin_Ajax_Post {
|
|
1381 |
) );
|
1382 |
}
|
1383 |
|
1384 |
-
$dir
|
1385 |
-
$dir
|
1386 |
-
$images
|
1387 |
|
1388 |
foreach ( new IteratorIterator( $dir ) as $file ) {
|
1389 |
if ( ! $file->isDir() ) {
|
@@ -1401,13 +1408,13 @@ class Imagify_Admin_Ajax_Post {
|
|
1401 |
'checkbox_value' => esc_attr( $placeholder ) . '#///#' . esc_attr( $relative_path ),
|
1402 |
'checkbox_id' => sanitize_html_class( $placeholder ),
|
1403 |
'checkbox_selected' => isset( $selected[ $placeholder ] ),
|
1404 |
-
'label' =>
|
1405 |
) );
|
1406 |
}
|
1407 |
|
1408 |
if ( $images ) {
|
1409 |
/* translators: %s is a formatted number, dont use %d. */
|
1410 |
-
$output .= '<li class="imagify-number-of-images-in-folder"><em><span class="dashicons dashicons-images-alt"></span> ' . sprintf( _n( '%s
|
1411 |
}
|
1412 |
|
1413 |
if ( ! $output ) {
|
16 |
* @since 1.6.11
|
17 |
* @author Grégory Viguier
|
18 |
*/
|
19 |
+
const VERSION = '1.0.4';
|
20 |
|
21 |
/**
|
22 |
* Actions to be triggered on admin ajax and admin post.
|
244 |
imagify_check_user_capacity( 'manual-optimize', $attachment_id );
|
245 |
|
246 |
$attachment = get_imagify_attachment( $context, $attachment_id, 'imagify_optimize_missing_sizes' );
|
247 |
+
$context = $attachment->get_context();
|
248 |
+
|
249 |
+
if ( ! $attachment->is_image() ) {
|
250 |
+
$output = get_imagify_attachment_optimization_text( $attachment, $context );
|
251 |
+
wp_send_json_error( $output );
|
252 |
+
}
|
253 |
|
254 |
// Optimize the missing thumbnails.
|
255 |
$attachment->optimize_missing_thumbnails();
|
1365 |
imagify_die( __( 'This file is not a folder.', 'imagify' ) );
|
1366 |
}
|
1367 |
|
1368 |
+
$folder = $this->filesystem->normalize_dir_path( $folder );
|
1369 |
+
|
1370 |
if ( Imagify_Files_Scan::is_path_forbidden( $folder ) ) {
|
1371 |
imagify_die( __( 'This folder is not allowed.', 'imagify' ) );
|
1372 |
}
|
1373 |
|
1374 |
// Finally we made all our validations.
|
1375 |
$selected = ! empty( $_POST['selected'] ) && is_array( $_POST['selected'] ) ? array_flip( $_POST['selected'] ) : array();
|
|
|
1376 |
$views = Imagify_Views::get_instance();
|
1377 |
$output = '';
|
1378 |
|
1388 |
) );
|
1389 |
}
|
1390 |
|
1391 |
+
$dir = new DirectoryIterator( $folder );
|
1392 |
+
$dir = new Imagify_Files_Iterator( $dir );
|
1393 |
+
$images = 0;
|
1394 |
|
1395 |
foreach ( new IteratorIterator( $dir ) as $file ) {
|
1396 |
if ( ! $file->isDir() ) {
|
1408 |
'checkbox_value' => esc_attr( $placeholder ) . '#///#' . esc_attr( $relative_path ),
|
1409 |
'checkbox_id' => sanitize_html_class( $placeholder ),
|
1410 |
'checkbox_selected' => isset( $selected[ $placeholder ] ),
|
1411 |
+
'label' => $this->filesystem->file_name( $folder_path ),
|
1412 |
) );
|
1413 |
}
|
1414 |
|
1415 |
if ( $images ) {
|
1416 |
/* translators: %s is a formatted number, dont use %d. */
|
1417 |
+
$output .= '<li class="imagify-number-of-images-in-folder"><em><span class="dashicons dashicons-images-alt"></span> ' . sprintf( _n( '%s Media File', '%s Media Files', $images, 'imagify' ), number_format_i18n( $images ) ) . '</em></li>';
|
1418 |
}
|
1419 |
|
1420 |
if ( ! $output ) {
|
inc/classes/class-imagify-attachment.php
CHANGED
@@ -101,6 +101,10 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
101 |
* @return array
|
102 |
*/
|
103 |
public function get_dimensions() {
|
|
|
|
|
|
|
|
|
104 |
$values = wp_get_attachment_image_src( $this->id, 'full' );
|
105 |
|
106 |
return array(
|
@@ -119,7 +123,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
119 |
*/
|
120 |
public function update_metadata_size() {
|
121 |
// Check if the attachment extension is allowed.
|
122 |
-
if ( ! $this->is_extension_supported() ) {
|
123 |
return false;
|
124 |
}
|
125 |
|
@@ -248,18 +252,12 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
248 |
$thumbnail_path = $original_dirname . $result[ $thumbnail_size ]['file'];
|
249 |
|
250 |
// Since we used the backup image as source, the new image is still in the backup folder, we need to move it.
|
251 |
-
$this->filesystem->move( $backup_thumb_path, $thumbnail_path, true );
|
252 |
-
|
253 |
-
if ( $this->filesystem->exists( $backup_thumb_path ) ) {
|
254 |
-
$this->filesystem->delete( $backup_thumb_path );
|
255 |
-
}
|
256 |
|
257 |
-
if ( ! $
|
258 |
return new WP_Error( 'image_resize_error' );
|
259 |
}
|
260 |
|
261 |
-
$this->filesystem->chmod_file( $thumbnail_path );
|
262 |
-
|
263 |
return reset( $result );
|
264 |
}
|
265 |
|
@@ -274,7 +272,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
274 |
* @return array An array of thumbnail data (width, height, crop, file).
|
275 |
*/
|
276 |
protected function create_missing_thumbnails( $missing_sizes ) {
|
277 |
-
if ( ! $missing_sizes ) {
|
278 |
return array();
|
279 |
}
|
280 |
|
@@ -328,7 +326,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
328 |
|
329 |
$optimization_level = isset( $optimization_level ) ? (int) $optimization_level : get_imagify_option( 'optimization_level' );
|
330 |
$metadata = $metadata ? $metadata : wp_get_attachment_metadata( $this->id );
|
331 |
-
$sizes =
|
332 |
|
333 |
// To avoid issue with "original_size" at 0 in "_imagify_data".
|
334 |
if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
|
@@ -336,7 +334,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
336 |
}
|
337 |
|
338 |
// Check if the full size is already optimized.
|
339 |
-
if ( $this->is_optimized() &&
|
340 |
return;
|
341 |
}
|
342 |
|
@@ -351,14 +349,14 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
351 |
* @since 1.0
|
352 |
*
|
353 |
* @param int $id The attachment ID.
|
354 |
-
|
355 |
do_action( 'before_imagify_optimize_attachment', $this->id );
|
356 |
|
357 |
$this->set_running_status();
|
358 |
|
359 |
// Get the resize values for the original size.
|
360 |
$resized = false;
|
361 |
-
$do_resize = get_imagify_option( 'resize_larger' );
|
362 |
|
363 |
if ( $do_resize ) {
|
364 |
$resize_width = get_imagify_option( 'resize_larger_w' );
|
@@ -372,12 +370,6 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
372 |
imagify_backup_file( $attachment_path );
|
373 |
|
374 |
$this->filesystem->move( $resized_attachment_path, $attachment_path, true );
|
375 |
-
$this->filesystem->chmod_file( $attachment_path );
|
376 |
-
|
377 |
-
// If resized temp file still exists, delete it.
|
378 |
-
if ( $this->filesystem->exists( $resized_attachment_path ) ) {
|
379 |
-
$this->filesystem->delete( $resized_attachment_path );
|
380 |
-
}
|
381 |
|
382 |
$resized = true;
|
383 |
}
|
@@ -394,6 +386,23 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
394 |
|
395 |
$data = $this->fill_data( null, $response );
|
396 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
397 |
// Save the optimization level.
|
398 |
update_post_meta( $this->id, '_imagify_optimization_level', $optimization_level );
|
399 |
|
@@ -416,18 +425,34 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
416 |
$attachment_url_dirname = $this->filesystem->dir_path( $attachment_url );
|
417 |
|
418 |
foreach ( $sizes as $size_key => $size_data ) {
|
|
|
|
|
|
|
419 |
// Check if this size has to be optimized.
|
420 |
if ( ! $is_active_for_network && isset( $disallowed_sizes[ $size_key ] ) ) {
|
421 |
$data['sizes'][ $size_key ] = array(
|
422 |
'success' => false,
|
423 |
'error' => __( 'This size isn\'t authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' ),
|
424 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
continue;
|
426 |
}
|
427 |
|
428 |
-
$thumbnail_path = $attachment_path_dirname . $size_data['file'];
|
429 |
-
$thumbnail_url = $attachment_url_dirname . $size_data['file'];
|
430 |
-
|
431 |
// Optimize the thumbnail size.
|
432 |
$response = do_imagify( $thumbnail_path, array(
|
433 |
'backup' => false,
|
@@ -438,20 +463,21 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
438 |
$data = $this->fill_data( $data, $response, $size_key );
|
439 |
|
440 |
/**
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
|
|
455 |
} // End foreach().
|
456 |
} // End if().
|
457 |
|
@@ -489,7 +515,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
489 |
*/
|
490 |
public function optimize_missing_thumbnails( $optimization_level = null ) {
|
491 |
// Check if the attachment extension is allowed.
|
492 |
-
if ( ! $this->is_extension_supported() ) {
|
493 |
return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
|
494 |
}
|
495 |
|
@@ -556,9 +582,10 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
556 |
) );
|
557 |
|
558 |
$imagify_data = $this->fill_data( $imagify_data, $response, $size_name );
|
|
|
559 |
|
560 |
/** This filter is documented in inc/classes/class-imagify-attachment.php. */
|
561 |
-
$imagify_data = apply_filters( 'imagify_fill_thumbnail_data', $imagify_data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_name, $optimization_level );
|
562 |
}
|
563 |
|
564 |
// Save Imagify data.
|
@@ -602,7 +629,7 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
602 |
*/
|
603 |
public function reoptimize_thumbnails( $sizes ) {
|
604 |
// Check if the attachment extension is allowed.
|
605 |
-
if ( ! $this->is_extension_supported() ) {
|
606 |
return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
|
607 |
}
|
608 |
|
@@ -739,19 +766,21 @@ class Imagify_Attachment extends Imagify_Abstract_Attachment {
|
|
739 |
$this->filesystem->copy( $backup_path, $attachment_path, true );
|
740 |
$this->filesystem->chmod_file( $attachment_path );
|
741 |
|
742 |
-
if (
|
743 |
-
|
744 |
-
|
|
|
745 |
|
746 |
-
|
747 |
-
|
|
|
|
|
|
|
|
|
748 |
|
749 |
// Remove old optimization data.
|
750 |
$this->delete_imagify_data();
|
751 |
|
752 |
-
// Restore the original size in the metadata.
|
753 |
-
$this->update_metadata_size();
|
754 |
-
|
755 |
/**
|
756 |
* Fires after restoring an attachment.
|
757 |
*
|
101 |
* @return array
|
102 |
*/
|
103 |
public function get_dimensions() {
|
104 |
+
if ( ! $this->is_image() ) {
|
105 |
+
return parent::get_dimensions();
|
106 |
+
}
|
107 |
+
|
108 |
$values = wp_get_attachment_image_src( $this->id, 'full' );
|
109 |
|
110 |
return array(
|
123 |
*/
|
124 |
public function update_metadata_size() {
|
125 |
// Check if the attachment extension is allowed.
|
126 |
+
if ( ! $this->is_extension_supported() || ! $this->is_image() ) {
|
127 |
return false;
|
128 |
}
|
129 |
|
252 |
$thumbnail_path = $original_dirname . $result[ $thumbnail_size ]['file'];
|
253 |
|
254 |
// Since we used the backup image as source, the new image is still in the backup folder, we need to move it.
|
255 |
+
$moved = $this->filesystem->move( $backup_thumb_path, $thumbnail_path, true );
|
|
|
|
|
|
|
|
|
256 |
|
257 |
+
if ( ! $moved ) {
|
258 |
return new WP_Error( 'image_resize_error' );
|
259 |
}
|
260 |
|
|
|
|
|
261 |
return reset( $result );
|
262 |
}
|
263 |
|
272 |
* @return array An array of thumbnail data (width, height, crop, file).
|
273 |
*/
|
274 |
protected function create_missing_thumbnails( $missing_sizes ) {
|
275 |
+
if ( ! $missing_sizes || ! $this->is_image() ) {
|
276 |
return array();
|
277 |
}
|
278 |
|
326 |
|
327 |
$optimization_level = isset( $optimization_level ) ? (int) $optimization_level : get_imagify_option( 'optimization_level' );
|
328 |
$metadata = $metadata ? $metadata : wp_get_attachment_metadata( $this->id );
|
329 |
+
$sizes = ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) && $this->is_image() ? $metadata['sizes'] : array();
|
330 |
|
331 |
// To avoid issue with "original_size" at 0 in "_imagify_data".
|
332 |
if ( 0 === (int) $this->get_stats_data( 'original_size' ) ) {
|
334 |
}
|
335 |
|
336 |
// Check if the full size is already optimized.
|
337 |
+
if ( $this->is_optimized() && $this->get_optimization_level() === $optimization_level ) {
|
338 |
return;
|
339 |
}
|
340 |
|
349 |
* @since 1.0
|
350 |
*
|
351 |
* @param int $id The attachment ID.
|
352 |
+
*/
|
353 |
do_action( 'before_imagify_optimize_attachment', $this->id );
|
354 |
|
355 |
$this->set_running_status();
|
356 |
|
357 |
// Get the resize values for the original size.
|
358 |
$resized = false;
|
359 |
+
$do_resize = $this->is_image() && get_imagify_option( 'resize_larger' );
|
360 |
|
361 |
if ( $do_resize ) {
|
362 |
$resize_width = get_imagify_option( 'resize_larger_w' );
|
370 |
imagify_backup_file( $attachment_path );
|
371 |
|
372 |
$this->filesystem->move( $resized_attachment_path, $attachment_path, true );
|
|
|
|
|
|
|
|
|
|
|
|
|
373 |
|
374 |
$resized = true;
|
375 |
}
|
386 |
|
387 |
$data = $this->fill_data( null, $response );
|
388 |
|
389 |
+
/**
|
390 |
+
* Filter the optimization data of the full size.
|
391 |
+
*
|
392 |
+
* @since 1.8
|
393 |
+
* @author Grégory Viguier
|
394 |
+
*
|
395 |
+
* @param array $data The statistics data.
|
396 |
+
* @param object $response The API response.
|
397 |
+
* @param int $id The attachment ID.
|
398 |
+
* @param string $attachment_path The attachment path.
|
399 |
+
* @param string $attachment_url The attachment URL.
|
400 |
+
* @param string $size_key The attachment size key. The value is obviously 'full' but it's kept for concistancy with other filters.
|
401 |
+
* @param int $optimization_level The optimization level.
|
402 |
+
* @param array $metadata WP metadata.
|
403 |
+
*/
|
404 |
+
$data = apply_filters( 'imagify_fill_full_size_data', $data, $response, $this->id, $attachment_path, $attachment_url, 'full', $optimization_level, $metadata );
|
405 |
+
|
406 |
// Save the optimization level.
|
407 |
update_post_meta( $this->id, '_imagify_optimization_level', $optimization_level );
|
408 |
|
425 |
$attachment_url_dirname = $this->filesystem->dir_path( $attachment_url );
|
426 |
|
427 |
foreach ( $sizes as $size_key => $size_data ) {
|
428 |
+
$thumbnail_path = $attachment_path_dirname . $size_data['file'];
|
429 |
+
$thumbnail_url = $attachment_url_dirname . $size_data['file'];
|
430 |
+
|
431 |
// Check if this size has to be optimized.
|
432 |
if ( ! $is_active_for_network && isset( $disallowed_sizes[ $size_key ] ) ) {
|
433 |
$data['sizes'][ $size_key ] = array(
|
434 |
'success' => false,
|
435 |
'error' => __( 'This size isn\'t authorized to be optimized. Update your Imagify settings if you want to optimize it.', 'imagify' ),
|
436 |
);
|
437 |
+
|
438 |
+
/**
|
439 |
+
* Filter the optimization data of an unauthorized thumbnail.
|
440 |
+
*
|
441 |
+
* @since 1.8
|
442 |
+
* @author Grégory Viguier
|
443 |
+
*
|
444 |
+
* @param array $data The statistics data.
|
445 |
+
* @param int $id The attachment ID.
|
446 |
+
* @param string $thumbnail_path The thumbnail path.
|
447 |
+
* @param string $thumbnail_url The thumbnail URL.
|
448 |
+
* @param string $size_key The thumbnail size key.
|
449 |
+
* @param int $optimization_level The optimization level.
|
450 |
+
* @param array $metadata WP metadata.
|
451 |
+
*/
|
452 |
+
$data = apply_filters( 'imagify_fill_unauthorized_thumbnail_data', $data, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level, $metadata );
|
453 |
continue;
|
454 |
}
|
455 |
|
|
|
|
|
|
|
456 |
// Optimize the thumbnail size.
|
457 |
$response = do_imagify( $thumbnail_path, array(
|
458 |
'backup' => false,
|
463 |
$data = $this->fill_data( $data, $response, $size_key );
|
464 |
|
465 |
/**
|
466 |
+
* Filter the optimization data of a specific thumbnail.
|
467 |
+
*
|
468 |
+
* @since 1.0
|
469 |
+
* @since 1.8 Added $metadata.
|
470 |
+
*
|
471 |
+
* @param array $data The statistics data.
|
472 |
+
* @param object $response The API response.
|
473 |
+
* @param int $id The attachment ID.
|
474 |
+
* @param string $thumbnail_path The thumbnail path.
|
475 |
+
* @param string $thumbnail_url The thumbnail URL.
|
476 |
+
* @param string $size_key The thumbnail size key.
|
477 |
+
* @param int $optimization_level The optimization level.
|
478 |
+
* @param array $metadata WP metadata.
|
479 |
+
*/
|
480 |
+
$data = apply_filters( 'imagify_fill_thumbnail_data', $data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_key, $optimization_level, $metadata );
|
481 |
} // End foreach().
|
482 |
} // End if().
|
483 |
|
515 |
*/
|
516 |
public function optimize_missing_thumbnails( $optimization_level = null ) {
|
517 |
// Check if the attachment extension is allowed.
|
518 |
+
if ( ! $this->is_extension_supported() || ! $this->is_image() ) {
|
519 |
return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
|
520 |
}
|
521 |
|
582 |
) );
|
583 |
|
584 |
$imagify_data = $this->fill_data( $imagify_data, $response, $size_name );
|
585 |
+
$metadata = wp_get_attachment_metadata( $this->id );
|
586 |
|
587 |
/** This filter is documented in inc/classes/class-imagify-attachment.php. */
|
588 |
+
$imagify_data = apply_filters( 'imagify_fill_thumbnail_data', $imagify_data, $response, $this->id, $thumbnail_path, $thumbnail_url, $size_name, $optimization_level, $metadata );
|
589 |
}
|
590 |
|
591 |
// Save Imagify data.
|
629 |
*/
|
630 |
public function reoptimize_thumbnails( $sizes ) {
|
631 |
// Check if the attachment extension is allowed.
|
632 |
+
if ( ! $this->is_extension_supported() || ! $this->is_image() ) {
|
633 |
return new WP_Error( 'mime_type_not_supported', __( 'This type of file is not supported.', 'imagify' ) );
|
634 |
}
|
635 |
|
766 |
$this->filesystem->copy( $backup_path, $attachment_path, true );
|
767 |
$this->filesystem->chmod_file( $attachment_path );
|
768 |
|
769 |
+
if ( $this->is_image() ) {
|
770 |
+
if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
|
771 |
+
require_once( ABSPATH . 'wp-admin/includes/image.php' );
|
772 |
+
}
|
773 |
|
774 |
+
remove_filter( 'wp_generate_attachment_metadata', '_imagify_optimize_attachment', IMAGIFY_INT_MAX );
|
775 |
+
wp_generate_attachment_metadata( $this->id, $attachment_path );
|
776 |
+
|
777 |
+
// Restore the original size in the metadata.
|
778 |
+
$this->update_metadata_size();
|
779 |
+
}
|
780 |
|
781 |
// Remove old optimization data.
|
782 |
$this->delete_imagify_data();
|
783 |
|
|
|
|
|
|
|
784 |
/**
|
785 |
* Fires after restoring an attachment.
|
786 |
*
|
inc/classes/class-imagify-cron-library-size.php
CHANGED
File without changes
|
inc/classes/class-imagify-cron-rating.php
CHANGED
File without changes
|
inc/classes/class-imagify-cron-sync-files.php
CHANGED
File without changes
|
inc/classes/class-imagify-custom-folders.php
CHANGED
@@ -14,7 +14,7 @@ class Imagify_Custom_Folders {
|
|
14 |
*
|
15 |
* @var string
|
16 |
*/
|
17 |
-
const VERSION = '1.0.
|
18 |
|
19 |
|
20 |
/** ----------------------------------------------------------------------------------------- */
|
@@ -176,7 +176,7 @@ class Imagify_Custom_Folders {
|
|
176 |
), $args );
|
177 |
|
178 |
$filesystem = imagify_get_filesystem();
|
179 |
-
$file = $args['file'] &&
|
180 |
|
181 |
// The file.
|
182 |
if ( ! $args['file_path'] && $args['path'] ) {
|
@@ -947,7 +947,7 @@ class Imagify_Custom_Folders {
|
|
947 |
continue;
|
948 |
}
|
949 |
|
950 |
-
if ( Imagify_Files_Scan::is_path_forbidden( $full_path ) ) {
|
951 |
continue;
|
952 |
}
|
953 |
|
14 |
*
|
15 |
* @var string
|
16 |
*/
|
17 |
+
const VERSION = '1.0.2';
|
18 |
|
19 |
|
20 |
/** ----------------------------------------------------------------------------------------- */
|
176 |
), $args );
|
177 |
|
178 |
$filesystem = imagify_get_filesystem();
|
179 |
+
$file = $args['file'] && $args['file'] instanceof Imagify_File_Attachment ? $args['file'] : false;
|
180 |
|
181 |
// The file.
|
182 |
if ( ! $args['file_path'] && $args['path'] ) {
|
947 |
continue;
|
948 |
}
|
949 |
|
950 |
+
if ( Imagify_Files_Scan::is_path_forbidden( trailingslashit( $full_path ) ) ) {
|
951 |
continue;
|
952 |
}
|
953 |
|
inc/classes/class-imagify-data.php
CHANGED
File without changes
|
inc/classes/class-imagify-db.php
CHANGED
File without changes
|
inc/classes/class-imagify-file-attachment.php
CHANGED
@@ -426,11 +426,11 @@ class Imagify_File_Attachment extends Imagify_Attachment {
|
|
426 |
}
|
427 |
|
428 |
$data = imagify_merge_intersect( $this->get_row(), array(
|
429 |
-
'original_size'
|
430 |
-
'optimized_size'
|
431 |
-
'percent'
|
432 |
-
'status'
|
433 |
-
'error'
|
434 |
) );
|
435 |
|
436 |
$data['success'] = 'success' === $data['status'];
|
426 |
}
|
427 |
|
428 |
$data = imagify_merge_intersect( $this->get_row(), array(
|
429 |
+
'original_size' => 0,
|
430 |
+
'optimized_size' => false,
|
431 |
+
'percent' => 0,
|
432 |
+
'status' => false,
|
433 |
+
'error' => false,
|
434 |
) );
|
435 |
|
436 |
$data['success'] = 'success' === $data['status'];
|
inc/classes/class-imagify-files-db.php
CHANGED
File without changes
|
inc/classes/class-imagify-files-iterator.php
CHANGED
@@ -17,7 +17,7 @@ class Imagify_Files_Iterator extends FilterIterator {
|
|
17 |
* @since 1.7
|
18 |
* @author Grégory Viguier
|
19 |
*/
|
20 |
-
const VERSION = '1.0.
|
21 |
|
22 |
/**
|
23 |
* Tell if the iterator will return both folders and images, or only images.
|
@@ -66,14 +66,19 @@ class Imagify_Files_Iterator extends FilterIterator {
|
|
66 |
static $extensions, $has_extension_method;
|
67 |
|
68 |
// Forbidden file/folder paths and names.
|
|
|
69 |
$file_path = $this->current()->getPathname();
|
70 |
|
|
|
|
|
|
|
|
|
71 |
if ( Imagify_Files_Scan::is_path_forbidden( $file_path ) ) {
|
72 |
return false;
|
73 |
}
|
74 |
|
75 |
// OK for folders.
|
76 |
-
if ( $this->include_folders && $
|
77 |
return true;
|
78 |
}
|
79 |
|
17 |
* @since 1.7
|
18 |
* @author Grégory Viguier
|
19 |
*/
|
20 |
+
const VERSION = '1.0.2';
|
21 |
|
22 |
/**
|
23 |
* Tell if the iterator will return both folders and images, or only images.
|
66 |
static $extensions, $has_extension_method;
|
67 |
|
68 |
// Forbidden file/folder paths and names.
|
69 |
+
$is_dir = $this->isDir();
|
70 |
$file_path = $this->current()->getPathname();
|
71 |
|
72 |
+
if ( $is_dir ) {
|
73 |
+
$file_path = trailingslashit( $file_path );
|
74 |
+
}
|
75 |
+
|
76 |
if ( Imagify_Files_Scan::is_path_forbidden( $file_path ) ) {
|
77 |
return false;
|
78 |
}
|
79 |
|
80 |
// OK for folders.
|
81 |
+
if ( $this->include_folders && $is_dir ) {
|
82 |
return true;
|
83 |
}
|
84 |
|
inc/classes/class-imagify-files-list-table.php
CHANGED
@@ -352,10 +352,10 @@ class Imagify_Files_List_Table extends WP_List_Table {
|
|
352 |
}
|
353 |
|
354 |
$status_filters = array(
|
355 |
-
'' => __( 'All
|
356 |
-
'optimized' =>
|
357 |
-
'unoptimized' =>
|
358 |
-
'errors' =>
|
359 |
);
|
360 |
|
361 |
// Get submitted values.
|
@@ -503,25 +503,33 @@ class Imagify_Files_List_Table extends WP_List_Table {
|
|
503 |
* @param object $item The current File object.
|
504 |
*/
|
505 |
public function column_title( $item ) {
|
506 |
-
$item
|
507 |
-
$url
|
508 |
-
$base
|
509 |
-
$title
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
$
|
517 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
} else {
|
519 |
-
$
|
|
|
520 |
}
|
521 |
?>
|
522 |
<strong class="has-media-icon">
|
523 |
<a href="<?php echo esc_url( $url ); ?>" target="_blank">
|
524 |
-
<span class="media-icon
|
525 |
<span class="centered">
|
526 |
<?php echo $image_tag; ?>
|
527 |
</span>
|
@@ -628,7 +636,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
|
|
628 |
|
629 |
if ( ! $status ) {
|
630 |
// File is not optimized.
|
631 |
-
$messages[] = '<strong class="imagify-status-not-optimized">' . esc_html_x( 'Not optimized', '
|
632 |
} elseif ( $error_text ) {
|
633 |
// Error or already optimized.
|
634 |
$messages[] = '<span class="imagify-status-' . $status . '">' . esc_html( imagify_translate_api_message( $error_text ) ) . '</span>';
|
@@ -869,7 +877,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
|
|
869 |
* @param object $item The current File object.
|
870 |
*/
|
871 |
protected function comparison_tool_button( $item ) {
|
872 |
-
if ( ! $item->is_optimized() || ! $item->has_backup() ) {
|
873 |
return;
|
874 |
}
|
875 |
|
352 |
}
|
353 |
|
354 |
$status_filters = array(
|
355 |
+
'' => __( 'All Media Files', 'imagify' ),
|
356 |
+
'optimized' => _x( 'Optimized', 'Media Files','imagify' ) . ' (' . $status_filters['optimized'] . ')',
|
357 |
+
'unoptimized' => _x( 'Unoptimized', 'Media Files','imagify' ) . ' (' . $status_filters['unoptimized'] . ')',
|
358 |
+
'errors' => _x( 'Errors', 'Media Files','imagify' ) . ' (' . $status_filters['errors'] . ')',
|
359 |
);
|
360 |
|
361 |
// Get submitted values.
|
503 |
* @param object $item The current File object.
|
504 |
*/
|
505 |
public function column_title( $item ) {
|
506 |
+
$item = $this->maybe_set_item_folder( $item );
|
507 |
+
$url = $item->get_original_url();
|
508 |
+
$base = ! empty( $item->folder_path ) ? Imagify_Files_Scan::remove_placeholder( $item->folder_path ) : '';
|
509 |
+
$title = $this->filesystem->make_path_relative( $item->get_original_path(), $base );
|
510 |
+
|
511 |
+
list( $mime ) = explode( '/', $item->get_mime_type() );
|
512 |
+
|
513 |
+
if ( $item->is_image() ) {
|
514 |
+
$dimensions = $item->get_dimensions();
|
515 |
+
$orientation = $dimensions['width'] > $dimensions['height'] ? ' landscape' : ' portrait';
|
516 |
+
$orientation = $dimensions['width'] && $dimensions['height'] ? $orientation : '';
|
517 |
+
|
518 |
+
if ( ! wp_doing_ajax() && $item->get_optimized_size( false ) > 100000 ) {
|
519 |
+
// LazyLoad.
|
520 |
+
$image_tag = '<img src="' . esc_url( IMAGIFY_ASSETS_IMG_URL . 'lazyload.png' ) . '" data-lazy-src="' . esc_url( $url ) . '" alt="" />';
|
521 |
+
$image_tag .= '<noscript><img src="' . esc_url( $url ) . '" alt="" /></noscript>';
|
522 |
+
} else {
|
523 |
+
$image_tag = '<img src="' . esc_url( $url ) . '" class="hide-if-no-js" alt="" />';
|
524 |
+
}
|
525 |
} else {
|
526 |
+
$orientation = '';
|
527 |
+
$image_tag = '<img src="' . esc_url( wp_mime_type_icon( $mime ) ) . '" class="hide-if-no-js" alt="" />';
|
528 |
}
|
529 |
?>
|
530 |
<strong class="has-media-icon">
|
531 |
<a href="<?php echo esc_url( $url ); ?>" target="_blank">
|
532 |
+
<span class="media-icon <?php echo sanitize_html_class( $mime . '-icon' ); ?><?php echo $orientation; ?>">
|
533 |
<span class="centered">
|
534 |
<?php echo $image_tag; ?>
|
535 |
</span>
|
636 |
|
637 |
if ( ! $status ) {
|
638 |
// File is not optimized.
|
639 |
+
$messages[] = '<strong class="imagify-status-not-optimized">' . esc_html_x( 'Not optimized', 'Media File', 'imagify' ) . '</strong>';
|
640 |
} elseif ( $error_text ) {
|
641 |
// Error or already optimized.
|
642 |
$messages[] = '<span class="imagify-status-' . $status . '">' . esc_html( imagify_translate_api_message( $error_text ) ) . '</span>';
|
877 |
* @param object $item The current File object.
|
878 |
*/
|
879 |
protected function comparison_tool_button( $item ) {
|
880 |
+
if ( ! $item->is_optimized() || ! $item->has_backup() || ! $item->is_image() ) {
|
881 |
return;
|
882 |
}
|
883 |
|
inc/classes/class-imagify-files-recursive-iterator.php
CHANGED
@@ -17,7 +17,7 @@ class Imagify_Files_Recursive_Iterator extends RecursiveFilterIterator {
|
|
17 |
* @since 1.7
|
18 |
* @author Grégory Viguier
|
19 |
*/
|
20 |
-
const VERSION = '1.0.
|
21 |
|
22 |
/**
|
23 |
* Filesystem object.
|
@@ -58,6 +58,10 @@ class Imagify_Files_Recursive_Iterator extends RecursiveFilterIterator {
|
|
58 |
// Forbidden file/folder paths and names.
|
59 |
$file_path = $this->current()->getPathname();
|
60 |
|
|
|
|
|
|
|
|
|
61 |
if ( Imagify_Files_Scan::is_path_forbidden( $file_path ) ) {
|
62 |
return false;
|
63 |
}
|
17 |
* @since 1.7
|
18 |
* @author Grégory Viguier
|
19 |
*/
|
20 |
+
const VERSION = '1.0.2';
|
21 |
|
22 |
/**
|
23 |
* Filesystem object.
|
58 |
// Forbidden file/folder paths and names.
|
59 |
$file_path = $this->current()->getPathname();
|
60 |
|
61 |
+
if ( $this->current()->isDir() ) {
|
62 |
+
$file_path = trailingslashit( $file_path );
|
63 |
+
}
|
64 |
+
|
65 |
if ( Imagify_Files_Scan::is_path_forbidden( $file_path ) ) {
|
66 |
return false;
|
67 |
}
|
inc/classes/class-imagify-files-scan.php
CHANGED
@@ -16,7 +16,7 @@ class Imagify_Files_Scan {
|
|
16 |
* @since 1.7
|
17 |
* @author Grégory Viguier
|
18 |
*/
|
19 |
-
const VERSION = '1.
|
20 |
|
21 |
/**
|
22 |
* Get files (optimizable by Imagify) recursively from a specific folder.
|
@@ -46,7 +46,7 @@ class Imagify_Files_Scan {
|
|
46 |
return new WP_Error( 'not_a_folder', __( 'This file is not a folder.', 'imagify' ) );
|
47 |
}
|
48 |
|
49 |
-
if ( self::is_path_forbidden( $folder ) ) {
|
50 |
return new WP_Error( 'folder_forbidden', __( 'This folder is not allowed.', 'imagify' ) );
|
51 |
}
|
52 |
|
@@ -76,10 +76,17 @@ class Imagify_Files_Scan {
|
|
76 |
return $images;
|
77 |
}
|
78 |
|
|
|
|
|
|
|
|
|
|
|
79 |
/**
|
80 |
* Tell if a path is autorized.
|
|
|
81 |
*
|
82 |
* @since 1.7.1
|
|
|
83 |
* @access public
|
84 |
* @author Grégory Viguier
|
85 |
*
|
@@ -92,8 +99,10 @@ class Imagify_Files_Scan {
|
|
92 |
|
93 |
/**
|
94 |
* Tell if a path is forbidden.
|
|
|
95 |
*
|
96 |
* @since 1.7
|
|
|
97 |
* @access public
|
98 |
* @author Grégory Viguier
|
99 |
*
|
@@ -126,11 +135,11 @@ class Imagify_Files_Scan {
|
|
126 |
return true;
|
127 |
}
|
128 |
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
}
|
135 |
}
|
136 |
|
@@ -160,38 +169,43 @@ class Imagify_Files_Scan {
|
|
160 |
}
|
161 |
|
162 |
$filesystem = imagify_get_filesystem();
|
|
|
163 |
$folders = array(
|
164 |
// Server.
|
165 |
-
$
|
166 |
// WordPress.
|
167 |
-
$
|
168 |
-
$
|
169 |
-
get_imagify_upload_basedir( true ), // Media library.
|
170 |
-
WP_CONTENT_DIR . '/languages', // Translations.
|
171 |
WP_CONTENT_DIR . '/mu-plugins', // MU plugins.
|
172 |
WP_CONTENT_DIR . '/upgrade', // Upgrade.
|
173 |
// Plugins.
|
174 |
-
WP_CONTENT_DIR . '/backups', // A folder commonly used by backup plugins.
|
175 |
-
WP_CONTENT_DIR . '/cache', // A folder commonly used by cache plugins.
|
176 |
WP_CONTENT_DIR . '/bps-backup', // BulletProof Security.
|
|
|
177 |
WP_CONTENT_DIR . '/ngg', // NextGen Gallery.
|
178 |
WP_CONTENT_DIR . '/ngg_styles', // NextGen Gallery.
|
179 |
WP_CONTENT_DIR . '/w3tc-config', // W3 Total Cache.
|
180 |
WP_CONTENT_DIR . '/wfcache', // WP Fastest Cache.
|
181 |
WP_CONTENT_DIR . '/wp-rocket-config', // WP Rocket.
|
182 |
-
Imagify_Custom_Folders::get_backup_dir_path(), // Imagify "Custom folders" backup.
|
183 |
-
IMAGIFY_PATH, // Imagify plugin.
|
184 |
-
self::
|
185 |
-
self::get_ewww_tools_path(), // EWWW.
|
186 |
);
|
187 |
|
188 |
-
// NextGen Gallery.
|
189 |
if ( ! is_multisite() ) {
|
190 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
}
|
192 |
|
193 |
-
$folders = array_map( '
|
194 |
-
$folders = array_map( 'wp_normalize_path', $folders );
|
195 |
|
196 |
/**
|
197 |
* Add folders to the list of forbidden ones.
|
@@ -210,8 +224,7 @@ class Imagify_Files_Scan {
|
|
210 |
return $folders;
|
211 |
}
|
212 |
|
213 |
-
$added_folders = array_map( '
|
214 |
-
$added_folders = array_map( 'wp_normalize_path', $added_folders );
|
215 |
|
216 |
$folders = array_merge( $folders, $added_folders );
|
217 |
$folders = array_flip( array_flip( $folders ) );
|
@@ -220,8 +233,10 @@ class Imagify_Files_Scan {
|
|
220 |
}
|
221 |
|
222 |
/**
|
223 |
-
* Get the list of folder patterns where Imagify won't look for files to optimize.
|
224 |
-
* `^` will be prepended to each pattern (aka, the pattern must match an absolute path).
|
|
|
|
|
225 |
*
|
226 |
* @since 1.7
|
227 |
* @access public
|
@@ -238,25 +253,25 @@ class Imagify_Files_Scan {
|
|
238 |
|
239 |
$folders = array();
|
240 |
|
241 |
-
//
|
242 |
-
|
243 |
-
$folders[] = self::get_ngg_galleries_path();
|
244 |
-
}
|
245 |
|
246 |
-
if (
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
|
|
|
|
254 |
}
|
255 |
}
|
256 |
|
257 |
/**
|
258 |
* Add folder patterns to the list of forbidden ones.
|
259 |
-
* Don't forget to use `
|
260 |
*
|
261 |
* @since 1.7
|
262 |
* @author Grégory Viguier
|
@@ -321,6 +336,12 @@ class Imagify_Files_Scan {
|
|
321 |
'.DS_Store',
|
322 |
'.git',
|
323 |
'.svn',
|
|
|
|
|
|
|
|
|
|
|
|
|
324 |
'node_modules',
|
325 |
'Thumbs.db',
|
326 |
);
|
@@ -350,6 +371,11 @@ class Imagify_Files_Scan {
|
|
350 |
return $file_names;
|
351 |
}
|
352 |
|
|
|
|
|
|
|
|
|
|
|
353 |
/**
|
354 |
* Add a placeholder to a path.
|
355 |
*
|
@@ -418,14 +444,16 @@ class Imagify_Files_Scan {
|
|
418 |
return $replacements;
|
419 |
}
|
420 |
|
|
|
421 |
$replacements = array(
|
422 |
-
'{{PLUGINS}}/' => WP_PLUGIN_DIR
|
423 |
-
'{{MU_PLUGINS}}/' => WPMU_PLUGIN_DIR
|
424 |
-
'{{THEMES}}/' => WP_CONTENT_DIR . '/themes
|
425 |
-
'{{
|
|
|
426 |
'{{ABSPATH}}/' => ABSPATH,
|
427 |
);
|
428 |
-
$replacements = array_map( '
|
429 |
|
430 |
return $replacements;
|
431 |
}
|
@@ -450,6 +478,7 @@ class Imagify_Files_Scan {
|
|
450 |
'{{PLUGINS}}/' => plugins_url( '/' ),
|
451 |
'{{MU_PLUGINS}}/' => plugins_url( '/', WPMU_PLUGIN_DIR . '/.' ),
|
452 |
'{{THEMES}}/' => content_url( 'themes/' ),
|
|
|
453 |
'{{CONTENT}}/' => content_url( '/' ),
|
454 |
'{{ABSPATH}}/' => site_url( '/' ),
|
455 |
);
|
@@ -471,58 +500,63 @@ class Imagify_Files_Scan {
|
|
471 |
return imagify_get_filesystem()->is_readable( self::remove_placeholder( $file_path ) );
|
472 |
}
|
473 |
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
* @since 1.7
|
479 |
-
* @access public
|
480 |
-
* @author Grégory Viguier
|
481 |
-
*
|
482 |
-
* @param string $file_path The file path.
|
483 |
-
* @return string The normalized file path.
|
484 |
-
*/
|
485 |
-
public static function normalize_path_for_comparison( $file_path ) {
|
486 |
-
return strtolower( wp_normalize_path( trailingslashit( $file_path ) ) );
|
487 |
-
}
|
488 |
|
489 |
/**
|
490 |
-
* Get the path to NextGen galleries
|
491 |
*
|
492 |
* @since 1.7
|
493 |
* @access public
|
494 |
* @author Grégory Viguier
|
495 |
*
|
496 |
-
* @return string An absolute path.
|
497 |
*/
|
498 |
public static function get_ngg_galleries_path() {
|
499 |
-
$
|
500 |
|
501 |
-
if ( empty( $
|
502 |
-
|
503 |
-
return get_imagify_upload_basedir( true ) . 'sites/%BLOG_ID%/nggallery';
|
504 |
-
}
|
505 |
-
|
506 |
-
return WP_CONTENT_DIR . '/gallery/';
|
507 |
}
|
508 |
|
|
|
|
|
|
|
|
|
509 |
$ngg_root = defined( 'NGG_GALLERY_ROOT_TYPE' ) ? NGG_GALLERY_ROOT_TYPE : 'site';
|
510 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
511 |
if ( 'content' === $ngg_root ) {
|
512 |
-
$ngg_root = WP_CONTENT_DIR
|
513 |
} else {
|
514 |
-
$ngg_root =
|
515 |
}
|
516 |
|
517 |
-
if (
|
518 |
-
|
519 |
}
|
520 |
|
521 |
-
return $
|
522 |
}
|
523 |
|
524 |
/**
|
525 |
-
* Get the path to WooCommerce logs.
|
526 |
*
|
527 |
* @since 1.7
|
528 |
* @access public
|
@@ -535,11 +569,12 @@ class Imagify_Files_Scan {
|
|
535 |
return WC_LOG_DIR;
|
536 |
}
|
537 |
|
538 |
-
return
|
539 |
}
|
540 |
|
541 |
/**
|
542 |
* Get the path to EWWW optimization tools.
|
|
|
543 |
*
|
544 |
* @since 1.7
|
545 |
* @access public
|
@@ -554,4 +589,127 @@ class Imagify_Files_Scan {
|
|
554 |
|
555 |
return WP_CONTENT_DIR . '/ewww/';
|
556 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
557 |
}
|
16 |
* @since 1.7
|
17 |
* @author Grégory Viguier
|
18 |
*/
|
19 |
+
const VERSION = '1.1';
|
20 |
|
21 |
/**
|
22 |
* Get files (optimizable by Imagify) recursively from a specific folder.
|
46 |
return new WP_Error( 'not_a_folder', __( 'This file is not a folder.', 'imagify' ) );
|
47 |
}
|
48 |
|
49 |
+
if ( self::is_path_forbidden( trailingslashit( $folder ) ) ) {
|
50 |
return new WP_Error( 'folder_forbidden', __( 'This folder is not allowed.', 'imagify' ) );
|
51 |
}
|
52 |
|
76 |
return $images;
|
77 |
}
|
78 |
|
79 |
+
|
80 |
+
/** ----------------------------------------------------------------------------------------- */
|
81 |
+
/** FORBIDDEN FOLDERS AND FILES ============================================================= */
|
82 |
+
/** ----------------------------------------------------------------------------------------- */
|
83 |
+
|
84 |
/**
|
85 |
* Tell if a path is autorized.
|
86 |
+
* When testing a folder, the path MUST have a trailing slash.
|
87 |
*
|
88 |
* @since 1.7.1
|
89 |
+
* @since 1.8 The path must have a trailing slash if for a folder.
|
90 |
* @access public
|
91 |
* @author Grégory Viguier
|
92 |
*
|
99 |
|
100 |
/**
|
101 |
* Tell if a path is forbidden.
|
102 |
+
* When testing a folder, the path MUST have a trailing slash.
|
103 |
*
|
104 |
* @since 1.7
|
105 |
+
* @since 1.8 The path must have a trailing slash if for a folder.
|
106 |
* @access public
|
107 |
* @author Grégory Viguier
|
108 |
*
|
135 |
return true;
|
136 |
}
|
137 |
|
138 |
+
$delim = Imagify_Filesystem::PATTERN_DELIMITER;
|
139 |
+
|
140 |
+
foreach ( self::get_forbidden_folder_patterns() as $pattern ) {
|
141 |
+
if ( preg_match( $delim . '^' . $pattern . $delim, $file_path ) ) {
|
142 |
+
return true;
|
143 |
}
|
144 |
}
|
145 |
|
169 |
}
|
170 |
|
171 |
$filesystem = imagify_get_filesystem();
|
172 |
+
$abspath = $filesystem->get_abspath();
|
173 |
$folders = array(
|
174 |
// Server.
|
175 |
+
$abspath . 'cgi-bin', // `cgi-bin`
|
176 |
// WordPress.
|
177 |
+
$abspath . 'wp-admin', // `wp-admin`
|
178 |
+
$abspath . WPINC, // `wp-includes`
|
|
|
|
|
179 |
WP_CONTENT_DIR . '/mu-plugins', // MU plugins.
|
180 |
WP_CONTENT_DIR . '/upgrade', // Upgrade.
|
181 |
// Plugins.
|
|
|
|
|
182 |
WP_CONTENT_DIR . '/bps-backup', // BulletProof Security.
|
183 |
+
self::get_ewww_tools_path(), // EWWW: /wp-content/ewww.
|
184 |
WP_CONTENT_DIR . '/ngg', // NextGen Gallery.
|
185 |
WP_CONTENT_DIR . '/ngg_styles', // NextGen Gallery.
|
186 |
WP_CONTENT_DIR . '/w3tc-config', // W3 Total Cache.
|
187 |
WP_CONTENT_DIR . '/wfcache', // WP Fastest Cache.
|
188 |
WP_CONTENT_DIR . '/wp-rocket-config', // WP Rocket.
|
189 |
+
Imagify_Custom_Folders::get_backup_dir_path(), // Imagify "Custom folders" backup: /imagify-backup.
|
190 |
+
IMAGIFY_PATH, // Imagify plugin: /wp-content/plugins/imagify.
|
191 |
+
self::get_shortpixel_path(), // ShortPixel: /wp-content/uploads/ShortpixelBackups.
|
|
|
192 |
);
|
193 |
|
|
|
194 |
if ( ! is_multisite() ) {
|
195 |
+
$uploads_dir = $filesystem->get_upload_basedir( true );
|
196 |
+
$ngg_galleries = self::get_ngg_galleries_path();
|
197 |
+
|
198 |
+
if ( $ngg_galleries ) {
|
199 |
+
$folders[] = $ngg_galleries; // NextGen Gallery: /wp-content/gallery.
|
200 |
+
}
|
201 |
+
|
202 |
+
$folders[] = $uploads_dir . 'formidable'; // Formidable Forms: /wp-content/uploads/formidable.
|
203 |
+
$folders[] = get_imagify_backup_dir_path( true ); // Imagify Media Library backup: /wp-content/uploads/backup.
|
204 |
+
$folders[] = self::get_wc_logs_path(); // WooCommerce Logs: /wp-content/uploads/wc-logs.
|
205 |
+
$folders[] = $uploads_dir . 'woocommerce_uploads'; // WooCommerce uploads: /wp-content/uploads/woocommerce_uploads.
|
206 |
}
|
207 |
|
208 |
+
$folders = array_map( array( $filesystem, 'normalize_dir_path' ), $folders );
|
|
|
209 |
|
210 |
/**
|
211 |
* Add folders to the list of forbidden ones.
|
224 |
return $folders;
|
225 |
}
|
226 |
|
227 |
+
$added_folders = array_map( array( $filesystem, 'normalize_dir_path' ), $added_folders );
|
|
|
228 |
|
229 |
$folders = array_merge( $folders, $added_folders );
|
230 |
$folders = array_flip( array_flip( $folders ) );
|
233 |
}
|
234 |
|
235 |
/**
|
236 |
+
* Get the list of folder patterns where Imagify won't look for files to optimize. This is meant for paths that are dynamic.
|
237 |
+
* `^` will be prepended to each pattern (aka, the pattern must match an absolute path).
|
238 |
+
* Pattern delimiter is `Imagify_Filesystem::PATTERN_DELIMITER`.
|
239 |
+
* Paths tested against these patterns are lower-cased.
|
240 |
*
|
241 |
* @since 1.7
|
242 |
* @access public
|
253 |
|
254 |
$folders = array();
|
255 |
|
256 |
+
// Media Library: /wp\-content/uploads/(sites/\d+/)?\d{4}/\d{2}/.
|
257 |
+
$folders[] = self::get_media_library_pattern();
|
|
|
|
|
258 |
|
259 |
+
if ( is_multisite() ) {
|
260 |
+
/**
|
261 |
+
* On multisite we can't exclude Imagify's library backup folders, or any other folder located in the uploads folders (created by other plugins): there are too many ways it can fail.
|
262 |
+
* Only exception we're aware of so far is NextGen Gallery, because it provides a clear pattern to use.
|
263 |
+
*/
|
264 |
+
$ngg_galleries = self::get_ngg_galleries_multisite_pattern();
|
265 |
+
|
266 |
+
if ( $ngg_galleries ) {
|
267 |
+
// NextGen Gallery: /wp\-content/uploads/sites/\d+/nggallery/.
|
268 |
+
$folders[] = $ngg_galleries;
|
269 |
}
|
270 |
}
|
271 |
|
272 |
/**
|
273 |
* Add folder patterns to the list of forbidden ones.
|
274 |
+
* Don't forget to use `Imagify_Files_Scan::normalize_path_for_regex( $path )`!
|
275 |
*
|
276 |
* @since 1.7
|
277 |
* @author Grégory Viguier
|
336 |
'.DS_Store',
|
337 |
'.git',
|
338 |
'.svn',
|
339 |
+
'backup',
|
340 |
+
'backups',
|
341 |
+
'cache',
|
342 |
+
'lang',
|
343 |
+
'langs',
|
344 |
+
'languages',
|
345 |
'node_modules',
|
346 |
'Thumbs.db',
|
347 |
);
|
371 |
return $file_names;
|
372 |
}
|
373 |
|
374 |
+
|
375 |
+
/** ----------------------------------------------------------------------------------------- */
|
376 |
+
/** PLACEHOLDERS ============================================================================ */
|
377 |
+
/** ----------------------------------------------------------------------------------------- */
|
378 |
+
|
379 |
/**
|
380 |
* Add a placeholder to a path.
|
381 |
*
|
444 |
return $replacements;
|
445 |
}
|
446 |
|
447 |
+
$filesystem = imagify_get_filesystem();
|
448 |
$replacements = array(
|
449 |
+
'{{PLUGINS}}/' => WP_PLUGIN_DIR,
|
450 |
+
'{{MU_PLUGINS}}/' => WPMU_PLUGIN_DIR,
|
451 |
+
'{{THEMES}}/' => WP_CONTENT_DIR . '/themes',
|
452 |
+
'{{UPLOADS}}/' => $filesystem->get_main_upload_basedir(),
|
453 |
+
'{{CONTENT}}/' => WP_CONTENT_DIR,
|
454 |
'{{ABSPATH}}/' => ABSPATH,
|
455 |
);
|
456 |
+
$replacements = array_map( array( $filesystem, 'normalize_dir_path' ), $replacements );
|
457 |
|
458 |
return $replacements;
|
459 |
}
|
478 |
'{{PLUGINS}}/' => plugins_url( '/' ),
|
479 |
'{{MU_PLUGINS}}/' => plugins_url( '/', WPMU_PLUGIN_DIR . '/.' ),
|
480 |
'{{THEMES}}/' => content_url( 'themes/' ),
|
481 |
+
'{{UPLOADS}}/' => imagify_get_filesystem()->get_main_upload_baseurl(),
|
482 |
'{{CONTENT}}/' => content_url( '/' ),
|
483 |
'{{ABSPATH}}/' => site_url( '/' ),
|
484 |
);
|
500 |
return imagify_get_filesystem()->is_readable( self::remove_placeholder( $file_path ) );
|
501 |
}
|
502 |
|
503 |
+
|
504 |
+
/** ----------------------------------------------------------------------------------------- */
|
505 |
+
/** PATHS =================================================================================== */
|
506 |
+
/** ----------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
|
508 |
/**
|
509 |
+
* Get the path to NextGen galleries on monosites.
|
510 |
*
|
511 |
* @since 1.7
|
512 |
* @access public
|
513 |
* @author Grégory Viguier
|
514 |
*
|
515 |
+
* @return string|bool An absolute path. False if it can't be retrieved.
|
516 |
*/
|
517 |
public static function get_ngg_galleries_path() {
|
518 |
+
$galleries_path = get_site_option( 'ngg_options' );
|
519 |
|
520 |
+
if ( empty( $galleries_path['gallerypath'] ) ) {
|
521 |
+
return false;
|
|
|
|
|
|
|
|
|
522 |
}
|
523 |
|
524 |
+
$filesystem = imagify_get_filesystem();
|
525 |
+
$galleries_path = $filesystem->normalize_dir_path( $galleries_path['gallerypath'] );
|
526 |
+
$galleries_path = trim( $galleries_path, '/' ); // Something like `wp-content/gallery`.
|
527 |
+
|
528 |
$ngg_root = defined( 'NGG_GALLERY_ROOT_TYPE' ) ? NGG_GALLERY_ROOT_TYPE : 'site';
|
529 |
|
530 |
+
if ( $galleries_path && 'content' === $ngg_root ) {
|
531 |
+
$ngg_root = $filesystem->normalize_dir_path( WP_CONTENT_DIR );
|
532 |
+
$ngg_root = trim( $ngg_root, '/' ); // Something like `abs-path/to/wp-content`.
|
533 |
+
|
534 |
+
$exploded_root = explode( '/', $ngg_root );
|
535 |
+
$exploded_galleries = explode( '/', $galleries_path );
|
536 |
+
$first_gallery_dirname = reset( $exploded_galleries );
|
537 |
+
$last_root_dirname = end( $exploded_root );
|
538 |
+
|
539 |
+
if ( $last_root_dirname === $first_gallery_dirname ) {
|
540 |
+
array_shift( $exploded_galleries );
|
541 |
+
$galleries_path = implode( '/', $exploded_galleries );
|
542 |
+
}
|
543 |
+
}
|
544 |
+
|
545 |
if ( 'content' === $ngg_root ) {
|
546 |
+
$ngg_root = $filesystem->normalize_dir_path( WP_CONTENT_DIR );
|
547 |
} else {
|
548 |
+
$ngg_root = $filesystem->get_abspath();
|
549 |
}
|
550 |
|
551 |
+
if ( strpos( $galleries_path, $ngg_root ) !== 0 ) {
|
552 |
+
$galleries_path = $ngg_root . $galleries_path;
|
553 |
}
|
554 |
|
555 |
+
return $galleries_path . '/';
|
556 |
}
|
557 |
|
558 |
/**
|
559 |
+
* Get the path to WooCommerce logs on monosites.
|
560 |
*
|
561 |
* @since 1.7
|
562 |
* @access public
|
569 |
return WC_LOG_DIR;
|
570 |
}
|
571 |
|
572 |
+
return imagify_get_filesystem()->get_upload_basedir( true ) . 'wc-logs/';
|
573 |
}
|
574 |
|
575 |
/**
|
576 |
* Get the path to EWWW optimization tools.
|
577 |
+
* It is the same for all sites on multisite.
|
578 |
*
|
579 |
* @since 1.7
|
580 |
* @access public
|
589 |
|
590 |
return WP_CONTENT_DIR . '/ewww/';
|
591 |
}
|
592 |
+
|
593 |
+
/**
|
594 |
+
* Get the path to ShortPixel backup folder.
|
595 |
+
* It is the same for all sites on multisite (and yes, you'll get a surprise if your upload base dir -aka uploads/sites/12/- is not 2 folders deeper than theuploads folder).
|
596 |
+
*
|
597 |
+
* @since 1.8
|
598 |
+
* @access public
|
599 |
+
* @author Grégory Viguier
|
600 |
+
*
|
601 |
+
* @return string An absolute path.
|
602 |
+
*/
|
603 |
+
public static function get_shortpixel_path() {
|
604 |
+
if ( defined( 'SHORTPIXEL_BACKUP_FOLDER' ) ) {
|
605 |
+
return trailingslashit( SHORTPIXEL_BACKUP_FOLDER );
|
606 |
+
}
|
607 |
+
|
608 |
+
$filesystem = imagify_get_filesystem();
|
609 |
+
$path = $filesystem->get_upload_basedir( true );
|
610 |
+
$path = is_main_site() ? $path : $filesystem->dir_path( $filesystem->dir_path( $path ) );
|
611 |
+
|
612 |
+
return $path . 'ShortpixelBackups/';
|
613 |
+
}
|
614 |
+
|
615 |
+
|
616 |
+
/** ----------------------------------------------------------------------------------------- */
|
617 |
+
/** REGEX PATTERNS ========================================================================== */
|
618 |
+
/** ----------------------------------------------------------------------------------------- */
|
619 |
+
|
620 |
+
/**
|
621 |
+
* Get the regex pattern used to match the paths to the media library.
|
622 |
+
* Pattern delimiter is `Imagify_Filesystem::PATTERN_DELIMITER`.
|
623 |
+
* Paths tested against these patterns are lower-cased.
|
624 |
+
*
|
625 |
+
* @since 1.8
|
626 |
+
* @access public
|
627 |
+
* @author Grégory Viguier
|
628 |
+
*
|
629 |
+
* @return string Something like `/wp\-content/uploads/(sites/\d+/)?\d{4}/\d{2}/`.
|
630 |
+
*/
|
631 |
+
public static function get_media_library_pattern() {
|
632 |
+
$filesystem = imagify_get_filesystem();
|
633 |
+
$uploads_dir = self::normalize_path_for_regex( $filesystem->get_main_upload_basedir() );
|
634 |
+
|
635 |
+
if ( ! is_multisite() ) {
|
636 |
+
if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
|
637 |
+
// In year/month folders.
|
638 |
+
return $uploads_dir . '\d{4}/\d{2}/';
|
639 |
+
}
|
640 |
+
|
641 |
+
// Not in year/month folders.
|
642 |
+
return $uploads_dir . '[^/]+$';
|
643 |
+
}
|
644 |
+
|
645 |
+
$pattern = $filesystem->get_multisite_uploads_subdir_pattern();
|
646 |
+
|
647 |
+
if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
|
648 |
+
// In year/month folders.
|
649 |
+
return $uploads_dir . '(' . $pattern . ')?\d{4}/\d{2}/';
|
650 |
+
}
|
651 |
+
|
652 |
+
// Not in year/month folders.
|
653 |
+
return $uploads_dir . '(' . $pattern . ')?[^/]+$';
|
654 |
+
}
|
655 |
+
|
656 |
+
/**
|
657 |
+
* Get the regex pattern used to match the paths to NextGen galleries on multisite.
|
658 |
+
* Pattern delimiter is `Imagify_Filesystem::PATTERN_DELIMITER`.
|
659 |
+
* Paths tested against these patterns are lower-cased.
|
660 |
+
*
|
661 |
+
* @since 1.8
|
662 |
+
* @access public
|
663 |
+
* @author Grégory Viguier
|
664 |
+
*
|
665 |
+
* @return string|bool Something like `/wp-content/uploads/sites/\d+/nggallery/`. False if it can't be retrieved.
|
666 |
+
*/
|
667 |
+
public static function get_ngg_galleries_multisite_pattern() {
|
668 |
+
$galleries_path = self::get_ngg_galleries_path(); // Something like `wp-content/uploads/sites/%BLOG_ID%/nggallery/`.
|
669 |
+
|
670 |
+
if ( ! $galleries_path ) {
|
671 |
+
return false;
|
672 |
+
}
|
673 |
+
|
674 |
+
$galleries_path = self::normalize_path_for_regex( $galleries_path );
|
675 |
+
$galleries_path = str_replace( array( '%blog_name%', '%blog_id%' ), array( '.+', '\d+' ), $galleries_path );
|
676 |
+
|
677 |
+
return $galleries_path;
|
678 |
+
}
|
679 |
+
|
680 |
+
|
681 |
+
/** ----------------------------------------------------------------------------------------- */
|
682 |
+
/** NORMALIZATION TOOLS ===================================================================== */
|
683 |
+
/** ----------------------------------------------------------------------------------------- */
|
684 |
+
|
685 |
+
/**
|
686 |
+
* Normalize a file path, aiming for path comparison.
|
687 |
+
* The path is normalized and case-lowered.
|
688 |
+
*
|
689 |
+
* @since 1.7
|
690 |
+
* @since 1.8 No trailing slash anymore, because it can be used for files.
|
691 |
+
* @access public
|
692 |
+
* @author Grégory Viguier
|
693 |
+
*
|
694 |
+
* @param string $file_path The file path.
|
695 |
+
* @return string The normalized file path.
|
696 |
+
*/
|
697 |
+
public static function normalize_path_for_comparison( $file_path ) {
|
698 |
+
return strtolower( wp_normalize_path( $file_path ) );
|
699 |
+
}
|
700 |
+
|
701 |
+
/**
|
702 |
+
* Normalize a file path, aiming for use in a regex pattern.
|
703 |
+
* The path is normalized, case-lowered, and escaped.
|
704 |
+
*
|
705 |
+
* @since 1.8
|
706 |
+
* @access public
|
707 |
+
* @author Grégory Viguier
|
708 |
+
*
|
709 |
+
* @param string $file_path The file path.
|
710 |
+
* @return string The normalized file path.
|
711 |
+
*/
|
712 |
+
public static function normalize_path_for_regex( $file_path ) {
|
713 |
+
return preg_quote( imagify_get_filesystem()->normalize_path_for_comparison( $file_path ), Imagify_Filesystem::PATTERN_DELIMITER );
|
714 |
+
}
|
715 |
}
|
inc/classes/class-imagify-files-stats.php
CHANGED
File without changes
|
inc/classes/class-imagify-filesystem.php
CHANGED
@@ -17,7 +17,16 @@ class Imagify_Filesystem extends WP_Filesystem_Direct {
|
|
17 |
*
|
18 |
* @var string
|
19 |
*/
|
20 |
-
const VERSION = '1.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
/**
|
23 |
* The single instance of the class.
|
@@ -124,7 +133,7 @@ class Imagify_Filesystem extends WP_Filesystem_Direct {
|
|
124 |
* @param string $file_path Path to the file.
|
125 |
* @param string $option If present, specifies a specific element to be returned; one of 'dir_path', 'file_name', 'extension' or 'file_base'.
|
126 |
* If option is not specified, returns all available elements.
|
127 |
-
* @return array|string
|
128 |
*/
|
129 |
public function path_info( $file_path, $option = null ) {
|
130 |
if ( ! $file_path ) {
|
@@ -175,22 +184,6 @@ class Imagify_Filesystem extends WP_Filesystem_Direct {
|
|
175 |
);
|
176 |
}
|
177 |
|
178 |
-
/**
|
179 |
-
* Determine if a file or directory is writable.
|
180 |
-
* This function is used to work around certain ACL issues in PHP primarily affecting Windows Servers.
|
181 |
-
* Replacement for is_writable().
|
182 |
-
*
|
183 |
-
* @param string $file_path Path to the file.
|
184 |
-
* @return bool
|
185 |
-
*/
|
186 |
-
public function is_writable( $file_path ) {
|
187 |
-
if ( ! $file_path ) {
|
188 |
-
return false;
|
189 |
-
}
|
190 |
-
|
191 |
-
return wp_is_writable( $file_path );
|
192 |
-
}
|
193 |
-
|
194 |
/**
|
195 |
* Recursive directory creation based on full path. Will attempt to set permissions on folders.
|
196 |
* Replacement for recursive mkdir().
|
@@ -388,11 +381,132 @@ class Imagify_Filesystem extends WP_Filesystem_Direct {
|
|
388 |
return false;
|
389 |
}
|
390 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
|
392 |
/** ----------------------------------------------------------------------------------------- */
|
393 |
/** WORK WITH IMAGES ======================================================================== */
|
394 |
/** ----------------------------------------------------------------------------------------- */
|
395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
/**
|
397 |
* Get an image data.
|
398 |
* Replacement for getimagesize().
|
@@ -402,7 +516,7 @@ class Imagify_Filesystem extends WP_Filesystem_Direct {
|
|
402 |
* @author Grégory Viguier
|
403 |
*
|
404 |
* @param string $file_path Path to the file.
|
405 |
-
* @return array
|
406 |
*/
|
407 |
public function get_image_size( $file_path ) {
|
408 |
if ( ! $file_path ) {
|
@@ -638,7 +752,7 @@ class Imagify_Filesystem extends WP_Filesystem_Direct {
|
|
638 |
|
639 |
$abspath = trailingslashit( $abspath );
|
640 |
|
641 |
-
if ( '/' !== substr( $abspath, 0, 1 ) && ':' !== substr( $
|
642 |
$abspath = '/' . $abspath;
|
643 |
}
|
644 |
|
@@ -716,4 +830,114 @@ class Imagify_Filesystem extends WP_Filesystem_Direct {
|
|
716 |
|
717 |
return $upload_baseurl;
|
718 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
719 |
}
|
17 |
*
|
18 |
* @var string
|
19 |
*/
|
20 |
+
const VERSION = '1.1';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Delimiter used for regex patterns.
|
24 |
+
*
|
25 |
+
* @var string
|
26 |
+
* @since 1.8
|
27 |
+
* @author Grégory Viguier
|
28 |
+
*/
|
29 |
+
const PATTERN_DELIMITER = '@';
|
30 |
|
31 |
/**
|
32 |
* The single instance of the class.
|
133 |
* @param string $file_path Path to the file.
|
134 |
* @param string $option If present, specifies a specific element to be returned; one of 'dir_path', 'file_name', 'extension' or 'file_base'.
|
135 |
* If option is not specified, returns all available elements.
|
136 |
+
* @return array|string|null If the option parameter is not passed, an associative array containing the following elements is returned: 'dir_path' (with trailing slash), 'file_name' (with extension), 'extension' (if any), and 'file_base' (without extension).
|
137 |
*/
|
138 |
public function path_info( $file_path, $option = null ) {
|
139 |
if ( ! $file_path ) {
|
184 |
);
|
185 |
}
|
186 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
/**
|
188 |
* Recursive directory creation based on full path. Will attempt to set permissions on folders.
|
189 |
* Replacement for recursive mkdir().
|
381 |
return false;
|
382 |
}
|
383 |
|
384 |
+
/**
|
385 |
+
* Tell if a file is a pdf.
|
386 |
+
*
|
387 |
+
* @since 1.8
|
388 |
+
* @access public
|
389 |
+
* @author Grégory Viguier
|
390 |
+
*
|
391 |
+
* @param string $file_path Path to the file.
|
392 |
+
* @return bool
|
393 |
+
*/
|
394 |
+
public function is_pdf( $file_path ) {
|
395 |
+
if ( function_exists( 'finfo_fopen' ) ) {
|
396 |
+
$finfo = finfo_open( FILEINFO_MIME );
|
397 |
+
|
398 |
+
if ( $finfo ) {
|
399 |
+
$mimetype = finfo_file( $finfo, $file_path );
|
400 |
+
|
401 |
+
if ( false !== $mimetype ) {
|
402 |
+
return 'application/pdf' === $mimetype;
|
403 |
+
}
|
404 |
+
}
|
405 |
+
}
|
406 |
+
|
407 |
+
if ( function_exists( 'mime_content_type' ) ) {
|
408 |
+
$mimetype = mime_content_type( $file_path );
|
409 |
+
return 'application/pdf' === $mimetype;
|
410 |
+
}
|
411 |
+
|
412 |
+
return false;
|
413 |
+
}
|
414 |
+
|
415 |
+
|
416 |
+
/** ----------------------------------------------------------------------------------------- */
|
417 |
+
/** CLASS OVERWRITES ======================================================================== */
|
418 |
+
/** ----------------------------------------------------------------------------------------- */
|
419 |
+
|
420 |
+
/**
|
421 |
+
* Move a file and apply chmod.
|
422 |
+
* If the file failed to be moved once, a 2nd attempt is made after applying chmod.
|
423 |
+
*
|
424 |
+
* @since 1.8
|
425 |
+
* @access public
|
426 |
+
* @author Grégory Viguier
|
427 |
+
*
|
428 |
+
* @param string $source Path to the file to move.
|
429 |
+
* @param string $destination Path to the destination.
|
430 |
+
* @param bool $overwrite Allow to overwrite existing file at destination.
|
431 |
+
* @return bool True on success, false on failure.
|
432 |
+
*/
|
433 |
+
public function move( $source, $destination, $overwrite = false ) {
|
434 |
+
if ( parent::move( $source, $destination, $overwrite ) ) {
|
435 |
+
return $this->chmod_file( $destination );
|
436 |
+
}
|
437 |
+
|
438 |
+
if ( ! $this->chmod_file( $destination ) ) {
|
439 |
+
return false;
|
440 |
+
}
|
441 |
+
|
442 |
+
if ( parent::move( $source, $destination, $overwrite ) ) {
|
443 |
+
return $this->chmod_file( $destination );
|
444 |
+
}
|
445 |
+
|
446 |
+
return false;
|
447 |
+
}
|
448 |
+
|
449 |
+
/**
|
450 |
+
* Determine if a file or directory is writable.
|
451 |
+
* This function is used to work around certain ACL issues in PHP primarily affecting Windows Servers.
|
452 |
+
* Replacement for is_writable().
|
453 |
+
*
|
454 |
+
* @since 1.7.1
|
455 |
+
* @access public
|
456 |
+
* @author Grégory Viguier
|
457 |
+
*
|
458 |
+
* @param string $file_path Path to the file.
|
459 |
+
* @return bool
|
460 |
+
*/
|
461 |
+
public function is_writable( $file_path ) {
|
462 |
+
if ( ! $file_path ) {
|
463 |
+
return false;
|
464 |
+
}
|
465 |
+
|
466 |
+
return wp_is_writable( $file_path );
|
467 |
+
}
|
468 |
+
|
469 |
|
470 |
/** ----------------------------------------------------------------------------------------- */
|
471 |
/** WORK WITH IMAGES ======================================================================== */
|
472 |
/** ----------------------------------------------------------------------------------------- */
|
473 |
|
474 |
+
/**
|
475 |
+
* Tell if a file is an image.
|
476 |
+
*
|
477 |
+
* @since 1.8
|
478 |
+
* @access public
|
479 |
+
* @author Grégory Viguier
|
480 |
+
*
|
481 |
+
* @param string $file_path Path to the file.
|
482 |
+
* @return bool
|
483 |
+
*/
|
484 |
+
public function is_image( $file_path ) {
|
485 |
+
if ( function_exists( 'finfo_fopen' ) ) {
|
486 |
+
$finfo = finfo_open( FILEINFO_MIME );
|
487 |
+
|
488 |
+
if ( $finfo ) {
|
489 |
+
$mimetype = finfo_file( $finfo, $file_path );
|
490 |
+
|
491 |
+
if ( false !== $mimetype ) {
|
492 |
+
return strpos( $mimetype, 'image/' ) === 0;
|
493 |
+
}
|
494 |
+
}
|
495 |
+
}
|
496 |
+
|
497 |
+
if ( function_exists( 'exif_imagetype' ) ) {
|
498 |
+
$mimetype = exif_imagetype( $file_path );
|
499 |
+
return (bool) $mimetype;
|
500 |
+
}
|
501 |
+
|
502 |
+
if ( function_exists( 'mime_content_type' ) ) {
|
503 |
+
$mimetype = mime_content_type( $file_path );
|
504 |
+
return strpos( $mimetype, 'image/' ) === 0;
|
505 |
+
}
|
506 |
+
|
507 |
+
return false;
|
508 |
+
}
|
509 |
+
|
510 |
/**
|
511 |
* Get an image data.
|
512 |
* Replacement for getimagesize().
|
516 |
* @author Grégory Viguier
|
517 |
*
|
518 |
* @param string $file_path Path to the file.
|
519 |
+
* @return array The image data. An empty array on failure.
|
520 |
*/
|
521 |
public function get_image_size( $file_path ) {
|
522 |
if ( ! $file_path ) {
|
752 |
|
753 |
$abspath = trailingslashit( $abspath );
|
754 |
|
755 |
+
if ( '/' !== substr( $abspath, 0, 1 ) && ':' !== substr( $abspath, 1, 1 ) ) {
|
756 |
$abspath = '/' . $abspath;
|
757 |
}
|
758 |
|
830 |
|
831 |
return $upload_baseurl;
|
832 |
}
|
833 |
+
|
834 |
+
/**
|
835 |
+
* Get the path to the uploads base directory of the main site.
|
836 |
+
*
|
837 |
+
* @since 1.8
|
838 |
+
* @access public
|
839 |
+
* @author Grégory Viguier
|
840 |
+
*
|
841 |
+
* @return string
|
842 |
+
*/
|
843 |
+
public function get_main_upload_basedir() {
|
844 |
+
static $basedir;
|
845 |
+
|
846 |
+
if ( isset( $basedir ) ) {
|
847 |
+
return $basedir;
|
848 |
+
}
|
849 |
+
|
850 |
+
$basedir = get_imagify_upload_basedir( true );
|
851 |
+
|
852 |
+
if ( is_multisite() ) {
|
853 |
+
$pattern = '/' . $this->get_multisite_uploads_subdir_pattern() . '$';
|
854 |
+
$basedir = preg_replace( self::PATTERN_DELIMITER . $pattern . self::PATTERN_DELIMITER, '/', $basedir );
|
855 |
+
}
|
856 |
+
|
857 |
+
return $basedir;
|
858 |
+
}
|
859 |
+
|
860 |
+
/**
|
861 |
+
* Get the URL of the uploads base directory of the main site.
|
862 |
+
*
|
863 |
+
* @since 1.8
|
864 |
+
* @access public
|
865 |
+
* @author Grégory Viguier
|
866 |
+
*
|
867 |
+
* @return string
|
868 |
+
*/
|
869 |
+
public function get_main_upload_baseurl() {
|
870 |
+
static $baseurl;
|
871 |
+
|
872 |
+
if ( isset( $baseurl ) ) {
|
873 |
+
return $baseurl;
|
874 |
+
}
|
875 |
+
|
876 |
+
$baseurl = get_imagify_upload_baseurl( true );
|
877 |
+
|
878 |
+
if ( is_multisite() ) {
|
879 |
+
$pattern = '/' . $this->get_multisite_uploads_subdir_pattern() . '$';
|
880 |
+
$baseurl = preg_replace( self::PATTERN_DELIMITER . $pattern . self::PATTERN_DELIMITER, '/', $baseurl );
|
881 |
+
}
|
882 |
+
|
883 |
+
return $baseurl;
|
884 |
+
}
|
885 |
+
|
886 |
+
/**
|
887 |
+
* Get the regex pattern used to match the uploads subdir on multisite in a file path.
|
888 |
+
* Pattern delimiter is `Imagify_Filesystem::PATTERN_DELIMITER`.
|
889 |
+
* Paths tested against these patterns are lower-cased.
|
890 |
+
*
|
891 |
+
* @since 1.8
|
892 |
+
* @access public
|
893 |
+
* @see _wp_upload_dir()
|
894 |
+
* @author Grégory Viguier
|
895 |
+
*
|
896 |
+
* @return string
|
897 |
+
*/
|
898 |
+
public function get_multisite_uploads_subdir_pattern() {
|
899 |
+
static $pattern;
|
900 |
+
|
901 |
+
if ( isset( $pattern ) ) {
|
902 |
+
return $pattern;
|
903 |
+
}
|
904 |
+
|
905 |
+
$pattern = '';
|
906 |
+
|
907 |
+
if ( ! is_multisite() ) {
|
908 |
+
return $pattern;
|
909 |
+
}
|
910 |
+
|
911 |
+
if ( ! get_site_option( 'ms_files_rewriting' ) ) {
|
912 |
+
if ( defined( 'MULTISITE' ) ) {
|
913 |
+
$pattern = 'sites/\d+/';
|
914 |
+
} else {
|
915 |
+
$pattern = '\d+/';
|
916 |
+
}
|
917 |
+
} elseif ( defined( 'UPLOADS' ) ) {
|
918 |
+
$site_id = (string) get_current_blog_id();
|
919 |
+
$path = $this->get_upload_basedir( true ); // Something like `/absolute/path/to/wp-content/blogs.dir/3/files/`, also for site 1.
|
920 |
+
$path = strrev( $path );
|
921 |
+
|
922 |
+
if ( preg_match( self::PATTERN_DELIMITER . '^.*' . strrev( $site_id ) . '[^/]*/' . self::PATTERN_DELIMITER . 'U', $path, $matches ) ) {
|
923 |
+
$pattern = end( $matches );
|
924 |
+
$pattern = ltrim( strtolower( strrev( $pattern ) ), '/' );
|
925 |
+
$pattern = str_replace( $site_id, '\d+', $pattern );
|
926 |
+
}
|
927 |
+
}
|
928 |
+
|
929 |
+
/**
|
930 |
+
* Filter the regex pattern used to match the uploads subdir on multisite in a file path.
|
931 |
+
* Pattern delimiter is `Imagify_Filesystem::PATTERN_DELIMITER`.
|
932 |
+
* Important: lowercase, no heading slash, mandatory trailing slash.
|
933 |
+
*
|
934 |
+
* @since 1.8
|
935 |
+
* @author Grégory Viguier
|
936 |
+
*
|
937 |
+
* @param string $pattern The regex pattern.
|
938 |
+
*/
|
939 |
+
$pattern = apply_filters( 'imagify_multisite_uploads_subdir_pattern', $pattern );
|
940 |
+
|
941 |
+
return $pattern;
|
942 |
+
}
|
943 |
}
|
inc/classes/class-imagify-folders-db.php
CHANGED
File without changes
|
inc/classes/class-imagify-options.php
CHANGED
File without changes
|
inc/classes/class-imagify-requirements.php
CHANGED
File without changes
|
inc/classes/class-imagify-settings.php
CHANGED
File without changes
|
inc/classes/class-imagify-views.php
CHANGED
@@ -257,7 +257,7 @@ class Imagify_Views {
|
|
257 |
'unoptimized_attachment_limit' => 0,
|
258 |
// What to optimize.
|
259 |
'icon' => 'images-alt2',
|
260 |
-
'title' => __( 'Optimize your
|
261 |
'groups' => array(),
|
262 |
);
|
263 |
|
@@ -301,7 +301,7 @@ class Imagify_Views {
|
|
301 |
'context' => 'wp',
|
302 |
'title' => __( 'Media Library', 'imagify' ),
|
303 |
/* translators: 1 is the opening of a link, 2 is the closing of this link. */
|
304 |
-
'footer' => sprintf( __( 'You can also re-optimize your
|
305 |
);
|
306 |
}
|
307 |
|
@@ -316,7 +316,7 @@ class Imagify_Views {
|
|
316 |
'context' => 'File',
|
317 |
'title' => __( 'Custom folders', 'imagify' ),
|
318 |
/* translators: 1 is the opening of a link, 2 is the closing of this link. */
|
319 |
-
'footer' => sprintf( __( 'You can re-optimize your
|
320 |
);
|
321 |
}
|
322 |
}
|
257 |
'unoptimized_attachment_limit' => 0,
|
258 |
// What to optimize.
|
259 |
'icon' => 'images-alt2',
|
260 |
+
'title' => __( 'Optimize your media files', 'imagify' ),
|
261 |
'groups' => array(),
|
262 |
);
|
263 |
|
301 |
'context' => 'wp',
|
302 |
'title' => __( 'Media Library', 'imagify' ),
|
303 |
/* translators: 1 is the opening of a link, 2 is the closing of this link. */
|
304 |
+
'footer' => sprintf( __( 'You can also re-optimize your media files from your %1$sMedia Library%2$s screen.', 'imagify' ), '<a href="' . esc_url( admin_url( 'upload.php' ) ) . '">', '</a>' ),
|
305 |
);
|
306 |
}
|
307 |
|
316 |
'context' => 'File',
|
317 |
'title' => __( 'Custom folders', 'imagify' ),
|
318 |
/* translators: 1 is the opening of a link, 2 is the closing of this link. */
|
319 |
+
'footer' => sprintf( __( 'You can re-optimize your media files more finely directly in the %1$smedia management%2$s.', 'imagify' ), '<a href="' . esc_url( get_imagify_admin_url( 'files-list' ) ) . '">', '</a>' ),
|
320 |
);
|
321 |
}
|
322 |
}
|
inc/classes/class-imagify.php
CHANGED
File without changes
|
inc/classes/class-wp-async-request.php
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WP Async Request
|
4 |
+
*
|
5 |
+
* @package WP-Background-Processing
|
6 |
+
*/
|
7 |
+
|
8 |
+
if ( ! class_exists( 'WP_Async_Request' ) ) {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Abstract WP_Async_Request class.
|
12 |
+
*
|
13 |
+
* @abstract
|
14 |
+
*/
|
15 |
+
abstract class WP_Async_Request {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Prefix
|
19 |
+
*
|
20 |
+
* (default value: 'wp')
|
21 |
+
*
|
22 |
+
* @var string
|
23 |
+
* @access protected
|
24 |
+
*/
|
25 |
+
protected $prefix = 'wp';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Action
|
29 |
+
*
|
30 |
+
* (default value: 'async_request')
|
31 |
+
*
|
32 |
+
* @var string
|
33 |
+
* @access protected
|
34 |
+
*/
|
35 |
+
protected $action = 'async_request';
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Identifier
|
39 |
+
*
|
40 |
+
* @var mixed
|
41 |
+
* @access protected
|
42 |
+
*/
|
43 |
+
protected $identifier;
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Data
|
47 |
+
*
|
48 |
+
* (default value: array())
|
49 |
+
*
|
50 |
+
* @var array
|
51 |
+
* @access protected
|
52 |
+
*/
|
53 |
+
protected $data = array();
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Initiate new async request
|
57 |
+
*/
|
58 |
+
public function __construct() {
|
59 |
+
$this->identifier = $this->prefix . '_' . $this->action;
|
60 |
+
|
61 |
+
add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
62 |
+
add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Set data used during the request
|
67 |
+
*
|
68 |
+
* @param array $data Data.
|
69 |
+
*
|
70 |
+
* @return $this
|
71 |
+
*/
|
72 |
+
public function data( $data ) {
|
73 |
+
$this->data = $data;
|
74 |
+
|
75 |
+
return $this;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Dispatch the async request
|
80 |
+
*
|
81 |
+
* @return array|WP_Error
|
82 |
+
*/
|
83 |
+
public function dispatch() {
|
84 |
+
$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
|
85 |
+
$args = $this->get_post_args();
|
86 |
+
|
87 |
+
return wp_remote_post( esc_url_raw( $url ), $args );
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get query args
|
92 |
+
*
|
93 |
+
* @return array
|
94 |
+
*/
|
95 |
+
protected function get_query_args() {
|
96 |
+
if ( property_exists( $this, 'query_args' ) ) {
|
97 |
+
return $this->query_args;
|
98 |
+
}
|
99 |
+
|
100 |
+
return array(
|
101 |
+
'action' => $this->identifier,
|
102 |
+
'nonce' => wp_create_nonce( $this->identifier ),
|
103 |
+
);
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Get query URL
|
108 |
+
*
|
109 |
+
* @return string
|
110 |
+
*/
|
111 |
+
protected function get_query_url() {
|
112 |
+
if ( property_exists( $this, 'query_url' ) ) {
|
113 |
+
return $this->query_url;
|
114 |
+
}
|
115 |
+
|
116 |
+
return admin_url( 'admin-ajax.php' );
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Get post args
|
121 |
+
*
|
122 |
+
* @return array
|
123 |
+
*/
|
124 |
+
protected function get_post_args() {
|
125 |
+
if ( property_exists( $this, 'post_args' ) ) {
|
126 |
+
return $this->post_args;
|
127 |
+
}
|
128 |
+
|
129 |
+
return array(
|
130 |
+
'timeout' => 0.01,
|
131 |
+
'blocking' => false,
|
132 |
+
'body' => $this->data,
|
133 |
+
'cookies' => $_COOKIE,
|
134 |
+
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
|
135 |
+
);
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Maybe handle
|
140 |
+
*
|
141 |
+
* Check for correct nonce and pass to handler.
|
142 |
+
*/
|
143 |
+
public function maybe_handle() {
|
144 |
+
// Don't lock up other requests while processing
|
145 |
+
session_write_close();
|
146 |
+
|
147 |
+
check_ajax_referer( $this->identifier, 'nonce' );
|
148 |
+
|
149 |
+
$this->handle();
|
150 |
+
|
151 |
+
wp_die();
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Handle
|
156 |
+
*
|
157 |
+
* Override this method to perform any actions required
|
158 |
+
* during the async request.
|
159 |
+
*/
|
160 |
+
abstract protected function handle();
|
161 |
+
|
162 |
+
}
|
163 |
+
}
|
inc/classes/class-wp-background-process.php
ADDED
@@ -0,0 +1,506 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WP Background Process
|
4 |
+
*
|
5 |
+
* @package WP-Background-Processing
|
6 |
+
*/
|
7 |
+
|
8 |
+
if ( ! class_exists( 'WP_Background_Process' ) ) {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Abstract WP_Background_Process class.
|
12 |
+
*
|
13 |
+
* @abstract
|
14 |
+
* @extends WP_Async_Request
|
15 |
+
*/
|
16 |
+
abstract class WP_Background_Process extends WP_Async_Request {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Action
|
20 |
+
*
|
21 |
+
* (default value: 'background_process')
|
22 |
+
*
|
23 |
+
* @var string
|
24 |
+
* @access protected
|
25 |
+
*/
|
26 |
+
protected $action = 'background_process';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Start time of current process.
|
30 |
+
*
|
31 |
+
* (default value: 0)
|
32 |
+
*
|
33 |
+
* @var int
|
34 |
+
* @access protected
|
35 |
+
*/
|
36 |
+
protected $start_time = 0;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Cron_hook_identifier
|
40 |
+
*
|
41 |
+
* @var mixed
|
42 |
+
* @access protected
|
43 |
+
*/
|
44 |
+
protected $cron_hook_identifier;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Cron_interval_identifier
|
48 |
+
*
|
49 |
+
* @var mixed
|
50 |
+
* @access protected
|
51 |
+
*/
|
52 |
+
protected $cron_interval_identifier;
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Initiate new background process
|
56 |
+
*/
|
57 |
+
public function __construct() {
|
58 |
+
parent::__construct();
|
59 |
+
|
60 |
+
$this->cron_hook_identifier = $this->identifier . '_cron';
|
61 |
+
$this->cron_interval_identifier = $this->identifier . '_cron_interval';
|
62 |
+
|
63 |
+
add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
|
64 |
+
add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Dispatch
|
69 |
+
*
|
70 |
+
* @access public
|
71 |
+
* @return void
|
72 |
+
*/
|
73 |
+
public function dispatch() {
|
74 |
+
// Schedule the cron healthcheck.
|
75 |
+
$this->schedule_event();
|
76 |
+
|
77 |
+
// Perform remote post.
|
78 |
+
return parent::dispatch();
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Push to queue
|
83 |
+
*
|
84 |
+
* @param mixed $data Data.
|
85 |
+
*
|
86 |
+
* @return $this
|
87 |
+
*/
|
88 |
+
public function push_to_queue( $data ) {
|
89 |
+
$this->data[] = $data;
|
90 |
+
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Save queue
|
96 |
+
*
|
97 |
+
* @return $this
|
98 |
+
*/
|
99 |
+
public function save() {
|
100 |
+
$key = $this->generate_key();
|
101 |
+
|
102 |
+
if ( ! empty( $this->data ) ) {
|
103 |
+
update_site_option( $key, $this->data );
|
104 |
+
}
|
105 |
+
|
106 |
+
return $this;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Update queue
|
111 |
+
*
|
112 |
+
* @param string $key Key.
|
113 |
+
* @param array $data Data.
|
114 |
+
*
|
115 |
+
* @return $this
|
116 |
+
*/
|
117 |
+
public function update( $key, $data ) {
|
118 |
+
if ( ! empty( $data ) ) {
|
119 |
+
update_site_option( $key, $data );
|
120 |
+
}
|
121 |
+
|
122 |
+
return $this;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Delete queue
|
127 |
+
*
|
128 |
+
* @param string $key Key.
|
129 |
+
*
|
130 |
+
* @return $this
|
131 |
+
*/
|
132 |
+
public function delete( $key ) {
|
133 |
+
delete_site_option( $key );
|
134 |
+
|
135 |
+
return $this;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Generate key
|
140 |
+
*
|
141 |
+
* Generates a unique key based on microtime. Queue items are
|
142 |
+
* given a unique key so that they can be merged upon save.
|
143 |
+
*
|
144 |
+
* @param int $length Length.
|
145 |
+
*
|
146 |
+
* @return string
|
147 |
+
*/
|
148 |
+
protected function generate_key( $length = 64 ) {
|
149 |
+
$unique = md5( microtime() . rand() );
|
150 |
+
$prepend = $this->identifier . '_batch_';
|
151 |
+
|
152 |
+
return substr( $prepend . $unique, 0, $length );
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Maybe process queue
|
157 |
+
*
|
158 |
+
* Checks whether data exists within the queue and that
|
159 |
+
* the process is not already running.
|
160 |
+
*/
|
161 |
+
public function maybe_handle() {
|
162 |
+
// Don't lock up other requests while processing
|
163 |
+
session_write_close();
|
164 |
+
|
165 |
+
if ( $this->is_process_running() ) {
|
166 |
+
// Background process already running.
|
167 |
+
wp_die();
|
168 |
+
}
|
169 |
+
|
170 |
+
if ( $this->is_queue_empty() ) {
|
171 |
+
// No data to process.
|
172 |
+
wp_die();
|
173 |
+
}
|
174 |
+
|
175 |
+
check_ajax_referer( $this->identifier, 'nonce' );
|
176 |
+
|
177 |
+
$this->handle();
|
178 |
+
|
179 |
+
wp_die();
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Is queue empty
|
184 |
+
*
|
185 |
+
* @return bool
|
186 |
+
*/
|
187 |
+
protected function is_queue_empty() {
|
188 |
+
global $wpdb;
|
189 |
+
|
190 |
+
$table = $wpdb->options;
|
191 |
+
$column = 'option_name';
|
192 |
+
|
193 |
+
if ( is_multisite() ) {
|
194 |
+
$table = $wpdb->sitemeta;
|
195 |
+
$column = 'meta_key';
|
196 |
+
}
|
197 |
+
|
198 |
+
$key = Imagify_DB::esc_like( $this->identifier . '_batch_' ) . '%';
|
199 |
+
|
200 |
+
$count = $wpdb->get_var( $wpdb->prepare( "
|
201 |
+
SELECT COUNT(*)
|
202 |
+
FROM {$table}
|
203 |
+
WHERE {$column} LIKE %s
|
204 |
+
", $key ) );
|
205 |
+
|
206 |
+
return ( $count > 0 ) ? false : true;
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Is process running
|
211 |
+
*
|
212 |
+
* Check whether the current process is already running
|
213 |
+
* in a background process.
|
214 |
+
*/
|
215 |
+
protected function is_process_running() {
|
216 |
+
if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
|
217 |
+
// Process already running.
|
218 |
+
return true;
|
219 |
+
}
|
220 |
+
|
221 |
+
return false;
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Lock process
|
226 |
+
*
|
227 |
+
* Lock the process so that multiple instances can't run simultaneously.
|
228 |
+
* Override if applicable, but the duration should be greater than that
|
229 |
+
* defined in the time_exceeded() method.
|
230 |
+
*/
|
231 |
+
protected function lock_process() {
|
232 |
+
$this->start_time = time(); // Set start time of current process.
|
233 |
+
|
234 |
+
$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
|
235 |
+
$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
|
236 |
+
|
237 |
+
set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Unlock process
|
242 |
+
*
|
243 |
+
* Unlock the process so that other instances can spawn.
|
244 |
+
*
|
245 |
+
* @return $this
|
246 |
+
*/
|
247 |
+
protected function unlock_process() {
|
248 |
+
delete_site_transient( $this->identifier . '_process_lock' );
|
249 |
+
|
250 |
+
return $this;
|
251 |
+
}
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Get batch
|
255 |
+
*
|
256 |
+
* @return stdClass Return the first batch from the queue
|
257 |
+
*/
|
258 |
+
protected function get_batch() {
|
259 |
+
global $wpdb;
|
260 |
+
|
261 |
+
$table = $wpdb->options;
|
262 |
+
$column = 'option_name';
|
263 |
+
$key_column = 'option_id';
|
264 |
+
$value_column = 'option_value';
|
265 |
+
|
266 |
+
if ( is_multisite() ) {
|
267 |
+
$table = $wpdb->sitemeta;
|
268 |
+
$column = 'meta_key';
|
269 |
+
$key_column = 'meta_id';
|
270 |
+
$value_column = 'meta_value';
|
271 |
+
}
|
272 |
+
|
273 |
+
$key = Imagify_DB::esc_like( $this->identifier . '_batch_' ) . '%';
|
274 |
+
|
275 |
+
$query = $wpdb->get_row( $wpdb->prepare( "
|
276 |
+
SELECT *
|
277 |
+
FROM {$table}
|
278 |
+
WHERE {$column} LIKE %s
|
279 |
+
ORDER BY {$key_column} ASC
|
280 |
+
LIMIT 1
|
281 |
+
", $key ) );
|
282 |
+
|
283 |
+
$batch = new stdClass();
|
284 |
+
$batch->key = $query->$column;
|
285 |
+
$batch->data = maybe_unserialize( $query->$value_column );
|
286 |
+
|
287 |
+
return $batch;
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Handle
|
292 |
+
*
|
293 |
+
* Pass each queue item to the task handler, while remaining
|
294 |
+
* within server memory and time limit constraints.
|
295 |
+
*/
|
296 |
+
protected function handle() {
|
297 |
+
$this->lock_process();
|
298 |
+
|
299 |
+
do {
|
300 |
+
$batch = $this->get_batch();
|
301 |
+
|
302 |
+
foreach ( $batch->data as $key => $value ) {
|
303 |
+
$task = $this->task( $value );
|
304 |
+
|
305 |
+
if ( false !== $task ) {
|
306 |
+
$batch->data[ $key ] = $task;
|
307 |
+
} else {
|
308 |
+
unset( $batch->data[ $key ] );
|
309 |
+
}
|
310 |
+
|
311 |
+
if ( $this->time_exceeded() || $this->memory_exceeded() ) {
|
312 |
+
// Batch limits reached.
|
313 |
+
break;
|
314 |
+
}
|
315 |
+
}
|
316 |
+
|
317 |
+
// Update or delete current batch.
|
318 |
+
if ( ! empty( $batch->data ) ) {
|
319 |
+
$this->update( $batch->key, $batch->data );
|
320 |
+
} else {
|
321 |
+
$this->delete( $batch->key );
|
322 |
+
}
|
323 |
+
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
|
324 |
+
|
325 |
+
$this->unlock_process();
|
326 |
+
|
327 |
+
// Start next batch or complete process.
|
328 |
+
if ( ! $this->is_queue_empty() ) {
|
329 |
+
$this->dispatch();
|
330 |
+
} else {
|
331 |
+
$this->complete();
|
332 |
+
}
|
333 |
+
|
334 |
+
wp_die();
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Memory exceeded
|
339 |
+
*
|
340 |
+
* Ensures the batch process never exceeds 90%
|
341 |
+
* of the maximum WordPress memory.
|
342 |
+
*
|
343 |
+
* @return bool
|
344 |
+
*/
|
345 |
+
protected function memory_exceeded() {
|
346 |
+
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
|
347 |
+
$current_memory = memory_get_usage( true );
|
348 |
+
$return = false;
|
349 |
+
|
350 |
+
if ( $current_memory >= $memory_limit ) {
|
351 |
+
$return = true;
|
352 |
+
}
|
353 |
+
|
354 |
+
return apply_filters( $this->identifier . '_memory_exceeded', $return );
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Get memory limit
|
359 |
+
*
|
360 |
+
* @return int
|
361 |
+
*/
|
362 |
+
protected function get_memory_limit() {
|
363 |
+
if ( function_exists( 'ini_get' ) ) {
|
364 |
+
$memory_limit = ini_get( 'memory_limit' );
|
365 |
+
} else {
|
366 |
+
// Sensible default.
|
367 |
+
$memory_limit = '128M';
|
368 |
+
}
|
369 |
+
|
370 |
+
if ( ! $memory_limit || -1 === intval( $memory_limit ) ) {
|
371 |
+
// Unlimited, set to 32GB.
|
372 |
+
$memory_limit = '32000M';
|
373 |
+
}
|
374 |
+
|
375 |
+
return intval( $memory_limit ) * 1024 * 1024;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Time exceeded.
|
380 |
+
*
|
381 |
+
* Ensures the batch never exceeds a sensible time limit.
|
382 |
+
* A timeout limit of 30s is common on shared hosting.
|
383 |
+
*
|
384 |
+
* @return bool
|
385 |
+
*/
|
386 |
+
protected function time_exceeded() {
|
387 |
+
$finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
|
388 |
+
$return = false;
|
389 |
+
|
390 |
+
if ( time() >= $finish ) {
|
391 |
+
$return = true;
|
392 |
+
}
|
393 |
+
|
394 |
+
return apply_filters( $this->identifier . '_time_exceeded', $return );
|
395 |
+
}
|
396 |
+
|
397 |
+
/**
|
398 |
+
* Complete.
|
399 |
+
*
|
400 |
+
* Override if applicable, but ensure that the below actions are
|
401 |
+
* performed, or, call parent::complete().
|
402 |
+
*/
|
403 |
+
protected function complete() {
|
404 |
+
// Unschedule the cron healthcheck.
|
405 |
+
$this->clear_scheduled_event();
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Schedule cron healthcheck
|
410 |
+
*
|
411 |
+
* @access public
|
412 |
+
* @param mixed $schedules Schedules.
|
413 |
+
* @return mixed
|
414 |
+
*/
|
415 |
+
public function schedule_cron_healthcheck( $schedules ) {
|
416 |
+
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
|
417 |
+
|
418 |
+
if ( property_exists( $this, 'cron_interval' ) ) {
|
419 |
+
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
|
420 |
+
}
|
421 |
+
|
422 |
+
// Adds every 5 minutes to the existing schedules.
|
423 |
+
$schedules[ $this->identifier . '_cron_interval' ] = array(
|
424 |
+
'interval' => MINUTE_IN_SECONDS * $interval,
|
425 |
+
'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
|
426 |
+
);
|
427 |
+
|
428 |
+
return $schedules;
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Handle cron healthcheck
|
433 |
+
*
|
434 |
+
* Restart the background process if not already running
|
435 |
+
* and data exists in the queue.
|
436 |
+
*/
|
437 |
+
public function handle_cron_healthcheck() {
|
438 |
+
if ( $this->is_process_running() ) {
|
439 |
+
// Background process already running.
|
440 |
+
exit;
|
441 |
+
}
|
442 |
+
|
443 |
+
if ( $this->is_queue_empty() ) {
|
444 |
+
// No data to process.
|
445 |
+
$this->clear_scheduled_event();
|
446 |
+
exit;
|
447 |
+
}
|
448 |
+
|
449 |
+
$this->handle();
|
450 |
+
|
451 |
+
exit;
|
452 |
+
}
|
453 |
+
|
454 |
+
/**
|
455 |
+
* Schedule event
|
456 |
+
*/
|
457 |
+
protected function schedule_event() {
|
458 |
+
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
|
459 |
+
wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
|
460 |
+
}
|
461 |
+
}
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Clear scheduled event
|
465 |
+
*/
|
466 |
+
protected function clear_scheduled_event() {
|
467 |
+
$timestamp = wp_next_scheduled( $this->cron_hook_identifier );
|
468 |
+
|
469 |
+
if ( $timestamp ) {
|
470 |
+
wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
|
471 |
+
}
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* Cancel Process
|
476 |
+
*
|
477 |
+
* Stop processing queue items, clear cronjob and delete batch.
|
478 |
+
*
|
479 |
+
*/
|
480 |
+
public function cancel_process() {
|
481 |
+
if ( ! $this->is_queue_empty() ) {
|
482 |
+
$batch = $this->get_batch();
|
483 |
+
|
484 |
+
$this->delete( $batch->key );
|
485 |
+
|
486 |
+
wp_clear_scheduled_hook( $this->cron_hook_identifier );
|
487 |
+
}
|
488 |
+
|
489 |
+
}
|
490 |
+
|
491 |
+
/**
|
492 |
+
* Task
|
493 |
+
*
|
494 |
+
* Override this method to perform any actions required on each
|
495 |
+
* queue item. Return the modified item for further processing
|
496 |
+
* in the next pass through. Or, return false to remove the
|
497 |
+
* item from the queue.
|
498 |
+
*
|
499 |
+
* @param mixed $item Queue item to iterate over.
|
500 |
+
*
|
501 |
+
* @return mixed
|
502 |
+
*/
|
503 |
+
abstract protected function task( $item );
|
504 |
+
|
505 |
+
}
|
506 |
+
}
|
inc/functions/admin-stats.php
CHANGED
@@ -280,10 +280,12 @@ function imagify_count_saving_data( $key = '' ) {
|
|
280 |
unset( $attachment_data['sizes']['full'] );
|
281 |
|
282 |
// Increment the thumbnails sizes.
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
|
|
|
|
287 |
}
|
288 |
}
|
289 |
}
|
@@ -367,10 +369,12 @@ function imagify_count_saving_data( $key = '' ) {
|
|
367 |
unset( $attachment_data['sizes']['full'], $original_data );
|
368 |
|
369 |
// Increment the thumbnails sizes.
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
|
|
|
|
374 |
}
|
375 |
}
|
376 |
|
280 |
unset( $attachment_data['sizes']['full'] );
|
281 |
|
282 |
// Increment the thumbnails sizes.
|
283 |
+
if ( $attachment_data['sizes'] ) {
|
284 |
+
foreach ( $attachment_data['sizes'] as $size_data ) {
|
285 |
+
if ( ! empty( $size_data['success'] ) ) {
|
286 |
+
$original_size += $size_data['original_size'] ? $size_data['original_size'] : 0;
|
287 |
+
$optimized_size += $size_data['optimized_size'] ? $size_data['optimized_size'] : 0;
|
288 |
+
}
|
289 |
}
|
290 |
}
|
291 |
}
|
369 |
unset( $attachment_data['sizes']['full'], $original_data );
|
370 |
|
371 |
// Increment the thumbnails sizes.
|
372 |
+
if ( $attachment_data['sizes'] ) {
|
373 |
+
foreach ( $attachment_data['sizes'] as $size_data ) {
|
374 |
+
if ( ! empty( $size_data['success'] ) ) {
|
375 |
+
$original_size += ! empty( $size_data['original_size'] ) ? $size_data['original_size'] : 0;
|
376 |
+
$optimized_size += ! empty( $size_data['optimized_size'] ) ? $size_data['optimized_size'] : 0;
|
377 |
+
}
|
378 |
}
|
379 |
}
|
380 |
|
inc/functions/admin-ui.php
CHANGED
@@ -82,11 +82,13 @@ function get_imagify_attachment_optimization_text( $attachment, $context = 'wp'
|
|
82 |
|
83 |
$output .= $output_before . '<span class="data">' . __( 'Level:', 'imagify' ) . '</span> <strong>' . $optimization_level . '</strong>' . $output_after;
|
84 |
|
85 |
-
|
|
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
90 |
}
|
91 |
|
92 |
// End of list.
|
@@ -109,13 +111,16 @@ function get_imagify_attachment_optimization_text( $attachment, $context = 'wp'
|
|
109 |
$output .= '</a>';
|
110 |
|
111 |
if ( ! $is_library_page ) {
|
112 |
-
$dimensions = $attachment->get_dimensions();
|
113 |
-
|
114 |
$output .= '<input id="imagify-original-src" type="hidden" value="' . esc_url( $attachment->get_backup_url() ) . '">';
|
115 |
$output .= '<input id="imagify-original-size" type="hidden" value="' . $attachment->get_original_size() . '">';
|
116 |
$output .= '<input id="imagify-full-src" type="hidden" value="' . esc_url( $attachment->get_original_url() ) . '">';
|
117 |
-
|
118 |
-
|
|
|
|
|
|
|
|
|
|
|
119 |
}
|
120 |
}
|
121 |
|
@@ -234,6 +239,9 @@ function get_imagify_attachment_reoptimize_link( $attachment, $context = 'wp' )
|
|
234 |
* @return string The output to print.
|
235 |
*/
|
236 |
function get_imagify_attachment_optimize_missing_thumbnails_link( $attachment, $context = 'wp' ) {
|
|
|
|
|
|
|
237 |
/**
|
238 |
* Allow to not display the "Optimize missing thumbnails" link.
|
239 |
*
|
@@ -247,7 +255,7 @@ function get_imagify_attachment_optimize_missing_thumbnails_link( $attachment, $
|
|
247 |
$display = apply_filters( 'imagify_display_missing_thumbnails_link', true, $attachment, $context );
|
248 |
|
249 |
// Stop the process if the filter is false, or if the API key isn't valid, or if there is no backup file.
|
250 |
-
if ( ! $display
|
251 |
return '';
|
252 |
}
|
253 |
|
@@ -389,7 +397,7 @@ function imagify_get_folder_type_data( $folder_type ) {
|
|
389 |
* Format the data.
|
390 |
*/
|
391 |
/* translators: %s is a formatted number, dont use %d. */
|
392 |
-
$data['images-optimized'] = sprintf( _n( '%s
|
393 |
|
394 |
if ( $data['errors'] ) {
|
395 |
/* translators: %s is a formatted number, dont use %d. */
|
82 |
|
83 |
$output .= $output_before . '<span class="data">' . __( 'Level:', 'imagify' ) . '</span> <strong>' . $optimization_level . '</strong>' . $output_after;
|
84 |
|
85 |
+
if ( $attachment->is_image() ) {
|
86 |
+
$total_optimized_thumbnails = $attachment->get_optimized_sizes_count();
|
87 |
|
88 |
+
if ( $total_optimized_thumbnails ) {
|
89 |
+
$output .= $output_before . '<span class="data">' . __( 'Thumbnails Optimized:', 'imagify' ) . '</span> <strong>' . $total_optimized_thumbnails . '</strong>' . $output_after;
|
90 |
+
$output .= $output_before . '<span class="data">' . __( 'Overall Saving:', 'imagify' ) . '</span> <strong>' . $attachment->get_overall_saving_percent() . '%</strong>' . $output_after;
|
91 |
+
}
|
92 |
}
|
93 |
|
94 |
// End of list.
|
111 |
$output .= '</a>';
|
112 |
|
113 |
if ( ! $is_library_page ) {
|
|
|
|
|
114 |
$output .= '<input id="imagify-original-src" type="hidden" value="' . esc_url( $attachment->get_backup_url() ) . '">';
|
115 |
$output .= '<input id="imagify-original-size" type="hidden" value="' . $attachment->get_original_size() . '">';
|
116 |
$output .= '<input id="imagify-full-src" type="hidden" value="' . esc_url( $attachment->get_original_url() ) . '">';
|
117 |
+
|
118 |
+
if ( $attachment->is_image() ) {
|
119 |
+
$dimensions = $attachment->get_dimensions();
|
120 |
+
|
121 |
+
$output .= '<input id="imagify-full-width" type="hidden" value="' . $dimensions['width'] . '">';
|
122 |
+
$output .= '<input id="imagify-full-height" type="hidden" value="' . $dimensions['height'] . '">';
|
123 |
+
}
|
124 |
}
|
125 |
}
|
126 |
|
239 |
* @return string The output to print.
|
240 |
*/
|
241 |
function get_imagify_attachment_optimize_missing_thumbnails_link( $attachment, $context = 'wp' ) {
|
242 |
+
if ( ! $attachment->is_image() || ! Imagify_Requirements::is_api_key_valid() || ! $attachment->has_backup() ) {
|
243 |
+
return '';
|
244 |
+
}
|
245 |
/**
|
246 |
* Allow to not display the "Optimize missing thumbnails" link.
|
247 |
*
|
255 |
$display = apply_filters( 'imagify_display_missing_thumbnails_link', true, $attachment, $context );
|
256 |
|
257 |
// Stop the process if the filter is false, or if the API key isn't valid, or if there is no backup file.
|
258 |
+
if ( ! $display ) {
|
259 |
return '';
|
260 |
}
|
261 |
|
397 |
* Format the data.
|
398 |
*/
|
399 |
/* translators: %s is a formatted number, dont use %d. */
|
400 |
+
$data['images-optimized'] = sprintf( _n( '%s Media File Optimized', '%s Media Files Optimized', $data['images-optimized'], 'imagify' ), '<span>' . number_format_i18n( $data['images-optimized'] ) . '</span>' );
|
401 |
|
402 |
if ( $data['errors'] ) {
|
403 |
/* translators: %s is a formatted number, dont use %d. */
|
inc/functions/api.php
CHANGED
@@ -208,12 +208,12 @@ function imagify_translate_api_message( $message ) {
|
|
208 |
$messages = array(
|
209 |
// Local messages from Imagify::curl_http_call() and Imagify::handle_response().
|
210 |
'Unknown error occurred' => __( 'Unknown error occurred.', 'imagify' ),
|
211 |
-
'Your image is too big to be uploaded on our server' => __( 'Your
|
212 |
'cURL isn\'t installed on the server' => __( 'cURL is not available on the server.', 'imagify' ),
|
213 |
// API messages.
|
214 |
'Authentification not provided' => __( 'Authentication not provided.', 'imagify' ),
|
215 |
'Cannot create client token' => __( 'Cannot create client token.', 'imagify' ),
|
216 |
-
'Confirm your account to continue optimizing image' => __( 'Confirm your account to continue optimizing
|
217 |
'Coupon doesn\'t exist' => __( 'Coupon does not exist.', 'imagify' ),
|
218 |
'Email field shouldn\'t be empty' => __( 'Email field should not be empty.', 'imagify' ),
|
219 |
'Email or Password field shouldn\'t be empty' => __( 'This account already exists.', 'imagify' ),
|
@@ -226,7 +226,7 @@ function imagify_translate_api_message( $message ) {
|
|
226 |
'Too many request, be patient' => __( 'Too many requests, please be patient.', 'imagify' ),
|
227 |
'Unable to regenerate access token' => __( 'Unable to regenerate access token.', 'imagify' ),
|
228 |
'User not valid' => __( 'User not valid.', 'imagify' ),
|
229 |
-
'WELL DONE. This image is already compressed, no further compression required' => __( 'WELL DONE. This
|
230 |
'You are not authorized to perform this action' => __( 'You are not authorized to perform this action.', 'imagify' ),
|
231 |
'You\'ve consumed all your data. You have to upgrade your account to continue' => __( 'You have consumed all your data. You have to upgrade your account to continue.', 'imagify' ),
|
232 |
'Invalid token' => __( 'Invalid API key', 'imagify' ),
|
208 |
$messages = array(
|
209 |
// Local messages from Imagify::curl_http_call() and Imagify::handle_response().
|
210 |
'Unknown error occurred' => __( 'Unknown error occurred.', 'imagify' ),
|
211 |
+
'Your image is too big to be uploaded on our server' => __( 'Your file is too big to be uploaded on our server.', 'imagify' ),
|
212 |
'cURL isn\'t installed on the server' => __( 'cURL is not available on the server.', 'imagify' ),
|
213 |
// API messages.
|
214 |
'Authentification not provided' => __( 'Authentication not provided.', 'imagify' ),
|
215 |
'Cannot create client token' => __( 'Cannot create client token.', 'imagify' ),
|
216 |
+
'Confirm your account to continue optimizing image' => __( 'Confirm your account to continue optimizing files.', 'imagify' ),
|
217 |
'Coupon doesn\'t exist' => __( 'Coupon does not exist.', 'imagify' ),
|
218 |
'Email field shouldn\'t be empty' => __( 'Email field should not be empty.', 'imagify' ),
|
219 |
'Email or Password field shouldn\'t be empty' => __( 'This account already exists.', 'imagify' ),
|
226 |
'Too many request, be patient' => __( 'Too many requests, please be patient.', 'imagify' ),
|
227 |
'Unable to regenerate access token' => __( 'Unable to regenerate access token.', 'imagify' ),
|
228 |
'User not valid' => __( 'User not valid.', 'imagify' ),
|
229 |
+
'WELL DONE. This image is already compressed, no further compression required' => __( 'WELL DONE. This media file is already optimized, no further optimization is required.', 'imagify' ),
|
230 |
'You are not authorized to perform this action' => __( 'You are not authorized to perform this action.', 'imagify' ),
|
231 |
'You\'ve consumed all your data. You have to upgrade your account to continue' => __( 'You have consumed all your data. You have to upgrade your account to continue.', 'imagify' ),
|
232 |
'Invalid token' => __( 'Invalid API key', 'imagify' ),
|
inc/functions/attachments.php
CHANGED
@@ -5,21 +5,32 @@ defined( 'ABSPATH' ) || die( 'Cheatin\' uh?' );
|
|
5 |
* Get all mime types which could be optimized by Imagify.
|
6 |
*
|
7 |
* @since 1.7
|
|
|
8 |
*
|
9 |
-
* @return
|
|
|
10 |
*/
|
11 |
-
function imagify_get_mime_types() {
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
}
|
18 |
|
19 |
/**
|
20 |
* Tell if an attachment has a supported mime type.
|
21 |
* Was previously Imagify_AS3CF::is_mime_type_supported() since 1.6.6.
|
22 |
-
* Ironically, this function is used in Imagify::is_mime_type_supported() since 1.6.9.
|
23 |
*
|
24 |
* @since 1.6.8
|
25 |
* @author Grégory Viguier
|
5 |
* Get all mime types which could be optimized by Imagify.
|
6 |
*
|
7 |
* @since 1.7
|
8 |
+
* @since 1.8 Added $type parameter.
|
9 |
*
|
10 |
+
* @param string $type One of 'image', 'not-image'. Any other value will return all mime types.
|
11 |
+
* @return array The mime types.
|
12 |
*/
|
13 |
+
function imagify_get_mime_types( $type = null ) {
|
14 |
+
$mimes = array();
|
15 |
+
|
16 |
+
if ( 'not-image' !== $type ) {
|
17 |
+
$mimes = array(
|
18 |
+
'jpg|jpeg|jpe' => 'image/jpeg',
|
19 |
+
'png' => 'image/png',
|
20 |
+
'gif' => 'image/gif',
|
21 |
+
);
|
22 |
+
}
|
23 |
+
|
24 |
+
if ( 'image' !== $type ) {
|
25 |
+
$mimes['pdf'] = 'application/pdf';
|
26 |
+
}
|
27 |
+
|
28 |
+
return $mimes;
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
* Tell if an attachment has a supported mime type.
|
33 |
* Was previously Imagify_AS3CF::is_mime_type_supported() since 1.6.6.
|
|
|
34 |
*
|
35 |
* @since 1.6.8
|
36 |
* @author Grégory Viguier
|
inc/functions/common.php
CHANGED
@@ -212,6 +212,8 @@ function imagify_autoload( $class ) {
|
|
212 |
'Imagify_User' => 1,
|
213 |
'Imagify_Views' => 1,
|
214 |
'Imagify' => 1,
|
|
|
|
|
215 |
);
|
216 |
|
217 |
if ( isset( $classes[ $class ] ) ) {
|
@@ -222,15 +224,18 @@ function imagify_autoload( $class ) {
|
|
222 |
|
223 |
// Third party classes.
|
224 |
$classes = array(
|
225 |
-
'Imagify_AS3CF_Attachment'
|
226 |
-
'Imagify_AS3CF'
|
227 |
-
'Imagify_Enable_Media_Replace'
|
228 |
-
'Imagify_Formidable_Pro'
|
229 |
-
'Imagify_NGG_Attachment'
|
230 |
-
'Imagify_NGG_DB'
|
231 |
-
'
|
232 |
-
'
|
233 |
-
'
|
|
|
|
|
|
|
234 |
);
|
235 |
|
236 |
if ( isset( $classes[ $class ] ) ) {
|
212 |
'Imagify_User' => 1,
|
213 |
'Imagify_Views' => 1,
|
214 |
'Imagify' => 1,
|
215 |
+
'WP_Async_Request' => 1,
|
216 |
+
'WP_Background_Process' => 1,
|
217 |
);
|
218 |
|
219 |
if ( isset( $classes[ $class ] ) ) {
|
224 |
|
225 |
// Third party classes.
|
226 |
$classes = array(
|
227 |
+
'Imagify_AS3CF_Attachment' => 'amazon-s3-and-cloudfront',
|
228 |
+
'Imagify_AS3CF' => 'amazon-s3-and-cloudfront',
|
229 |
+
'Imagify_Enable_Media_Replace' => 'enable-media-replace',
|
230 |
+
'Imagify_Formidable_Pro' => 'formidable-pro',
|
231 |
+
'Imagify_NGG_Attachment' => 'nextgen-gallery',
|
232 |
+
'Imagify_NGG_DB' => 'nextgen-gallery',
|
233 |
+
'Imagify_NGG_Dynamic_Thumbnails_Background_Process' => 'nextgen-gallery',
|
234 |
+
'Imagify_NGG_Storage' => 'nextgen-gallery',
|
235 |
+
'Imagify_NGG' => 'nextgen-gallery',
|
236 |
+
'Imagify_Regenerate_Thumbnails' => 'regenerate-thumbnails',
|
237 |
+
'Imagify_WP_Retina_2x' => 'wp-retina-2x',
|
238 |
+
'Imagify_WP_Retina_2x_Core' => 'wp-retina-2x',
|
239 |
);
|
240 |
|
241 |
if ( isset( $classes[ $class ] ) ) {
|
inc/functions/deprecated.php
CHANGED
@@ -628,6 +628,84 @@ if ( class_exists( 'C_NextGEN_Bootstrap' ) && class_exists( 'Mixin' ) && get_sit
|
|
628 |
|
629 |
endif;
|
630 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
631 |
/**
|
632 |
* Combine two arrays with some specific keys.
|
633 |
* We use this function to combine the result of 2 SQL queries.
|
628 |
|
629 |
endif;
|
630 |
|
631 |
+
if ( function_exists( 'wr2x_delete_attachment' ) ) :
|
632 |
+
|
633 |
+
/**
|
634 |
+
* Remove all retina versions if they exist.
|
635 |
+
*
|
636 |
+
* @since 1.0
|
637 |
+
* @since 1.8 Deprecated.
|
638 |
+
* @deprecated
|
639 |
+
*
|
640 |
+
* @param int $attachment_id An attachment ID.
|
641 |
+
*/
|
642 |
+
function _imagify_wr2x_delete_attachment_on_restore( $attachment_id ) {
|
643 |
+
_deprecated_function( __FUNCTION__ . '()', '1.8' );
|
644 |
+
|
645 |
+
wr2x_delete_attachment( $attachment_id );
|
646 |
+
}
|
647 |
+
|
648 |
+
/**
|
649 |
+
* Regenerate all retina versions.
|
650 |
+
*
|
651 |
+
* @since 1.0
|
652 |
+
* @since 1.8 Deprecated.
|
653 |
+
* @deprecated
|
654 |
+
*
|
655 |
+
* @param int $attachment_id An attachment ID.
|
656 |
+
*/
|
657 |
+
function _imagify_wr2x_generate_images_on_restore( $attachment_id ) {
|
658 |
+
_deprecated_function( __FUNCTION__ . '()', '1.8' );
|
659 |
+
|
660 |
+
wr2x_delete_attachment( $attachment_id );
|
661 |
+
wr2x_generate_images( wp_get_attachment_metadata( $attachment_id ) );
|
662 |
+
}
|
663 |
+
|
664 |
+
/**
|
665 |
+
* Filter the optimization data of each thumbnail.
|
666 |
+
*
|
667 |
+
* @since 1.0
|
668 |
+
* @since 1.8 Deprecated.
|
669 |
+
* @deprecated
|
670 |
+
*
|
671 |
+
* @param array $data The statistics data.
|
672 |
+
* @param object $response The API response.
|
673 |
+
* @param int $id The attachment ID.
|
674 |
+
* @param string $path The attachment path.
|
675 |
+
* @param string $url The attachment URL.
|
676 |
+
* @param string $size_key The attachment size key.
|
677 |
+
* @param bool $optimization_level The optimization level.
|
678 |
+
* @return array $data The new optimization data.
|
679 |
+
*/
|
680 |
+
function _imagify_optimize_wr2x( $data, $response, $id, $path, $url, $size_key, $optimization_level ) {
|
681 |
+
_deprecated_function( __FUNCTION__ . '()', '1.8', 'Imagify_WP_Retina_2x::optimize_retina_version()' );
|
682 |
+
|
683 |
+
/**
|
684 |
+
* Allow to optimize the retina version generated by WP Retina x2.
|
685 |
+
*
|
686 |
+
* @since 1.0
|
687 |
+
*
|
688 |
+
* @param bool $do_retina True will force the optimization.
|
689 |
+
*/
|
690 |
+
$do_retina = apply_filters( 'do_imagify_optimize_retina', true );
|
691 |
+
$retina_path = wr2x_get_retina( $path );
|
692 |
+
|
693 |
+
if ( empty( $retina_path ) || ! $do_retina ) {
|
694 |
+
return $data;
|
695 |
+
}
|
696 |
+
|
697 |
+
$response = do_imagify( $retina_path, array(
|
698 |
+
'backup' => false,
|
699 |
+
'optimization_level' => $optimization_level,
|
700 |
+
'context' => 'wp-retina',
|
701 |
+
) );
|
702 |
+
$attachment = get_imagify_attachment( 'wp', $id, 'imagify_fill_thumbnail_data' );
|
703 |
+
|
704 |
+
return $attachment->fill_data( $data, $response, $size_key . '@2x' );
|
705 |
+
}
|
706 |
+
|
707 |
+
endif;
|
708 |
+
|
709 |
/**
|
710 |
* Combine two arrays with some specific keys.
|
711 |
* We use this function to combine the result of 2 SQL queries.
|
inc/functions/i18n.php
CHANGED
@@ -83,11 +83,15 @@ function get_imagify_localize_script_translations( $context ) {
|
|
83 |
);
|
84 |
|
85 |
case 'twentytwenty':
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
91 |
}
|
92 |
|
93 |
return array(
|
@@ -99,8 +103,8 @@ function get_imagify_localize_script_translations( $context ) {
|
|
99 |
'filesize' => __( 'File Size:', 'imagify' ),
|
100 |
'saving' => __( 'Original Saving:', 'imagify' ),
|
101 |
'close' => __( 'Close', 'imagify' ),
|
102 |
-
'originalL' => __( 'Original
|
103 |
-
'optimizedL' => __( 'Optimized
|
104 |
'compare' => __( 'Compare Original VS Optimized', 'imagify' ),
|
105 |
'optimize' => __( 'Optimize', 'imagify' ),
|
106 |
),
|
@@ -150,13 +154,13 @@ function get_imagify_localize_script_translations( $context ) {
|
|
150 |
'editorMissing' => __( 'No php extensions are available to edit images on the server.', 'imagify' ),
|
151 |
'extHttpBlocked' => __( 'External HTTP requests are blocked.', 'imagify' ),
|
152 |
'apiDown' => __( 'Sorry, our servers are temporarily unavailable. Please, try again in a couple of minutes.', 'imagify' ),
|
153 |
-
'invalidAPIKeyTitle' => __( 'Your API key
|
154 |
'overQuotaTitle' => __( 'You have used all your credits!', 'imagify' ),
|
155 |
'processing' => __( 'Imagify is still processing. Are you sure you want to leave this page?', 'imagify' ),
|
156 |
'waitTitle' => __( 'Please wait...', 'imagify' ),
|
157 |
-
'waitText' => __( 'We are trying to get your unoptimized
|
158 |
'noAttachmentToOptimizeTitle' => __( 'Hold on!', 'imagify' ),
|
159 |
-
'noAttachmentToOptimizeText' => __( 'All your
|
160 |
'optimizing' => __( 'Optimizing', 'imagify' ),
|
161 |
'error' => __( 'Error', 'imagify' ),
|
162 |
'ajaxErrorText' => __( 'The operation failed.', 'imagify' ),
|
@@ -171,10 +175,10 @@ function get_imagify_localize_script_translations( $context ) {
|
|
171 |
'textToShare' => __( 'Discover @imagify, the new compression tool to optimize your images for free. I saved %1$s out of %2$s!', 'imagify' ),
|
172 |
'twitterShareURL' => imagify_get_external_url( 'share-twitter' ),
|
173 |
'getUnoptimizedImagesErrorTitle' => __( 'Oops, There is something wrong!', 'imagify' ),
|
174 |
-
'getUnoptimizedImagesErrorText' => __( 'An unknown error occurred when we tried to get all your unoptimized
|
175 |
'waitingOtimizationsText' => __( 'Waiting other optimizations to finish.', 'imagify' ),
|
176 |
/* translators: %s is a formatted number, dont use %d. */
|
177 |
-
'imagesOptimizedText' => __( '%s
|
178 |
/* translators: %s is a formatted number, dont use %d. */
|
179 |
'imagesErrorText' => __( '%s Error(s)', 'imagify' ),
|
180 |
'bulkInfoTitle' => __( 'Information', 'imagify' ),
|
83 |
);
|
84 |
|
85 |
case 'twentytwenty':
|
86 |
+
$image = array( '', 0, 0 );
|
87 |
+
|
88 |
+
if ( imagify_is_screen( 'attachment' ) && wp_attachment_is_image( $post_id ) ) {
|
89 |
+
$attachment = get_imagify_attachment( 'wp', $post_id, 'imagify_localize_script_translations' );
|
90 |
+
|
91 |
+
if ( $attachment->is_image() ) {
|
92 |
+
$image = wp_get_attachment_image_src( $post_id, 'full' );
|
93 |
+
$image = $image && is_array( $image ) ? $image : array( '', 0, 0 );
|
94 |
+
}
|
95 |
}
|
96 |
|
97 |
return array(
|
103 |
'filesize' => __( 'File Size:', 'imagify' ),
|
104 |
'saving' => __( 'Original Saving:', 'imagify' ),
|
105 |
'close' => __( 'Close', 'imagify' ),
|
106 |
+
'originalL' => __( 'Original File', 'imagify' ),
|
107 |
+
'optimizedL' => __( 'Optimized File', 'imagify' ),
|
108 |
'compare' => __( 'Compare Original VS Optimized', 'imagify' ),
|
109 |
'optimize' => __( 'Optimize', 'imagify' ),
|
110 |
),
|
154 |
'editorMissing' => __( 'No php extensions are available to edit images on the server.', 'imagify' ),
|
155 |
'extHttpBlocked' => __( 'External HTTP requests are blocked.', 'imagify' ),
|
156 |
'apiDown' => __( 'Sorry, our servers are temporarily unavailable. Please, try again in a couple of minutes.', 'imagify' ),
|
157 |
+
'invalidAPIKeyTitle' => __( 'Your API key is not valid!', 'imagify' ),
|
158 |
'overQuotaTitle' => __( 'You have used all your credits!', 'imagify' ),
|
159 |
'processing' => __( 'Imagify is still processing. Are you sure you want to leave this page?', 'imagify' ),
|
160 |
'waitTitle' => __( 'Please wait...', 'imagify' ),
|
161 |
+
'waitText' => __( 'We are trying to get your unoptimized media files, it may take time depending on the number of files.', 'imagify' ),
|
162 |
'noAttachmentToOptimizeTitle' => __( 'Hold on!', 'imagify' ),
|
163 |
+
'noAttachmentToOptimizeText' => __( 'All your media files have been optimized by Imagify. Congratulations!', 'imagify' ),
|
164 |
'optimizing' => __( 'Optimizing', 'imagify' ),
|
165 |
'error' => __( 'Error', 'imagify' ),
|
166 |
'ajaxErrorText' => __( 'The operation failed.', 'imagify' ),
|
175 |
'textToShare' => __( 'Discover @imagify, the new compression tool to optimize your images for free. I saved %1$s out of %2$s!', 'imagify' ),
|
176 |
'twitterShareURL' => imagify_get_external_url( 'share-twitter' ),
|
177 |
'getUnoptimizedImagesErrorTitle' => __( 'Oops, There is something wrong!', 'imagify' ),
|
178 |
+
'getUnoptimizedImagesErrorText' => __( 'An unknown error occurred when we tried to get all your unoptimized media files. Try again and if the issue still persists, please contact us!', 'imagify' ),
|
179 |
'waitingOtimizationsText' => __( 'Waiting other optimizations to finish.', 'imagify' ),
|
180 |
/* translators: %s is a formatted number, dont use %d. */
|
181 |
+
'imagesOptimizedText' => __( '%s Media File(s) Optimized', 'imagify' ),
|
182 |
/* translators: %s is a formatted number, dont use %d. */
|
183 |
'imagesErrorText' => __( '%s Error(s)', 'imagify' ),
|
184 |
'bulkInfoTitle' => __( 'Information', 'imagify' ),
|
inc/functions/process.php
CHANGED
@@ -43,8 +43,10 @@ function do_imagify( $file_path, $args = array() ) {
|
|
43 |
return new WP_Error( 'curl', __( 'cURL is not available on the server.', 'imagify' ) );
|
44 |
}
|
45 |
|
|
|
|
|
46 |
// Check if imageMagick or GD is available.
|
47 |
-
if ( ! Imagify_Requirements::supports_image_editor() ) {
|
48 |
return new WP_Error( 'image_editor', __( 'No php extensions are available to edit images on the server.', 'imagify' ) );
|
49 |
}
|
50 |
|
@@ -58,8 +60,6 @@ function do_imagify( $file_path, $args = array() ) {
|
|
58 |
return new WP_Error( 'api_server_down', __( 'Sorry, our servers are temporarily unavailable. Please, try again in a couple of minutes.', 'imagify' ) );
|
59 |
}
|
60 |
|
61 |
-
$filesystem = imagify_get_filesystem();
|
62 |
-
|
63 |
// Check that the file exists.
|
64 |
if ( ! $filesystem->is_writable( $file_path ) || ! $filesystem->is_file( $file_path ) ) {
|
65 |
/* translators: %s is a file path. */
|
@@ -82,6 +82,18 @@ function do_imagify( $file_path, $args = array() ) {
|
|
82 |
*/
|
83 |
do_action( 'before_do_imagify', $file_path, $args['backup'] );
|
84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
// Send image for optimization and fetch the response.
|
86 |
$response = upload_imagify_image( array(
|
87 |
'image' => $file_path,
|
@@ -99,12 +111,6 @@ function do_imagify( $file_path, $args = array() ) {
|
|
99 |
return new WP_Error( 'api_error', $response->get_error_message() );
|
100 |
}
|
101 |
|
102 |
-
// Create a backup file.
|
103 |
-
if ( $args['backup'] && ! $args['resized'] ) {
|
104 |
-
// TODO (@Greg): Send an error message if the backup fails.
|
105 |
-
imagify_backup_file( $file_path, $args['backup_path'] );
|
106 |
-
}
|
107 |
-
|
108 |
if ( ! function_exists( 'download_url' ) ) {
|
109 |
require_once ABSPATH . 'wp-admin/includes/file.php';
|
110 |
}
|
@@ -116,12 +122,6 @@ function do_imagify( $file_path, $args = array() ) {
|
|
116 |
}
|
117 |
|
118 |
$filesystem->move( $temp_file, $file_path, true );
|
119 |
-
$filesystem->chmod_file( $file_path );
|
120 |
-
|
121 |
-
// If temp file still exists, delete it.
|
122 |
-
if ( $filesystem->exists( $temp_file ) ) {
|
123 |
-
$filesystem->delete( $temp_file );
|
124 |
-
}
|
125 |
|
126 |
/**
|
127 |
* Fires after to optimize the Image with Imagify.
|
43 |
return new WP_Error( 'curl', __( 'cURL is not available on the server.', 'imagify' ) );
|
44 |
}
|
45 |
|
46 |
+
$filesystem = imagify_get_filesystem();
|
47 |
+
|
48 |
// Check if imageMagick or GD is available.
|
49 |
+
if ( $filesystem->is_image( $file_path ) && ! Imagify_Requirements::supports_image_editor() ) {
|
50 |
return new WP_Error( 'image_editor', __( 'No php extensions are available to edit images on the server.', 'imagify' ) );
|
51 |
}
|
52 |
|
60 |
return new WP_Error( 'api_server_down', __( 'Sorry, our servers are temporarily unavailable. Please, try again in a couple of minutes.', 'imagify' ) );
|
61 |
}
|
62 |
|
|
|
|
|
63 |
// Check that the file exists.
|
64 |
if ( ! $filesystem->is_writable( $file_path ) || ! $filesystem->is_file( $file_path ) ) {
|
65 |
/* translators: %s is a file path. */
|
82 |
*/
|
83 |
do_action( 'before_do_imagify', $file_path, $args['backup'] );
|
84 |
|
85 |
+
// Create a backup file before sending to optimization (to make sure we can backup the file).
|
86 |
+
$do_backup = $args['backup'] && ! $args['resized'];
|
87 |
+
|
88 |
+
if ( $do_backup ) {
|
89 |
+
$backup_result = imagify_backup_file( $file_path, $args['backup_path'] );
|
90 |
+
|
91 |
+
if ( is_wp_error( $backup_result ) ) {
|
92 |
+
// Stop the process if we can't backup the file.
|
93 |
+
return $backup_result;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
// Send image for optimization and fetch the response.
|
98 |
$response = upload_imagify_image( array(
|
99 |
'image' => $file_path,
|
111 |
return new WP_Error( 'api_error', $response->get_error_message() );
|
112 |
}
|
113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
if ( ! function_exists( 'download_url' ) ) {
|
115 |
require_once ABSPATH . 'wp-admin/includes/file.php';
|
116 |
}
|
122 |
}
|
123 |
|
124 |
$filesystem->move( $temp_file, $file_path, true );
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
/**
|
127 |
* Fires after to optimize the Image with Imagify.
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: wp_media, GregLone
|
3 |
Tags: compress image, images, performance, optimization, photos, upload, resize, gif, png, jpg, reduce image size, retina
|
4 |
Requires at least: 3.7.0
|
5 |
-
Tested up to: 4.9.
|
6 |
-
Stable tag: 1.
|
7 |
|
8 |
Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.
|
9 |
|
@@ -138,6 +138,12 @@ When the plugin is disabled, your existing images remain optimized. Backups of t
|
|
138 |
4. Other Media Page
|
139 |
|
140 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
= 1.7.1.3 - 2018/04/12 =
|
142 |
* Bug Fix: a fatal error with outdated versions of php.
|
143 |
|
2 |
Contributors: wp_media, GregLone
|
3 |
Tags: compress image, images, performance, optimization, photos, upload, resize, gif, png, jpg, reduce image size, retina
|
4 |
Requires at least: 3.7.0
|
5 |
+
Tested up to: 4.9.6
|
6 |
+
Stable tag: 1.8
|
7 |
|
8 |
Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth.
|
9 |
|
138 |
4. Other Media Page
|
139 |
|
140 |
== Changelog ==
|
141 |
+
= 1.8 - 2018/06/19 =
|
142 |
+
* New: you can now optimize pdf files.
|
143 |
+
* Improvement: custom folders, you can now optimize files located in the *uploads* folder.
|
144 |
+
* Improvement: support for thumbnails dynamically generated by NextGen Gallery plugin.
|
145 |
+
* Bug Fix: revamped support for WP Retina 2x plugin.
|
146 |
+
|
147 |
= 1.7.1.3 - 2018/04/12 =
|
148 |
* Bug Fix: a fatal error with outdated versions of php.
|
149 |
|
uninstall.php
CHANGED
@@ -27,12 +27,13 @@ delete_transient( 'imagify_user' );
|
|
27 |
|
28 |
// Delete transients.
|
29 |
$transients = implode( '" OR option_name LIKE "', array(
|
30 |
-
'
|
31 |
-
'
|
32 |
-
'
|
33 |
-
'
|
|
|
34 |
) );
|
35 |
-
$wpdb->query(
|
36 |
|
37 |
// Clear scheduled hooks.
|
38 |
wp_clear_scheduled_hook( 'imagify_rating_event' );
|
27 |
|
28 |
// Delete transients.
|
29 |
$transients = implode( '" OR option_name LIKE "', array(
|
30 |
+
'\_transient\_%imagify-async-in-progress-%',
|
31 |
+
'\_transient\_%imagify-ngg-async-in-progress-%',
|
32 |
+
'\_site\_transient\_%imagify-file-async-in-progress-%',
|
33 |
+
'\_transient\_%imagify\_rpc\_%',
|
34 |
+
'\_site\_transient\_imagify\_%\_process\_lock%',
|
35 |
) );
|
36 |
+
$wpdb->query( "DELETE from $wpdb->options WHERE option_name LIKE \"$transients\"" ); // WPCS: unprepared SQL ok.
|
37 |
|
38 |
// Clear scheduled hooks.
|
39 |
wp_clear_scheduled_hook( 'imagify_rating_event' );
|
views/part-settings-custom-folders.php
CHANGED
@@ -12,6 +12,7 @@ $themes = array();
|
|
12 |
if ( $custom_folders ) {
|
13 |
$custom_folders = array_combine( $custom_folders, $custom_folders );
|
14 |
$custom_folders = array_map( array( 'Imagify_Files_Scan', 'remove_placeholder' ), $custom_folders );
|
|
|
15 |
$custom_folders = array_filter( $custom_folders, array( 'Imagify_Files_Scan', 'is_path_autorized' ) );
|
16 |
}
|
17 |
|
@@ -154,6 +155,19 @@ if ( ! is_network_admin() ) {
|
|
154 |
?>
|
155 |
</fieldset>
|
156 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
<p class="imagify-success hidden"><?php _e( 'You changed your custom folder settings, don\'t forget to save your changes!', 'imagify' ); ?></p>
|
158 |
|
159 |
<script type="text/html" id="tmpl-imagify-custom-folder">
|
12 |
if ( $custom_folders ) {
|
13 |
$custom_folders = array_combine( $custom_folders, $custom_folders );
|
14 |
$custom_folders = array_map( array( 'Imagify_Files_Scan', 'remove_placeholder' ), $custom_folders );
|
15 |
+
$custom_folders = array_map( 'trailingslashit', $custom_folders );
|
16 |
$custom_folders = array_filter( $custom_folders, array( 'Imagify_Files_Scan', 'is_path_autorized' ) );
|
17 |
}
|
18 |
|
155 |
?>
|
156 |
</fieldset>
|
157 |
|
158 |
+
<p>
|
159 |
+
<?php
|
160 |
+
printf(
|
161 |
+
/* translators: 1 and 2 are <strong> opening and closing tags. */
|
162 |
+
__( '%1$sSelecting a folder will also optimize images in sub-folders.%2$s The only exception is "Site’s root": when selected, only images that are directly at the site’s root will be optimized (sub-folders can be selected separately).', 'imagify' ),
|
163 |
+
'<strong>',
|
164 |
+
'</strong>'
|
165 |
+
);
|
166 |
+
?>
|
167 |
+
<br/>
|
168 |
+
<?php _e( 'Folders that are hidden in the folder selector window are excluded and will not be optimized even if a parent folder is selected.', 'imagify' ); ?>
|
169 |
+
</p>
|
170 |
+
|
171 |
<p class="imagify-success hidden"><?php _e( 'You changed your custom folder settings, don\'t forget to save your changes!', 'imagify' ); ?></p>
|
172 |
|
173 |
<script type="text/html" id="tmpl-imagify-custom-folder">
|