PluginProbe
Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts / 2.8.13
Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts v2.8.13
2.8.14 2.8.13 2.8.12 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.10 2.8.11 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 trunk 1.0.1 1.0.2 1.1.0 1.1.1 All 147 releases
content-blocks-builder / includes / icon-library.php

icon-library.php in Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts 2.8.13, at includes/icon-library.php

396 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The icon library
4 *
5 * @package BoldBlocks
6 * @author Phi Phan <mrphipv@gmail.com>
7 * @copyright Copyright (c) 2022, Phi Phan
8 */
9
10 namespace BoldBlocks;
11
12 // Exit if accessed directly.
13 defined( 'ABSPATH' ) || exit;
14
15 if ( ! class_exists( IconLibrary::class ) ) :
16 /**
17 * The controller class for icon library.
18 */
19 class IconLibrary extends CoreComponent {
20 /**
21 * Run main hooks
22 *
23 * @return void
24 */
25 public function run() {
26 // Add rest api endpoint to query icon library.
27 add_action( 'rest_api_init', [ $this, 'register_icon_library_endpoint' ] );
28 }
29
30 /**
31 * Build a custom endpoint to query icon library.
32 *
33 * @return void
34 */
35 public function register_icon_library_endpoint() {
36 register_rest_route(
37 'cbb/v1',
38 '/getIconLibrary/',
39 array(
40 'methods' => 'GET',
41 'callback' => [ $this, 'get_icon_library' ],
42 'permission_callback' => function () {
43 return current_user_can( 'publish_posts' );
44 },
45 )
46 );
47 }
48
49 /**
50 * Get icon library.
51 *
52 * @param WP_REST_Request $request The request object.
53 * @return void
54 */
55 public function get_icon_library( $request ) {
56 // icons file path.
57 $icons_file = $this->the_plugin_instance->get_file_path( 'data/icon-library/icons.json' );
58
59 // Send the error if the icons file is not exists.
60 if ( ! \file_exists( $icons_file ) ) {
61 wp_send_json_error( __( 'The icons.json file is not exists.', 'content-blocks-builder' ), 500 );
62 }
63
64 // Parse json.
65 $icons = wp_json_file_decode( $icons_file, [ 'associative' => true ] );
66
67 // Query svg images from the media library.
68 $media_svg_images = $this->query_svg_images();
69
70 if ( $media_svg_images ) {
71 $icons = array_merge( $media_svg_images, $icons );
72 }
73
74 wp_send_json(
75 [
76 'data' => $icons,
77 'success' => true,
78 ]
79 );
80 }
81
82 /**
83 * Query SVG images from the library
84 *
85 * @return array
86 */
87 private function query_svg_images() {
88 $media_svgs = [];
89 $images = get_posts(
90 [
91 'post_type' => 'attachment',
92 'post_mime_type' => [ 'image/svg+xml' ],
93 'post_status' => 'any',
94 'posts_per_page' => 100,
95 ]
96 );
97
98 if ( $images ) {
99 foreach ( $images as $image ) {
100 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
101 $icon = file_get_contents( get_attached_file( $image->ID ) );
102 if ( $icon ) {
103 $media_svgs[] = [
104 'name' => $image->post_name,
105 'title' => $image->post_title,
106 'icon' => $icon,
107 'categories' => [ 'Media Library' ],
108 'provider' => 'Media Library',
109 ];
110 }
111 }
112 }
113
114 return $media_svgs;
115 }
116
117 /**
118 * Sanitize SVG
119 *
120 * @param string $svg
121 * @return string
122 */
123 public function sanitize_svg( $svg ) {
124 if ( ! is_string( $svg ) ) {
125 return '';
126 }
127
128 if ( ! preg_match( '/^\s*<svg\b/i', $svg ) ) {
129 return '';
130 }
131
132 // Hard block dangerous stuff.
133 if (
134 preg_match(
135 '/<(script|iframe|object|embed|foreignObject|image|feImage|use|animate|set)\b/i',
136 $svg
137 )
138 ) {
139 return '';
140 }
141
142 // Remove null bytes.
143 $svg = wp_kses_no_null( $svg );
144
145 // Remove event handlers.
146 $svg = preg_replace(
147 '/\son[a-z-]+\s*=\s*("|\').*?\1/i',
148 '',
149 $svg
150 );
151
152 // Remove href-like attrs.
153 $svg = preg_replace(
154 '/\s(?:href|xlink:href|src)\s*=\s*("|\').*?\1/i',
155 '',
156 $svg
157 );
158
159 // KSES sanitization.
160 $svg = wp_kses(
161 $svg,
162 $this->get_allowed_svg_tags()
163 );
164
165 return trim( $svg );
166 }
167
168 /**
169 * Get allowed svg tags and attributes
170 *
171 * @return array
172 */
173 private function get_allowed_svg_tags() {
174 $global_attrs = [
175 // Common.
176 'id' => true,
177 'class' => true,
178 'aria-hidden' => true,
179
180 // Presentation.
181 'clip-path' => true,
182 'clip-rule' => true,
183 'color' => true,
184 'color-interpolation' => true,
185 'display' => true,
186 'fill' => true,
187 'fill-opacity' => true,
188 'fill-rule' => true,
189 'mask' => true,
190 'opacity' => true,
191 'pointer-events' => true,
192 'shape-rendering' => true,
193 'stroke' => true,
194 'stroke-dasharray' => true,
195 'stroke-dashoffset' => true,
196 'stroke-linecap' => true,
197 'stroke-linejoin' => true,
198 'stroke-miterlimit' => true,
199 'stroke-opacity' => true,
200 'stroke-width' => true,
201 'transform' => true,
202 'vector-effect' => true,
203 'visibility' => true,
204 ];
205
206 $allowed_svg = [
207 'svg' => array_merge(
208 $global_attrs,
209 [
210 'xmlns' => true,
211 'viewbox' => true,
212 'width' => true,
213 'height' => true,
214 'x' => true,
215 'y' => true,
216 'preserveaspectratio' => true,
217 'name' => true,
218 'role' => true,
219 'focusable' => true,
220 'aria-labelledby' => true,
221 ]
222 ),
223
224 'g' => $global_attrs,
225
226 'defs' => [],
227
228 'symbol' => [
229 'id' => true,
230 'viewbox' => true,
231 ],
232
233 'title' => [],
234 'desc' => [],
235
236 'path' => array_merge(
237 $global_attrs,
238 [
239 'd' => true,
240 'pathlength' => true,
241 ]
242 ),
243
244 'circle' => array_merge(
245 $global_attrs,
246 [
247 'cx' => true,
248 'cy' => true,
249 'r' => true,
250 'pathlength' => true,
251 ]
252 ),
253
254 'ellipse' => array_merge(
255 $global_attrs,
256 [
257 'cx' => true,
258 'cy' => true,
259 'rx' => true,
260 'ry' => true,
261 'pathlength' => true,
262 ]
263 ),
264
265 'rect' => array_merge(
266 $global_attrs,
267 [
268 'x' => true,
269 'y' => true,
270 'width' => true,
271 'height' => true,
272 'rx' => true,
273 'ry' => true,
274 'pathlength' => true,
275 ]
276 ),
277
278 'line' => array_merge(
279 $global_attrs,
280 [
281 'x1' => true,
282 'y1' => true,
283 'x2' => true,
284 'y2' => true,
285 'pathlength' => true,
286 ]
287 ),
288
289 'polyline' => array_merge(
290 $global_attrs,
291 [
292 'points' => true,
293 'pathlength' => true,
294 ]
295 ),
296
297 'polygon' => array_merge(
298 $global_attrs,
299 [
300 'points' => true,
301 'pathlength' => true,
302 ]
303 ),
304
305 'linearGradient' => [
306 'id' => true,
307 'x1' => true,
308 'y1' => true,
309 'x2' => true,
310 'y2' => true,
311 'gradientunits' => true,
312 'gradienttransform' => true,
313 'spreadmethod' => true,
314 ],
315
316 'radialGradient' => [
317 'id' => true,
318 'cx' => true,
319 'cy' => true,
320 'r' => true,
321 'fx' => true,
322 'fy' => true,
323 'gradientunits' => true,
324 'gradienttransform' => true,
325 'spreadmethod' => true,
326 ],
327
328 'stop' => [
329 'offset' => true,
330 'stop-color' => true,
331 'stop-opacity' => true,
332 ],
333
334 'clipPath' => [
335 'id' => true,
336 'clippathunits' => true,
337 'transform' => true,
338 ],
339
340 'mask' => [
341 'id' => true,
342 'x' => true,
343 'y' => true,
344 'width' => true,
345 'height' => true,
346 'maskunits' => true,
347 'maskcontentunits' => true,
348 ],
349
350 'pattern' => [
351 'id' => true,
352 'x' => true,
353 'y' => true,
354 'width' => true,
355 'height' => true,
356 'patternunits' => true,
357 'patterntransform' => true,
358 'viewbox' => true,
359 ],
360
361 'text' => array_merge(
362 $global_attrs,
363 [
364 'x' => true,
365 'y' => true,
366 'dx' => true,
367 'dy' => true,
368 'textlength' => true,
369 'rotate' => true,
370 'text-anchor' => true,
371 'font-size' => true,
372 'font-family' => true,
373 'font-weight' => true,
374 'letter-spacing' => true,
375 'lengthadjust' => true,
376 ]
377 ),
378
379 'tspan' => [
380 'x' => true,
381 'y' => true,
382 'dx' => true,
383 'dy' => true,
384 'text-anchor' => true,
385 'font-size' => true,
386 'font-family' => true,
387 'font-weight' => true,
388 'letter-spacing' => true,
389 ],
390 ];
391
392 return apply_filters( 'cbb_get_allowed_svg_tags', $allowed_svg );
393 }
394 }
395 endif;
396