PluginProbe
Snippet Shortcodes / 4.2.3
Snippet Shortcodes v4.2.3
5.2.1 5.2 5.1.8 5.1.6 5.1.7 5.1.5 trunk 1.0 1.1 1.2 1.3 1.3.1 1.4 1.5 1.5.1 1.6 1.6.1 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.8 2.0 2.0.1 All 74 releases
shortcode-variables / includes / functions.php

functions.php in Snippet Shortcodes 4.2.3, at includes/functions.php

735 lines 16.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 defined('ABSPATH') or die('Jog on!');
4
5 /**
6 * Save / Insert a shortcode
7 *
8 * @return bool
9 */
10 function sh_cd_shortcodes_save_post() {
11
12 // Capture the raw $_POST fields, the save functions will process and validate the data
13 $shortcode = sh_cd_get_values_from_post( [ 'id', 'slug', 'previous_slug', 'data', 'disabled', 'multisite' ] );
14
15 // If we are not premium, then the user is not allowed to change the site slug (otherwise they could just re-use variables and by pass the limit)
16 if ( ! SH_CD_IS_PREMIUM && false === empty( $shortcode[ 'previous_slug' ] ) ) {
17 $shortcode[ 'slug' ] = $shortcode[ 'previous_slug' ];
18 }
19
20 return sh_cd_db_shortcodes_save( $shortcode );
21 }
22
23 /**
24 * Replace user parameters within a shortcode e.g. look for %%parameter%% and replace
25 *
26 * @param $shortcode
27 * @param $user_defined_parameters
28 *
29 * @return mixed
30 */
31 function sh_cd_apply_user_defined_parameters( $shortcode, $user_defined_parameters ){
32
33 // Ensure we have something to do!
34 if ( true === empty( $user_defined_parameters ) || false === is_array( $user_defined_parameters ) ) {
35 return $shortcode;
36 }
37
38 foreach ( $user_defined_parameters as $key => $value ) {
39 $shortcode = str_replace( '%%' . $key . '%%', $value, $shortcode );
40 }
41
42 return $shortcode;
43 }
44
45 /**
46 * Generate a unique slug
47 *
48 * @param $slug
49 *
50 * @return string
51 */
52 function sh_cd_slug_generate( $slug, $exising_id = NULL ) {
53
54 if ( true === empty( $slug ) ) {
55 return NULL;
56 }
57
58 $slug = sanitize_title( $slug );
59
60 $original_slug = $slug;
61
62 $try = 1;
63
64 // Ensure the slug is unique
65 while ( false === sh_cd_slug_is_unique( $slug, $exising_id ) ) {
66
67 $slug = sprintf( '%s_%d', $original_slug, $try );
68
69 $try++;
70 }
71
72 return $slug;
73 }
74
75 /**
76 * Clone an existing shortcode!
77 *
78 * @param $id
79 *
80 * @return bool
81 */
82 function sh_cd_clone( $id ) {
83
84 if( false === SH_CD_IS_PREMIUM ) {
85 return true;
86 }
87
88 if ( false === is_numeric( $id ) ) {
89 return false;
90 }
91
92 $to_be_cloned = sh_cd_db_shortcodes_by_id( $id );
93
94 if ( true === empty( $to_be_cloned ) ) {
95 return false;
96 }
97
98 unset( $to_be_cloned['id'] );
99
100 return sh_cd_db_shortcodes_save( $to_be_cloned );
101 }
102
103 /**
104 * Display message in admin UI
105 *
106 * @param $text
107 * @param bool $error
108 */
109 function sh_cd_message_display( $text, $error = false ) {
110
111 if ( true === empty( $text ) ) {
112 return;
113 }
114
115 printf( '<div class="%s"><p>%s</p></div>',
116 true === $error ? 'error' : 'updated',
117 esc_html( $text )
118 );
119
120 //TODO: Hook this to use admin_notices
121 }
122
123 /**
124 * Fetch cache item
125 *
126 * @param $key
127 *
128 * @return mixed
129 */
130 function sh_cd_cache_get( $key ) {
131
132 $key = sh_cd_cache_generate_key( $key );
133
134 return get_transient( $key );
135 }
136
137 /**
138 * Set cache item
139 *
140 * @param $key
141 * @param $data
142 */
143 function sh_cd_cache_set( $key, $data, $expire = NULL ) {
144
145
146 $expire = ( false === empty( $expire ) ) ? (int) $expire : 1 * HOUR_IN_SECONDS;
147
148 $key = sh_cd_cache_generate_key( $key );
149
150 set_transient( $key, $data, $expire );
151 }
152
153 /**
154 * Delete cache for given shortcode slug / ID
155 *
156 * @param $slug_or_key
157 */
158 function sh_cd_cache_delete_by_slug_or_key( $slug_or_key ) {
159
160 if ( true === is_numeric( $slug_or_key ) ) {
161
162 $slug_or_key = sh_cd_db_shortcodes_get_slug_by_id( $slug_or_key );
163
164 sh_cd_cache_delete( $slug_or_key );
165
166 } else {
167 sh_cd_cache_delete( $slug_or_key );
168 }
169
170 // Delete site option
171 $slug_or_key = SH_CD_PREFIX . $slug_or_key;
172
173 delete_site_option( $slug_or_key );
174
175 }
176
177 /**
178 * Delete cache item
179 *
180 * @param $key
181 *
182 * @return mixed
183 */
184 function sh_cd_cache_delete( $key ) {
185
186 $key = sh_cd_cache_generate_key( $key );
187
188 return delete_transient( $key );
189 }
190
191 /**
192 * Generate cache key
193 *
194 * @param $key
195 *
196 * @return string
197 */
198 function sh_cd_cache_generate_key( $key ) {
199 return SH_CD_SHORTCODE . SH_CD_PLUGIN_VERSION . $key;
200 }
201
202 /**
203 * Return link to list own shortcodes
204 *
205 * @return mixed
206 */
207 function sh_cd_link_your_shortcodes() {
208
209 $link = admin_url('admin.php?page=sh-cd-shortcode-variables-your-shortcodes');
210
211 return esc_url( $link );
212 }
213
214 /**
215 * Return link to add own shortcode
216 *
217 * @return mixed
218 */
219 function sh_cd_link_your_shortcodes_add() {
220
221 $link = admin_url('admin.php?page=sh-cd-shortcode-variables-your-shortcodes&action=add');
222
223 return esc_url( $link );
224 }
225
226 /**
227 * Return link to edit own shortcode
228 *
229 * @return mixed
230 */
231 function sh_cd_link_your_shortcodes_edit( $id ) {
232
233 $link = admin_url('admin.php?page=sh-cd-shortcode-variables-your-shortcodes&action=edit&id=' . (int) $id );
234
235 return esc_url( $link );
236 }
237
238 /**
239 * Return link to delete own shortcode
240 *
241 * @param $id
242 * @return mixed
243 */
244 function sh_cd_link_your_shortcodes_delete( $id ) {
245
246 $link = admin_url('admin.php?page=sh-cd-shortcode-variables-your-shortcodes&action=delete&id=' . (int) $id );
247
248 return esc_url( $link );
249 }
250
251 /**
252 * Either fetch data from the $_POST object or from the array passed in!
253 *
254 * @param $object
255 * @param $key
256 * @return string
257 */
258 function sh_cd_get_value_from_post_or_obj( $object, $key ) {
259
260 if ( true === isset( $_POST[ $key ] ) ) {
261 return $_POST[ $key ];
262 }
263
264 if ( true === isset( $object[ $key ] ) ) {
265 return $object[ $key ];
266 }
267
268 return '';
269 }
270
271 /**
272 * Either fetch data from the $_POST object for the given object keys
273 *
274 * @param $keys
275 * @return array
276 */
277 function sh_cd_get_values_from_post( $keys ) {
278
279 $data = [];
280
281 foreach ( $keys as $key ) {
282
283 if ( true === isset( $_POST[ $key ] ) ) {
284 $data[ $key ] = $_POST[ $key ];
285 } else {
286 $data[ $key ] = '';
287 }
288
289 }
290
291 return $data;
292 }
293
294 /**
295 * Toggle the status of a shortcode
296 *
297 * @param $id
298 */
299 function sh_cd_toggle_status( $id ) {
300
301 $slug = sh_cd_db_shortcodes_by_id( (int) $id );
302
303 if ( false === empty( $slug ) ) {
304
305 $status = ( 1 === (int) $slug['disabled'] ) ? 0 : 1 ;
306
307 sh_cd_db_shortcodes_update_status( $id, $status );
308
309 return $status;
310 }
311
312 return NULL;
313 }
314
315 /**
316 * Toggle the multisite of a shortcode
317 *
318 * @param $id
319 * @return int|null
320 */
321 function sh_cd_toggle_multisite( $id ) {
322
323 $slug = sh_cd_db_shortcodes_by_id( (int) $id );
324
325 if ( false === empty( $slug ) ) {
326
327 $multisite = ( 1 === (int) $slug['multisite'] ) ? 0 : 1 ;
328
329 sh_cd_db_shortcodes_update_multisite( $id, $multisite );
330
331 return $multisite;
332 }
333
334 return NULL;
335 }
336
337
338 /**
339 * Display a table of premade shortcodes
340 *
341 * @param string $display
342 * @return string
343 */
344 function sh_cd_display_premade_shortcodes( $display = 'all' ) {
345
346 $premium_user = SH_CD_IS_PREMIUM;
347 $upgrade_link = sprintf( '<a class="button" href="%1$s"><i class="fas fa-check"></i> %2$s</a>', sh_cd_license_upgrade_link(), __('Upgrade now', SH_CD_SLUG ) );
348
349 switch ( $display ) {
350 case 'free':
351 $shortcodes = sh_cd_shortcode_presets_free_list();
352 $show_premium_col = false;
353 break;
354 case 'premium':
355 $shortcodes = sh_cd_shortcode_presets_premium_list();
356 $show_premium_col = false;
357 break;
358 default:
359 $shortcodes = sh_cd_presets_both_lists();
360 $show_premium_col = true;
361 }
362
363 $html = sprintf('<table class="widefat sh-cd-table" width="100%%">
364 <tr class="row-title">
365 <th class="row-title" width="30%%">%s</th>', __('Shortcode', SH_CD_SLUG ) );
366
367 if ( true === $show_premium_col) {
368 $html .= sprintf( '<th class="row-title">%s</th>', __('Premium', SH_CD_SLUG ) );
369 }
370
371 $html .= sprintf( '<th width="*">%s</th>
372 </tr>', __('Description', SH_CD_SLUG ) );
373
374 $class = '';
375
376 foreach ( $shortcodes as $key => $data ) {
377
378 $class = ($class == 'alternate') ? '' : 'alternate';
379
380 $shortcode = '[' . SH_CD_SHORTCODE. ' slug="' . $key . '"]';
381
382 $premium_shortcode = ( true === isset( $data['premium'] ) && true === $data['premium'] );
383
384 $html .= sprintf( '<tr class="%s"><td>%s</td>', $class, esc_html( $shortcode ) );
385
386
387 if ( true === $show_premium_col) {
388
389 $html .= sprintf( '<td align="middle">%s%s</td>',
390 ( true === $premium_shortcode && true === $premium_user ) ? '<i class="fas fa-check"></i>' : '',
391 ( true == $premium_shortcode && false === $premium_user ) ? $upgrade_link : ''
392 );
393 }
394
395 $html .= sprintf( '<td>%s</td></tr>', wp_kses_post( $data['description'] ) );
396
397 }
398
399 $html .= '</table>';
400
401 return $html;
402 }
403
404 /**
405 * Display an upgrade button
406 *
407 * @param string $css_class
408 * @param null $link
409 */
410 function sh_cd_upgrade_button( $css_class = '', $link = NULL ) {
411
412 $link = ( false === empty( $link ) ) ? $link : SH_CD_UPGRADE_LINK . '?hash=' . sh_cd_generate_site_hash() ;
413
414 echo sprintf('<a href="%s" class="button-primary sh-cd-upgrade-button%s"><i class="far fa-credit-card"></i> %s £%s %s</a>',
415 esc_url( $link ),
416 esc_attr( ' ' . $css_class ),
417 __( 'Upgrade to Premium for ', SH_CD_SLUG ),
418 esc_html( sh_cd_license_price() ),
419 __( 'a year ', SH_CD_SLUG )
420 );
421 }
422
423 /**
424 * Is multsite functionality active for this install?
425 *
426 * @return bool
427 */
428 function sh_cd_is_multisite_enabled() {
429
430 if ( false === is_multisite() ) {
431 return false;
432 }
433
434 if ( false === SH_CD_IS_PREMIUM ) {
435 return false;
436 }
437
438 return true;
439 }
440
441 /**
442 * Fetch all multisite slugs
443 *
444 * @return array|null
445 */
446 function sh_cd_multisite_slugs() {
447
448 if ( false === is_multisite() ) {
449 return [];
450 }
451
452 $cache = sh_cd_cache_get( 'sh-cd-multisite-slugs' );
453
454 if ( false !== $cache ) {
455 return $cache;
456 }
457
458 $slugs = sh_cd_db_shortcodes_multisite_slugs();
459
460 $slugs = ( false === empty( $slugs ) ) ? wp_list_pluck( $slugs, 'slug' ) : [];
461
462 // Cache this for a short time
463 sh_cd_cache_set( 'sh-cd-multisite-slugs', $slugs, 30 );
464
465 return ( true === is_array( $slugs ) ) ? $slugs : [];
466 }
467
468 /**
469 * Have we reached the limit of free shortcodes?
470 * @return bool
471 */
472 function sh_cd_reached_free_limit() {
473
474 if ( true === SH_CD_IS_PREMIUM ) {
475 return false;
476 }
477
478 $existing_shortcodes = sh_cd_db_shortcodes_count();
479
480 if ( true === empty( $existing_shortcodes ) ) {
481 return false;
482 }
483
484 return ( (int) $existing_shortcodes >= SH_CD_FREE_SHORTCODE_LIMIT );
485 }
486
487 /**
488 * Get the minimum user role allowed for viewing data pages in admin
489 * @return mixed|void
490 */
491 function sh_cd_permission_role() {
492
493 // If not premium, then admin only
494 if ( false === SH_CD_IS_PREMIUM ) {
495 return 'manage_options';
496 }
497
498 $permission_role = get_option( 'sh-cd-edit-permissions', 'manage_options' );
499
500 return ( false === empty( $permission_role ) ) ? $permission_role : 'manage_options';
501 }
502
503 /**
504 * Does the user have the correct permissions to view this page?
505 */
506 function sh_cd_permission_check() {
507
508 $allowed_viewer = sh_cd_permission_role();
509
510 if ( false === current_user_can( $allowed_viewer ) ) {
511 wp_die( __( 'You do not have sufficient permissions to access this page.', SH_CD_SLUG ) );
512 }
513 }
514
515 /**
516 * Is the shortcode [sv slug="sc-db-value-by-id"] enabled
517 * @return bool (default false)
518 */
519 function sh_cd_is_shortcode_db_value_by_id_enabled() {
520
521 if ( false === SH_CD_IS_PREMIUM ) {
522 return false;
523 }
524
525 // Disabling by filter overrides the setting in WP admin
526 if ( true === apply_filters( 'disable-ss-sc-db-value-by-id', __return_false() ) ) {
527 return false;
528 }
529
530 $value = get_option( 'sh-cd-shortcode-db-value-by-id-enabled', false );
531
532 return sh_cd_to_bool( $value );
533 }
534
535 /**
536 * Display upgrade notice
537 *
538 * @param bool $pro_plus
539 */
540 function sh_cd_display_pro_upgrade_notice( ) {
541 ?>
542
543 <div class="postbox sh-cd-advertise-premium">
544 <h3 class="hndle"><span><?php echo __( 'Upgrade Snippet Shortcodes and get more features!', SH_CD_SLUG ); ?> </span></h3>
545 <div style="padding: 0px 15px 0px 15px">
546 <p><a href="<?php echo esc_url( admin_url('admin.php?page=sh-cd-shortcode-variables-license') ); ?>" class="button-primary"><?php echo __( 'Upgrade now', SH_CD_SLUG ); ?></a></p>
547 </div>
548 </div>
549
550 <?php
551 }
552
553
554 /**
555 * Process a CSV attachment and import into database
556 *
557 * @param $attachment_id
558 *
559 * @param bool $dry_run
560 *
561 * @return string
562 */
563 function sh_cd_import_csv( $attachment_id, $dry_run = true ) {
564
565 if ( false === sh_cd_permission_check() ) {
566 return 'You do not have the correct admin permissions';
567 }
568
569 if ( false === SH_CD_IS_PREMIUM ) {
570 return 'This is a premium feature';
571 }
572
573 $csv_path = get_attached_file( $attachment_id );
574 $admin_id = get_current_user_id();
575
576 if ( true === empty( $csv_path ) || false === file_exists( $csv_path )) {
577 return 'Error: Error loading CSV from disk.';
578 }
579
580 $csv = array_map('str_getcsv', file( $csv_path ) );
581
582 if ( true === empty( $csv ) ) {
583 return 'Error: The CSV appears to be empty.';
584 }
585
586 array_walk($csv, function(&$a) use ($csv) {
587 $a = array_combine($csv[0], $a);
588 });
589
590 $validate_header_result = sh_cd_import_csv_validate_header( $csv[0] );
591
592 if ( true !== $validate_header_result ) {
593 return $validate_header_result;
594 }
595
596 array_shift($csv );
597
598 if ( true === empty( $csv ) ) {
599 return 'Error: The CSV appears to be empty (when header hs been removed).';
600 }
601
602 $errors = 0;
603
604 $output = sprintf( '%d rows to process...' . PHP_EOL, count( $csv ) );
605
606 if ( true === $dry_run ) {
607 $output .= 'DRY RUN MODE! No data will be imported.' . PHP_EOL;
608 }
609
610 foreach ( $csv as $row ) {
611
612 if ( $errors >= 50 ) {
613 $output .= 'Aborted! More than 50 errors have been detected in this file.' . PHP_EOL;
614 break;
615 }
616
617 $row = array_change_key_case( $row ); // Force CSV headers to lowercase
618
619 $validation_result = sh_cd_import_csv_validate_row( $row );
620
621 // Validate a row before proceeding
622 if ( true !== $validation_result ) {
623 $output .= $validation_result . PHP_EOL;
624 $errors++;
625 continue;
626 }
627
628 if ( false === $dry_run ) {
629
630 $shortcode = [ 'slug' => $row[ 'slug' ],
631 'previous_slug' => '',
632 'data' => $row[ 'content' ],
633 'disabled' => ! sh_cd_to_bool( $row[ 'enabled' ] ),
634 'multisite' => sh_cd_to_bool( $row[ 'global' ] )
635 ];
636
637 $result = sh_cd_db_shortcodes_save( $shortcode );
638
639 if ( false === $result ) {
640 $output .= 'Skipped: Error inserting into database (most likely a field contains too many characters or in the wrong format): ' . implode( ',', $row ) . PHP_EOL;
641 }
642 }
643
644 }
645
646 if ( $errors > 0 ) {
647 $output .= sprintf( '%d errors were detected and the rows skipped.' . PHP_EOL, $errors );
648 }
649
650 $output .= 'Completed.';
651
652 return $output;
653
654 }
655
656 /**
657 * Verify header row
658 * @param $header_row
659 *
660 * @return bool|string
661 */
662 function sh_cd_import_csv_validate_header( $header_row ) {
663
664 $expected_headers = [ 'slug', 'content', 'global', 'enabled' ];
665
666 foreach ( $expected_headers as $column ) {
667
668 if ( false === isset( $header_row[ $column ] ) ) {
669 return 'Missing column: ' . $column . '. Expecting: ' . implode( ',', $expected_headers ) . PHP_EOL;
670 }
671 }
672
673 return true;
674 }
675
676 /**
677 * Validate CSV row
678 * @param $csv_row
679 *
680 * @return bool|string
681 */
682 function sh_cd_import_csv_validate_row( $csv_row ) {
683
684 if ( true === empty( $csv_row[ 'slug' ] ) ) {
685 return 'Skipped: Missing slug: ' . implode( ',', $csv_row );
686 }
687
688 if ( false === empty( $isset[ 'content' ] ) ) {
689 return 'Skipped: Content: ' . implode( ',', $csv_row );
690 }
691
692 $allowed_bools = [ 'yes', 'no', 'true', 'false', '1', '0' ];
693
694 if ( true === empty( $csv_row[ 'global' ] ) ||
695 false === in_array( $csv_row[ 'global' ], $allowed_bools ) ) {
696 return 'Skipped: Invalid "global" value. Must be "yes" or "no": ' . implode( ',', $csv_row );
697 }
698
699 if ( true === empty( $csv_row[ 'enabled' ] ) ||
700 false === in_array( $csv_row[ 'enabled' ], $allowed_bools ) ) {
701 return 'Skipped: Invalid "enabled" value. Must be "yes" or "no": ' . implode( ',', $csv_row );
702 }
703
704 return true;
705 }
706
707 /**
708 * Convert string to bool
709 * @param $string
710 * @return mixed
711 */
712 function sh_cd_to_bool( $string ) {
713 return filter_var( $string, FILTER_VALIDATE_BOOLEAN );
714 }
715
716 /**
717 * Our version of kses and the HTML we are happy with
718 */
719 function sh_cd_wp_kses( $value ) {
720
721 $basic_tags = wp_kses_allowed_html( 'html' );
722
723 $basic_tags[ 'a' ] = [ 'id' => true, 'class' => true, 'href' => true, 'title' => true, 'target' => true];
724 $basic_tags[ 'canvas' ] = [ 'id' => true, 'class' => true ];
725 $basic_tags[ 'div' ] = [ 'id' => true, 'class' => true, 'style' => true ];
726 $basic_tags[ 'i' ] = [ 'id' => true, 'class' => true ];
727 $basic_tags[ 'p' ] = [ 'id' => true, 'class' => true ];
728 $basic_tags[ 'span' ] = [ 'id' => true, 'class' => true ];
729 $basic_tags[ 'table' ] = [ 'id' => true, 'class' => true ];
730 $basic_tags[ 'tr' ] = [ 'id' => true, 'class' => true ];
731 $basic_tags[ 'td' ] = [ 'id' => true, 'class' => true ];
732 $basic_tags[ 'li' ] = [ 'class' => true ];
733
734 return wp_kses( $value, $basic_tags );
735 }