PluginProbe
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts / 2.7.1
Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts v2.7.1
2.7.7 2.7.6 2.7.5 2.7.4 trunk 1.3 2.0.4 2.0.6 2.1.91 2.2.4 2.2.7 2.2.9 2.3.1 2.3.10 2.4.10 2.4.2 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.6.0 2.6.1 2.7.0 All 28 releases
insert-php / admin / includes / class.common.snippet.php

class.common.snippet.php in Woody Code Snippets – Insert PHP, CSS, JS, and Header/Footer Scripts 2.7.1, at admin/includes/class.common.snippet.php

890 lines 26.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Common functions for snippets
4 *
5 * @package Woody_Code_Snippets
6 */
7
8 // Exit if accessed directly.
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Class for common snippet functions
15 */
16 class WINP_Common_Snippet {
17
18 /**
19 * Register hooks
20 *
21 * @return void
22 */
23 public function register_hooks() {
24 add_action( 'current_screen', [ $this, 'current_screen' ] );
25 add_action( 'edit_form_before_permalink', [ $this, 'edit_form_before_permalink' ] );
26 add_action( 'admin_notices', [ $this, 'create_uploads_directory' ] );
27 add_action( 'before_delete_post', [ $this, 'before_delete_post' ] );
28 add_action( 'save_post', [ $this, 'save_post' ] );
29 add_action( 'save_post_' . WINP_SNIPPETS_POST_TYPE, [ $this, 'save_snippet' ], 10, 3 );
30 add_action( 'auto-draft_to_publish', [ $this, 'publish_snippet' ] );
31
32 add_filter( 'script_loader_src', [ $this, 'unload_scripts' ], 10, 2 );
33 }
34
35 /**
36 * Create the custom-css-js dir in uploads directory
37 *
38 * Show a message if the directory is not writable
39 *
40 * Create an empty index.php file inside
41 *
42 * @return void
43 */
44 public function create_uploads_directory() {
45 $current_screen = get_current_screen();
46
47 // Check if we are editing a custom-css-js post.
48 if ( 'post' !== $current_screen->base || WINP_SNIPPETS_POST_TYPE !== $current_screen->post_type ) {
49 return;
50 }
51
52 $dir = WINP_UPLOAD_DIR;
53
54 // Create the dir if it doesn't exist.
55 if ( ! file_exists( $dir ) ) {
56 wp_mkdir_p( $dir );
57 }
58
59 // Show a message if it couldn't create the dir.
60 if ( ! file_exists( $dir ) ) { ?>
61 <div class="notice notice-error is-dismissible">
62 <?php
63 /* translators: %s: Directory name */
64 ?>
65 <p>
66 <?php
67 printf(
68 /* translators: %s: Directory path */
69 esc_html__( 'The %s directory could not be created', 'insert-php' ),
70 '<b>winp-css-js</b>'
71 );
72 ?>
73 </p>
74 <p><?php _e( 'Please run the following commands in order to make the directory', 'insert-php' ); ?>:
75 <br/><strong>mkdir <?php echo $dir; ?>; </strong><br/><strong>chmod 777 <?php echo $dir; ?>
76 ;</strong></p>
77 </div>
78 <?php
79 return;
80 }
81
82 // Show a message if the dir is not writable.
83 if ( ! wp_is_writable( $dir ) ) {
84 ?>
85 <div class="notice notice-error is-dismissible">
86 <p>
87 <?php
88 printf(
89 /* translators: %s: Directory path */
90 esc_html__( 'The %s directory is not writable, therefore the CSS and JS files cannot be saved.', 'insert-php' ),
91 '<b>' . esc_html( $dir ) . '</b>'
92 );
93 ?>
94 </p>
95 <p><?php _e( 'Please run the following command to make the directory writable', 'insert-php' ); ?>:<br/><strong>chmod
96 777 <?php echo $dir; ?> </strong></p>
97 </div>
98 <?php
99 return;
100 }
101
102 // Write a blank index.php.
103 if ( ! file_exists( $dir . '/index.php' ) ) {
104 $content = '<?php' . PHP_EOL . '// Silence is golden.';
105 @file_put_contents( $dir . '/index.php', $content );
106 }
107 }
108
109 /**
110 * Add quick buttons
111 *
112 * @return void
113 */
114 public function current_screen_edit() {
115 $strings = [
116 'php' => __( 'PHP Snippet', 'insert-php' ),
117 'css' => __( 'CSS Snippet', 'insert-php' ),
118 'js' => __( 'JS Snippet', 'insert-php' ),
119 'text' => __( 'Text Snippet', 'insert-php' ),
120 'html' => __( 'HTML Snippet', 'insert-php' ),
121 'advert' => __( 'Advertisement', 'insert-php' ),
122 'universal' => __( 'Universal', 'insert-php' ),
123 ];
124
125 $this->render_snippet_dropdown( $strings, __( 'New Snippet: PHP', 'insert-php' ) );
126 }
127
128 /**
129 * Add quick buttons
130 *
131 * @return void
132 */
133 public function current_screen_post() {
134 global $post;
135 $post_id = null;
136
137 if ( ! empty( $post ) && is_object( $post ) && isset( $post->ID ) ) {
138 $post_id = $post->ID;
139 } elseif ( ! empty( $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
140 $post_id = absint( $_GET['post'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
141 } else {
142 $post_id = WINP_HTTP::get( 'post', null );
143 }
144
145 $type = WINP_Helper::get_snippet_type( $post_id );
146
147 $strings = [
148 'php' => __( 'PHP Snippet', 'insert-php' ),
149 'css' => __( 'CSS Snippet', 'insert-php' ),
150 'js' => __( 'JS Snippet', 'insert-php' ),
151 'text' => __( 'Text Snippet', 'insert-php' ),
152 'html' => __( 'HTML Snippet', 'insert-php' ),
153 'advert' => __( 'Advertisement', 'insert-php' ),
154 'universal' => __( 'Universal', 'insert-php' ),
155 ];
156
157 $label_map = [
158 'php' => __( 'New Snippet: PHP', 'insert-php' ),
159 'css' => __( 'New Snippet: CSS', 'insert-php' ),
160 'js' => __( 'New Snippet: JS', 'insert-php' ),
161 'text' => __( 'New Snippet: Text', 'insert-php' ),
162 'html' => __( 'New Snippet: HTML', 'insert-php' ),
163 'advert' => __( 'New Snippet: Advertisement', 'insert-php' ),
164 'universal' => __( 'New Snippet: Universal', 'insert-php' ),
165 ];
166
167 $button_label = isset( $label_map[ $type ] ) ? $label_map[ $type ] : __( 'New Snippet: PHP', 'insert-php' );
168
169 $this->render_snippet_dropdown( $strings, $button_label, ! empty( $post_id ) );
170 }
171
172 /**
173 * Render snippet type dropdown
174 *
175 * @param array<string, string> $strings Snippet type labels (type => label).
176 * @param string $button_label Button label text.
177 * @param bool $show_title Whether to show the edit title.
178 *
179 * @return void
180 */
181 private function render_snippet_dropdown( $strings, $button_label, $show_title = false ) {
182 $type_display_labels = [
183 'php' => __( 'PHP', 'insert-php' ),
184 'css' => __( 'CSS', 'insert-php' ),
185 'js' => __( 'JS', 'insert-php' ),
186 'text' => __( 'Text', 'insert-php' ),
187 'html' => __( 'HTML', 'insert-php' ),
188 'advert' => __( 'Advertisement', 'insert-php' ),
189 'universal' => __( 'Universal', 'insert-php' ),
190 ];
191
192 // Get edit title if needed.
193 $edit_title = '';
194 if ( $show_title ) {
195 global $post;
196 $post_id = null;
197
198 if ( ! empty( $post ) && is_object( $post ) && isset( $post->ID ) ) {
199 $post_id = $post->ID;
200 } elseif ( ! empty( $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
201 $post_id = absint( $_GET['post'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
202 } else {
203 $post_id = WINP_HTTP::get( 'post', null );
204 }
205
206 if ( ! empty( $post_id ) ) {
207 $type = WINP_Helper::get_snippet_type( $post_id );
208 $edit_labels = [
209 'php' => __( 'Edit PHP Snippet', 'insert-php' ),
210 'css' => __( 'Edit CSS Snippet', 'insert-php' ),
211 'js' => __( 'Edit JS Snippet', 'insert-php' ),
212 'text' => __( 'Edit Text Snippet', 'insert-php' ),
213 'html' => __( 'Edit HTML Snippet', 'insert-php' ),
214 'advert' => __( 'Edit Advertisement Snippet', 'insert-php' ),
215 'universal' => __( 'Edit Universal Snippet', 'insert-php' ),
216 ];
217 $edit_title = isset( $edit_labels[ $type ] ) ? $edit_labels[ $type ] : '';
218 }
219 }
220 ?>
221 <style>
222 .winp-dropdown-button {
223 position: relative;
224 display: inline-flex;
225 margin-left: 10px;
226 }
227 .winp-main-button {
228 background: #6366f1;
229 color: #fff;
230 border: none;
231 border-radius: 3px 0 0 3px;
232 padding: 6px 12px;
233 font-size: 13px;
234 font-weight: 500;
235 cursor: pointer;
236 display: inline-flex;
237 align-items: center;
238 gap: 6px;
239 box-shadow: 0 1px 2px rgba(0,0,0,0.05);
240 text-decoration: none;
241 }
242 .winp-main-button:hover {
243 background: #4f46e5;
244 box-shadow: 0 2px 4px rgba(0,0,0,0.1);
245 color: #fff;
246 }
247 .winp-main-button .dashicons {
248 font-size: 16px;
249 width: 16px;
250 height: 16px;
251 }
252 .winp-dropdown-toggle {
253 background: #6366f1;
254 color: #fff;
255 border: none;
256 border-left: 1px solid rgba(255,255,255,0.2);
257 border-radius: 0 3px 3px 0;
258 padding: 6px 8px;
259 font-size: 13px;
260 font-weight: 500;
261 cursor: pointer;
262 display: inline-flex;
263 align-items: center;
264 box-shadow: 0 1px 2px rgba(0,0,0,0.05);
265 }
266 .winp-dropdown-toggle:hover {
267 background: #4f46e5;
268 box-shadow: 0 2px 4px rgba(0,0,0,0.1);
269 }
270 .winp-dropdown-toggle.active {
271 background: #4f46e5 !important;
272 border-color: rgba(255,255,255,0.2) !important;
273 color: #fff !important;
274 box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
275 }
276 .winp-dropdown-toggle .dashicons {
277 font-size: 16px;
278 width: 16px;
279 height: 16px;
280 transition: transform 0.3s ease;
281 }
282 .winp-dropdown-toggle.active .dashicons-arrow-down-alt2 {
283 transform: rotate(180deg);
284 }
285 .winp-dropdown-menu {
286 display: block;
287 position: absolute;
288 top: 100%;
289 right: 0;
290 margin-top: 4px;
291 background: #fff;
292 border: 1px solid #ddd;
293 border-radius: 4px;
294 box-shadow: 0 4px 12px rgba(0,0,0,0.15);
295 min-width: 180px;
296 z-index: 99999;
297 opacity: 0;
298 visibility: hidden;
299 transform: translateY(-8px);
300 transition: all 0.2s ease;
301 overflow: hidden;
302 }
303 .winp-dropdown-menu.show {
304 opacity: 1;
305 visibility: visible;
306 transform: translateY(0);
307 }
308 .winp-dropdown-item {
309 display: flex;
310 align-items: center;
311 gap: 8px;
312 padding: 6px 12px;
313 cursor: pointer;
314 text-decoration: none;
315 color: #2c3338;
316 border-bottom: 1px solid #f0f0f1;
317 font-size: 13px;
318 position: relative;
319 }
320 .winp-dropdown-item:first-child {
321 border-top-left-radius: 4px;
322 border-top-right-radius: 4px;
323 }
324 .winp-dropdown-item:last-child {
325 border-bottom: none;
326 border-bottom-left-radius: 4px;
327 border-bottom-right-radius: 4px;
328 }
329 .winp-dropdown-item:hover,
330 .winp-dropdown-item:focus {
331 background: #eef2ff;
332 color: #6366f1;
333 outline: none;
334 }
335 .winp-snippet-icon {
336 width: 26px;
337 height: 26px;
338 border-radius: 3px;
339 display: flex;
340 align-items: center;
341 justify-content: center;
342 font-size: 10px;
343 font-weight: 700;
344 color: #fff;
345 flex-shrink: 0;
346 box-shadow: 0 1px 2px rgba(0,0,0,0.1);
347 }
348 .winp-snippet-icon.php { background: linear-gradient(135deg, #8892BF 0%, #7380b0 100%); }
349 .winp-snippet-icon.css { background: linear-gradient(135deg, #4A90E2 0%, #357abd 100%); }
350 .winp-snippet-icon.js { background: linear-gradient(135deg, #F7C948 0%, #e6b938 100%); color: #333; }
351 .winp-snippet-icon.text { background: linear-gradient(135deg, #7E8C8D 0%, #6d7a7b 100%); }
352 .winp-snippet-icon.html { background: linear-gradient(135deg, #E74C3C 0%, #d63c2d 100%); }
353 .winp-snippet-icon.advert { background: linear-gradient(135deg, #27AE60 0%, #229d56 100%); }
354 .winp-snippet-icon.universal { background: linear-gradient(135deg, #9B59B6 0%, #8a4aa5 100%); }
355
356 /* Keyboard navigation highlight */
357 .winp-dropdown-item.keyboard-focus {
358 background: #eef2ff;
359 color: #6366f1;
360 }
361 </style>
362 <script type="text/javascript">
363 /* <![CDATA[ */
364 jQuery(window).ready(function ($) {
365 $('#wpbody-content a.page-title-action').hide();
366
367 <?php if ( $show_title && ! empty( $edit_title ) ) : ?>
368 // Update the h1 with edit title
369 var currentH1 = $('#wpbody-content h1').text();
370 $('#wpbody-content h1').text('<?php echo esc_js( $edit_title ); ?>');
371 <?php endif; ?>
372
373 // Determine the initial selected type from the button label
374 var snippetTypes = {
375 <?php
376 $first = true;
377 foreach ( $strings as $type => $label ) :
378 if ( ! $first ) {
379 echo ',';
380 }
381 echo "'" . esc_js( $type ) . "': '" . esc_js( $label ) . "'";
382 $first = false;
383 endforeach;
384 ?>
385 };
386
387 var buttonLabel = '<?php echo esc_js( $button_label ); ?>';
388 var selectedType = 'php'; // default
389
390 // Try to determine the selected type from the button label
391 for (var type in snippetTypes) {
392 if (buttonLabel.indexOf(snippetTypes[type]) !== -1) {
393 selectedType = type;
394 break;
395 }
396 }
397
398 // Base URL for creating new snippets
399 var baseUrl = <?php echo wp_json_encode( admin_url( 'post-new.php?post_type=' . WINP_SNIPPETS_POST_TYPE . '&winp_item=' ) ); ?>;
400
401 var dropdownHtml = '<div class="winp-dropdown-button">';
402 dropdownHtml += '<a href="' + baseUrl + selectedType + '" class="winp-main-button" id="winp-main-action">';
403 dropdownHtml += '<span class="dashicons dashicons-plus-alt2"></span>';
404 dropdownHtml += '<span class="winp-button-text"><?php echo esc_js( $button_label ); ?></span>';
405 dropdownHtml += '</a>';
406 dropdownHtml += '<button class="winp-dropdown-toggle" type="button" aria-haspopup="true" aria-expanded="false">';
407 dropdownHtml += '<span class="dashicons dashicons-arrow-down-alt2"></span>';
408 dropdownHtml += '</button>';
409 dropdownHtml += '<div class="winp-dropdown-menu" role="menu">';
410 <?php foreach ( $strings as $type => $label ) : ?>
411 dropdownHtml += '<a href="#" class="winp-dropdown-item" data-type="<?php echo esc_js( $type ); ?>" role="menuitem" tabindex="-1">';
412 dropdownHtml += '<span class="winp-snippet-icon <?php echo esc_js( $type ); ?>"><?php echo esc_js( strtoupper( 'advert' === $type ? 'AD' : ( 'universal' === $type ? 'UNI' : $type ) ) ); ?></span>';
413 dropdownHtml += '<span><?php echo esc_js( $label ); ?></span>';
414 dropdownHtml += '</a>';
415 <?php endforeach; ?>
416 dropdownHtml += '</div>';
417 dropdownHtml += '</div>';
418
419 $('#wpbody-content h1').append(dropdownHtml);
420
421 var $toggle = $('.winp-dropdown-toggle');
422 var $mainButton = $('.winp-main-button');
423 var $buttonText = $('.winp-button-text');
424 var $menu = $('.winp-dropdown-menu');
425 var $items = $('.winp-dropdown-item');
426 var currentFocus = -1;
427 var currentSelectedType = selectedType;
428
429 // Type display labels from PHP
430 var typeLabels = {
431 <?php
432 $first = true;
433 foreach ( $type_display_labels as $type => $display_label ) :
434 if ( ! $first ) {
435 echo ',';
436 }
437 echo "'" . esc_js( $type ) . "': '" . esc_js( $display_label ) . "'";
438 $first = false;
439 endforeach;
440 ?>
441 };
442
443 // Handle dropdown item click
444 $items.on('click', function(e) {
445 e.preventDefault();
446 e.stopPropagation();
447
448 var type = $(this).data('type');
449 currentSelectedType = type;
450
451 // Update button text and href
452 if (typeLabels[type]) {
453 var newLabel = 'New Snippet: ' + typeLabels[type];
454 $buttonText.text(newLabel);
455 $mainButton.attr('href', baseUrl + type);
456 }
457
458 closeDropdown();
459 });
460
461 // Toggle dropdown
462 $toggle.on('click', function(e) {
463 e.stopPropagation();
464 var isOpen = $menu.hasClass('show');
465
466 if (isOpen) {
467 closeDropdown();
468 } else {
469 openDropdown();
470 }
471 });
472
473 function openDropdown() {
474 $menu.addClass('show');
475 $toggle.addClass('active').attr('aria-expanded', 'true');
476 $items.first().focus();
477 currentFocus = 0;
478 }
479
480 function closeDropdown() {
481 $menu.removeClass('show');
482 $toggle.removeClass('active').attr('aria-expanded', 'false');
483 $items.removeClass('keyboard-focus');
484 currentFocus = -1;
485 }
486
487 // Close on outside click
488 $(document).on('click', function(e) {
489 if (!$(e.target).closest('.winp-dropdown-button').length) {
490 closeDropdown();
491 }
492 });
493
494 // Keyboard navigation
495 $(document).on('keydown', function(e) {
496 if (!$menu.hasClass('show')) {
497 return;
498 }
499
500 // ESC key
501 if (e.keyCode === 27) {
502 e.preventDefault();
503 closeDropdown();
504 $toggle.focus();
505 }
506
507 // Arrow Down
508 if (e.keyCode === 40) {
509 e.preventDefault();
510 currentFocus++;
511 if (currentFocus >= $items.length) {
512 currentFocus = 0;
513 }
514 setFocus();
515 }
516
517 // Arrow Up
518 if (e.keyCode === 38) {
519 e.preventDefault();
520 currentFocus--;
521 if (currentFocus < 0) {
522 currentFocus = $items.length - 1;
523 }
524 setFocus();
525 }
526
527 // Enter or Space
528 if (e.keyCode === 13 || e.keyCode === 32) {
529 if (currentFocus > -1) {
530 e.preventDefault();
531 $items.eq(currentFocus).trigger('click');
532 }
533 }
534 });
535
536 function setFocus() {
537 $items.removeClass('keyboard-focus');
538 $items.eq(currentFocus).addClass('keyboard-focus').focus();
539 }
540
541 // Hover updates focus
542 $items.on('mouseenter', function() {
543 currentFocus = $items.index(this);
544 $items.removeClass('keyboard-focus');
545 });
546 });
547 /* ]]> */
548 </script>
549 <?php
550 }
551
552 /**
553 * Add quick buttons
554 *
555 * @param \WP_Screen $current_screen WordPress screen object.
556 *
557 * @return void
558 */
559 public function current_screen( $current_screen ) {
560 if ( WINP_SNIPPETS_POST_TYPE !== $current_screen->post_type ) {
561 return;
562 }
563
564 if ( 'post' === $current_screen->base ) {
565 add_action( 'admin_head', [ $this, 'current_screen_post' ] );
566 }
567
568 if ( 'edit' === $current_screen->base ) {
569 add_action( 'admin_head', [ $this, 'current_screen_edit' ] );
570 }
571 }
572
573 /**
574 * Show the Permalink edit form
575 *
576 * @param string|\WP_Post $filename Filename or post object.
577 * @param string $permalink Permalink URL.
578 * @param string $filetype File type.
579 *
580 * @return void
581 */
582 public function edit_form_before_permalink( $filename = '', $permalink = '', $filetype = 'css' ) {
583 $filetype = WINP_HTTP::get( 'winp_item', $filetype, true );
584
585 if ( ! in_array( $filetype, [ 'css', 'js' ] ) ) {
586 return;
587 }
588
589 if ( ! is_string( $filename ) ) {
590 global $post;
591
592 if ( ! is_object( $post ) ) {
593 return;
594 }
595
596 if ( WINP_SNIPPETS_POST_TYPE !== $post->post_type ) {
597 return;
598 }
599
600 $post = $filename;
601 $slug = WINP_Helper::getMetaOption( $post->ID, 'css_js_slug', '' );
602 $default_filetype = WINP_Helper::getMetaOption( $post->ID, 'filetype', '' );
603 if ( $default_filetype ) {
604 $filetype = $default_filetype;
605 } else {
606 $filetype = WINP_Helper::get_snippet_type( $post->ID );
607 }
608
609 if ( ! in_array( $filetype, [ 'css', 'js' ] ) ) {
610 return;
611 }
612
613 if ( ! @file_exists( WINP_UPLOAD_DIR . '/' . $slug . '.' . $filetype ) ) {
614 $slug = false;
615 }
616 $filename = ( $slug ) ? $slug : $post->ID;
617 }
618
619 if ( empty( $permalink ) ) {
620 $permalink = WINP_UPLOAD_URL . '/' . $filename . '.' . $filetype;
621 }
622 ?>
623 <div class="inside">
624 <div id="edit-slug-box" class="hide-if-no-js">
625 <strong><?php _e( 'Permalink', 'insert-php' ); ?>:</strong>
626 <span id="sample-permalink"><a
627 href="<?php echo esc_url( $permalink ); ?>"><?php echo esc_html( WINP_UPLOAD_URL ) . '/'; ?><span
628 id="editable-post-name"><?php echo esc_html( $filename ); ?></span>.<?php echo esc_html( $filetype ); ?></a></span>
629 <span id="winp-edit-slug-buttons"><button type="button"
630 class="winp-edit-slug button button-small hide-if-no-js"
631 aria-label="<?php _e( 'Edit URL Slug', 'insert-php' ); ?>"><?php _e( 'Edit', 'insert-php' ); ?></button></span>
632 <span id="editable-post-name-full"><?php echo esc_html( $filename ); ?></span>
633 </div>
634 <?php wp_nonce_field( 'winp-permalink', 'winp-permalink-nonce' ); ?>
635 </div>
636 <?php
637 }
638
639 /**
640 * Remove the JS/CSS file from the disk when deleting the post
641 *
642 * @param int $postid Post ID.
643 *
644 * @return void
645 */
646 public function before_delete_post( $postid ) {
647 global $post;
648
649 if ( ! is_object( $post ) ) {
650 return;
651 }
652 if ( WINP_SNIPPETS_POST_TYPE !== $post->post_type ) {
653 return;
654 }
655 if ( ! wp_is_writable( WINP_UPLOAD_DIR ) ) {
656 return;
657 }
658
659 $default_filetype = WINP_Helper::get_snippet_type( $post->ID );
660 $filetype = WINP_Helper::getMetaOption( $postid, 'filetype', $default_filetype );
661
662 if ( ! in_array( $filetype, [ 'css', 'js' ] ) ) {
663 return;
664 }
665
666 $slug = WINP_Helper::getMetaOption( $postid, 'css_js_slug' );
667 $file_name = $postid . '.' . $filetype;
668
669 @unlink( WINP_UPLOAD_DIR . '/' . $file_name );
670
671 if ( ! empty( $slug ) ) {
672 @unlink( WINP_UPLOAD_DIR . '/' . $slug . '.' . $filetype );
673 }
674 }
675
676 /**
677 * Save post
678 *
679 * @param int $post_id Post ID.
680 *
681 * @return void
682 */
683 public function save_post( $post_id ) {
684 $nonce = WINP_HTTP::post( 'winp-permalink-nonce' );
685
686 if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'winp-permalink' ) ) {
687 return;
688 }
689
690 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
691 return;
692 }
693
694 if ( WINP_SNIPPETS_POST_TYPE != WINP_HTTP::post( 'post_type' ) ) {
695 return;
696 }
697
698 $default_filetype = WINP_Helper::get_snippet_type( $post_id );
699 $filetype = WINP_Helper::getMetaOption( $post_id, 'filetype', $default_filetype );
700
701 if ( ! in_array( $filetype, [ 'css', 'js' ] ) ) {
702 return;
703 }
704
705 $plugin_title = __( 'Woody Code Snippets', 'insert-php' );
706 $before = $after = '';
707
708 $snippet_linking = WINP_HTTP::post( 'wbcr_inp_snippet_linking' );
709 $linking = ! empty( $snippet_linking ) ? $snippet_linking : 'external';
710 $content = get_post( $post_id )->post_content;
711
712 // Save the Custom Code in a file in `wp-content/uploads/winp-css-js`.
713 if ( 'inline' == $linking ) {
714 $before = '<!-- start ' . $plugin_title . ' CSS and JS -->' . PHP_EOL;
715 $after = '<!-- end ' . $plugin_title . ' CSS and JS -->' . PHP_EOL;
716
717 if ( 'css' == $filetype ) {
718 $before .= '<style type="text/css">' . PHP_EOL;
719 $after = '</style>' . PHP_EOL . $after;
720 }
721
722 if ( 'js' == $filetype ) {
723 if ( ! preg_match( '/<script\b[^>]*>([\s\S]*?)<\/script>/im', $content ) ) {
724 $before .= '<script type="text/javascript">' . PHP_EOL;
725 $after = PHP_EOL . '</script>' . PHP_EOL . $after;
726 } else {
727 // the content has a <script> tag, then remove the comments so they don't show up on the frontend.
728 $content = preg_replace( '@/\*[\s\S]*?\*/@', '', $content );
729 }
730 }
731 }
732
733 if ( 'external' == $linking ) {
734 $before = '/******* Do not edit this file *******' . PHP_EOL . $plugin_title . ' CSS and JS' . PHP_EOL . 'Saved: ' . date( 'M d Y | H:i:s' ) . ' */' . PHP_EOL;
735
736 // Save version for js and css file.
737 WINP_Helper::updateMetaOption( $post_id, 'css_js_version', time() );
738 }
739
740 if ( wp_is_writable( WINP_UPLOAD_DIR ) ) {
741 $file_content = $before . $content . $after;
742
743 // save the file as the Permalink slug.
744 $slug = WINP_Helper::getMetaOption( $post_id, 'css_js_slug' );
745 if ( $slug ) {
746 $file_name = $slug . '.' . $filetype;
747 $file_slug = $slug;
748 } else {
749 $file_name = $post_id . '.' . $filetype;
750 $file_slug = $post_id;
751 }
752
753 // Delete old file.
754 $old_slug = WINP_Helper::getMetaOption( $post_id, 'css_js_exist_slug' );
755 if ( $old_slug ) {
756 @unlink( WINP_UPLOAD_DIR . '/' . $old_slug . '.' . $filetype );
757 }
758
759 // Save exist file slug.
760 WINP_Helper::updateMetaOption( $post_id, 'css_js_exist_slug', $file_slug );
761
762 @file_put_contents( WINP_UPLOAD_DIR . '/' . $file_name, $file_content );
763 }
764 }
765
766 /**
767 * Action for pre saved snippet.
768 * Если это не обновление поста, если это "черновик", и есть параметр с id сниппета, то заполняем данные сниппета для просмотра
769 *
770 * @param int $post_ID Post ID.
771 * @param \WP_Post $current_post Current post object.
772 * @param bool $update Whether this is an existing post being updated.
773 *
774 * @return void
775 */
776 public function save_snippet( $post_ID, $current_post, $update ) {
777 $snippet_id = WINP_HTTP::get( 'snippet_id' );
778 $common = WINP_HTTP::get( 'common', false );
779
780 if ( ! $update && 'auto-draft' == $current_post->post_status && ! empty( $snippet_id ) && WINP_SNIPPETS_POST_TYPE == $current_post->post_type ) {
781 $snippet = [];
782 $saved_snippets = get_user_meta( get_current_user_id(), 'wbcr_inp_current_snippets', true );
783
784 if ( ! empty( $saved_snippets ) && isset( $saved_snippets[ $snippet_id ] ) ) {
785 $snippet = $saved_snippets[ $snippet_id ];
786 }
787
788 if ( empty( $snippet ) ) {
789 $_snippet = WINP_Plugin::app()->get_api_object()->get_snippet( $snippet_id, $common );
790 if ( ! empty( $_snippet ) ) {
791 $snippet = [
792 'title' => $_snippet->title,
793 'desc' => $_snippet->description,
794 'type' => $_snippet->type->slug,
795 'content' => $_snippet->content,
796 'type_id' => $_snippet->type_id,
797 'scope' => $_snippet->execute_everywhere,
798 'priority' => $_snippet->priority,
799 ];
800 }
801 }
802
803 if ( ! empty( $snippet ) ) {
804 $post_data = [
805 'ID' => $post_ID,
806 'post_title' => $snippet['title'],
807 'post_content' => $snippet['content'],
808 ];
809 wp_update_post( $post_data );
810
811 WINP_Helper::updateMetaOption( $post_ID, 'snippet_api_snippet', $snippet_id );
812 WINP_Helper::updateMetaOption( $post_ID, 'snippet_type', $snippet['type'] );
813 WINP_Helper::updateMetaOption( $post_ID, 'snippet_api_type', $snippet['type_id'] );
814 WINP_Helper::updateMetaOption( $post_ID, 'snippet_description', $snippet['desc'] );
815 WINP_Helper::updateMetaOption( $post_ID, 'snippet_draft', true );
816 WINP_Helper::updateMetaOption( $post_ID, 'snippet_scope', $snippet['scope'] );
817
818 if ( isset( $snippet['priority'] ) ) {
819 WINP_Helper::updateMetaOption( $post_ID, 'snippet_priority', $snippet['priority'] );
820 }
821
822 wp_safe_redirect( admin_url( 'post.php?post=' . $post_ID . '&action=edit' ) );
823 }
824 }
825 }
826
827 /**
828 * Delete auto-draft status after post snippet is publishing
829 *
830 * @param \WP_Post $post Post object.
831 *
832 * @return void
833 */
834 public function publish_snippet( $post ) {
835 if ( WINP_SNIPPETS_POST_TYPE == $post->post_type ) {
836 delete_post_meta( $post->ID, 'wbcr_inp_snippet_draft' );
837 }
838 }
839
840 /**
841 * Action admin_footer
842 *
843 * @return void
844 */
845 public function admin_footer() {
846 ?>
847 <script type="text/javascript">!function (e, t, n) {
848 function a() {
849 var e = t.getElementsByTagName("script")[0], n = t.createElement("script");
850 n.type = "text/javascript", n.async = !0, n.src = "https://beacon-v2.helpscout.net", e.parentNode.insertBefore(n, e)
851 }
852
853 if (e.Beacon = n = function (t, n, a) {
854 e.Beacon.readyQueue.push({
855 method: t,
856 options: n,
857 data: a
858 })
859 }, n.readyQueue = [], "complete" === t.readyState) {
860 return a();
861 }
862 e.attachEvent ? e.attachEvent("onload", a) : e.addEventListener("load", a, !1)
863 }(window, document, window.Beacon || function () {
864 });</script>
865 <script type="text/javascript">window.Beacon('init', '1a4078fd-3e77-4692-bcfa-47bb4da0cee5')</script>
866 <?php
867 }
868
869 /**
870 * Unload specific scripts
871 *
872 * @param string $src Script source URL.
873 * @param string $handle Script handle.
874 *
875 * @return bool|string False to prevent loading, otherwise the script source URL.
876 */
877 public function unload_scripts( $src, $handle ) {
878 global $post;
879
880 // Check if we are editing a snippet post.
881 if ( is_admin() && ! empty( $post ) && $post->post_type == WINP_SNIPPETS_POST_TYPE ) {
882 // Unload ckeditor.js from theme The Rex.
883 if ( 'bk-ckeditor-js' == $handle ) {
884 return false;
885 }
886 }
887
888 return $src;
889 }
890 }