PluginProbe
Boxzilla – WordPress Popup Builder / 3.2.7
Boxzilla – WordPress Popup Builder v3.2.7
3.4.11 3.4.10 3.4.9 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 trunk 3.0 3.0.1 3.0.2 3.0.3 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 All 72 releases
boxzilla / src / admin / class-admin.php

class-admin.php in Boxzilla – WordPress Popup Builder 3.2.7, at src/admin/class-admin.php

769 lines 19.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Boxzilla\Admin;
4
5 use Boxzilla\Plugin,
6 Boxzilla\Box,
7 Boxzilla\Boxzilla;
8 use WP_Post;
9 use WP_Screen;
10
11 class Admin {
12
13 /**
14 * @var Plugin $plugin
15 */
16 private $plugin;
17
18 /**
19 * @var Boxzilla
20 */
21 protected $boxzilla;
22
23 /**
24 * @var ReviewNotice
25 */
26 protected $review_notice;
27
28 /**
29 * @param Plugin $plugin
30 * @param Boxzilla $boxzilla
31 */
32 public function __construct( Plugin $plugin, Boxzilla $boxzilla ) {
33 $this->plugin = $plugin;
34 $this->boxzilla = $boxzilla;
35 $this->review_notice = new ReviewNotice();
36 }
37
38 /**
39 * Initialise the all admin related stuff
40 */
41 public function init() {
42
43 // Load the plugin textdomain
44 load_plugin_textdomain( 'boxzilla', null, basename( $this->plugin->dir() ) . '/languages' );
45
46 // action hooks
47 $this->add_hooks();
48 $this->run_migrations();
49 }
50
51 /**
52 * Add necessary hooks
53 */
54 protected function add_hooks() {
55 add_action( 'admin_init', array( $this, 'lazy_add_hooks' ) );
56 add_action( 'admin_init', array( $this, 'register' ) );
57 add_action( 'init', array( $this, 'listen_for_actions' ) );
58 add_action( 'admin_menu', array( $this, 'menu' ) );
59 add_action( 'admin_notices', array( $this, 'notices' ) );
60 add_action( 'save_post_boxzilla-box', array( $this, 'save_box_options' ), 20, 2 );
61 add_action( 'trashed_post', array( $this, 'flush_rules' ) );
62 add_action( 'untrashed_post', array( $this, 'flush_rules' ) );
63
64 $this->review_notice->add_hooks();
65 }
66
67 /**
68 * Listen for admin actions.
69 */
70 public function listen_for_actions() {
71
72 // triggered?
73 $vars = array_merge( $_POST, $_GET );
74 if( empty( $vars['_boxzilla_admin_action'] ) ) {
75 return false;
76 }
77
78 // authorized?
79 if( ! current_user_can( 'edit_posts' ) ) {
80 return false;
81 }
82
83 // fire action
84 $action = $vars['_boxzilla_admin_action'];
85 do_action( 'boxzilla_admin_' . $action );
86
87 return true;
88 }
89
90 /**
91 * All logic for admin notices lives here.
92 */
93 public function notices() {
94 global $pagenow,
95 $current_screen;
96
97 if( ( $pagenow === 'plugins.php' || ( $current_screen && $current_screen->post_type === 'boxzilla-box' ) )
98 && current_user_can( 'install_plugins' )
99 && is_plugin_active( 'scroll-triggered-boxes/index.php' ) ) {
100
101 $url = wp_nonce_url( 'plugins.php?action=deactivate&plugin=scroll-triggered-boxes/index.php', 'deactivate-plugin_' . 'scroll-triggered-boxes/index.php' );
102 ?>
103 <div class="notice notice-info">
104 <p><?php printf( __( 'Awesome, you are using Boxzilla! You can now safely <a href="%s">deactivate the Scroll Triggered Boxes plugin</a>.', 'boxzilla' ), $url ); ?></p>
105 </div>
106 <?php
107 }
108
109 }
110
111 /**
112 * Checks current version against stored version & runs necessary update routines.
113 *
114 * @return bool
115 */
116 protected function run_migrations() {
117
118 // Only run if db option is at older version than code constant
119 $previous_version = get_option( 'boxzilla_version', '0' );
120 $current_version = $this->plugin->version();
121
122 if( version_compare( $current_version, $previous_version, '<=' ) ) {
123 return false;
124 }
125
126 $upgrade_routines = new Migrations( $previous_version, $current_version, __DIR__ . '/migrations' );
127 $upgrade_routines->run();
128 update_option( 'boxzilla_version', $current_version );
129 }
130
131 public function lazy_add_hooks() {
132 global $pagenow;
133
134 add_action( 'admin_enqueue_scripts', array( $this, 'load_assets' ) );
135 add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
136 add_filter( 'tiny_mce_before_init', array( $this, 'tinymce_init' ) );
137 add_filter( 'manage_edit-boxzilla-box_columns', array( $this, 'post_type_column_titles' ) );
138 add_action( 'manage_boxzilla-box_posts_custom_column', array( $this, 'post_type_column_content' ), 10, 2 );
139 add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ) );
140
141 if ( $pagenow === 'plugins.php' ) {
142 add_filter( 'plugin_action_links', array( $this, 'add_plugin_settings_link' ), 10, 2 );
143 add_filter( 'plugin_row_meta', array( $this, 'add_plugin_meta_links' ), 10, 2 );
144 }
145 }
146
147 /**
148 * @param $post_id
149 */
150 public function post_type_column_box_id_content( $post_id ) {
151 echo $post_id;
152 }
153
154 /**
155 * @param $column
156 * @param $post_id
157 */
158 public function post_type_column_content( $column, $post_id ) {
159 $method_name = 'post_type_column_' . $column . '_content';
160 if ( method_exists( $this, $method_name ) ) {
161 call_user_func( array( $this, $method_name ), $post_id );
162 }
163 }
164
165 /**
166 * @param $columns
167 *
168 * @return mixed
169 */
170 public function post_type_column_titles( $columns ) {
171 $columns = self::array_insert( $columns, array(
172 'box_id' => __( 'Box ID', 'boxzilla' )
173 ), 1 );
174
175 $columns['title'] = __( 'Box Title', 'boxzilla' );
176
177 return $columns;
178 }
179
180 /**
181 * Register stuffs
182 */
183 public function register() {
184
185 // register settings
186 register_setting( 'boxzilla_settings', 'boxzilla_settings', array( $this, 'sanitize_settings' ) );
187
188 // register scripts
189 $pre_suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
190
191 wp_register_script( 'boxzilla-admin', $this->plugin->url( '/assets/js/admin-script' . $pre_suffix . '.js' ), array(
192 'jquery',
193 'wp-util',
194 'wp-color-picker',
195 'suggest'
196 ), $this->plugin->version(), true );
197
198 // load stylesheets
199 wp_register_style( 'boxzilla-admin', $this->plugin->url( '/assets/css/admin-styles' . $pre_suffix . '.css' ), array(), $this->plugin->version() );
200 }
201
202 /**
203 * Renders the STB Menu items
204 */
205 public function menu() {
206
207 $menu_items = array(
208 array(
209 __( 'Settings', 'boxzilla' ),
210 __( 'Settings', 'boxzilla' ),
211 'boxzilla-settings',
212 array( $this, 'show_settings_page' )
213 ),
214 array(
215 __( 'Extensions', 'boxzilla' ),
216 '<span style="color: orange">' . __( 'Extensions', 'boxzilla' ) . '</span>',
217 'boxzilla-extensions',
218 array( $this, 'show_extensions_page' )
219 )
220 );
221
222 $menu_items = apply_filters( 'boxzilla_admin_menu_items', $menu_items );
223
224 foreach ( $menu_items as $item ) {
225 add_submenu_page( 'edit.php?post_type=boxzilla-box', $item[0] . '- Boxzilla', $item[1], 'manage_options', $item[2], $item[3] );
226 }
227 }
228
229 /**
230 * Shows the settings page
231 */
232 public function show_settings_page() {
233 $opts = $this->boxzilla->options;
234 require __DIR__ . '/views/settings.php';
235 }
236
237 /**
238 * Shows the extensions page
239 */
240 public function show_extensions_page() {
241 $extensions = $this->fetch_extensions();
242 require __DIR__ . '/views/extensions.php';
243 }
244
245 /**
246 * Are we currently editing a box?
247 *
248 * @return bool
249 */
250 protected function on_edit_box_page() {
251 global $pagenow;
252
253 if ( ! in_array( $pagenow, array( 'post-new.php', 'post.php' ) ) ) {
254 return false;
255 }
256
257 if ( isset( $_GET['post_type'] ) && $_GET['post_type'] === 'boxzilla-box' ) {
258 return true;
259 }
260
261 if ( get_post_type() === 'boxzilla-box' ) {
262 return true;
263 }
264
265 return false;
266 }
267
268 /**
269 * @param $args
270 *
271 * @return mixed
272 */
273 public function tinymce_init( $args ) {
274
275 // only act on our post type
276 if ( get_post_type() !== 'boxzilla-box' ) {
277 return $args;
278 }
279
280 $args['setup'] = 'function( editor ) { if(typeof(window.Boxzilla_Admin) === \'undefined\') { return; } editor.on("PreInit", window.Boxzilla_Admin.Designer.init ); }';
281
282 return $args;
283 }
284
285 /**
286 * Load plugin assets
287 */
288 public function load_assets() {
289
290 $screen = get_current_screen();
291
292 if ( ! $screen instanceof WP_Screen ) {
293 return false;
294 }
295
296 if ( $screen->base === 'edit' && $screen->post_type === 'boxzilla-box' ) {
297 wp_enqueue_style( 'boxzilla-admin' );
298 }
299
300 if ( $screen->base === 'post' && $screen->post_type === 'boxzilla-box' ) {
301 // color picker
302 wp_enqueue_style( 'wp-color-picker' );
303
304 // load scripts
305 wp_enqueue_script( 'boxzilla-admin' );
306
307 $data = array(
308 'and' => __( 'and', 'boxzilla' ),
309 'or' => __( 'or', 'boxzilla' ),
310 'enterCommaSeparatedValues' => __( 'Enter a comma-separated list of values.', 'boxzilla' ),
311 'enterCommaSeparatedPosts' => __( "Enter a comma-separated list of post slugs or post ID's..", 'boxzilla' ),
312 'enterCommaSeparatedPages' => __( "Enter a comma-separated list of page slugs or page ID's..", 'boxzilla' ),
313 'enterCommaSeparatedPostTypes' => __( "Enter a comma-separated list of post types..", 'boxzilla' ),
314 'enterCommaSeparatedRelativeUrls' => __( "Enter a comma-separated list of relative URL's, eg /contact/", 'boxzilla' ),
315 );
316 wp_localize_script( 'boxzilla-admin' ,'boxzilla_i18n', $data );
317
318 // load stylesheets
319 wp_enqueue_style( 'boxzilla-admin' );
320
321 // allow add-ons to easily load their own scripts or stylesheets
322 do_action( 'boxzilla_load_admin_assets' );
323 }
324
325 if ( isset( $_GET['page'] ) && $_GET['page'] === 'boxzilla-settings' ) {
326 wp_enqueue_style( 'boxzilla-admin' );
327 }
328
329 }
330
331 /**
332 * Register meta boxes
333 *
334 * @param string $post_type
335 *
336 * @return bool
337 */
338 public function add_meta_boxes( $post_type ) {
339
340 if ( $post_type !== 'boxzilla-box' ) {
341 return false;
342 }
343
344 add_meta_box(
345 'boxzilla-box-appearance-controls',
346 __( 'Box Appearance', 'boxzilla' ),
347 array( $this, 'metabox_box_appearance_controls' ),
348 'boxzilla-box',
349 'normal',
350 'core'
351 );
352
353 add_meta_box(
354 'boxzilla-box-options-controls',
355 __( 'Box Options', 'boxzilla' ),
356 array( $this, 'metabox_box_option_controls' ),
357 'boxzilla-box',
358 'normal',
359 'core'
360 );
361
362 add_meta_box(
363 'boxzilla-support',
364 __( 'Looking for help?', 'boxzilla' ),
365 array( $this, 'metabox_support' ),
366 'boxzilla-box',
367 'side'
368 );
369
370 add_meta_box(
371 'boxzilla-email-optin',
372 __( 'Subscribe to our newsletter', 'boxzilla' ),
373 array( $this, 'metabox_email_optin' ),
374 'boxzilla-box',
375 'side'
376 );
377
378 return true;
379 }
380
381 /**
382 * @param \WP_Post $post
383 * @param $metabox
384 */
385 public function metabox_box_appearance_controls( \WP_Post $post, $metabox ) {
386
387 // get box options
388 $box = new Box( $post );
389 $opts = $box->get_options();
390
391 // include view
392 include __DIR__ . '/views/metaboxes/box-appearance-controls.php';
393 }
394
395 /**
396 * @param \WP_Post $post
397 * @param $metabox
398 */
399 public function metabox_box_option_controls( \WP_Post $post, $metabox ) {
400
401 // get box options
402 $box = new Box( $post );
403 $opts = $box->get_options();
404 $global_opts = $this->boxzilla->options;
405
406 if ( empty( $opts['rules'] ) ) {
407 $opts['rules'][] = array( 'condition' => '', 'qualifier' => 1, 'value' => '' );
408 }
409
410 // include view
411 include __DIR__ . '/views/metaboxes/box-option-controls.php';
412 }
413
414 /**
415 * @param \WP_Post $post
416 * @param $metabox
417 */
418 public function metabox_email_optin( \WP_Post $post, $metabox ) {
419 include __DIR__ . '/views/metaboxes/email-optin.php';
420 }
421
422 /**
423 * @param \WP_Post $post
424 * @param $metabox
425 */
426 public function metabox_support( \WP_Post $post, $metabox ) {
427 include __DIR__ . '/views/metaboxes/need-help.php';
428 }
429
430
431 /**
432 * Saves box options and rules
433 *
434 * @param int $box_id
435 *
436 * @return bool
437 */
438 public function save_box_options( $box_id, $post ) {
439
440 // Only act on our own post type
441 if ( $post->post_type !== 'boxzilla-box' ) {
442 return false;
443 }
444
445 // is this a revision save?
446 if ( wp_is_post_revision( $box_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ) {
447 return false;
448 }
449
450 // can user edit this post?
451 if ( ! current_user_can( 'edit_post', $box_id ) ) {
452 return false;
453 }
454
455 // make sure options array is set
456 if ( ! isset( $_POST['boxzilla_box'] ) || ! is_array( $_POST['boxzilla_box'] ) ) {
457 return false;
458 }
459
460 // get new options from $_POST
461 $opts = $this->sanitize_box_options( $_POST['boxzilla_box'] );
462
463 // allow extensions to filter the saved options
464 $opts = apply_filters( 'boxzilla_saved_options', $opts, $box_id );
465
466 // save individual box settings
467 update_post_meta( $box_id, 'boxzilla_options', $opts );
468
469 // update global settings if given
470 if( ! empty( $_POST['boxzilla_global_settings'] ) ) {
471 $global_settings = get_option( 'boxzilla_settings', array() );
472 if( ! is_array( $global_settings ) ) { $global_settings = array(); }
473 $global_settings = array_merge( $global_settings, $_POST['boxzilla_global_settings'] );
474 update_option( 'boxzilla_settings', $global_settings );
475 }
476
477 $this->flush_rules( $box_id );
478
479 return true;
480 }
481
482 /**
483 * @param array $opts
484 *
485 * @return array
486 */
487 public function sanitize_settings( $opts ) {
488 return $opts;
489 }
490
491 /**
492 * @param string $url_string
493 *
494 * @return string
495 */
496 public function sanitize_url( $url_string ) {
497
498 // if empty, just return a slash
499 if( empty( $url_string ) ) {
500 return '/';
501 }
502
503 // if string looks like an absolute URL, extract just the path
504 if( preg_match( '/^((https|http)?\:\/\/)?(\w+\.)?\w+\.\w+\.*/i', $url_string ) ) {
505
506 // make sure URL has scheme prepended, to make parse_url() understand..
507 $url_string = 'https://' . str_replace( array( 'http://', 'https://' ), '', $url_string );
508
509 // get just the path
510 $url_string = parse_url( $url_string, PHP_URL_PATH );
511 }
512
513 // leading slash it
514 return $url_string;
515 }
516
517 /**
518 * @param array $rule
519 * @return array The sanitized rule array
520 */
521 public function sanitize_box_rule( $rule) {
522
523 $rule['value'] = trim( $rule['value'] );
524
525 // convert to array
526 $rule['value'] = explode( ',', trim( $rule['value'], ',' ) );
527
528 // trim all whitespace in value field
529 $rule['value'] = array_map( 'trim', $rule['value'] );
530
531 // Make sure "is_url" values have a leading slash
532 if ( $rule['condition'] === 'is_url' ) {
533 $rule['value'] = array_map( array( $this, 'sanitize_url' ), $rule['value'] );
534 }
535
536 // (re)set value to 0 when condition is everywhere
537 if ( $rule['condition'] === 'everywhere' ) {
538 $rule['value'] = '';
539 }
540
541 // convert back to string before saving
542 if ( is_array( $rule['value'] ) ) {
543 $rule['value'] = join( ',', $rule['value'] );
544 }
545
546 return $rule;
547 }
548
549 /**
550 * @param array $css
551 * @return array
552 */
553 public function sanitize_box_css( $css ) {
554
555 // sanitize settings
556 if ( '' !== $css['width'] ) {
557 $css['width'] = absint( $css['width'] );
558 }
559
560 if ( '' !== $css['border_width'] ) {
561 $css['border_width'] = absint( $css['border_width'] );
562 }
563
564 // make sure colors start with `#`
565 $color_keys = array( 'color', 'background_color', 'border_color' );
566 foreach ( $color_keys as $key ) {
567 $value = $css[ $key ];
568 $color = sanitize_text_field( $value );
569
570 // make sure color starts with `#`
571 if ( '' !== $color && $color[0] !== '#' ) {
572 $color = '#' . $color;
573 }
574 $css[ $key ] = $color;
575 }
576
577 return $css;
578 }
579
580 /**
581 * Sanitize the options for this box.
582 *
583 * @param array $opts
584 *
585 * @return array
586 */
587 protected function sanitize_box_options( $opts ) {
588
589 static $defaults = array(
590 'rules' => array(),
591 'css' => array()
592 );
593
594 $opts = array_replace_recursive( $defaults, $opts );
595
596 $opts['rules'] = array_map( array( $this, 'sanitize_box_rule' ), $opts['rules'] );
597 $opts['css'] = $this->sanitize_box_css( $opts['css'] );
598 $opts['cookie']['triggered'] = absint( $opts['cookie']['triggered'] );
599 $opts['cookie']['dismissed'] = absint( $opts['cookie']['dismissed'] );
600 $opts['trigger'] = sanitize_text_field( $opts['trigger'] );
601 $opts['trigger_percentage'] = absint( $opts['trigger_percentage'] );
602 $opts['trigger_element'] = sanitize_text_field( $opts['trigger_element'] );
603 $opts['screen_size_condition']['value'] = intval( $opts['screen_size_condition']['value'] );
604
605 return $opts;
606 }
607
608 /**
609 * Add the settings link to the Plugins overview
610 *
611 * @param array $links
612 * @param string $slug
613 *
614 * @return array
615 */
616 public function add_plugin_settings_link( $links, $slug ) {
617 if ( $slug !== $this->plugin->slug() || ! is_array( $links ) ) {
618 return $links;
619 }
620
621 $settings_link = '<a href="' . admin_url( 'edit.php?post_type=boxzilla-box' ) . '">' . __( 'Boxes' ) . '</a>';
622 array_unshift( $links, $settings_link );
623
624 return $links;
625 }
626
627 /**
628 * Adds meta links to the plugin in the WP Admin > Plugins screen
629 *
630 * @param array $links
631 * @param string $slug
632 *
633 * @return array
634 */
635 public function add_plugin_meta_links( $links, $slug ) {
636 if ( $slug !== $this->plugin->slug() ) {
637 return $links;
638 }
639
640 $links[] = '<a href="https://kb.boxzillaplugin.com/#utm_source=wp-plugin&utm_medium=boxzilla&utm_campaign=plugins-page">Documentation</a>';
641 $links[] = '<a href="https://boxzillaplugin.com/add-ons/#utm_source=wp-plugin&utm_medium=boxzilla&utm_campaign=plugins-page">Add-ons</a>';
642
643 return $links;
644 }
645
646 /**
647 * Flush all box rules
648 *
649 * Loops through all published boxes and fills the rules option
650 *
651 * @param int $post_id
652 */
653 public function flush_rules( $post_id ) {
654
655 // only act on our own post type
656 $post = get_post( $post_id );
657 if ( ! $post instanceof WP_Post || $post->post_type !== 'boxzilla-box' ) {
658 return;
659 }
660
661 // get all published boxes
662 $boxes = get_posts(
663 array(
664 'post_type' => 'boxzilla-box',
665 'post_status' => 'publish',
666 'numberposts' => - 1
667 )
668 );
669
670 // setup empty array of rules
671 $rules = array();
672
673 // fill rules array
674 if ( is_array( $boxes ) ) {
675
676 foreach ( $boxes as $box ) {
677 // get box meta data
678 $box_meta = get_post_meta( $box->ID, 'boxzilla_options', true );
679
680 // add box rules to all rules
681 $rules[ $box->ID ] = $box_meta['rules'];
682 $rules[ $box->ID ]['comparision'] = isset( $box_meta['rules_comparision'] ) ? $box_meta['rules_comparision'] : 'any';
683
684 }
685
686 }
687
688 update_option( 'boxzilla_rules', $rules );
689 }
690
691 /**
692 * Fetches a list of available add-on plugins
693 *
694 * @return array
695 */
696 protected function fetch_extensions() {
697
698 $extensions = get_transient( 'boxzilla_remote_extensions' );
699 if ( $extensions ) {
700 return $extensions;
701 }
702 $request = wp_remote_get( 'https://api.boxzillaplugin.com/v1/plugins' );
703
704 if ( is_wp_error( $request ) ) {
705 return array();
706 }
707
708 $response = wp_remote_retrieve_body( $request );
709 $response = json_decode( $response );
710
711 if ( is_array( $response->data ) ) {
712 set_transient( 'boxzilla_remote_extensions', $response->data, 24 * HOUR_IN_SECONDS );
713
714 return $response->data;
715 }
716
717 return array();
718 }
719
720 /**
721 * @param $arr
722 * @param $insert
723 * @param $position
724 *
725 * @return array
726 */
727 public static function array_insert( $arr, $insert, $position ) {
728 $i = 0;
729 $ret = array();
730 foreach ( $arr as $key => $value ) {
731 if ( $i == $position ) {
732 foreach ( $insert as $ikey => $ivalue ) {
733 $ret[ $ikey ] = $ivalue;
734 }
735 }
736 $ret[ $key ] = $value;
737 $i ++;
738 }
739
740 return $ret;
741 }
742
743 /**
744 * @param string $text
745 *
746 * @return string
747 */
748 public function admin_footer_text( $text ) {
749 $screen = get_current_screen();
750
751 if ( ! $screen instanceof WP_Screen ) {
752 return $text;
753 }
754
755 $on_edit_page = $screen->parent_base === 'edit' && $screen->post_type === 'boxzilla-box';
756 if ( $on_edit_page ) {
757 return sprintf( 'If you enjoy using <strong>Boxzilla</strong>, please <a href="%s" target="_blank">leave us a �
758
759
760
761
762 rating</a>. A <strong style="text-decoration: underline;">huge</strong> thank you in advance!', 'https://wordpress.org/support/view/plugin-reviews/boxzilla?rate=5#postform' );
763 }
764
765 return $text;
766 }
767
768 }
769