PluginProbe
Boxzilla – WordPress Popup Builder / 3.2
Boxzilla – WordPress Popup Builder v3.2
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 +763 -861 3.4.103.2 View file →
@@ -1,861 +1,763 @@
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 - /**
203 - * Register stuffs
204 - */
205 - public function register()
206 - {
207 -
208 - register_setting('boxzilla_settings', 'boxzilla_settings', [ $this, 'sanitize_settings' ]);
209 -
210 - wp_register_script(
211 - 'boxzilla-admin',
212 - $this->plugin->url('/assets/js/admin-script.js'),
213 - [
214 - 'jquery',
215 - 'wp-util',
216 - 'wp-color-picker',
217 - 'suggest',
218 - ],
219 - $this->plugin->version(),
220 - true
221 - );
222 -
223 - wp_register_style('boxzilla-admin', $this->plugin->url('/assets/css/admin-styles.css'), [], $this->plugin->version());
224 - }
225 -
226 - /**
227 - * Renders the Boxzilla admin menu items
228 - */
229 - public function menu()
230 - {
231 - $menu_items = [
232 - [
233 - esc_html__('Settings', 'boxzilla'),
234 - esc_html__('Settings', 'boxzilla'),
235 - 'boxzilla-settings',
236 - [ $this, 'show_settings_page' ],
237 - ],
238 - [
239 - esc_html__('Extensions', 'boxzilla'),
240 - '<span style="color: orange">' . esc_html__('Extensions', 'boxzilla') . '</span>',
241 - 'boxzilla-extensions',
242 - [ $this, 'show_extensions_page' ],
243 - ],
244 - ];
245 -
246 - $menu_items = apply_filters('boxzilla_admin_menu_items', $menu_items);
247 -
248 - foreach ($menu_items as $item) {
249 - add_submenu_page('edit.php?post_type=boxzilla-box', $item[0] . '- Boxzilla', $item[1], 'manage_options', $item[2], $item[3]);
250 - }
251 - }
252 -
253 - /**
254 - * Shows the settings page
255 - */
256 - public function show_settings_page()
257 - {
258 - $opts = $this->boxzilla->options;
259 - require __DIR__ . '/views/settings.php';
260 - }
261 -
262 - /**
263 - * Shows the extensions page
264 - */
265 - public function show_extensions_page()
266 - {
267 - $extensions = $this->fetch_extensions();
268 - require __DIR__ . '/views/extensions.php';
269 - }
270 -
271 - /**
272 - * Are we currently editing a box?
273 - *
274 - * @return bool
275 - */
276 - protected function on_edit_box_page()
277 - {
278 - global $pagenow;
279 -
280 - if (! in_array($pagenow, [ 'post-new.php', 'post.php' ], true)) {
281 - return false;
282 - }
283 -
284 - if (isset($_GET['post_type']) && $_GET['post_type'] === 'boxzilla-box') {
285 - return true;
286 - }
287 -
288 - if (get_post_type() === 'boxzilla-box') {
289 - return true;
290 - }
291 -
292 - return false;
293 - }
294 -
295 - /**
296 - * @param $args
297 - *
298 - * @return mixed
299 - */
300 - public function tinymce_init($args)
301 - {
302 -
303 - // only act on our post type
304 - if (get_post_type() !== 'boxzilla-box') {
305 - return $args;
306 - }
307 -
308 - $args['setup'] = 'function( editor ) { if(typeof(window.Boxzilla_Admin) === \'undefined\') { return; } editor.on("PreInit", window.Boxzilla_Admin.Designer.init ); }';
309 -
310 - return $args;
311 - }
312 -
313 - /**
314 - * Load plugin assets
315 - */
316 - public function load_assets()
317 - {
318 - $screen = get_current_screen();
319 -
320 - if (! $screen instanceof WP_Screen) {
321 - return false;
322 - }
323 -
324 - if ($screen->base === 'edit' && $screen->post_type === 'boxzilla-box') {
325 - wp_enqueue_style('boxzilla-admin');
326 - }
327 -
328 - if ($screen->base === 'post' && $screen->post_type === 'boxzilla-box') {
329 - // color picker
330 - wp_enqueue_style('wp-color-picker');
331 -
332 - // load scripts
333 - wp_enqueue_script('boxzilla-admin');
334 -
335 - $data = [
336 - 'and' => esc_html__('and', 'boxzilla'),
337 - 'or' => esc_html__('or', 'boxzilla'),
338 - 'enterCommaSeparatedValues' => esc_html__('Enter a comma-separated list of values.', 'boxzilla'),
339 - 'enterCommaSeparatedPosts' => esc_html__("Enter a comma-separated list of post slugs or post ID's..", 'boxzilla'),
340 - 'enterCommaSeparatedPages' => esc_html__("Enter a comma-separated list of page slugs or page ID's..", 'boxzilla'),
341 - 'enterCommaSeparatedPostTypes' => esc_html__('Enter a comma-separated list of post types..', 'boxzilla'),
342 - 'enterCommaSeparatedRelativeUrls' => esc_html__("Enter a comma-separated list of relative URL's, eg /contact/", 'boxzilla'),
343 - ];
344 - wp_localize_script('boxzilla-admin', 'boxzilla_i18n', $data);
345 -
346 - // load stylesheets
347 - wp_enqueue_style('boxzilla-admin');
348 -
349 - // allow add-ons to easily load their own scripts or stylesheets
350 - do_action('boxzilla_load_admin_assets');
351 - }
352 -
353 - if (isset($_GET['page']) && $_GET['page'] === 'boxzilla-settings') {
354 - wp_enqueue_style('boxzilla-admin');
355 - }
356 - }
357 -
358 - /**
359 - * Register meta boxes
360 - *
361 - * @param string $post_type
362 - */
363 - public function add_meta_boxes($post_type)
364 - {
365 - if ($post_type !== 'boxzilla-box') {
366 - return;
367 - }
368 -
369 - add_meta_box(
370 - 'boxzilla-box-appearance-controls',
371 - esc_html__('Box Appearance', 'boxzilla'),
372 - [ $this, 'metabox_box_appearance_controls' ],
373 - 'boxzilla-box',
374 - 'normal',
375 - 'core'
376 - );
377 -
378 - add_meta_box(
379 - 'boxzilla-box-options-controls',
380 - esc_html__('Box Options', 'boxzilla'),
381 - [ $this, 'metabox_box_option_controls' ],
382 - 'boxzilla-box',
383 - 'normal',
384 - 'core'
385 - );
386 -
387 - add_meta_box(
388 - 'boxzilla-support',
389 - esc_html__('Looking for help?', 'boxzilla'),
390 - [ $this, 'metabox_support' ],
391 - 'boxzilla-box',
392 - 'side'
393 - );
394 -
395 - add_meta_box(
396 - 'boxzilla-our-other-plugins',
397 - esc_html__('Our other plugins', 'boxzilla'),
398 - [ $this, 'metabox_our_other_plugins' ],
399 - 'boxzilla-box',
400 - 'side'
401 - );
402 - }
403 -
404 - /**
405 - * @param \WP_Post $post
406 - * @param $metabox
407 - */
408 - public function metabox_box_appearance_controls(\WP_Post $post, $metabox)
409 - {
410 -
411 - // get box options
412 - $box = new Box($post);
413 - $opts = $box->get_options();
414 -
415 - // include view
416 - include __DIR__ . '/views/metaboxes/box-appearance-controls.php';
417 - }
418 -
419 - /**
420 - * @param \WP_Post $post
421 - * @param $metabox
422 - */
423 - public function metabox_box_option_controls(\WP_Post $post, $metabox)
424 - {
425 -
426 - // get box options
427 - $box = new Box($post);
428 - $opts = $box->get_options();
429 - $global_opts = $this->boxzilla->options;
430 -
431 - if (empty($opts['rules'])) {
432 - $opts['rules'][] = [
433 - 'condition' => '',
434 - 'qualifier' => 1,
435 - 'value' => '',
436 - ];
437 - }
438 -
439 - // include view
440 - include __DIR__ . '/views/metaboxes/box-option-controls.php';
441 - }
442 -
443 - /**
444 - * @param \WP_Post $post
445 - * @param $metabox
446 - */
447 - public function metabox_our_other_plugins(\WP_Post $post, $metabox)
448 - {
449 - include __DIR__ . '/views/metaboxes/our-other-plugins.php';
450 - }
451 -
452 - /**
453 - * @param \WP_Post $post
454 - * @param $metabox
455 - */
456 - public function metabox_support(\WP_Post $post, $metabox)
457 - {
458 - include __DIR__ . '/views/metaboxes/need-help.php';
459 - }
460 -
461 -
462 - /**
463 - * Saves box options and rules
464 - *
465 - * @param int $box_id
466 - * @param \WP_Post $post
467 - */
468 - public function save_box_options($box_id, $post)
469 - {
470 - // Only act on our own post type
471 - if ($post->post_type !== 'boxzilla-box') {
472 - return;
473 - }
474 -
475 - // is this a revision save?
476 - if (wp_is_post_revision($box_id) || ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )) {
477 - return;
478 - }
479 -
480 - // can user edit this post?
481 - if (! current_user_can('edit_post', $box_id)) {
482 - return;
483 - }
484 -
485 - // make sure options array is set
486 - if (! isset($_POST['boxzilla_box']) || ! is_array($_POST['boxzilla_box'])) {
487 - return;
488 - }
489 -
490 - // get new options from $_POST
491 - $opts = $this->sanitize_box_options($_POST['boxzilla_box']);
492 -
493 - // allow extensions to filter the saved options
494 - $opts = apply_filters('boxzilla_saved_options', $opts, $box_id);
495 -
496 - // save individual box settings
497 - update_post_meta($box_id, 'boxzilla_options', $opts);
498 -
499 - // update global settings if given
500 - if (! empty($_POST['boxzilla_global_settings'])) {
501 - $raw_global_settings = $_POST['boxzilla_global_settings'];
502 - $global_settings = get_option('boxzilla_settings', []);
503 - if (! is_array($global_settings)) {
504 - $global_settings = [];
505 - }
506 - if (isset($raw_global_settings['test_mode'])) {
507 - $global_settings['test_mode'] = absint($raw_global_settings['test_mode']);
508 - }
509 - update_option('boxzilla_settings', $global_settings);
510 - }
511 -
512 - $this->flush_rules($box_id);
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'] = intval($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 - $href = admin_url('edit.php?post_type=boxzilla-box');
659 - $label = esc_html__('Boxes', 'boxzilla');
660 - $settings_link = "<a href=\"{$href}\">{$label}</a>";
661 - array_unshift($links, $settings_link);
662 - return $links;
663 - }
664 -
665 - /**
666 - * Adds meta links to the plugin in the WP Admin > Plugins screen
667 - *
668 - * @param array $links
669 - * @param string $slug
670 - *
671 - * @return array
672 - */
673 - public function add_plugin_meta_links($links, $slug)
674 - {
675 - if ($slug !== $this->plugin->slug()) {
676 - return $links;
677 - }
678 -
679 - $links[] = '<a href="https://boxzillaplugin.com/kb/">Documentation</a>';
680 - $links[] = '<a href="https://boxzillaplugin.com/add-ons/">Add-ons</a>';
681 -
682 - return $links;
683 - }
684 -
685 - /**
686 - * Flush all box rules
687 - *
688 - * Loops through all published boxes and fills the rules option
689 - *
690 - * @param int $post_id
691 - */
692 - public function flush_rules($post_id)
693 - {
694 -
695 - // only act on our own post type
696 - $post = get_post($post_id);
697 - if (! $post instanceof WP_Post || $post->post_type !== 'boxzilla-box') {
698 - return;
699 - }
700 -
701 - // get all published boxes
702 - $query = new \WP_Query();
703 - $boxes = $query->query(
704 - [
705 - 'post_type' => 'boxzilla-box',
706 - 'post_status' => 'publish',
707 - 'posts_per_page' => - 1,
708 - 'ignore_sticky_posts' => true,
709 - 'no_found_rows' => true,
710 - ]
711 - );
712 -
713 - // setup empty array of rules
714 - $rules = [];
715 -
716 - // fill rules array
717 - if (is_array($boxes)) {
718 - foreach ($boxes as $box) {
719 - // get box meta data
720 - $box_meta = get_post_meta($box->ID, 'boxzilla_options', true);
721 - if (! $box_meta || ! is_array($box_meta) || empty($box_meta['rules'])) {
722 - continue;
723 - }
724 -
725 - // add box rules to all rules
726 - $rules[ $box->ID ] = (array) $box_meta['rules'];
727 - $rules[ $box->ID ]['comparision'] = isset($box_meta['rules_comparision']) ? $box_meta['rules_comparision'] : 'any';
728 - }
729 - }
730 -
731 - update_option('boxzilla_rules', $rules);
732 - }
733 -
734 - /**
735 - * Fetches a list of available add-on plugins
736 - *
737 - * @return array
738 - */
739 - protected function fetch_extensions()
740 - {
741 - return [
742 - 0 =>
743 - (object) [
744 - 'name' => 'Theme Pack',
745 - 'description' => 'A beautiful set of eye-catching themes for your boxes',
746 - 'url' => 'https://boxzillaplugin.com/add-ons/theme-pack',
747 - 'image_url' => plugins_url("assets/img/theme-pack.png", BOXZILLA_FILE),
748 - 'page_url' => 'https://boxzillaplugin.com/add-ons/theme-pack',
749 - ],
750 - 1 =>
751 - (object) [
752 - 'name' => 'MailChimp',
753 - 'description' => 'Hide boxes for MailChimp subscribers.',
754 - 'url' => 'https://boxzillaplugin.com/add-ons/mailchimp',
755 - 'image_url' => plugins_url("assets/img/mailchimp.png", BOXZILLA_FILE),
756 - 'page_url' => 'https://boxzillaplugin.com/add-ons/mailchimp',
757 - ],
758 - 2 =>
759 - (object) [
760 - 'name' => 'Google Analytics',
761 - 'description' => 'Track box events in Google Analytics.',
762 - 'url' => 'https://boxzillaplugin.com/add-ons/google-analytics',
763 - 'image_url' => plugins_url("assets/img/google-analytics.png", BOXZILLA_FILE),
764 - 'page_url' => 'https://boxzillaplugin.com/add-ons/google-analytics',
765 - ],
766 - 3 =>
767 - (object) [
768 - 'name' => 'Exit Intent',
769 - 'description' => 'Trigger a box when a visitor intents to leave your webpage.',
770 - 'url' => 'https://boxzillaplugin.com/add-ons/exit-intent',
771 - 'image_url' => plugins_url("assets/img/exit-intent.png", BOXZILLA_FILE),
772 - 'page_url' => 'https://boxzillaplugin.com/add-ons/exit-intent',
773 - ],
774 - 4 =>
775 - (object) [
776 - 'name' => 'Time on Site',
777 - 'description' => 'Trigger a box after a visitor spent an amount of time on your site.',
778 - 'url' => 'https://boxzillaplugin.com/add-ons/time-on-site',
779 - 'image_url' => plugins_url("assets/img/time-on-site.png", BOXZILLA_FILE),
780 - 'page_url' => 'https://boxzillaplugin.com/add-ons/time-on-site',
781 - ],
782 - 5 =>
783 - (object) [
784 - 'name' => 'Pageviews',
785 - 'description' => 'Allows you to trigger a box after a certain number of pageviews.',
786 - 'url' => 'https://boxzillaplugin.com/add-ons/pageviews',
787 - 'image_url' => plugins_url("assets/img/pageviews.png", BOXZILLA_FILE),
788 - 'page_url' => 'https://boxzillaplugin.com/add-ons/pageviews',
789 - ],
790 - 6 =>
791 - (object) [
792 - 'name' => 'WooCommerce',
793 - 'description' => 'Offers advanced integration with WooCommerce.',
794 - 'url' => 'https://boxzillaplugin.com/add-ons/woocommerce',
795 - 'image_url' => plugins_url("assets/img/woocommerce.png", BOXZILLA_FILE),
796 - 'page_url' => 'https://boxzillaplugin.com/add-ons/woocommerce',
797 - ],
798 - 7 =>
799 - (object) [
800 - 'name' => 'Stats',
801 - 'description' => 'Measure how well your boxes are performing with simple statistics.',
802 - 'url' => 'https://boxzillaplugin.com/add-ons/stats',
803 - 'image_url' => plugins_url("assets/img/stats.png", BOXZILLA_FILE),
804 - 'page_url' => 'https://boxzillaplugin.com/add-ons/stats',
805 - ],
806 - 8 =>
807 - (object) [
808 - 'name' => 'Date Range',
809 - 'description' => 'Only load a box when date is within a certain range of one or two dates.',
810 - 'url' => 'https://boxzillaplugin.com/add-ons/date-range/',
811 - 'image_url' => plugins_url("assets/img/date-range.png", BOXZILLA_FILE),
812 - 'page_url' => 'https://boxzillaplugin.com/add-ons/date-range/',
813 - ],
814 - ];
815 - }
816 -
817 - /**
818 - * @param $arr
819 - * @param $insert
820 - * @param $position
821 - *
822 - * @return array
823 - */
824 - public static function array_insert($arr, $insert, $position)
825 - {
826 - $i = 0;
827 - $ret = [];
828 - foreach ($arr as $key => $value) {
829 - if ($i == $position) {
830 - foreach ($insert as $ikey => $ivalue) {
831 - $ret[ $ikey ] = $ivalue;
832 - }
833 - }
834 - $ret[ $key ] = $value;
835 - $i++;
836 - }
837 -
838 - return $ret;
839 - }
840 -
841 - /**
842 - * @param string $text
843 - *
844 - * @return string
845 - */
846 - public function admin_footer_text($text)
847 - {
848 - $screen = get_current_screen();
849 -
850 - if (! $screen instanceof WP_Screen) {
851 - return $text;
852 - }
853 -
854 - $on_edit_page = $screen->parent_base === 'edit' && $screen->post_type === 'boxzilla-box';
855 - if ($on_edit_page) {
856 - 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');
857 - }
858 -
859 - return $text;
860 - }
861 -}
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 + 'enterCommaSeparatedValues' => __( 'Enter a comma-separated list of values.', 'boxzilla' ),
309 + 'enterCommaSeparatedPosts' => __( "Enter a comma-separated list of post slugs or post ID's..", 'boxzilla' ),
310 + 'enterCommaSeparatedPages' => __( "Enter a comma-separated list of page slugs or page ID's..", 'boxzilla' ),
311 + 'enterCommaSeparatedPostTypes' => __( "Enter a comma-separated list of post types..", 'boxzilla' ),
312 + 'enterCommaSeparatedRelativeUrls' => __( "Enter a comma-separated list of relative URL's, eg /contact/", 'boxzilla' ),
313 + );
314 + wp_localize_script( 'boxzilla-admin' ,'boxzilla_i18n', $data );
315 +
316 + // load stylesheets
317 + wp_enqueue_style( 'boxzilla-admin' );
318 +
319 + // allow add-ons to easily load their own scripts or stylesheets
320 + do_action( 'boxzilla_load_admin_assets' );
321 + }
322 +
323 + if ( isset( $_GET['page'] ) && $_GET['page'] === 'boxzilla-settings' ) {
324 + wp_enqueue_style( 'boxzilla-admin' );
325 + }
326 +
327 + }
328 +
329 + /**
330 + * Register meta boxes
331 + *
332 + * @param string $post_type
333 + *
334 + * @return bool
335 + */
336 + public function add_meta_boxes( $post_type ) {
337 +
338 + if ( $post_type !== 'boxzilla-box' ) {
339 + return false;
340 + }
341 +
342 + add_meta_box(
343 + 'boxzilla-box-appearance-controls',
344 + __( 'Box Appearance', 'boxzilla' ),
345 + array( $this, 'metabox_box_appearance_controls' ),
346 + 'boxzilla-box',
347 + 'normal',
348 + 'core'
349 + );
350 +
351 + add_meta_box(
352 + 'boxzilla-box-options-controls',
353 + __( 'Box Options', 'boxzilla' ),
354 + array( $this, 'metabox_box_option_controls' ),
355 + 'boxzilla-box',
356 + 'normal',
357 + 'core'
358 + );
359 +
360 + add_meta_box(
361 + 'boxzilla-support',
362 + __( 'Looking for help?', 'boxzilla' ),
363 + array( $this, 'metabox_support' ),
364 + 'boxzilla-box',
365 + 'side'
366 + );
367 +
368 + add_meta_box(
369 + 'boxzilla-email-optin',
370 + __( 'Subscribe to our newsletter', 'boxzilla' ),
371 + array( $this, 'metabox_email_optin' ),
372 + 'boxzilla-box',
373 + 'side'
374 + );
375 +
376 + return true;
377 + }
378 +
379 + /**
380 + * @param \WP_Post $post
381 + * @param $metabox
382 + */
383 + public function metabox_box_appearance_controls( \WP_Post $post, $metabox ) {
384 +
385 + // get box options
386 + $box = new Box( $post );
387 + $opts = $box->get_options();
388 +
389 + // include view
390 + include __DIR__ . '/views/metaboxes/box-appearance-controls.php';
391 + }
392 +
393 + /**
394 + * @param \WP_Post $post
395 + * @param $metabox
396 + */
397 + public function metabox_box_option_controls( \WP_Post $post, $metabox ) {
398 +
399 + // get box options
400 + $box = new Box( $post );
401 + $opts = $box->get_options();
402 + $global_opts = $this->boxzilla->options;
403 +
404 + if ( empty( $opts['rules'] ) ) {
405 + $opts['rules'][] = array( 'condition' => '', 'qualifier' => 1, 'value' => '' );
406 + }
407 +
408 + // include view
409 + include __DIR__ . '/views/metaboxes/box-option-controls.php';
410 + }
411 +
412 + /**
413 + * @param \WP_Post $post
414 + * @param $metabox
415 + */
416 + public function metabox_email_optin( \WP_Post $post, $metabox ) {
417 + include __DIR__ . '/views/metaboxes/email-optin.php';
418 + }
419 +
420 + /**
421 + * @param \WP_Post $post
422 + * @param $metabox
423 + */
424 + public function metabox_support( \WP_Post $post, $metabox ) {
425 + include __DIR__ . '/views/metaboxes/need-help.php';
426 + }
427 +
428 +
429 + /**
430 + * Saves box options and rules
431 + *
432 + * @param int $box_id
433 + *
434 + * @return bool
435 + */
436 + public function save_box_options( $box_id, $post ) {
437 +
438 + // Only act on our own post type
439 + if ( $post->post_type !== 'boxzilla-box' ) {
440 + return false;
441 + }
442 +
443 + // is this a revision save?
444 + if ( wp_is_post_revision( $box_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ) {
445 + return false;
446 + }
447 +
448 + // can user edit this post?
449 + if ( ! current_user_can( 'edit_post', $box_id ) ) {
450 + return false;
451 + }
452 +
453 + // make sure options array is set
454 + if ( ! isset( $_POST['boxzilla_box'] ) || ! is_array( $_POST['boxzilla_box'] ) ) {
455 + return false;
456 + }
457 +
458 + // get new options from $_POST
459 + $opts = $this->sanitize_box_options( $_POST['boxzilla_box'] );
460 +
461 + // allow extensions to filter the saved options
462 + $opts = apply_filters( 'boxzilla_saved_options', $opts, $box_id );
463 +
464 + // save individual box settings
465 + update_post_meta( $box_id, 'boxzilla_options', $opts );
466 +
467 + // update global settings if given
468 + if( ! empty( $_POST['boxzilla_global_settings'] ) ) {
469 + $global_settings = get_option( 'boxzilla_settings', array() );
470 + if( ! is_array( $global_settings ) ) { $global_settings = array(); }
471 + $global_settings = array_merge( $global_settings, $_POST['boxzilla_global_settings'] );
472 + update_option( 'boxzilla_settings', $global_settings );
473 + }
474 +
475 + $this->flush_rules( $box_id );
476 +
477 + return true;
478 + }
479 +
480 + /**
481 + * @param array $opts
482 + *
483 + * @return array
484 + */
485 + public function sanitize_settings( $opts ) {
486 + return $opts;
487 + }
488 +
489 + /**
490 + * @param string $url_string
491 + *
492 + * @return string
493 + */
494 + public function sanitize_url( $url_string ) {
495 +
496 + // if empty, just return a slash
497 + if( empty( $url_string ) ) {
498 + return '/';
499 + }
500 +
501 + // if string looks like an absolute URL, extract just the path
502 + if( preg_match( '/^((https|http)?\:\/\/)?(\w+\.)?\w+\.\w+\.*/i', $url_string ) ) {
503 +
504 + // make sure URL has scheme prepended, to make parse_url() understand..
505 + $url_string = 'https://' . str_replace( array( 'http://', 'https://' ), '', $url_string );
506 +
507 + // get just the path
508 + $url_string = parse_url( $url_string, PHP_URL_PATH );
509 + }
510 +
511 + // leading slash it
512 + return '/' . ltrim( $url_string, '/' );
513 + }
514 +
515 + /**
516 + * @param array $rule
517 + * @return array The sanitized rule array
518 + */
519 + public function sanitize_box_rule( $rule) {
520 +
521 + $rule['value'] = trim( $rule['value'] );
522 +
523 + // convert to array
524 + $rule['value'] = explode( ',', trim( $rule['value'], ',' ) );
525 +
526 + // trim all whitespace in value field
527 + $rule['value'] = array_map( 'trim', $rule['value'] );
528 +
529 + // Make sure "is_url" values have a leading slash
530 + if ( $rule['condition'] === 'is_url' ) {
531 + $rule['value'] = array_map( array( $this, 'sanitize_url' ), $rule['value'] );
532 + }
533 +
534 + // (re)set value to 0 when condition is everywhere
535 + if ( $rule['condition'] === 'everywhere' ) {
536 + $rule['value'] = '';
537 + }
538 +
539 + // convert back to string before saving
540 + if ( is_array( $rule['value'] ) ) {
541 + $rule['value'] = join( ',', $rule['value'] );
542 + }
543 +
544 + $rule['qualifier'] = isset( $rule['qualifier'] ) && ! $rule['qualifier'] ? 0 : 1;
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 ★★★★★ 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' );
758 + }
759 +
760 + return $text;
761 + }
762 +
763 +}