PluginProbe ʕ •ᴥ•ʔ
Shortcodes and extra features for Phlox theme / 2.17.14
Shortcodes and extra features for Phlox theme v2.17.14
2.17.21 2.17.20 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.6 1.0.9 1.1.0 1.3.0 1.3.1 1.3.10 1.3.14 1.3.2 1.3.3 1.3.6 1.4.0 1.4.1 1.4.2 1.5.0 1.5.2 1.6.0 1.6.2 1.6.4 1.7.0 1.7.2 2.10.0 2.10.1 2.10.3 2.10.5 2.10.7 2.10.8 2.10.9 2.11.0 2.11.1 2.11.2 2.12.0 2.14.0 2.15.0 2.15.2 2.15.4 2.15.5 2.15.6 2.15.7 2.15.8 2.15.9 2.16.0 2.16.1 2.16.2 2.16.3 2.16.4 2.17.0 2.17.1 2.17.12 2.17.13 2.17.14 2.17.15 2.17.16 2.17.2 2.17.3 2.17.4 2.17.5 2.17.6 2.17.8 2.17.9 2.4.12 2.4.13 2.4.14 2.4.16 2.4.18 2.4.19 2.4.9 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.14 2.5.15 2.5.16 2.5.17 2.5.19 2.5.2 2.5.20 2.5.3 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.10 2.6.12 2.6.13 2.6.14 2.6.15 2.6.16 2.6.17 2.6.19 2.6.2 2.6.20 2.6.4 2.6.5 2.6.7 2.7.0 2.7.1 2.7.10 2.7.11 2.7.12 2.7.13 2.7.14 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.9 2.9.0 2.9.12 2.9.14 2.9.15 2.9.16 2.9.17 2.9.18 2.9.19 2.9.2 2.9.20 2.9.21 2.9.22 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 2.9.8
auxin-elements / includes / classes / class-auxin-svg-support.php
auxin-elements / includes / classes Last commit date
class-auxels-admin-assets.php 1 year ago class-auxels-archive-menu-links.php 1 year ago class-auxels-envato-elements.php 1 year ago class-auxels-import-parser.php 3 years ago class-auxels-import.php 3 years ago class-auxels-search-post-type.php 6 months ago class-auxels-wc-attribute-nav-menu.php 1 year ago class-auxin-admin-dashboard.php 1 year ago class-auxin-demo-importer.php 6 months ago class-auxin-dependency-sorting.php 3 years ago class-auxin-import.php 1 year ago class-auxin-install.php 1 year ago class-auxin-master-nav-menu-admin.php 1 year ago class-auxin-page-template.php 1 year ago class-auxin-permalink.php 1 year ago class-auxin-plugin-requirements.php 3 years ago class-auxin-post-type-base.php 1 year ago class-auxin-svg-support-allowedattributes.php 7 years ago class-auxin-svg-support-allowedtags.php 7 years ago class-auxin-svg-support.php 1 year ago class-auxin-walker-nav-menu-back.php 1 year ago class-auxin-welcome-sections.php 1 year ago class-auxin-welcome.php 6 months ago class-auxin-whitelabel.php 3 years ago class-auxin-widget-indie.php 1 year ago class-auxin-widget-shortcode-map.php 11 months ago class-auxin-widget.php 1 year ago
class-auxin-svg-support.php
457 lines
1 <?php
2
3 /**
4 * Class Auxin_SVG_Support
5 */
6 class Auxin_SVG_Support {
7
8
9 protected $sanitizer;
10
11 /**
12 * Instance of this class.
13 *
14 * @var object
15 */
16 protected static $instance = null;
17
18 /**
19 * Return an instance of this class.
20 *
21 * @return object A single instance of this class.
22 */
23 public static function get_instance() {
24
25 // If the single instance hasn't been set, set it now.
26 if ( null == self::$instance ) {
27 self::$instance = new self;
28 }
29
30 return self::$instance;
31 }
32
33 /**
34 * Set up the class
35 */
36 public function __construct() {
37 $this->sanitizer = new enshrined\svgSanitize\Sanitizer();
38 $this->sanitizer->minify( true );
39
40 add_filter( 'upload_mimes', array( $this, 'allow_svg' ) );
41 add_filter( 'wp_handle_upload_prefilter', array( $this, 'check_for_svg' ) );
42 add_filter( 'wp_check_filetype_and_ext', array( $this, 'fix_mime_type_svg' ), 75, 4 );
43 add_filter( 'wp_prepare_attachment_for_js', array( $this, 'fix_admin_preview' ), 10, 3 );
44 add_filter( 'wp_get_attachment_image_src', array( $this, 'one_pixel_fix' ), 10, 4 );
45 add_filter( 'admin_post_thumbnail_html', array( $this, 'featured_image_fix' ), 10, 3 );
46 add_action( 'get_image_tag', array( $this, 'get_image_tag_override' ), 10, 6 );
47 add_filter( 'wp_generate_attachment_metadata', array( $this, 'skip_svg_regeneration' ), 10, 2 );
48 add_filter( 'wp_get_attachment_metadata', array( $this, 'metadata_error_fix' ), 10, 2 );
49 add_filter( 'wp_get_attachment_image_attributes', array( $this, 'fix_direct_image_output' ), 10, 2 );
50 }
51
52 /**
53 * Allow SVG Uploads
54 *
55 * @param $mimes
56 *
57 * @return mixed
58 */
59 public function allow_svg( $mimes ) {
60 $mimes['svg'] = 'image/svg+xml';
61 $mimes['svgz'] = 'image/svg+xml';
62
63 return $mimes;
64 }
65
66 /**
67 * Fixes the issue in WordPress 4.7.1 being unable to correctly identify SVGs
68 *
69 * @thanks @lewiscowles
70 *
71 * @param null $data
72 * @param null $file
73 * @param null $filename
74 * @param null $mimes
75 *
76 * @return null
77 */
78 public function fix_mime_type_svg( $data = null, $file = null, $filename = null, $mimes = null ) {
79 $ext = isset( $data['ext'] ) ? $data['ext'] : '';
80 if ( strlen( $ext ) < 1 ) {
81 $exploded = explode( '.', $filename );
82 $ext = strtolower( end( $exploded ) );
83 }
84 if ( $ext === 'svg' ) {
85 $data['type'] = 'image/svg+xml';
86 $data['ext'] = 'svg';
87 } elseif ( $ext === 'svgz' ) {
88 $data['type'] = 'image/svg+xml';
89 $data['ext'] = 'svgz';
90 }
91
92 return $data;
93 }
94
95 /**
96 * Check if the file is an SVG, if so handle appropriately
97 *
98 * @param $file
99 *
100 * @return mixed
101 */
102 public function check_for_svg( $file ) {
103
104 if ( $file['type'] === 'image/svg+xml' && ! class_exists( 'safe_svg' ) ) {
105 if ( ! $this->sanitize( $file['tmp_name'] ) ) {
106 $file['error'] = __( "Sorry, this file couldn't be sanitized so for security reasons wasn't uploaded",
107 'auxin-elements' );
108 }
109 }
110
111 return $file;
112 }
113
114 /**
115 * Sanitize the SVG
116 *
117 * @param $file
118 *
119 * @return bool|int
120 */
121 protected function sanitize( $file ) {
122 $dirty = file_get_contents( $file );
123
124 // Is the SVG gzipped? If so we try and decode the string
125 if ( $is_zipped = $this->is_gzipped( $dirty ) ) {
126 $dirty = gzdecode( $dirty );
127
128 // If decoding fails, bail as we're not secure
129 if ( $dirty === false ) {
130 return false;
131 }
132 }
133
134 /**
135 * Load extra filters to allow devs to access the safe tags and attrs by themselves.
136 */
137 $this->sanitizer->setAllowedTags( new Auxin_SVG_Support_AllowedTags() );
138 $this->sanitizer->setAllowedAttrs( new Auxin_SVG_Support_AllowedAttributes() );
139
140 $clean = $this->sanitizer->sanitize( $dirty );
141
142 if ( $clean === false ) {
143 return false;
144 }
145
146 // If we were gzipped, we need to re-zip
147 if ( $is_zipped ) {
148 $clean = gzencode( $clean );
149 }
150
151 file_put_contents( $file, $clean );
152
153 return true;
154 }
155
156 /**
157 * Check if the contents are gzipped
158 *
159 * @param $contents
160 *
161 * @return bool
162 */
163 protected function is_gzipped( $contents ) {
164 if ( function_exists( 'mb_strpos' ) ) {
165 return 0 === mb_strpos( $contents, "\x1f" . "\x8b" . "\x08" );
166 } else {
167 return 0 === strpos( $contents, "\x1f" . "\x8b" . "\x08" );
168 }
169 }
170
171 /**
172 * Filters the attachment data prepared for JavaScript to add the sizes array to the response
173 *
174 * @param array $response Array of prepared attachment data.
175 * @param int|object $attachment Attachment ID or object.
176 * @param array $meta Array of attachment meta data.
177 *
178 * @return array
179 */
180 public function fix_admin_preview( $response, $attachment, $meta ) {
181
182 if ( $response['mime'] == 'image/svg+xml' ) {
183 $dimensions = $this->svg_dimensions( get_attached_file( $attachment->ID ) );
184
185 if ( $dimensions ) {
186 $response = array_merge( $response, $dimensions );
187 }
188
189 $possible_sizes = apply_filters( 'image_size_names_choose', array(
190 'full' => __( 'Full Size', 'auxin-elements' ),
191 'thumbnail' => __( 'Thumbnail', 'auxin-elements' ),
192 'medium' => __( 'Medium', 'auxin-elements' ),
193 'large' => __( 'Large', 'auxin-elements' ),
194 ) );
195
196 $sizes = array();
197
198 foreach ( $possible_sizes as $size => $label ) {
199 $default_height = 2000;
200 $default_width = 2000;
201
202 if ( 'full' === $size && $dimensions ) {
203 $default_height = $dimensions['height'];
204 $default_width = $dimensions['width'];
205 }
206
207 $sizes[ $size ] = array(
208 'height' => get_option( "{$size}_size_w", $default_height ),
209 'width' => get_option( "{$size}_size_h", $default_width ),
210 'url' => $response['url'],
211 'orientation' => 'portrait',
212 );
213 }
214
215 $response['sizes'] = $sizes;
216 $response['icon'] = $response['url'];
217 }
218
219 return $response;
220 }
221
222 /**
223 * Filters the image src result.
224 * Here we're gonna spoof the image size and set it to 100 width and height
225 *
226 * @param array|false $image Either array with src, width & height, icon src, or false.
227 * @param int $attachment_id Image attachment ID.
228 * @param string|array $size Size of image. Image size or array of width and height values
229 * (in that order). Default 'thumbnail'.
230 * @param bool $icon Whether the image should be treated as an icon. Default false.
231 *
232 * @return array
233 */
234 public function one_pixel_fix( $image, $attachment_id, $size, $icon ) {
235 if ( get_post_mime_type( $attachment_id ) == 'image/svg+xml' ) {
236 $image['1'] = false;
237 $image['2'] = false;
238 }
239
240 return $image;
241 }
242
243 /**
244 * If the featured image is an SVG we wrap it in an SVG class so we can apply our CSS fix.
245 *
246 * @param string $content Admin post thumbnail HTML markup.
247 * @param int $post_id Post ID.
248 * @param int $thumbnail_id Thumbnail ID.
249 *
250 * @return string
251 */
252 public function featured_image_fix( $content, $post_id, $thumbnail_id ) {
253 $mime = get_post_mime_type( $thumbnail_id );
254
255 if ( 'image/svg+xml' === $mime ) {
256 $content = sprintf( '<span class="svg">%s</span>', $content );
257 }
258
259 return $content;
260 }
261
262 /**
263 * Override the default height and width string on an SVG
264 *
265 * @param string $html HTML content for the image.
266 * @param int $id Attachment ID.
267 * @param string $alt Alternate text.
268 * @param string $title Attachment title.
269 * @param string $align Part of the class name for aligning the image.
270 * @param string|array $size Size of image. Image size or array of width and height values (in that order).
271 * Default 'medium'.
272 *
273 * @return mixed
274 */
275 public function get_image_tag_override( $html, $id, $alt, $title, $align, $size ) {
276 $mime = get_post_mime_type( $id );
277
278 if ( 'image/svg+xml' === $mime ) {
279 if ( is_array( $size ) ) {
280 $width = $size[0];
281 $height = $size[1];
282 } elseif ( 'full' == $size && $dimensions = $this->svg_dimensions( get_attached_file( $id ) ) ) {
283 $width = $dimensions['width'];
284 $height = $dimensions['height'];
285 } else {
286 $width = get_option( "{$size}_size_w", false );
287 $height = get_option( "{$size}_size_h", false );
288 }
289
290 if ( $height && $width ) {
291 $html = str_replace( 'width="1" ', sprintf( 'width="%s" ', $width ), $html );
292 $html = str_replace( 'height="1" ', sprintf( 'height="%s" ', $height ), $html );
293 } else {
294 $html = str_replace( 'width="1" ', '', $html );
295 $html = str_replace( 'height="1" ', '', $html );
296 }
297
298 $html = str_replace( '/>', ' role="img" />', $html );
299 }
300
301 return $html;
302 }
303
304 /**
305 * Skip regenerating SVGs
306 *
307 * @param int $attachment_id Attachment Id to process.
308 * @param string $file Filepath of the Attached image.
309 *
310 * @return mixed Metadata for attachment.
311 */
312 public function skip_svg_regeneration( $metadata, $attachment_id ) {
313 $mime = get_post_mime_type( $attachment_id );
314 if ( 'image/svg+xml' === $mime ) {
315 $additional_image_sizes = wp_get_additional_image_sizes();
316 $svg_path = get_attached_file( $attachment_id );
317 $upload_dir = wp_upload_dir();
318 // get the path relative to /uploads/ - found no better way:
319 $relative_path = str_replace( $upload_dir['basedir'], '', $svg_path );
320 $filename = basename( $svg_path );
321
322 $dimensions = $this->svg_dimensions( $svg_path );
323
324 if ( ! $dimensions ) {
325 return $metadata;
326 }
327
328 $metadata = array(
329 'width' => intval( $dimensions['width'] ),
330 'height' => intval( $dimensions['height'] ),
331 'file' => $relative_path
332 );
333
334 // Might come handy to create the sizes array too - But it's not needed for this workaround! Always links to original svg-file => Hey, it's a vector graphic! ;)
335 $sizes = array();
336 foreach ( get_intermediate_image_sizes() as $s ) {
337 $sizes[ $s ] = array( 'width' => '', 'height' => '', 'crop' => false );
338
339 if ( isset( $additional_image_sizes[ $s ]['width'] ) ) {
340 // For theme-added sizes
341 $sizes[ $s ]['width'] = intval( $additional_image_sizes[ $s ]['width'] );
342 } else {
343 // For default sizes set in options
344 $sizes[ $s ]['width'] = get_option( "{$s}_size_w" );
345 }
346
347 if ( isset( $additional_image_sizes[ $s ]['height'] ) ) {
348 // For theme-added sizes
349 $sizes[ $s ]['height'] = intval( $additional_image_sizes[ $s ]['height'] );
350 } else {
351 // For default sizes set in options
352 $sizes[ $s ]['height'] = get_option( "{$s}_size_h" );
353 }
354
355 if ( isset( $additional_image_sizes[ $s ]['crop'] ) ) {
356 // For theme-added sizes
357 $sizes[ $s ]['crop'] = intval( $additional_image_sizes[ $s ]['crop'] );
358 } else {
359 // For default sizes set in options
360 $sizes[ $s ]['crop'] = get_option( "{$s}_crop" );
361 }
362
363 $sizes[ $s ]['file'] = $filename;
364 $sizes[ $s ]['mime-type'] = $mime;
365 }
366 $metadata['sizes'] = $sizes;
367 }
368
369 return $metadata;
370 }
371
372 /**
373 * Filters the attachment meta data.
374 *
375 * @param array|bool $data Array of meta data for the given attachment, or false
376 * if the object does not exist.
377 * @param int $post_id Attachment ID.
378 */
379 public function metadata_error_fix( $data, $post_id ) {
380
381 // If it's a WP_Error regenerate metadata and save it
382 if ( is_wp_error( $data ) ) {
383 $data = wp_generate_attachment_metadata( $post_id, get_attached_file( $post_id ) );
384 wp_update_attachment_metadata( $post_id, $data );
385 }
386
387 return $data;
388 }
389
390 /**
391 * Get SVG size from the width/height or viewport.
392 *
393 * @param $svg
394 *
395 * @return array|bool
396 */
397 protected function svg_dimensions( $svg ) {
398 $svg = @simplexml_load_file( $svg );
399 $width = 0;
400 $height = 0;
401 if ( $svg ) {
402 $attributes = $svg->attributes();
403 if ( isset( $attributes->width, $attributes->height ) ) {
404 $width = floatval( $attributes->width );
405 $height = floatval( $attributes->height );
406 } elseif ( isset( $attributes->viewBox ) ) {
407 $sizes = explode( ' ', $attributes->viewBox );
408 if ( isset( $sizes[2], $sizes[3] ) ) {
409 $width = floatval( $sizes[2] );
410 $height = floatval( $sizes[3] );
411 }
412 } else {
413 return false;
414 }
415 }
416
417 return array(
418 'width' => $width,
419 'height' => $height,
420 'orientation' => ( $width > $height ) ? 'landscape' : 'portrait'
421 );
422 }
423
424 /**
425 * Fix the output of images using wp_get_attachment_image
426 *
427 * @param array $attr Attributes for the image markup.
428 * @param WP_Post $attachment Image attachment post.
429 * @param string|array $size Requested size. Image size or array of width and height values
430 * (in that order). Default 'thumbnail'.
431 */
432 public function fix_direct_image_output( $attr, $attachment ) {
433
434 if ( ! $attachment instanceof WP_Post ) {
435 return $attr;
436 }
437
438 $mime = get_post_mime_type( $attachment->ID );
439 if ( 'image/svg+xml' === $mime ) {
440 $default_height = 100;
441 $default_width = 100;
442
443 $dimensions = $this->svg_dimensions( get_attached_file( $attachment->ID ) );
444
445 if ( $dimensions ) {
446 $default_height = $dimensions['height'];
447 $default_width = $dimensions['width'];
448 }
449
450 $attr['height'] = $default_height;
451 $attr['width'] = $default_width;
452 }
453
454 return $attr;
455 }
456
457 }