PluginProbe
Post Snippets – Custom WordPress Code Snippets Customizer / trunk
Post Snippets – Custom WordPress Code Snippets Customizer vtrunk
4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.1 1.7.2 1.7.3 1.8 1.8.1 1.8.2 1.8.3 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.8.9.1 1.8.9.2 1.9 1.9.1 1.9.2 1.9.3 1.9.4 1.9.5 All 115 releases
post-snippets / src / PostSnippets / Edit.php

Edit.php in Post Snippets – Custom WordPress Code Snippets Customizer trunk, at src/PostSnippets/Edit.php

1,811 lines 66.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace PostSnippets;
3
4 if ( ! defined( 'ABSPATH' ) ) exit;
5
6 /**
7 * Add or Edit Post Snippets.
8 *
9 * Class that renders out the HTML for Edit/Add snippet page.
10 *
11 */
12 class Edit {
13
14 private static $snippet_id = '';
15
16 public static $editSnippetPage = false;
17
18 protected $snippet_data;
19
20
21 function __construct() {
22
23 self::prepare();
24
25 $this->save_data();
26
27 $this->perform_actions_response();
28
29 $this->setup_code_editor();
30
31 $this->edit_snippets_meta_boxes();
32
33 $this->setup_sections();
34
35 $this->editPage();
36
37
38 }
39
40 public static function prepare(){
41
42 if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'edit' && isset($_REQUEST['snippet']) ){
43
44 self::$snippet_id = intval($_REQUEST['snippet']);
45
46 check_admin_referer( 'ps-snippets-hover-trigger_'.self::$snippet_id );
47
48 global $wpdb;
49
50 if( !$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM ".$wpdb->prefix.\PostSnippets::TABLE_NAME." WHERE ID = %d", self::$snippet_id) ) ){
51
52 self::$snippet_id = '';
53
54 wp_safe_redirect( admin_url('admin.php?page=post-snippets' ) );
55
56 }
57
58 if( !empty(self::$snippet_id) ){
59 self::$editSnippetPage = true;
60 }
61
62 }
63 }
64
65 public static function change_edit_snippet_page_title($admin_title, $title){
66
67
68 self::prepare();
69
70 if(self::$editSnippetPage){
71 $admin_title = str_replace( __("Add New", "post-snippets"), __("Edit Snippet", "post-snippets"), $admin_title);
72 return $admin_title;
73 }
74
75 return $admin_title;
76 }
77
78 function editPage(){
79
80
81 ?>
82 <div class="wrap">
83 <div id="icon-users" class="icon32"></div>
84
85 <?php
86
87 $edit_page = '';
88
89 if( self::$editSnippetPage ){
90 $page = self::get_snippet_page();
91 if( $page == 'post-snippets-edit-js' ){
92 $edit_page = "JS ";
93 }
94 elseif( $page == 'post-snippets-edit-css' ){
95 $edit_page = "CSS ";
96 }
97 ?>
98 <h1 class="wp-heading-inline"><?php echo $edit_page; esc_html_e( 'Edit', 'post-snippets' ); ?> Snippet</h1>
99 <a href="<?php echo esc_url("?page=$page") ?>" class="page-title-action"><?php esc_html_e( 'Add New', 'post-snippets' ); ?></a>
100 <?php
101 }
102 else{
103 ?>
104 <h1 class="wp-heading-inline"><?php echo $edit_page; esc_html_e( 'Add', 'post-snippets' ); ?> Snippet</h1>
105 <?php
106 }
107
108 ?>
109
110 <hr class="wp-header-end">
111 <form id="ps_edit_snippets" method="post">
112 <?php
113
114 wp_nonce_field( 'pspro_edit_snippet', 'pspro_edit_snippet_nonce', false );
115
116 // Pro
117
118 // wp_nonce_field('sync_up', 'sync_up');
119 // wp_nonce_field('sync_down', 'sync_down');
120
121 /* Used to save closed meta boxes and their order */
122 wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
123 wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
124
125 ?>
126
127 <div id="poststuff">
128 <!-- #post-body .metabox-holder goes here -->
129 <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
130 <!-- meta box containers here -->
131 <div id="post-body-content">
132 <!-- #post-body-content -->
133 <?php $this->body_content_cb(); ?>
134 </div>
135
136 <div id="postbox-container-1" class="postbox-container">
137 <?php
138 /**Add Meta Box to Side Bar */
139 do_meta_boxes('','side',null);
140
141 ?>
142
143 <div class ="save-button-area">
144
145 <?php
146
147 submit_button(__('Save','post-snippets'));
148
149 ?>
150
151 </div>
152
153 </div>
154
155 <div id="postbox-container-2" class="postbox-container">
156 <?php
157 /**Add Full witdh meta-boxes to bottom of Fixed content */
158 do_meta_boxes('','normal',null);
159 // do_meta_boxes('','advanced',null);
160
161 ?>
162 </div>
163
164
165 </div>
166 </div>
167
168
169
170 </form>
171
172 </div><!--/wrap -->
173
174 <?php
175
176 if( isset($_REQUEST['message']) && $_REQUEST['message'] == 1 ){
177
178 printf('<div class="notice notice-success is-dismissible"><p>%s..</p></div>', esc_html__( 'Snippet Added Successfully', 'post-snippets' ) );
179
180 }
181 }
182
183
184 /**
185 * Prints the jQuery script to initiliase the metaboxes
186 * Called on admin_footer-*
187 */
188 public static function footer_scripts(){
189 ?>
190 <script> postboxes.add_postbox_toggles(pagenow);</script>
191 <?php
192 }
193
194 /*
195 * Actions to be taken prior to page loading. This is after headers have been set.
196 * call on load-$hook
197 * This calls the add_meta_boxes hooks, adds screen options and enqueues the postbox.js script.
198 */
199 public static function page_actions(){
200
201 /* User can choose between 1 or 2 columns (default 2) */
202 add_screen_option('layout_columns', array('max' => 2, 'default' => 2) );
203
204 /* Enqueue WordPress' script for handling the metaboxes */
205 wp_enqueue_script('postbox');
206 }
207
208 public static function edit_snippets_meta_boxes(){
209
210 add_meta_box(
211 'ps_action_meta_box', //Meta box ID
212 __('Actions','post-snippets'), //Meta box Title
213 array(\PostSnippets::EDIT_CLASS, 'actions_metabox_content'), //Callback defining the metabox's innards
214 NULL, // Screen to which to add the meta box, blank means current screen
215 'side' // Context
216 );
217
218 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit-js' || $_REQUEST['page'] === 'post-snippets-edit-css'){
219
220 add_meta_box(
221 'ps_option_meta_box', //Meta box ID
222 __('Options','post-snippets'), //Meta box Title
223 array(\PostSnippets::EDIT_CLASS, 'options_metabox_content'), //Callback defining the metabox's innards
224 NULL, // Screen to which to add the meta box, blank means current screen
225 'side' // Context
226 );
227
228 add_meta_box(
229 'ps_preview_meta_box', //Meta box ID
230 __('Preview','post-snippets'), //Meta box Title
231 array(\PostSnippets::EDIT_CLASS, 'preview_metabox_content'), //Callback defining the metabox's innards
232 NULL, // Screen to which to add the meta box, blank means current screen
233 'normal' // Context
234 );
235
236 add_meta_box(
237 'ps_pages_meta_box', //Meta box ID
238 __('Apply only on these URLs','post-snippets'), //Meta box Title
239 array(\PostSnippets::EDIT_CLASS, 'pages_metabox_content'), //Callback defining the metabox's innards
240 NULL, // Screen to which to add the meta box, blank means current screen
241 'normal' // Context
242 );
243
244 }
245
246
247 }
248
249 function body_content_cb(){
250 $this->snippetTitle();
251 $this->codeEditor();
252 // $this->setup_sections();
253 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit'){
254 do_settings_sections( 'post-snippets-edit' );
255 }
256 $this->description();
257 // submit_button(__('Save','post-snippets'));
258 }
259
260 static function actions_metabox_content(){
261
262 if( !self::$editSnippetPage ){
263 $disabled_action = "style = opacity:40%";
264 $disabled_action_cursor = "style = cursor:not-allowed";
265 }
266 else{
267 $disabled_action = '';
268 $disabled_action_cursor = '';
269 }
270
271 ?>
272
273 <div id="sync-up-confirm" title="<?php _e( 'Confirm', 'post-snippets' ) ?>" style="display:none;">
274 <p><span class="dashicons dashicons-warning" style="float:left; margin-right:12px;"></span>
275 <?php _e( 'Do you want to upload the current snippet to the cloud', 'post-snippets' ) ?>
276 </div>
277
278
279 <div id="sync-down-confirm" title="<?php _e( 'Confirm', 'post-snippets' ) ?>" style="display:none;">
280 <p><span class="dashicons dashicons-warning" style="float:left; margin-right:12px;"></span>
281 <?php _e( 'Replace Current Snippet From Cloud', 'post-snippets' ) ?>
282 </div>
283
284
285 <div id="sync-up-success" title="<?php _e( 'Success', 'post-snippets' ) ?>" style="display:none;">
286 <p><span class="dashicons dashicons-thumbs-up" style="float:left; margin-right:12px;"></span>
287 <p upload-success></p>
288 </div>
289
290 <div id="sync-up-error" title="<?php _e( 'Error', 'post-snippets' ) ?>" style="display:none;">
291 <p><span class="dashicons dashicons-warning" style="float:left; margin-right:12px;"></span>
292 <p data-error></p>
293 </div>
294
295 <div id="sp-loading" style="display:none;">
296 <span></span>
297 </div>
298
299
300
301 <div class="pspro_edit_duplicate_snippet" <?php echo esc_attr( $disabled_action ) ?>>
302
303 <span class="dashicons dashicons-admin-page" style="width:30px; height:30px; font-size:25px;"></span>
304 <button <?php echo esc_attr( $disabled_action_cursor ) ?> class="link_style_button" type="<?php echo (self::$editSnippetPage) ? esc_attr( "submit" ) : esc_attr( "button" ) ?>" name="duplicate" value><?php esc_html_e( "Duplicate Snippet", 'post-snippets' ) ?></button>
305
306 </div>
307
308 <?php /**Shortcode Option only on PHP code page */
309
310 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit'){
311 ?>
312 <div class="pspro_edit_copy_shortcode" style="margin-top:1rem; text-align:center;"><?php
313
314 if(self::$editSnippetPage){?>
315
316 <div id="pspro_edit_shortcode_copied">
317 <span id="pspro_edit_shortcode_copied_text"><?php esc_html_e( "Shortcode Copied", "post-snippets" ) ?></span>
318 </div>
319
320 <input type="text" name="" id="pspro_edit_shotcode_text" disabled value = "<?php echo (esc_attr( self::generate_shortcode_text() )) ?>" style="width:100%;<?php echo self::get_data('snippet_shortcode')?'':'display:none;'; ?>">
321
322 <?php
323 }
324 ?>
325
326 <button type = "button" class="button"
327 <?php echo self::$editSnippetPage ? ( ( self::get_data('snippet_shortcode') == 0 )?( esc_attr( 'disabled' ) ):'') : ( esc_attr( 'disabled' ) ) ?>>
328 <?php esc_html_e( "Copy Shortcode", 'post-snippets' ) ?>
329 </button>
330 </div>
331 <?php
332 }
333 ?>
334
335 <div class="pspro_edit_snippet_status" style="margin-top:1rem;">
336 <label for="pspro_edit_snippet_status" style="font-size:17px;"><?php esc_html_e( "Status", 'post-snippets' ) ?><br>
337 <select name="snippet_status" id="pspro_select_snippet_status" style="width:100%;">
338 <option value="1" <?php echo ( self::get_data('snippet_status') == 1 )?( esc_attr( 'selected' ) ):'' ?>><?php esc_html_e( "Active", 'post-snippets' ) ?></option>
339 <option value="0" <?php echo ( self::get_data('snippet_status') == 0 )?( esc_attr( 'selected' ) ):'' ?>><?php esc_html_e( "InActive", 'post-snippets' ) ?></option>
340 </select>
341 </label>
342 </div>
343 <?php
344 }
345
346
347 static function groups_meta_box_content(){
348
349 global $wpdb;
350 $table_name = $wpdb->prefix.\PostSnippets::GROUP_TABLE_NAME;
351
352 $all_groups = $wpdb->get_results($wpdb->prepare("SELECT * FROM %1s", $table_name), ARRAY_A );
353 ?>
354
355 <div id="pspro_group_list" class="categorydiv">
356
357 <ul id="pspro_group-tabs" class="category-tabs">
358 <li class="tabs"> <?php esc_html_e( 'All Groups', 'post-snippets' ) ?></li>
359 </ul>
360
361 <div id="pspro-group-all" class="tabs-panel">
362
363 <ul id="pspro_group_checklist" data-wp-lists="list:pspro_group" class="categorychecklist form-no-clear">
364 <?php
365
366 $checked = ''; /** Preventing Further warning of undefind variable below */
367
368 foreach ($all_groups as $group_key => $group_value) {
369
370 if(self::$editSnippetPage){
371 $group_list = maybe_unserialize( self::get_data('snippet_group') );
372 $checked = in_array($group_value['ID'], $group_list)?"checked":"";
373 }
374
375 else{
376 $ungrouped_checked = (!strcmp($group_value['group_slug'], __('ungrouped','post-snippets') ))?"checked ":"";
377 }
378
379 ?>
380 <li id="pspro_group_<?php echo esc_attr( $group_value['ID'] )?>">
381 <label class="selectit">
382 <input value="<?php echo esc_attr( $group_value['ID'] )?>" type="checkbox" name="pspro_group_list[]" id="in_pspro_group_<?php echo esc_attr( $group_value['ID'] )?>"
383 <?php echo ( esc_attr( $ungrouped_checked?? '' ) );
384 echo ( esc_attr( $checked ) );
385 ?>/>
386 <?php
387 echo esc_html( $group_value['group_name'] );
388 ?>
389 </label>
390 </li>
391 <?php
392
393 }
394
395 ?>
396
397 </ul>
398 </div>
399 </div>
400 <?php
401 }
402
403 static function options_metabox_content(){
404
405 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit-js'){
406
407
408 $jsLocation = self::getLocation('js');
409 if( empty($jsLocation) ){
410 $jsLocation = 'header';
411 }
412
413 ?>
414
415 <div id="pspro_edit_options_where">
416
417 <h3 id = "pspro_edit_js_where_on_page"><?php esc_html_e( "Where on page", "post-snippets" ) ?></h3>
418
419 <input type="radio" name="pspro_edit_js_where" id="pspro_edit_js_header" class="pspro_edit_js_radio" value="header" <?php echo ( $jsLocation == 'header' ) ? ( esc_attr( 'checked' ) ) : '' ?> >
420 <label for="pspro_edit_js_header" class="pspro_edit_js_label"><?php esc_html_e( "Header", "post-snippets" ) ?></label><br>
421
422 <input type="radio" name="pspro_edit_js_where" id="pspro_edit_js_footer" class="pspro_edit_js_radio" value="footer" <?php echo ( $jsLocation == 'footer' ) ? ( esc_attr( 'checked' ) ) : '' ?> >
423 <label for="pspro_edit_js_footer" class="pspro_edit_js_label"><?php esc_html_e( "Footer", "post-snippets" ) ?></label><br>
424
425 </div>
426
427
428 <?php
429 }
430
431 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit-js' || $_REQUEST['page'] === 'post-snippets-edit-css'){
432
433 $location = self::getLocation('site');
434 if( empty($location) ){
435 $location = 'admin';
436 }
437 $available_site_locations = Edit::availableSiteLocations();
438
439 ?>
440
441 <div id="pspro_edit_options_where_in_site">
442
443 <h3 id = "pspro_edit_where_in_site"><?php esc_html_e( "Where in Site", "post-snippets" ) ?></h3>
444
445
446 <?php
447
448 foreach ($available_site_locations as $available_site_location_slug => $available_site_location) {
449 ?>
450 <input
451
452 type="radio" name="pspro_edit_where_site"
453 id="pspro_edit_<?php echo esc_attr( $available_site_location_slug ) ?>"
454 class="pspro_edit_js_radio"
455 value="<?php echo esc_attr( $available_site_location_slug ) ?>"
456 <?php echo ( $location == $available_site_location_slug ) ? ( esc_attr( 'checked' ) ) : '' ?>
457 >
458
459 <label
460
461 for="pspro_edit_<?php echo esc_attr( $available_site_location_slug ) ?>"
462 class="pspro_edit_js_label"><?php esc_html_e( $available_site_location, "post-snippets" )
463
464 ?></label><br>
465
466 <?php
467 }
468
469 ?>
470
471 </div>
472
473
474 <?php
475
476
477 }
478
479 }
480
481 static function preview_metabox_content(){
482
483 $pageLocation = self::getLocation('page');
484 $url = '';
485 if( is_array($pageLocation) && isset( $pageLocation['specific_page'] ) ){
486 $selected_page = $pageLocation['specific_page']; /**page_or_post_id */
487 $url = get_permalink( $selected_page );
488 }
489
490 ?>
491
492 <div id="pspro_edit_preview_page" class="pspro_edit_display_flex">
493
494 <input type="text" name="pspro_edit_preview_text" id="pspro_edit_preview_text" disabled
495 placeholder="<?php esc_attr_e( 'Full URL on which to preview the changes ...', 'post-snippets' )?>"
496 value = "<?php echo esc_url( $url )?>"
497 >
498
499 <button type="button" id="pspro_edit_preview_button" class="button button-primary" disabled><?php esc_html_e( 'Preview Changes', 'post-snippets' ) ?></button>
500
501 </div>
502
503 <?php
504
505
506 }
507
508 static function pages_metabox_content(){
509
510 $pages = self::getAllPagesAndPosts();
511 $pageLocation = self::getLocation('page');
512 $available_locations = Edit::availablePageLocations();
513 $disabled = 'disabled';
514 $selected_page = false;
515
516 if( empty($pageLocation) ){
517 $pageLocation = 'all_website';
518 }
519
520 if( is_array($pageLocation) && isset( $pageLocation['specific_page'] ) ){
521 $selected_page = $pageLocation['specific_page'];
522 $pageLocation = 'specific_page';
523 $disabled = '';
524 }
525
526 ?>
527 <div id="pspro_edit_select_location" class="pspro_edit_display_flex">
528
529 <select name="pspro_edit_location_select" id="pspro_edit_location_select">
530
531 <?php
532
533 foreach ($available_locations as $available_location_slug => $available_location) {
534 ?>
535 <option value="<?php echo esc_attr( $available_location_slug ) ?>" <?php echo ( $available_location_slug == $pageLocation ? 'selected' : '') ?>
536
537 ><?php esc_html_e( $available_location, 'post-snippets' ) ?></option>
538
539 <?php
540 }
541
542 ?>
543
544 </select>
545
546 <select name="pspro_edit_page_select" id="pspro_edit_page_select" <?php echo esc_attr( $disabled ) ?>>
547 <?php
548
549 foreach ($pages as $page) {
550 ?>
551 <option value="<?php echo esc_attr( $page->ID ) ?>" data-url = "<?php echo esc_attr( get_permalink($page->ID) ) ?>"
552 <?php echo ( $selected_page == $page->ID ? 'selected' : '' ) ?>
553
554 ><?php echo esc_attr( ( !empty($page->post_title) ) ? $page->post_title : $page->post_name ) ?></option>
555
556 <?php
557 }
558
559 ?>
560 </select>
561
562 <button type="button" id="pspro_edit_add_selection" class="button button-primary" disabled><?php esc_html_e( 'Add', 'post-snippets' ) ?></button>
563
564 </div>
565
566
567 <?php
568
569 }
570
571 static function getLocation($type = ''){
572
573 if( empty( $type ) ){
574 return '';
575 }
576
577 $location = Shortcode::filterVars( self::get_data('snippet_vars') );
578
579 if( $type === 'js' ){
580
581 if( !empty($location) ){
582
583 $location = array_keys($location);
584
585 if( !empty( $location[1] ) ){
586 $location = $location[1];
587 if($location !== 'header' && $location !== 'footer'){
588 $location = '';
589 }
590 }
591 else{
592 $location = '';
593 }
594 }
595 else{
596 $location = '';
597 }
598
599 return $location;
600 }
601 elseif( $type === 'site' ){
602
603 if( !empty($location) ){
604
605 $location = array_keys($location);
606
607 if( !empty( $location[2] ) ){
608 $location = $location[2];
609 $available_site_locations = array_keys( Edit::availableSiteLocations() );
610 if( !in_array($location, $available_site_locations) ){
611 $location = '';
612 }
613 }
614 else{
615 $location = '';
616 }
617 }
618 else{
619 $location = '';
620 }
621
622 return $location;
623 }
624 elseif( $type === 'page' ){
625
626 if( !empty($location) ){
627
628 $location_keys = array_keys($location);
629
630 if( !empty( $location_keys[0] ) ){
631
632 $location_type = $location_keys[0];
633 $available_locations = Edit::availablePageLocations();
634 $available_locations_slugs = array_keys($available_locations);
635
636 if($location_type === 'specific_page'){
637 $location_page = $location['specific_page'];
638
639 if( empty($location_page) || !Edit::isPageOrPost($location_page) ){
640 return '';
641 }
642
643 return array($location_type => $location_page);
644 }
645
646 if( !in_array( $location_type, $available_locations_slugs, true ) ){
647 return '';
648 }
649
650 return $location_type;
651 }
652 else{
653 $location = '';
654 }
655 }
656 else{
657 $location = '';
658 }
659
660 return $location;
661
662 }
663
664 return '';
665
666 }
667
668 static function getAllPagesAndPosts(){
669
670 $args = array(
671 'post_type' => array( 'page', 'post' ),
672 'numberposts' => -1
673 );
674
675 $pages = get_posts($args);
676
677 return $pages;
678
679 }
680
681 static function isPageOrPost( $id = '' ){
682
683 if( empty($id) ){
684 return false;
685 }
686
687 $pagesAndPosts = self::getAllPagesAndPosts();
688
689 if( !empty( $pagesAndPosts ) ){
690
691 foreach ($pagesAndPosts as $pageAndPost) {
692 if($id == $pageAndPost->ID){
693 return true;
694 }
695 continue;
696 }
697
698 return false;
699 }
700
701 return false;
702
703 }
704
705
706 function snippetTitle(){
707
708 ?>
709
710 <div id="titlediv">
711 <div id="titlewrap">
712 <?php
713 $title_placeholder = apply_filters( 'snippet_title_input', __( 'Enter Snippet Title' ) );
714 $snippet_title = self::get_data('snippet_title');
715 ?>
716 <label class="screen-reader-text" id="title-prompt-text" for="title"><?php echo esc_html($title_placeholder) ; ?></label>
717 <input type="text" name="snippet_title" size="30" value="<?php echo esc_attr( $snippet_title ); ?>" id="title" spellcheck="true" autocomplete="off" placeholder = "<?php echo esc_html($title_placeholder); ?>"/>
718
719 </div>
720
721 </div><!-- /titlediv -->
722
723 <?php
724
725 }
726
727 function setup_code_editor(){
728
729 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit-js' || $_REQUEST['page'] === 'post-snippets-edit-css'){
730
731 if( $_REQUEST['page'] === 'post-snippets-edit-js' ){
732 $type = 'text/javascript';
733 }
734 elseif( $_REQUEST['page'] === 'post-snippets-edit-css' ){
735 $type = 'text/css';
736 }
737
738 $cm_settings['codeEditor'] = wp_enqueue_code_editor(array(
739 // 'type' => 'application/x-httpd-php',
740 // 'type' => 'text/javascript',
741 'type' => $type,
742 'codemirror' => array(
743 // 'value' => '<script>',
744 'gutters' => array("CodeMirror-lint-markers", "CodeMirror-foldgutter"/*, "CodeMirror-markergutter"*/),
745 // 'theme' => 'dracula.css'
746 // 'lineNumbers' => false
747 // 'mode' => array(
748 // 'name' => "php",
749 // 'startOpen' => true
750 // ),
751 // 'mode' => "text/x-php",
752 'foldGutter' => true,
753 // 'markerGutter' => true,
754 'lint' => true
755 // 'htmllint' => true
756
757 )
758 ));
759
760 wp_localize_script('post-snippets', 'cm_settings', $cm_settings);
761
762 wp_enqueue_script('wp-theme-plugin-editor');
763 wp_enqueue_style('wp-codemirror');
764 wp_enqueue_style( 'post-snippets-edit', plugin_dir_url( PS_MAIN_FILE_PATH ) . "assets/edit.css");
765 wp_enqueue_script( 'post-snippets-edit-menu', plugin_dir_url( PS_MAIN_FILE_PATH ) . 'assets/edit.js');
766
767 return;
768 }
769
770 wp_enqueue_style( 'post-snippets-editor', plugin_dir_url( PS_MAIN_FILE_PATH ) . 'assets/editor.css' );
771 wp_enqueue_script( 'post-snippets-editor', plugin_dir_url( PS_MAIN_FILE_PATH ) . 'assets/editor.js' );
772
773 wp_enqueue_style( 'post-snippets-edit', plugin_dir_url( PS_MAIN_FILE_PATH ) . "assets/edit.css");
774 wp_enqueue_script( 'post-snippets-edit-menu', plugin_dir_url( PS_MAIN_FILE_PATH ) . 'assets/edit.js');
775 }
776
777 function codeEditor(){
778
779 $snippet_content = self::get_data('snippet_content');
780
781 ?>
782 <style>
783 #ps_snippet_code_editor textarea{
784
785 width: 100%;
786 min-height: 60vh;
787 height: calc(100vh - 295px);
788 border: 1px solid #dcdcde;
789 box-sizing: border-box;
790
791 font-family: Consolas, Monaco, monospace;
792 font-size:13px;
793 background:#f6f7f7;
794 -moz-tab-size:4;
795 -o-tab-size:4;
796 tab-size:4;
797
798 }
799
800 .pspro_codeEditor_heading{
801
802 margin-top: 1.5rem !important;
803 margin-bottom: 1rem !important;
804
805 }
806 div#ps_snippet_code_editor{
807 margin-bottom: 1rem;
808 }
809 </style>
810 <input type="hidden" name="pspro-edit-code-editor-page" value="<?php echo esc_attr( self::get_snippet_page() ) ?>">
811 <div id="ps_snippet_code_editor">
812 <h1 class="pspro_codeEditor_heading wp-heading"> <?php esc_html_e( 'Code Editor:', 'post-snippets' ) ?> </h1>
813 <textarea name="snippet_content" id="ps_code_editor"><?php echo esc_html( stripslashes( $snippet_content ) ) ?></textarea>
814 </div>
815 <?php
816
817 }
818
819 public static function setup_sections(){
820
821
822 add_settings_section( 'pspro_edit_snippet',
823 '',
824 '',
825 'post-snippets-edit' );
826
827 add_settings_field( 'snippet_vars', //unique_name
828 __('Variables:','post-snippets'), //Label
829 array( \PostSnippets::EDIT_CLASS, 'add_section_fields' ), //Callback Func
830 'post-snippets-edit', //page slug
831 'pspro_edit_snippet', //section slug
832 // 'snippet_vars'
833 array(
834 'id' => 'snippet_vars',
835 'label_for' => 'pspro_snippet_vars',
836 'description' => __( 'Enter Variables For This Snippet', 'post-snippets' )
837 )
838 ); //value to pass to callback function
839
840 add_settings_field( 'snippet_shortcode',
841 __('Shortcode:','post-snippets'),
842 array( \PostSnippets::EDIT_CLASS, 'add_section_fields' ),
843 'post-snippets-edit',
844 'pspro_edit_snippet',
845 // 'snippet_shortcode'
846 array(
847 'id' => 'snippet_shortcode',
848 'label_for' => 'pspro_snippet_shortcode',
849 'description' => __( 'Enable Shortcode For This Snippet', 'post-snippets' )
850 )
851 );
852
853 add_settings_field( 'snippet_php',
854 __('PHP Code:','post-snippets'),
855 array( \PostSnippets::EDIT_CLASS, 'add_section_fields' ),
856 'post-snippets-edit',
857 'pspro_edit_snippet',
858 // 'snippet_php'
859 array(
860 'id' => 'snippet_php',
861 'label_for' => 'pspro_snippet_php',
862 'description' => __( 'Enable PHP Rendering For This Snippet', 'post-snippets' )
863 )
864 );
865
866
867 add_settings_field( 'snippet_wptexturize',
868 __('WPtexturize:','post-snippets'),
869 array( \PostSnippets::EDIT_CLASS, 'add_section_fields' ),
870 'post-snippets-edit',
871 'pspro_edit_snippet',
872 // 'snippet_wptexturize'
873 array(
874 'id' => 'snippet_wptexturize',
875 'label_for' => 'pspro_snippet_wptexturize',
876 'description' => __( 'Enable WP_Texturize For This Snippet', 'post-snippets' )
877 )
878 );
879
880 add_settings_field( 'snippet_rawhtml',
881 __('Render HTML:','post-snippets'),
882 array( \PostSnippets::EDIT_CLASS, 'add_section_fields' ),
883 'post-snippets-edit',
884 'pspro_edit_snippet',
885 array(
886 'id' => 'snippet_rawhtml',
887 'label_for' => 'pspro_snippet_rawhtml',
888 'description' => __( 'Render snippet output as raw HTML instead of text', 'post-snippets' )
889 )
890 );
891 }
892
893 public static function add_section_fields( $arguments ) {
894
895 if ( $arguments['id'] == 'snippet_rawhtml' ) {
896 $is_checked = self::get_data( $arguments['id'] );
897
898 if ( ! self::$editSnippetPage && $is_checked === '' ) {
899 $is_checked = 1;
900 }
901
902 ?>
903
904 <input type="checkbox"
905 name="<?php echo esc_attr( $arguments['id'] ) ?>"
906 id="pspro_<?php echo esc_attr( $arguments['id'] ) ?>"
907 value = "1"
908 <?php echo ( ($is_checked)?esc_attr( 'checked' ):'' ) ?>
909
910 />
911
912 <?php
913 echo '<label>';
914 esc_html_e( 'When enabled, snippet output can render HTML tags. Disable this to print HTML as visible text.', 'post-snippets' );
915 echo '</label>';
916 return;
917 }
918
919 if($arguments['id'] == 'snippet_vars'){
920
921 $snippet_vars = self::get_data($arguments['id']);
922
923 ?>
924
925 <textarea
926 name="<?php echo esc_attr( $arguments['id'] ) ?>"
927 id="pspro_<?php echo esc_attr( $arguments['id'] ) ?>"
928 cols="55" rows="4"
929 ><?php echo esc_html( $snippet_vars ) ?></textarea>
930
931 <?php
932
933 return;
934 }
935 if($arguments['id'] == 'snippet_wptexturize'){
936 $is_checked = self::get_data($arguments['id']);
937
938 ?>
939
940 <input type="checkbox"
941 name="<?php echo esc_attr( $arguments['id'] ) ?>"
942 id="pspro_<?php echo esc_attr( $arguments['id'] ) ?>"
943 value = "1"
944 <?php echo ( ($is_checked)?esc_attr( 'checked' ):'' ) ?>
945
946 />
947
948 <?php
949 echo '<label>';
950 echo esc_html('Text enclosed in the tags <pre> <code>, <kbd>, <style>, <script>, and <tt> will be skipped.');
951 echo 'For more details please visit <a href="https://developer.wordpress.org/reference/functions/wptexturize/" target="_blank">WPtexturize</a>.';
952 echo '</label>';
953 }
954 else
955 {
956
957 $is_checked = self::get_data($arguments['id']);
958
959 ?>
960
961 <input type="checkbox"
962 name="<?php echo esc_attr( $arguments['id'] ) ?>"
963 id="pspro_<?php echo esc_attr( $arguments['id'] ) ?>"
964 value = "1"
965 <?php echo ( ($is_checked)?esc_attr( 'checked' ):'' ) ?>
966
967 />
968
969 <?php
970 }
971
972
973 }
974
975
976 function description(){
977
978 $snippet_desc = self::get_data('snippet_desc');
979 if ( isset( $snippet_desc ) && ! empty( $snippet_desc ) ) {
980 $snippet_desc = stripslashes( $snippet_desc );
981 }
982 else{
983 $snippet_desc ='';
984 }
985
986 ?>
987 <h1 class="ps_description_heading wp-heading" style="margin-top:1.5rem; margin-bottom:1.5rem"> <?php esc_html_e( 'Description:', 'post-snippets' ) ?> </h1>
988
989 <?php
990
991 wp_editor(stripslashes($snippet_desc), 'ps_snippet_description', array(
992
993 'textarea_name' => 'snippet_desc',
994
995 // 'wpautop' => true,
996 // 'media_buttons' => false,
997 // 'editor_class' => 'my_custom_class',
998 // 'textarea_rows' => 10
999
1000 ) );
1001
1002
1003 }
1004
1005 static function get_data($column){
1006
1007 $column = sanitize_key( $column );
1008
1009 if(self::$editSnippetPage){
1010
1011 global $wpdb;
1012
1013 $data = $wpdb->get_var($wpdb->prepare("SELECT $column FROM ".$wpdb->prefix.\PostSnippets::TABLE_NAME." WHERE ID = %d", self::$snippet_id));
1014 }
1015
1016 else{
1017
1018 if($column == "snippet_title"){
1019 $pattern = '/[\s]/i'; /**remove any WhiteSpaces */
1020 $replacement = '';
1021 $snippet_title = preg_replace($pattern, $replacement, $_REQUEST[$column]?? '');
1022 return $snippet_title;
1023 }
1024
1025 $data = $_REQUEST[$column]?? '';
1026
1027 }
1028
1029 return $data;
1030 }
1031
1032
1033 /**
1034 * Change Group Count When any Snippet group changes
1035 * or when a snippet is deleted or duplicated.
1036 *
1037 * @param Array $group_list - Group List
1038 * @param String $method - Whether to Increment or Decrement
1039 *
1040 * @return Void
1041 *
1042 */
1043 public static function change_group_count($group_list, $method){
1044
1045 global $wpdb;
1046
1047 if( !strcmp($method, 'increment') ){
1048
1049 foreach ($group_list as $key => $group_id) {
1050
1051 $group_count = $wpdb->get_var( $wpdb->prepare("SELECT group_count FROM ".$wpdb->prefix.\PostSnippets::GROUP_TABLE_NAME." WHERE ID = %d", $group_id) );
1052 $group_count = $group_count + 1;
1053
1054 $group_count_updated = $wpdb->update(
1055
1056 $wpdb->prefix.\PostSnippets::GROUP_TABLE_NAME,
1057 array( /**Data to update */
1058 'group_count' => $group_count
1059 ),
1060 array( /**Where Coulum = ? */
1061 'ID' => $group_id
1062 ),
1063 array( /**Data Format, %d or %s */
1064 '%d'
1065 ),
1066 array( /**Where Format, %d or %s */
1067 '%d'
1068 )
1069 );
1070 }
1071 }
1072
1073 elseif( !strcmp($method, 'decrement') ){
1074
1075 foreach ($group_list as $key => $group_id) {
1076
1077 $group_count = $wpdb->get_var( $wpdb->prepare("SELECT group_count FROM ".$wpdb->prefix.\PostSnippets::GROUP_TABLE_NAME." WHERE ID = %d", $group_id) );
1078
1079 if($group_count == 0){ /**if there is no snippet in a group but a snippet is deleted, this condition would never met but just in case*/
1080
1081 continue;
1082 }
1083
1084 $group_count = $group_count - 1; /**Decrement Group Count */
1085
1086 $wpdb->update(
1087 $wpdb->prefix.\PostSnippets::GROUP_TABLE_NAME,
1088 array( /**Data to update */
1089 'group_count' => $group_count
1090 ),
1091 array( /**Where Coulum = ? */
1092 'ID' => $group_id
1093 ),
1094 array( /**Data Format, %d or %s */
1095 '%d'
1096 ),
1097 array( /**Where Format, %d or %s */
1098 '%d'
1099 )
1100 );
1101 }
1102 }
1103 }
1104
1105 function is_JS(){
1106
1107 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit-js' /*&& isset($_REQUEST['pspro_edit_location_select'])*/ ){
1108
1109 return true;
1110 }
1111 else{
1112 return false;
1113 }
1114 }
1115
1116 function JS_location(){
1117
1118 if( $this->is_JS() && isset( $_REQUEST['pspro_edit_js_where'] ) && ( $_REQUEST['pspro_edit_js_where'] === 'header' || $_REQUEST['pspro_edit_js_where'] === 'footer' ) ){
1119
1120 return $_REQUEST['pspro_edit_js_where'];
1121 }
1122 elseif( $this->is_JS() ){
1123 return 'header';
1124 }
1125 elseif( $this->is_CSS() ){
1126 return 'css';
1127 }
1128 else{
1129 return '';
1130 }
1131
1132 }
1133
1134 function is_CSS(){
1135
1136 if( isset($_REQUEST['page']) && $_REQUEST['page'] === 'post-snippets-edit-css' /*&& isset($_REQUEST['pspro_edit_location_select'])*/ ){
1137
1138 return true;
1139 }
1140 else{
1141 return false;
1142 }
1143 }
1144
1145 function codeLocation(){
1146
1147 if( ( $this->is_JS() || $this->is_CSS() ) && isset( $_REQUEST['pspro_edit_location_select'] ) && $this->siteLocation() != 'admin'){
1148
1149 $selected_location = $_REQUEST['pspro_edit_location_select'];
1150 $available_locations = Edit::availablePageLocations();
1151 $available_locations_slugs = array_keys($available_locations);
1152
1153 if( $selected_location === 'specific_page'){
1154
1155 if( isset( $_REQUEST['pspro_edit_page_select'] ) && is_numeric( $_REQUEST['pspro_edit_page_select'] ) ){
1156
1157 $specific_page_exist = Edit::isPageOrPost( $_REQUEST['pspro_edit_page_select'] );
1158
1159 if( $specific_page_exist ){
1160 return 'specific_page='.$_REQUEST['pspro_edit_page_select'];
1161 }
1162 else{
1163 return '';
1164 }
1165 }
1166
1167 return '';
1168
1169 }
1170
1171 elseif( in_array($selected_location, $available_locations_slugs, true) ){
1172
1173 return $selected_location;
1174 }
1175
1176 return '';
1177 }
1178 elseif( $this->siteLocation() == 'admin' ){
1179 return 'all_website';
1180 }
1181 else{
1182 return '';
1183 }
1184 }
1185
1186 function siteLocation(){
1187
1188 if( ( $this->is_JS() || $this->is_CSS() ) && isset( $_REQUEST['pspro_edit_where_site'] ) ){
1189
1190 $selected_location = $_REQUEST['pspro_edit_where_site'];
1191 $available_site_locations = array_keys( Edit::availableSiteLocations() );
1192
1193 if( in_array($selected_location, $available_site_locations) ){
1194 return $selected_location;
1195 }
1196 return 'admin';
1197 }
1198 return '';
1199 }
1200
1201 static function availablePageLocations(){
1202
1203 return array(
1204 'all_website' => 'All Website',
1205 'homepage' => 'Homepage',
1206 'all_pages' => 'All Pages',
1207 'all_posts' => 'All Posts',
1208 'specific_page' => 'Specific page / post'
1209 );
1210 }
1211
1212 static function availableSiteLocations(){
1213
1214 return array(
1215 'frontend' => 'In Front-End',
1216 'admin' => 'In Admin',
1217 );
1218
1219 }
1220
1221 function save_data(){
1222
1223 if( isset($_REQUEST['submit']) ){
1224
1225 check_admin_referer( 'pspro_edit_snippet', 'pspro_edit_snippet_nonce' );
1226
1227 global $wpdb;
1228 $table_name = $wpdb->prefix.\PostSnippets::TABLE_NAME;
1229
1230
1231
1232 //******************** Preparing Group List ************************* */
1233
1234 $upgrouped_id = $wpdb->get_var( $wpdb->prepare("SELECT ID FROM ".$wpdb->prefix.\PostSnippets::GROUP_TABLE_NAME." WHERE group_slug = %s", __('ungrouped','post-snippets') ) );
1235 $group_list = $_REQUEST['pspro_group_list'] ?? array($upgrouped_id); /**If no group is selected */
1236
1237 //*************************** END ****************************** */
1238
1239
1240
1241 //******************** Preparing Snippet Title ************************* */
1242
1243 $snippet_title = self::filter_snippet_title( $_REQUEST['snippet_title'] );
1244
1245
1246 //****************************** END *********************************** */
1247
1248
1249 //******************** Preparing Snippet vars ************************* */
1250
1251 if( isset($_REQUEST['snippet_vars']) && !empty( $_REQUEST['snippet_vars'] ) ){
1252
1253 $snippet_vars = self::filter_snippet_vars( $_REQUEST['snippet_vars'] );
1254
1255 }
1256 elseif( isset($_REQUEST['snippet_vars']) && empty( $_REQUEST['snippet_vars'] ) ){
1257
1258 $snippet_vars = '';
1259
1260 }
1261 elseif( !isset($_REQUEST['snippet_vars']) && ( $this->is_JS() || $this->is_CSS() ) ){
1262
1263 $codeLocation = $this->codeLocation();
1264 $jsLocation = $this->JS_location();
1265 $siteLocation = $this->siteLocation();
1266
1267 if( !empty($codeLocation) && !empty($jsLocation) && !empty($siteLocation) ){
1268 $snippet_vars = $codeLocation.','.$jsLocation.','.$siteLocation;
1269 }
1270 else{
1271 return false;
1272 }
1273 }
1274 else{
1275 return false;
1276 }
1277
1278 //****************************** END *********************************** */
1279
1280
1281
1282 //******************** Preparing Snippet Content ************************* */
1283
1284 $snippet_content = $_REQUEST['snippet_content'];
1285 if ($this->is_CSS()) {
1286 // validate that the css snippet contains only css code
1287 //$snippet_content = wp_strip_all_tags($snippet_content);
1288 $snippet_content = wp_kses($snippet_content, array( 'style' => array() ));
1289 }
1290 // if( !empty($snippet_content) && $this->is_JS() ){
1291
1292 // $start = '<script type=\"text/javascript\">';
1293 // $end = '</script>';
1294
1295 // $snippet_content = $start.'\n'.$snippet_content.'\n'.$end;
1296
1297 // }
1298
1299 //****************************** END *********************************** */
1300
1301
1302
1303 //******************** Preparing Snippet Description ************************* */
1304
1305 $allowed_html = apply_filters( 'ps_snippet_desc_allowed_html', array(
1306 'h1' => array(),
1307 'h2' => array(),
1308 'h3' => array(),
1309 'h4' => array(),
1310 'h5' => array(),
1311 'h6' => array(),
1312 'b' => array(),
1313 'strong' => array(),
1314 'pre' => array(),
1315 'p' => array(),
1316 'ul' => array(),
1317 'ol' => array(),
1318 'li' => array(),
1319 ));
1320 $snippet_desc = wp_kses( $_REQUEST['snippet_desc'] ?? '', $allowed_html);
1321
1322 //****************************** END *********************************** */
1323
1324
1325
1326 //******************** Preparing Snippet PHP ************************* */
1327
1328 if( isset($_REQUEST['snippet_php']) ){
1329 $snippet_php = ( ($_REQUEST['snippet_php']?? 0 ) == 1) ? 1 : 0;
1330 }
1331 else{
1332 /**As this variable is not used in JS and CSS pages, they
1333 * can be used to save those pages. so new DB entry
1334 * doesn't need to be created.
1335 * 2 for JS and 3 for CSS.
1336 */
1337 if( $this->is_JS() ){
1338 $snippet_php = 2;
1339 }
1340 elseif( $this->is_CSS() ){
1341 $snippet_php = 3;
1342 }
1343 else{
1344 // return false;
1345 $snippet_php = '0';
1346 }
1347
1348 }
1349
1350 //****************************** END *********************************** */
1351
1352
1353 if( !empty($snippet_title) ){
1354
1355 if(self::$editSnippetPage){ /**This is a edit page of Previous Snippet */
1356
1357 $current_snippet_title = $wpdb->get_var( $wpdb->prepare("SELECT snippet_title FROM $table_name WHERE ID = %d", self::$snippet_id) );
1358
1359 if( $snippet_title != $current_snippet_title && $this->duplicate_title_check($snippet_title) ){
1360
1361 printf('<div class="notice notice-error is-dismissible"><p>%s..</p></div>', esc_html__( 'Duplicate Titles are Not Allowed', 'post-snippets' ) );
1362 return;
1363
1364 }
1365
1366 else{
1367
1368 $current_group_list = $group_list;
1369 $previous_group_list = maybe_unserialize( $wpdb->get_var( $wpdb->prepare("SELECT snippet_group FROM $table_name WHERE ID = %d", self::$snippet_id) ) );
1370
1371 $increment_count = array_diff($current_group_list, $previous_group_list);
1372
1373 $decrement_count = array_diff($previous_group_list, $current_group_list);
1374
1375 $snippet_updated = $wpdb->update(
1376 $table_name,
1377 array(
1378 'snippet_group' => maybe_serialize( $group_list ),
1379 'snippet_title' => $snippet_title,
1380 'snippet_content' => $snippet_content,
1381 'snippet_date' => current_time( 'mysql' ),
1382 'snippet_vars' => $snippet_vars,
1383 'snippet_desc' => $snippet_desc,
1384 'snippet_status' => ( ($_REQUEST['snippet_status']?? 0 ) == 1) ? 1 : 0, //Disable by default
1385 'snippet_shortcode' => ( ($_REQUEST['snippet_shortcode']?? 0 ) == 1) ? 1 : 0,
1386 'snippet_php' => $snippet_php,
1387 'snippet_wptexturize' => ( ($_REQUEST['snippet_wptexturize']?? 0 ) == 1) ? 1 : 0,
1388 'snippet_rawhtml' => isset( $_REQUEST['snippet_rawhtml'] ) ? 1 : 0,
1389 ),
1390 array( /**Where Coulum = ? */
1391 'ID' => self::$snippet_id,
1392 ),
1393 array( /**Data Format, %d or %s */
1394 '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d'
1395 ),
1396 array( /**Where Format, %d or %s */
1397 '%d'
1398 )
1399 );
1400
1401
1402 if($snippet_updated){
1403
1404 printf('<div class="notice notice-success is-dismissible"><p>%s..</p></div>', esc_html__( 'Snippet Updated', 'post-snippets' ) );
1405 // return;
1406 }
1407
1408 elseif(!$snippet_updated){
1409
1410 printf('<div class="notice notice-error is-dismissible"><p>%s..</p></div>', esc_html__( 'Snippet Update Failed', 'post-snippets' ) );
1411 // return;
1412 }
1413
1414 if( !empty($increment_count) || !empty($decrement_count) ){
1415
1416 //change group count here
1417 if( !empty($increment_count) ){ /**Increment Count of these groups */
1418
1419 self::change_group_count($increment_count, 'increment');
1420
1421 }
1422
1423 if( !empty($decrement_count) ){ /**Decrement Count of these groups */
1424
1425 self::change_group_count($decrement_count, 'decrement');
1426
1427 }
1428
1429 }
1430 }
1431 }
1432
1433 elseif( !self::$editSnippetPage && !$this->duplicate_title_check($snippet_title) ){ /**Adding New Snippet here */
1434
1435 $snippet_added = $wpdb->insert(
1436 $table_name,
1437 array(
1438 'snippet_group' => maybe_serialize( $group_list ),
1439 'snippet_title' => $snippet_title,
1440 'snippet_content' => $snippet_content,
1441 'snippet_date' => current_time( 'mysql' ),
1442 'snippet_vars' => $snippet_vars,
1443 'snippet_desc' => $snippet_desc,
1444 'snippet_status' => ( ($_REQUEST['snippet_status']?? 0 ) == 1) ? 1 : 0, //Disable by default
1445 'snippet_shortcode' => ( ($_REQUEST['snippet_shortcode']?? 0 ) == 1) ? 1 : 0,
1446 'snippet_php' => $snippet_php,
1447 'snippet_wptexturize' => ( ($_REQUEST['snippet_wptexturize']?? 0 ) == 1) ? 1 : 0,
1448 'snippet_rawhtml' => isset( $_REQUEST['snippet_rawhtml'] ) ? 1 : 0,
1449 )
1450 );
1451
1452 if( $snippet_added ){
1453
1454 self::change_group_count($group_list, 'increment');
1455
1456 $page = self::get_snippet_page();
1457 $url = admin_url( sprintf('admin.php?page=%s&action=edit&snippet=%s&message=%s&_wpnonce=%s', $page, $wpdb->insert_id, 1, wp_create_nonce('ps-snippets-hover-trigger_'.$wpdb->insert_id) ) );
1458
1459 ?> <script> <?php echo("location.href = '".$url."';"); ?> </script> <?php
1460
1461 }
1462
1463 elseif(!$snippet_added){
1464
1465 printf('<div class="notice notice-error is-dismissible"><p>%s..</p></div>', esc_html__( 'Snippet Not Added', 'post-snippets' ) );
1466
1467 }
1468 }
1469
1470 else{
1471
1472 printf('<div class="notice notice-error is-dismissible"><p>%s..</p></div>', esc_html__( 'Duplicate Titles are Not Allowed', 'post-snippets' ) );
1473
1474 }
1475 }
1476
1477 else{
1478
1479 printf('<div class="notice notice-error is-dismissible"><p>%s..</p></div>', esc_html__( 'Empty Title is Not Allowed', 'post-snippets' ) );
1480
1481 }
1482 }
1483 }
1484
1485 public static function get_snippet_page($id=''){
1486
1487 if(empty($id)){
1488
1489 if( isset($_REQUEST['page']) && ( $_REQUEST['page'] === 'post-snippets-edit' || $_REQUEST['page'] === 'post-snippets-edit-js' || $_REQUEST['page'] === 'post-snippets-edit-css' ) ){
1490 return $_REQUEST['page'];
1491 }
1492
1493 return 'post-snippets-edit';
1494 }else{
1495
1496 if($id == 2){
1497 return 'post-snippets-edit-js';
1498 }
1499 elseif($id == 3){
1500 return 'post-snippets-edit-css';
1501 }
1502 elseif($id == 0 || $id == 1){
1503 return 'post-snippets-edit';
1504 }
1505
1506 return 'post-snippets-edit';
1507
1508 }
1509
1510 }
1511
1512 public static function duplicate_title_check($snippet_title){
1513
1514 global $wpdb;
1515
1516 $table_name = $wpdb->prefix.\PostSnippets::TABLE_NAME;
1517
1518 $all_snippets_titles = $wpdb->get_results( $wpdb->prepare("SELECT snippet_title FROM %1s", $table_name), ARRAY_A );
1519
1520 $all_snippets_titles = array_column($all_snippets_titles, 'snippet_title');
1521
1522 $duplicate_title_exist = in_array($snippet_title, $all_snippets_titles);
1523
1524 if( $duplicate_title_exist ){
1525 /**Cause This function is also used to Increment
1526 * Title Count by number_duplicate_snippet_title,
1527 * otherwise, above written code would have to be
1528 * repeated.
1529 **/
1530
1531 return $all_snippets_titles;
1532
1533 }
1534 else{
1535
1536 return false;
1537
1538 }
1539
1540 }
1541
1542
1543 public static function number_duplicate_snippet_title($snippet_title){
1544
1545 if( empty($snippet_title) || !is_string($snippet_title) ){
1546 //redundancy
1547 $snippet_title = __('Untitled', 'post-snippets');
1548
1549 }
1550
1551 $all_snippets_titles = self::duplicate_title_check($snippet_title);
1552
1553 if(!$all_snippets_titles){
1554 return $snippet_title;
1555 }
1556
1557
1558 return self::increment_snippet_title( $all_snippets_titles, $snippet_title );
1559
1560
1561 }
1562
1563
1564 public static function increment_snippet_title( $all_snippets_titles, $snippet_title ){
1565
1566 /**Searching For Similar Titles */
1567 $same_titles = array();
1568 foreach ($all_snippets_titles as $title) {
1569 if( strpos( $title, $snippet_title ) === 0 ){
1570 $same_titles[] = $title;
1571 }
1572 }
1573
1574
1575 /**Incrementing Said Title */
1576 $counter = 1;
1577 while($counter){
1578
1579 if( in_array($snippet_title.'_'.$counter, $same_titles) ){
1580 $counter++;
1581 }
1582 else{
1583 break;
1584 }
1585 }
1586
1587 $new_snippet_title = $snippet_title.'_'.$counter;
1588
1589 return $new_snippet_title;
1590
1591 }
1592
1593
1594 static function generate_shortcode_text(){
1595
1596 if(self::$editSnippetPage){
1597
1598 $snippet_vars = Shortcode::filterVars( self::get_data('snippet_vars') );
1599
1600 $snippet_vars_text = '';
1601 foreach ($snippet_vars as $var => $value) {
1602 $snippet_vars_text .= ' '. $var . (!empty($value)?'=':'=""') . $value;
1603 }
1604
1605 $shortcode = '['.self::get_data('snippet_title') . $snippet_vars_text . ']';
1606
1607 return $shortcode;
1608 }
1609
1610
1611 }
1612
1613
1614 function perform_actions_response(){
1615
1616 if(self::$editSnippetPage){
1617
1618 if( isset($_REQUEST['download']) ){
1619
1620 check_admin_referer( 'pspro_edit_snippet', 'pspro_edit_snippet_nonce' );
1621
1622 $ie = new ImportExport();
1623
1624 $download_succeed = $ie->exportSnippets("(".self::$snippet_id.")");
1625
1626 if($download_succeed){
1627 printf('<div class="notice notice-success is-dismissible"><p>%s..</p></div>', esc_html__( 'Snippets Downloaded', 'post-snippets' ) );
1628
1629 }
1630 else{
1631 printf('<div class="notice notice-error is-dismissible"><p>%s..</p></div>', esc_html__( 'There has been an Error', 'post-snippets' ) );
1632 }
1633
1634 }
1635
1636
1637 if( isset($_REQUEST['upload']) ){
1638
1639 check_admin_referer( 'pspro_edit_snippet', 'pspro_edit_snippet_nonce' );
1640
1641
1642 }
1643
1644
1645 if( isset($_REQUEST['duplicate']) ){
1646
1647 check_admin_referer( 'pspro_edit_snippet', 'pspro_edit_snippet_nonce' );
1648
1649 if( PSallSnippets::duplicate_snippet(self::$snippet_id) ){
1650 printf('<div class="notice notice-success is-dismissible"><p>%s..</p></div>', esc_html__( 'Snippet Duplicated', 'post-snippets' ) );
1651 return;
1652 }
1653 else{
1654 printf('<div class="notice notice-error is-dismissible"><p>%s..</p></div>', esc_html__( 'There has been an Error', 'post-snippets' ) );
1655 }
1656
1657 }
1658
1659
1660 }
1661
1662
1663 }
1664
1665
1666 public static function addImportedSnippet( $imported_snippet = array() ){
1667
1668 if( !empty($imported_snippet) ){
1669
1670 global $wpdb;
1671 $table_name = $wpdb->prefix.\PostSnippets::TABLE_NAME;
1672
1673 $snippet_php = PSallSnippets::get_snippet_php($imported_snippet['snippet_php']);
1674
1675 // Sanitize imported snippet content to prevent XSS
1676 $sanitized_content = self::sanitize_snippet_content(
1677 $imported_snippet['snippet_content'] ?? '',
1678 $snippet_php
1679 );
1680
1681 $snippet_added = $wpdb->insert(
1682 $table_name,
1683 array(
1684 'snippet_group' => $imported_snippet['snippet_group'],
1685 'snippet_title' => self::filter_snippet_title( $imported_snippet['snippet_title'] ),
1686 'snippet_content' => $sanitized_content,
1687 'snippet_date' => current_time( 'mysql' ),
1688 'snippet_vars' => self::filter_snippet_vars( $imported_snippet['snippet_vars'] ),
1689 'snippet_desc' => sanitize_textarea_field($imported_snippet['snippet_desc'] ?? ''),
1690 'snippet_status' => (($imported_snippet['snippet_status']?? 0) == 1) ? 1 : 0, //Disable by default
1691 'snippet_shortcode' => (($imported_snippet['snippet_shortcode']?? 0) == 1) ? 1 : 0,
1692 'snippet_php' => $snippet_php,
1693 'snippet_wptexturize' => (($imported_snippet['snippet_wptexturize']?? 0) == 1) ? 1 : 0,
1694 'snippet_rawhtml' => (($imported_snippet['snippet_rawhtml'] ?? 1) == 1) ? 1 : 0,
1695 )
1696 );
1697
1698 if($snippet_added){
1699 self::change_group_count( maybe_unserialize( $imported_snippet['snippet_group'] ), 'increment');
1700 return true;
1701 }
1702 else{
1703 return false;
1704 }
1705
1706 }
1707 else{
1708 return false;
1709 }
1710
1711
1712 }
1713
1714
1715 public static function filter_snippet_vars($vars = ''){
1716
1717 if( !empty($vars) ){
1718
1719 $string = $vars;
1720 $pattern = '/([^A-Za-z,=:_\d])/i'; /**remove any character from vars that are not Letters, Numbers or digits or Illegal php variable name */
1721 $replacement = '';
1722 $snippet_vars = preg_replace($pattern, $replacement, $string);
1723
1724 return $snippet_vars;
1725 }
1726 else{
1727 return $vars;
1728 }
1729 }
1730
1731 public static function filter_snippet_title($title = ''){
1732
1733 $title = sanitize_text_field( $title );
1734
1735 if( !isset($title) || empty($title) ){
1736 // $snippet_title = __( 'Untitled', 'post-snippets' );
1737 $snippet_title = self::number_duplicate_snippet_title(__('Untitled', 'post-snippets'));
1738 }
1739 else{
1740 $snippet_title = sanitize_text_field( $title );
1741 }
1742
1743 $pattern = '/[\s]/i'; /**remove any WhiteSpaces */
1744 $replacement = '';
1745 $snippet_title = preg_replace($pattern, $replacement, $snippet_title);
1746
1747 return $snippet_title;
1748 }
1749
1750 /**
1751 * Sanitize snippet content based on snippet type
1752 *
1753 * @param string $content The snippet content to sanitize
1754 * @param int $snippet_php The snippet type (0=regular, 1=PHP, 2=JS, 3=CSS)
1755 * @return string Sanitized content
1756 */
1757 public static function sanitize_snippet_content($content, $snippet_php = 0) {
1758 if (empty($content)) {
1759 return $content;
1760 }
1761
1762 // For JavaScript snippets, validate and sanitize dangerous patterns
1763 if ($snippet_php == 2) {
1764 // Remove potential XSS vectors while preserving legitimate JavaScript code
1765 $dangerous_patterns = array(
1766 '/<script[^>]*>/i', // Remove script tags (they shouldn't be in content)
1767 '/<\/script>/i', // Remove closing script tags
1768 '/javascript\s*:/i', // Remove javascript: protocol
1769 '/on\w+\s*=/i', // Remove event handlers (onclick, onerror, etc.)
1770 '/<iframe/i', // Remove iframe tags
1771 '/<object/i', // Remove object tags
1772 '/<embed/i', // Remove embed tags
1773 );
1774
1775 // Remove dangerous patterns
1776 foreach ($dangerous_patterns as $pattern) {
1777 $content = preg_replace($pattern, '', $content);
1778 }
1779
1780 // Additional validation: check for common XSS patterns
1781 $xss_patterns = array(
1782 '/document\.cookie/i',
1783 '/document\.write\s*\(/i',
1784 '/eval\s*\(/i',
1785 '/Function\s*\(/i',
1786 );
1787
1788 // Log or remove XSS patterns (for now, we'll allow but could be more strict)
1789 // In production, you might want to reject snippets with these patterns
1790
1791 return $content;
1792 }
1793
1794 // For CSS snippets, sanitize CSS-specific XSS vectors
1795 if ($snippet_php == 3) {
1796 // Remove potential XSS in CSS
1797 $content = preg_replace('/expression\s*\(/i', '', $content); // Remove CSS expressions
1798 $content = preg_replace('/javascript\s*:/i', '', $content); // Remove javascript: protocol
1799 $content = preg_replace('/@import/i', '', $content); // Remove @import (could be used for XSS)
1800 // Remove HTML tags from CSS
1801 $content = wp_strip_all_tags($content);
1802 return $content;
1803 }
1804
1805 // For regular snippets, use standard WordPress sanitization
1806 return wp_kses_post($content);
1807 }
1808
1809
1810 }
1811