PluginProbe
Quick Download Button / trunk
Quick Download Button vtrunk
trunk 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.0 1.4.0
quick-download-button / class / shortcode.class.php

shortcode.class.php in Quick Download Button trunk, at class/shortcode.class.php

656 lines 23.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined( 'ABSPATH' ) || exit;
3
4 /**
5 * Shortcode class
6 */
7 class QDBU_QuickDownloadShortCode {
8
9
10 public $a;
11 public $pid;
12 public $attachment_id;
13 public $url;
14 public $open_new_window;
15 public $wait;
16 public $download_pid;
17 public $color_gb;
18 public $panel_color;
19 public $icon_id;
20 public $custom_file_type_icon;
21 public $file_size_icon_id;
22 public $custom_file_size_icon;
23 public $icon_position;
24 public $color_font;
25 public $color_icon_dark;
26 public $msg;
27 public $icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="22" height="22"><path d="M18 11.3l-1-1.1-4 4V3h-1.5v11.3L7 10.2l-1 1.1 6.2 5.8 5.8-5.8zm.5 3.7v3.5h-13V15H4v5h16v-5h-1.5z" /></svg>';
28 public $button_type;
29 private $user_role;
30 public $validate_msg;
31 public $popup_content;
32 public $popup_closable;
33
34
35
36 public function __construct() {
37 add_shortcode( 'quick_download_button', array( $this, 'quick_download_button_shortcode' ) );
38 }
39
40 /**
41 * @usage Add shortcode
42 *
43 * @param mixed $attr
44 * @return void
45 */
46 public function quick_download_button_shortcode( $attr, $content = null ) {
47
48 $this->a = shortcode_atts(
49 array(
50 'title' => 'Download',
51 'file_size' => '',
52 'url' => '',
53 'extension' => '',
54 'extension_text' => '0',
55 'url_external' => '',
56 'open_new_window' => 'false',
57 'wait' => 0,
58 'color_bg' => null,
59 'panel_color' => null,
60 'icon_id' => 'default',
61 'custom_file_type_icon' => '',
62 'file_size_icon_id' => 'folder',
63 'custom_file_size_icon' => '',
64 'icon_position' => 'left',
65 'color_font' => null,
66 'color_icon_dark' => 'true',
67 'msg' => 'Please wait...',
68 'button_type' => 'large',
69 'border_width' => null,
70 'border_style' => null,
71 'border_color' => null,
72 'border_radius' => null,
73 'align' => null,
74 'padding' => null,
75 'user_must_be' => '',
76 'validate' => false,
77 'validate_msg' => '',
78 'popup_closable' => '1'
79 ),
80 $attr
81 );
82
83 /**
84 * Filter: qdb_shortcode_atts
85 *
86 * Modify or extend parsed shortcode attributes before the button is built.
87 * Used by Pro: add 'required_product_id', 'download_limit', 'email_gate', etc.
88 *
89 * @param array $atts Parsed shortcode attributes.
90 * @param array $attr Raw attributes passed to the shortcode.
91 */
92 $this->a = apply_filters( 'qdb_shortcode_atts', $this->a, $attr );
93
94 global $post;
95 $this->pid = $post->ID;
96 $this->download_pid = (int) get_option( 'qdbu_quick_download_button_page_id' );
97
98 $this->attachment_id = attachment_url_to_postid( $this->a['url'] ); //get attachment id from URL
99
100 $quick_download_button_url = qdbu_default_url() . '?aid=' . $this->attachment_id; //pass attachment id to plugin download file
101
102
103 $this->url = ! empty( $this->a['url'] && strpos( $this->a['url'], site_url()) !== false ) ? $quick_download_button_url : $this->a['url_external']; //if url value is empty set url to external url (url_external)
104
105 $this->open_new_window = 'true' === $this->a['open_new_window'] ? 'true' : 'false';
106
107 $this->wait = $this->a['wait'] > 0 ? $this->a['wait'] : 0;
108
109 $this->color_gb = null !== $this->a['color_bg'] ? $this->a['color_bg'] : null;
110
111 $this->panel_color = null !== $this->a['panel_color'] ? $this->a['panel_color'] : null;
112
113 $this->icon_id = sanitize_key( $this->a['icon_id'] );
114 $this->custom_file_type_icon = wp_kses( $this->a['custom_file_type_icon'], array( 'svg' => array( 'xmlns' => true, 'viewbox' => true, 'width' => true, 'height' => true, 'aria-hidden' => true ), 'path' => array( 'd' => true, 'fill' => true ), 'g' => array( 'fill' => true ) ) );
115 $this->file_size_icon_id = sanitize_key( $this->a['file_size_icon_id'] );
116 $this->custom_file_size_icon = wp_kses( $this->a['custom_file_size_icon'], array( 'svg' => array( 'xmlns' => true, 'viewbox' => true, 'width' => true, 'height' => true, 'aria-hidden' => true ), 'path' => array( 'd' => true, 'fill' => true ), 'g' => array( 'fill' => true ) ) );
117 $this->icon_position = in_array( $this->a['icon_position'], array( 'left', 'right' ), true ) ? $this->a['icon_position'] : 'left';
118 $this->popup_content = $content ? do_shortcode( $content ) : null;
119 $this->popup_closable = '0' === $this->a['popup_closable'] ? '0' : '1';
120
121 $this->color_font = null !== $this->a['color_font'] ? $this->a['color_font'] : null;
122
123 $this->color_icon_dark = 'true' === $this->a['color_icon_dark'] ? 'true' : 'false';
124
125 $this->msg = !empty($this->a['msg']) && '' !== $this->a['msg'] ? $this->a['msg'] : 'Please wait...';
126
127 $this->button_type = !empty($this->a['button_type']) ? $this->a['button_type'] : 'large';
128
129 $this->border_width = !null !== $this->a['border_width'] ? $this->a['border_width'] : null;
130
131 $this->border_style = !null !== $this->a['border_style'] ? $this->a['border_style'] : null;
132
133 $this->border_color = !null !== $this->a['border_color'] ? $this->a['border_color'] : null;
134
135 $this->border_radius = !null !== $this->a['border_radius'] ? $this->a['border_radius'] : null;
136
137 $this->padding = !null !== $this->a['padding'] ? $this->a['padding'] : null;
138
139 $this->align = !null !== $this->a['align'] ? $this->a['align'] : null;
140
141 $this->user_role = '' !== $this->a['user_must_be'] ? trim(strtolower( $this->a['user_must_be'])) : '';
142
143 $this->validate_msg = '' !== $this->a['validate_msg'] ? esc_attr($this->a['validate_msg']) : 'Please contact the admin.';
144
145
146 return $this->generate_button();
147 }
148
149
150 /**
151 * @Output download button html
152 *
153 * @return void
154 */
155 public function generate_button() {
156
157 $l1_style = 'style="';
158 if(null !== $this->padding) {
159 $l1_style .= 'padding-top:' .esc_attr( $this->padding ). 'px;';
160 $l1_style .= 'padding-bottom:' .esc_attr( $this->padding ). 'px;';
161 }
162 if(null !== $this->align) {
163 $l1_style .= 'padding-top: ' .esc_attr( $this->padding ). 'px;';
164 $l1_style .= 'text-align: ' .esc_attr( $this->align ).';';
165 }
166 $l1_style .= '"';
167
168 // Compute btn_id once so it is available throughout generate_button() and to all Pro filters/actions.
169 $this->a['btn_id'] = substr( md5( $this->pid . '_' . $this->attachment_id . '_' . $this->a['url_external'] ), 0, 12 );
170
171 $hide_size = '' === $this->a['file_size'] ? ' hide-size' : '' ;
172 $hide_file = '' === $this->a['extension'] ? ' hide-file' : '' ;
173
174 // Built-in role/login check.
175 if ( in_array( $this->user_role, qdbn_get_current_user_roles() ) ) {
176 $this->a['validate'] = true;
177 } else {
178 $this->validate_msg = $this->user_role . ' account required.';
179 }
180 if ( 'loggedin' === $this->user_role ) {
181 if ( is_user_logged_in() ) {
182 $this->a['validate'] = true;
183 } else {
184 $this->validate_msg = 'You must be logged in to download.';
185 }
186 }
187
188 /**
189 * Filter: qdb_user_can_access
190 *
191 * Override or extend the access check for the download button.
192 * Return array with 'allowed' (bool) and 'message' (string).
193 * Used by Pro: WooCommerce purchase gate, email gate, download limit UI.
194 *
195 * @param array $access { 'allowed' => bool, 'message' => string }
196 * @param array $atts Shortcode attributes.
197 * @param int $user_id Current user ID (0 for guests).
198 */
199 $access = apply_filters(
200 'qdb_user_can_access',
201 array(
202 'allowed' => $this->a['validate'],
203 'message' => $this->validate_msg,
204 ),
205 $this->a,
206 get_current_user_id()
207 );
208 $this->a['validate'] = $access['allowed'];
209 $this->validate_msg = $access['message'];
210
211 ob_start();
212 ?>
213 <div className="qdbn-wrapper">
214 <div class="qdbn"
215 data-plugin-name="qdbn"
216 data-style="<?php echo esc_attr( $this->button_type ); ?>"
217 data-file="<?php echo esc_attr( $hide_file ) ;?>"
218 data-size="<?php echo esc_attr( $hide_size ) ; ?>"
219 data-icon-position="<?php echo esc_attr( $this->icon_position ); ?>"
220 <?php
221 echo wp_kses( $l1_style, array(
222 'style' => array(
223 'padding' => array(),
224 'text-align' => array(),
225 'margin' => array()
226 )
227 ) ); ?>
228 >
229 <div class="qdbn-download-button-inner"<?php
230 $new_styles = array( 'pill', 'card', 'ghost' );
231 if ( in_array( $this->button_type, $new_styles, true ) && ( null !== $this->border_width || null !== $this->border_style || null !== $this->border_color ) ) {
232 $c_width = null !== $this->border_width ? esc_attr( $this->border_width ) : '0';
233 $c_style = null !== $this->border_style ? esc_attr( $this->border_style ) : 'solid';
234 $c_color = null !== $this->border_color ? esc_attr( $this->border_color ) : 'transparent';
235 echo ' style="border:' . $c_width . 'px ' . $c_style . ' ' . $c_color . ';"';
236 }
237 ?>>
238 <button class="g-btn f-l" type="button" title="<?php echo esc_attr( $this->a['title'] ); ?>"
239 <?php if( $this->a['wait'] > 0 ) : ?>
240 data-spinner="<?php echo absint( $this->a['wait'] ); ?>"
241 <?php endif; ?>
242 <?php if ( '' !== $this->msg ) : ?>
243 data-msg="<?php echo esc_attr( $this->msg ); ?>";
244 <?php endif; ?>
245 <?php if ('' !== $this->a['user_must_be'] && $this->a['validate']) : ?>
246 data-validate="1"
247 <?php endif; ?>
248 <?php if ('' !== $this->a['user_must_be'] && !$this->a['validate']) : ?>
249 data-validate="0"
250 data-validate-msg="<?php echo esc_attr($this->validate_msg ); ?>"
251 <?php endif; ?>
252 data-has-icon-dark="<?php echo esc_attr( $this->color_icon_dark ); ?>"
253 <?php if ( $this->popup_content ) : ?>data-qdb-popup="1"<?php endif; ?>
254 <?php if ( $this->popup_content && '0' === $this->popup_closable ) : ?>data-qdb-popup-closable="0"<?php endif; ?>
255 data-qdb-btn-id="<?php echo esc_attr( $this->a['btn_id'] ); ?>"
256 <?php
257 if ( empty( $this->a['url_external'] ) && strpos( $this->a['url'], site_url()) !== false) :
258 ?>
259 data-attachment-id="<?php echo esc_attr( $this->add_ids( $this->attachment_id, $this->download_pid ) ); ?>" data-page-id="<?php echo intval( $this->download_pid ); ?>" data-post-id="<?php echo intval( $this->pid ); ?>"
260 <?php
261 else :
262 ?>
263 data-external-url="<?php echo esc_url( $this->a['url_external'] ); ?>"
264 <?php endif; ?>
265 data-target-blank="<?php echo esc_attr($this->a['open_new_window']);?>"
266 <?php
267 /**
268 * Filter: qdb_button_data_atts
269 *
270 * Add extra data-* attributes to the download button element.
271 * Used by Pro: email gate injects data-email-gate="1",
272 * WooCommerce gate injects data-product-id="X", etc.
273 * Return an associative array of attribute name => value.
274 *
275 * @param array $extra_atts Key/value pairs for data attributes.
276 * @param array $atts Shortcode attributes.
277 */
278 $extra_data_atts = apply_filters( 'qdb_button_data_atts', array(), $this->a );
279 foreach ( $extra_data_atts as $attr_name => $attr_value ) {
280 echo ' ' . esc_attr( $attr_name ) . '="' . esc_attr( $attr_value ) . '"';
281 }
282 ?>
283 <?php
284 $button_styles = 'style="';
285 if ( null !== $this->color_gb && in_array( $this->button_type, array( 'small', 'mid', 'basic', 'pill', 'card', 'ghost' ), true ) ) {
286 $button_styles .= 'background: ' .esc_attr( $this->color_gb ). ';';
287 }
288 if (null !== $this->color_font) {
289 $button_styles .= 'color: ' .esc_attr( $this->color_font ). ';';
290 }
291 if(null !== $this->border_radius) {
292 $button_styles .= 'border-radius: ' .esc_attr( $this->border_radius ). 'px;';
293 }
294
295 // Border on the button only for legacy styles; new styles (pill/card/ghost) get it on the container.
296 if ( ! in_array( $this->button_type, array( 'pill', 'card', 'ghost' ), true ) && ( null !== $this->border_width || null !== $this->border_style || null !== $this->border_color ) ) {
297 $width = null !== $this->border_width ? esc_attr( $this->border_width ) : '0';
298 $b_style = null !== $this->border_style ? esc_attr( $this->border_style) : 'solid';
299 $color = null !== $this->border_color ? esc_attr( $this->border_color) : 'transparent';
300 $button_styles .= 'border: '.$width.'px '.$b_style. ' '.$color;
301 }
302
303 $button_styles .= '"';
304 echo wp_kses( $button_styles, array(
305 'background' => array(
306 'color' => array()
307 ),
308 'color' => array(),
309 'border' => array()
310 ) );
311 ?>
312 >
313 <span class="download-btn-icon"><?php
314 if ( 'default' === $this->icon_id ) {
315 qdb_sanitize_svg( $this->icon );
316 } else {
317 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
318 echo qdb_get_builtin_icon( $this->icon_id );
319 }
320 ?></span>
321 <span><?php echo esc_attr( $this->a['title'] ); ?></span>
322 </button>
323
324 <?php
325 $p_styles = 'style="';
326 if ( 'large' === $this->button_type && null !== $this->color_gb || 'mid' === $this->button_type && null !== $this->color_gb ) {
327 $p_styles .= 'background: ' .esc_attr( $this->color_gb ). ';';
328 } elseif ( in_array( $this->button_type, array( 'pill', 'card', 'ghost' ), true ) && null !== $this->panel_color ) {
329 $p_styles .= 'background: ' . esc_attr( $this->panel_color ) . ';';
330 }
331 $p_styles .= '"';
332
333 ?>
334 <?php if ( '0' !== $this->a['extension'] ) : ?>
335 <p class="up" <?php echo $p_styles; ?>>
336 <?php if ( $this->custom_file_type_icon ) : ?>
337 <?php echo wp_kses( $this->custom_file_type_icon, array( 'svg' => array( 'xmlns' => true, 'viewbox' => true, 'width' => true, 'height' => true, 'aria-hidden' => true ), 'path' => array( 'd' => true, 'fill' => true ), 'g' => array( 'fill' => true ) ) ); ?>
338 <?php else : ?>
339 <i class="<?php echo esc_attr( $this->qdbu_extension( 'icon' ) ); ?>"></i>
340 <?php endif; ?>
341 <?php
342 if ( '1' === $this->a['extension_text'] ) {
343 echo '<span>' . esc_html( $this->qdbu_extension( 'ext' ) ) . '</span>';
344 }
345 ?>
346 </p>
347 <?php endif; ?>
348
349 <?php
350 $have_site_url = strpos( $this->a['url'], site_url() ) === false ? false: true;
351
352 if ( '1' === $this->a['file_size'] && $have_site_url ) :
353 $file_url = filesize( $this->qdb_convert_url_to_path( $this->a['url'] ) );
354 $file_size = $this->qdb_format_size_units( $file_url );
355 if ( '0 bytes' !== $file_size ) {
356 $file_blob_size = $this->qdb_format_size_units( $file_url );
357 $blob_number = explode( ' ', $file_blob_size );
358 $blob_number = $blob_number[0];
359
360 $blob_measure = explode( ' ', $file_blob_size );
361 $blob_measure = $blob_measure[1];
362 }
363 /* translators: %1$s is a filesize %2$s is the measurement */
364 $size_icon_html = $this->custom_file_size_icon ? wp_kses( $this->custom_file_size_icon, array( 'svg' => array( 'xmlns' => true, 'viewbox' => true, 'width' => true, 'height' => true, 'aria-hidden' => true ), 'path' => array( 'd' => true, 'fill' => true ), 'g' => array( 'fill' => true ) ) ) : qdb_get_builtin_icon( $this->file_size_icon_id );
365 printf( '<p class="down" %3$s>%4$s<span class="file-size">%1$s %2$s</span></p>', esc_attr( $blob_number ), esc_attr( $blob_measure ), $p_styles, $size_icon_html );
366
367 elseif ( '' !== $this->a['file_size'] ) :
368 /* translators: %1$s is a filesize */
369 $size_icon_html = $this->custom_file_size_icon ? wp_kses( $this->custom_file_size_icon, array( 'svg' => array( 'xmlns' => true, 'viewbox' => true, 'width' => true, 'height' => true, 'aria-hidden' => true ), 'path' => array( 'd' => true, 'fill' => true ), 'g' => array( 'fill' => true ) ) ) : qdb_get_builtin_icon( $this->file_size_icon_id );
370 printf( '<p class="down" %2$s>%3$s<span class="file-size"> %1$s </span></p>', esc_attr( $this->a['file_size'] ), $p_styles, $size_icon_html );
371
372 //else :
373 ?>
374
375 <?php endif; ?>
376
377 </div>
378 </div>
379 <quick-download-button-info class="qdb-btn-info"></quick-download-button-info>
380 <?php if ( $this->popup_content ) : ?>
381 <div class="qdb-popup-src" hidden><?php echo $this->popup_content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted: processed by do_shortcode, output by editor ?></div>
382 <?php endif; ?>
383 <?php
384 /**
385 * Action: qdb_gate_html
386 *
387 * Output additional HTML inside the button wrapper (after the button, before closing div).
388 * Used by Pro: inject email gate form, passcode input, etc.
389 *
390 * @param array $atts Shortcode attributes.
391 */
392 do_action( 'qdb_gate_html', $this->a );
393 ?>
394 </div>
395 <?php
396 /**
397 * Filter: qdb_shortcode_output
398 *
399 * Modify the final button HTML before it is returned to the page.
400 * Used by Pro: wrap with email capture form, modal overlay, etc.
401 *
402 * @param string $output The complete button HTML.
403 * @param array $atts Shortcode attributes.
404 */
405 return apply_filters( 'qdb_shortcode_output', ob_get_clean(), $this->a );
406 }
407
408 /**
409 * @usage Add file extension text, add icon
410 * @param mixed $value
411 * @return void
412 */
413 public function qdbu_extension( $value = '' ) {
414 $ex = array(
415 'ext' => '',
416 'icon' => '',
417 );
418
419 $extension_array = array( 'pdf', 'mp3', 'mov', 'zip', 'txt', 'doc', 'xml', 'mp4', 'ppt' );
420
421 $extension_path = explode( '.', $this->a['url'] );
422
423 $ex['ext'] = end( $extension_path );
424 $ex['ext'] = $ex['ext'];
425
426 if ( in_array( strtolower( $ex['ext'] ), $extension_array ) ) {
427 $ex['icon'] = 'fi fi-' . strtolower( $ex['ext'] );
428 } else {
429
430 $image_array = array( 'jpg', 'jpeg', 'tiff', 'png', 'bmp', 'gif' );
431 if ( in_array( strtolower( $ex['ext'] ), $image_array ) ) {
432 $ex['icon'] = 'fi fi-image';
433 } else {
434 $ex['icon'] = 'fi fi-file';
435 }
436 }
437
438 if ( 'icon' === $value ) {
439 $value = $ex['icon'];
440 }
441 if ( 'ext' === $value ) {
442 $value = $ex['ext'];
443 }
444
445 return $value;
446 }
447
448
449
450 /**
451 * @usage Convert URL to path
452 * @param mixed $url
453 * @return string
454 */
455 public function qdb_convert_url_to_path( $url ) {
456 return str_replace(
457 wp_get_upload_dir()['baseurl'],
458 wp_get_upload_dir()['basedir'],
459 $url
460 );
461 }
462
463
464
465 /**
466 * @usage Get file size
467 *
468 * @param mixed $bytes
469 * @return string
470 */
471 public function qdb_format_size_units( $bytes ) {
472 if ( $bytes >= 1073741824 ) {
473 $bytes = number_format( $bytes / 1073741824, 2 ) . ' GB';
474 } elseif ( $bytes >= 1048576 ) {
475 $bytes = number_format( $bytes / 1048576, 2 ) . ' MB';
476 } elseif ( $bytes >= 1024 ) {
477 $bytes = number_format( $bytes / 1024, 2 ) . ' KB';
478 } elseif ( $bytes > 1 ) {
479 $bytes = $bytes . ' bytes';
480 } elseif ( 1 === $bytes ) {
481 $bytes = $bytes . ' byte';
482 } else {
483 $bytes = '0 bytes';
484 }
485
486 return $bytes;
487 }
488
489
490 /**
491 * @usage add attachment ID + download page id, use this to disguise real attachment ID when view from browser inspect
492 * @param mixed $num1
493 * @param mixed $num2
494 * @return int
495 */
496 public static function add_ids( $num1, $num2 ) {
497 return intval( $num1 + $num2 );
498 }
499 }
500
501 /**
502 * Return an inline SVG string for a built-in icon ID.
503 * Used by the shortcode to match the Gutenberg block's icon set.
504 *
505 * @param string $id Icon ID (matches QDB_DOWNLOAD_ICONS / QDB_SIZE_ICONS in JS).
506 * @param int $size Icon size in px.
507 * @return string SVG HTML string, already escaped for output.
508 */
509 function qdb_get_builtin_icon( $id, $size = 20 ) {
510 $paths = array(
511 'default' => 'M18 11.3l-1-1.1-4 4V3h-1.5v11.3L7 10.2l-1 1.1 6.2 5.8 5.8-5.8zm.5 3.7v3.5h-13V15H4v5h16v-5h-1.5z',
512 'cloud' => 'M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z',
513 'circle' => 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 5h2v6h3l-4 4-4-4h3V7z',
514 'file-dl' => 'M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z',
515 'inbox' => 'M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5v-3h3.56c.69 1.19 1.97 2 3.45 2s2.75-.81 3.45-2H19v3zm0-5h-4.99c0 1.1-.9 1.99-2 1.99S10 15.1 10 14H5V5h14v9z',
516 'save' => 'M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z',
517 'bolt' => 'M7 2v11h3v9l7-12h-4l4-8z',
518 'folder' => 'M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z',
519 'archive' => 'M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z',
520 'info' => 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z',
521 'chip' => 'M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z',
522 );
523 $id = isset( $paths[ $id ] ) ? $id : 'default';
524 return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="' . absint( $size ) . '" height="' . absint( $size ) . '" aria-hidden="true"><path fill="currentColor" d="' . esc_attr( $paths[ $id ] ) . '"/></svg>';
525 }
526
527 /**
528 * Sanitize SVG
529 */
530
531 function qdb_sanitize_svg( $svg ) {
532 $kses_defaults = wp_kses_allowed_html( 'post' );
533
534 $svg_args = array(
535 'svg' => array(
536 'class' => true,
537 'aria-hidden' => true,
538 'aria-labelledby' => true,
539 'role' => true,
540 'xmlns' => true,
541 'width' => true,
542 'height' => true,
543 'viewbox' => true // <= Must be lower case!
544 ),
545 'g' => array( 'fill' => true ),
546 'title' => array( 'title' => true ),
547 'path' => array(
548 'd' => true,
549 'fill' => true
550 )
551 );
552
553 $allowed_tags = array_merge( $kses_defaults, $svg_args );
554
555 echo wp_kses( $svg, $allowed_tags );
556 }
557
558
559
560 /**
561 * Get the current user's role.
562 * @return array
563 */
564
565 function qdbn_get_current_user_roles() {
566
567 if( is_user_logged_in() ) {
568
569 $user = wp_get_current_user();
570
571 $roles = ( array ) $user->roles;
572
573 return $roles; // This will returns an array
574
575 } else {
576
577 return array();
578
579 }
580
581 }
582
583
584 function qdbn_get_user_rolls() {
585 $data = ['Nothing','Logged in'];
586 $roles = wp_roles()->get_names();
587
588 foreach( $roles as $role ) {
589 array_push($data, strtolower( translate_user_role( $role ) ));
590 }
591 return $data;
592 }
593
594
595 /**
596 * Shortcode: [quick_download_button_group]
597 *
598 * Wraps multiple [quick_download_button] shortcodes in a flex row.
599 *
600 * Attributes:
601 * layout - 'horizontal' (default) or 'stack'
602 * stack_on_mobile - 'true' (default) or 'false'
603 * alignment - 'left' (default), 'center', or 'right'
604 * gap - gap between buttons in px (default: 12)
605 *
606 * Example:
607 * [quick_download_button_group alignment="center" gap="16"]
608 * [quick_download_button url="..." title="Download v1"]
609 * [quick_download_button url="..." title="Download v2"]
610 * [/quick_download_button_group]
611 */
612 function qdbu_button_group_shortcode( $atts, $content = null ) {
613 $atts = shortcode_atts(
614 array(
615 'layout' => 'horizontal',
616 'stack_on_mobile' => 'true',
617 'alignment' => 'left',
618 'gap' => '12',
619 ),
620 $atts
621 );
622
623 $allowed_layouts = array( 'horizontal', 'stack' );
624 $allowed_alignment = array( 'left', 'center', 'right' );
625 $align_map = array( 'left' => 'flex-start', 'center' => 'center', 'right' => 'flex-end' );
626
627 $layout = in_array( $atts['layout'], $allowed_layouts, true ) ? $atts['layout'] : 'horizontal';
628 $alignment = in_array( $atts['alignment'], $allowed_alignment, true ) ? $atts['alignment'] : 'left';
629 $gap = absint( $atts['gap'] );
630
631 $classes = 'qdb-btn-row qdb-btn-row--' . $layout;
632 if ( 'true' === $atts['stack_on_mobile'] ) {
633 $classes .= ' qdb-btn-row--mobile-stack';
634 }
635 $classes .= ' qdb-btn-row--align-' . $alignment;
636
637 if ( 'stack' === $layout ) {
638 $style = 'gap:' . $gap . 'px;align-items:' . $align_map[ $alignment ] . ';';
639 } else {
640 $style = 'gap:' . $gap . 'px;justify-content:' . $align_map[ $alignment ] . ';align-items:flex-start;';
641 }
642
643 return '<div class="' . esc_attr( $classes ) . '" style="' . esc_attr( $style ) . '">'
644 . do_shortcode( $content )
645 . '</div>';
646 }
647 add_shortcode( 'quick_download_button_group', 'qdbu_button_group_shortcode' );
648
649
650
651
652
653
654
655
656