PluginProbe
Snippet Shortcodes / 5.0.1
Snippet Shortcodes v5.0.1
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 5.0.1, at includes/functions.php

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