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