PluginProbe
Admin and Site Enhancements (ASE) / 8.6.2
Admin and Site Enhancements (ASE) v8.6.2
9.1.1 9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 All 273 releases
admin-site-enhancements / classes / class-svg-upload.php
class-svg-upload.php
297 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ASENHA\Classes;
4
5 /**
6 * Class for SVG Upload module
7 *
8 * @since 6.9.5
9 */
10 class SVG_Upload {
11
12 /**
13 * Add SVG mime type for media library uploads
14 *
15 * @link https://developer.wordpress.org/reference/hooks/upload_mimes/
16 * @since 2.6.0
17 */
18 public function add_svg_mime( $mimes ) {
19
20 global $roles_svg_upload_enabled;
21
22 $current_user = wp_get_current_user();
23 $current_user_roles = (array) $current_user->roles; // single dimensional array of role slugs
24
25 if ( count( $roles_svg_upload_enabled ) > 0 ) {
26
27 // Add mime type for user roles set to enable SVG upload
28 foreach ( $current_user_roles as $role ) {
29 if ( in_array( $role, $roles_svg_upload_enabled ) ) {
30 $mimes['svg'] = 'image/svg+xml';
31 }
32 }
33
34 }
35
36 return $mimes;
37
38 }
39
40 /**
41 * Check and confirm if the real file type is indeed SVG
42 *
43 * @link https://developer.wordpress.org/reference/functions/wp_check_filetype_and_ext/
44 * @since 2.6.0
45 */
46 public function confirm_file_type_is_svg( $filetypes_extensions, $file, $filename, $mimes ) {
47
48 global $roles_svg_upload_enabled;
49
50 $current_user = wp_get_current_user();
51 $current_user_roles = (array) $current_user->roles; // single dimensional array of role slugs
52
53 if ( count( $roles_svg_upload_enabled ) > 0 ) {
54
55 // Check file extension
56 if ( substr( $filename, -4 ) == '.svg' ) {
57
58 // Add mime type for user roles set to enable SVG upload
59 foreach ( $current_user_roles as $role ) {
60 if ( in_array( $role, $roles_svg_upload_enabled ) ) {
61 $filetypes_extensions['type'] = 'image/svg+xml';
62 $filetypes_extensions['ext'] = 'svg';
63 }
64 }
65
66 }
67
68 }
69
70 return $filetypes_extensions;
71
72 }
73
74 /**
75 * Sanitize the SVG file and maybe allow upload based on the result
76 *
77 * @since 2.6.0
78 */
79 public function sanitize_and_maybe_allow_svg_upload( $file ) {
80 if ( ! isset( $file['tmp_name'] ) ) {
81 return $file;
82 }
83
84 $file_tmp_name = $file['tmp_name']; // full path
85 $file_name = isset( $file['name'] ) ? $file['name'] : '';
86 $file_type_ext = wp_check_filetype_and_ext( $file_tmp_name, $file_name );
87 $file_type = ! empty( $file_type_ext['type'] ) ? $file_type_ext['type'] : '';
88
89 if ( 'image/svg+xml' === $file_type ) {
90 $original_svg = file_get_contents( $file_tmp_name );
91
92 $sanitizer = $this->get_svg_sanitizer();
93 $sanitized_svg = $sanitizer->sanitize( $original_svg ); // boolean
94
95 if ( false === $sanitized_svg ) {
96
97 $file['error'] = 'This SVG file could not be sanitized, so, was not uploaded for security reasons.';
98
99 }
100
101 file_put_contents( $file_tmp_name, $sanitized_svg );
102 }
103
104 return $file;
105 }
106
107 /**
108 * Sanitize SVG upload via xmlrpc.php
109 *
110 * @link https://developer.wordpress.org/reference/hooks/xmlrpc_prepare_media_item/
111 * @since 7.9.8
112 */
113 public function sanitize_xmlrpc_svg_upload( $_media_item, $media_item ) {
114 if ( is_object( $media_item ) ) {
115 if ( property_exists( $media_item, 'ID' ) ) {
116 $file_path = get_attached_file( $media_item->ID );
117 $original_svg = file_get_contents( $file_path );
118
119 $sanitizer = $this->get_svg_sanitizer();
120 $sanitized_svg = $sanitizer->sanitize( $original_svg ); // boolean
121
122 if ( false !== $sanitized_svg ) {
123 // Sanitization was a success, let's write the result back to the file
124 file_put_contents( $file_path, $sanitized_svg );
125 }
126 }
127 }
128
129 return $_media_item;
130 }
131
132 /**
133 * Sanitize a file after it is added to the media library, e.g. via REST API POST request
134 *
135 * @since 7.5.2
136 */
137 public function sanitize_after_upload( $attachment, $request, $creating ) {
138 // Let's sanitize SVG upon creation/insertion in the media library.
139 if ( $creating ) {
140 if ( $attachment instanceof WP_Post ) {
141 $file_path = get_attached_file( $attachment->ID );
142 $original_svg = file_get_contents( $file_path );
143
144 $sanitizer = $this->get_svg_sanitizer();
145 $sanitized_svg = $sanitizer->sanitize( $original_svg ); // boolean
146
147 if ( false !== $sanitized_svg ) {
148 // Sanitization was a success, let's write the result back to the file
149 file_put_contents( $file_path, $sanitized_svg );
150 }
151 }
152 }
153 }
154
155 /**
156 * Get sanitizer object
157 *
158 * @since 7.5.2
159 */
160 public function get_svg_sanitizer() {
161 if ( ! class_exists( '\enshrined\svgSanitize\Sanitizer' ) ) {
162 // Load sanitizer library - https://github.com/darylldoyle/svg-sanitizer
163 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/data/AttributeInterface.php';
164 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/data/TagInterface.php';
165 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/data/AllowedAttributes.php';
166 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/data/AllowedTags.php';
167 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/data/XPath.php';
168 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/ElementReference/Resolver.php';
169 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/ElementReference/Subject.php';
170 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/ElementReference/Usage.php';
171 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/Exceptions/NestingException.php';
172 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/Helper.php';
173 require_once ASENHA_PATH . 'vendor/enshrined/svg-sanitize/src/Sanitizer.php';
174 }
175
176 // $sanitizer = new Sanitizer();
177 $sanitizer = new \enshrined\svgSanitize\Sanitizer();
178
179 return $sanitizer;
180 }
181
182 /**
183 * Generate metadata for the svg attachment
184 *
185 * @link https://developer.wordpress.org/reference/functions/wp_generate_attachment_metadata/
186 * @since 2.6.0
187 */
188 public function generate_svg_metadata( $metadata, $attachment_id, $context ) {
189
190 if ( get_post_mime_type( $attachment_id ) == 'image/svg+xml' ) {
191
192 // Get SVG intrinsic dimensions (prefer viewBox when width/height are %).
193 $svg_path = get_attached_file( $attachment_id );
194 $common_methods = new Common_Methods;
195 $dims = $common_methods->get_svg_intrinsic_dimensions_from_file( $svg_path );
196
197 $metadata['width'] = isset( $dims['width'] ) ? absint( $dims['width'] ) : 0;
198 $metadata['height'] = isset( $dims['height'] ) ? absint( $dims['height'] ) : 0;
199
200 // Get SVG filename
201 $svg_url = wp_get_original_image_url( $attachment_id );
202 $svg_url_path = str_replace( wp_upload_dir()['baseurl'] .'/' , '', $svg_url );
203 $metadata['file'] = $svg_url_path;
204
205 }
206
207 return $metadata;
208
209 }
210
211 /**
212 * Remove responsive image attributes, i.e. srcset attributes, from SVG images HTML
213 * This helps ensure SVGs are displayed properly on the frontend
214 *
215 * @link https://plugins.trac.wordpress.org/browser/svg-support/tags/2.5.7/functions/attachment.php#L282
216 * @since 7.3.0
217 */
218 public function disable_svg_srcset( $sources ) {
219 $first_element = reset( $sources );
220
221 if ( isset( $first_element ) && ! empty( $first_element['url'] ) ) {
222 $extension = pathinfo( reset($sources)['url'], PATHINFO_EXTENSION );
223
224 if ( 'svg' === $extension ) {
225 $sources = array(); // return empty array
226 return $sources;
227 } else {
228 return $sources;
229 }
230 } else {
231 return $sources;
232 }
233 }
234
235 /**
236 * Remove responsive image attributes, i.e. srcset attributes, from SVG images HTML
237 * This helps ensure SVGs are displayed properly on the frontend
238 *
239 * @link https://gist.github.com/ericvalois/5b1e161c127632a1ace7d65ce1363e69
240 * @since 7.3.0
241 */
242 public function remove_svg_responsive_image_attr( string $sizes, $size, $image_src = null ) {
243 $explode = explode( '.', $image_src );
244 $extension = end( $explode );
245
246 if( 'svg' === $extension ){
247 $sizes = '';
248 }
249
250 return $sizes;
251 }
252
253 /**
254 * Return svg file URL to show preview in media library
255 *
256 * @link https://developer.wordpress.org/reference/hooks/wp_ajax_action/
257 * @link https://developer.wordpress.org/reference/functions/wp_get_attachment_url/
258 * @since 2.6.0
259 */
260 public function get_svg_attachment_url() {
261
262 $attachment_url = '';
263 $attachment_id = isset( $_REQUEST['attachmentID'] ) ? $_REQUEST['attachmentID'] : '';
264
265 // Check response mime type
266 if ( $attachment_id ) {
267
268 echo esc_url( wp_get_attachment_url( $attachment_id ) );
269
270 die();
271
272 }
273
274 }
275
276 /**
277 * Return svg file URL to show preview in media library
278 *
279 * @link https://developer.wordpress.org/reference/functions/wp_prepare_attachment_for_js/
280 * @since 2.6.0
281 */
282 public function get_svg_url_in_media_library( $response ) {
283
284 // Check response mime type
285 if ( $response['mime'] === 'image/svg+xml' ) {
286
287 $response['image'] = array(
288 'src' => $response['url'],
289 );
290
291 }
292
293 return $response;
294
295 }
296
297 }