PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.14
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.14
3.1.14 3.1.13 3.1.12 3.1.11 3.1.10 3.1.9 3.1.8 3.1.7 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 All 123 releases
← All changes | Inc/Core/Migrator.php +168 -82 3.1.7 → 3.1.14 View file →
@@ -1,8 +1,8 @@
1 1 <?php
2 2 /**
3 3 * @package FireBox
4 - * @version 3.1.7 Free
4 + * @version 3.1.14 Free
5 5 *
6 6 * @author FirePlugins <[email protected]>
7 7 * @link https://www.fireplugins.com
8 8 * @copyright Copyright © 2026 FirePlugins All Rights Reserved
@@ -56,9 +56,12 @@
56 56 $this->addMissingCapabilities();
57 57
58 58
59 59 $this->addNewIndexes();
60 - $this->skipOnboarding();
60 + $this->addSubmissionsIndexes();
61 + $this->preserveCampaignRoleAccess();
62 + $this->grantExecutePHPCapability();
63 + $this->grantExecuteJSCapability();
61 64
62 65 // Update firebox version
63 66 if ($this->run)
64 67 {
@@ -477,8 +480,13 @@
477 480 if (isset($data['capabilities']['manage_options']) && $data['capabilities']['manage_options'])
478 481 {
479 482 $role = get_role($role_name);
480 483
484 + if (!$role)
485 + {
486 + continue;
487 + }
488 +
481 489 if ($role->has_cap($cap_name))
482 490 {
483 491 continue;
484 492 }
@@ -492,68 +500,10 @@
492 500
493 501 return true;
494 502 }
495 503
496 - #PRO-START
497 - public function update2136version()
498 - {
499 - if (version_compare($this->installedVersion, '2.1.36', '>='))
500 - {
501 - return;
502 - }
504 +
503 505
504 - // Get all boxes, regardless of post status, thus we pass [] to ensure all popups are returned.
505 - $boxes = \FireBox\Core\Helpers\BoxHelper::getAllBoxes([]);
506 -
507 - if (!$boxes->posts)
508 - {
509 - $this->run = true;
510 - return;
511 - }
512 -
513 - foreach ($boxes->posts as $box)
514 - {
515 - // Get post meta and add it to its object
516 - $meta = \FireBox\Core\Helpers\BoxHelper::getMeta($box->ID);
517 -
518 - $box->params = new \FPFramework\Libs\Registry($meta);
519 -
520 - // Migrate firing frequency
521 - $box->params->set('firing_frequency', (int) $box->params->get('firing_frequency') === 1);
522 -
523 - // Migrate scroll amount
524 - if (!$box->params->get('scroll_amount'))
525 - {
526 - $unit = '';
527 - $value = '';
528 -
529 - $scroll_depth = $box->params->get('scroll_depth', 'percentage');
530 -
531 - if ($scroll_depth === 'pixel')
532 - {
533 - $unit = 'px';
534 - $value = $box->params->get('scroll_pixel', 0);
535 - }
536 - else
537 - {
538 - $unit = '%';
539 - $value = $box->params->get('triggerpercentage', 0);
540 - }
541 -
542 - $box->params->set('scroll_amount', [
543 - 'unit' => $unit,
544 - 'value' => $value
545 - ]);
546 - }
547 -
548 - // Update popup settings
549 - update_post_meta($box->ID, 'fpframework_meta_settings', wp_slash(json_decode(wp_json_encode($box->params), true)));
550 - }
551 -
552 - $this->run = true;
553 - }
554 - #PRO_END
555 -
556 506
557 507
558 508 /**
559 509 * Adds new indexes to the logs details table.
@@ -598,49 +548,185 @@
598 548 $this->run = true;
599 549 }
600 550
601 551 /**
602 - * Skip onboarding for existing installations.
552 + * Checks whether an index exists in a table.
603 553 *
604 - * @since 3.1.5
554 + * @param string $index
555 + * @param string $table
605 556 *
557 + * @return bool
558 + */
559 + /**
560 + * Adds missing indexes on the submissions tables to speed up
561 + * form_id/state lookups and submission_id meta lookups.
562 + *
563 + * @since 3.1.9
564 + *
606 565 * @return void
607 566 */
608 - private function skipOnboarding()
567 + private function addSubmissionsIndexes()
609 568 {
610 - if (version_compare($this->installedVersion, '3.1.5', '>='))
569 + if (version_compare($this->installedVersion, '3.1.9', '>='))
611 570 {
612 571 return;
613 572 }
614 573
615 - // Check if this is truly an existing installation by looking for any FireBox campaigns
616 - $has_campaigns = get_posts([
617 - 'post_type' => 'firebox',
618 - 'post_status' => 'any',
619 - 'numberposts' => 1,
620 - 'fields' => 'ids'
621 - ]);
574 + if (!$this->hasIndex('idx_form_id_state', 'firebox_submissions'))
575 + {
576 + global $wpdb;
577 + $wpdb->query("ALTER TABLE {$wpdb->prefix}firebox_submissions ADD INDEX `idx_form_id_state` (`form_id`, `state`)");
578 + }
622 579
623 - // If no campaigns exist, this is likely a fresh install, so don't skip onboarding
624 - if (empty($has_campaigns))
580 + if (!$this->hasIndex('idx_submission_id', 'firebox_submission_meta'))
625 581 {
582 + global $wpdb;
583 + $wpdb->query("ALTER TABLE {$wpdb->prefix}firebox_submission_meta ADD INDEX `idx_submission_id` (`submission_id`)");
584 + }
585 +
586 + $this->run = true;
587 + }
588 +
589 + /**
590 + * Keeps existing roles' campaign access working after the campaign post type moved
591 + * from core's "post" capabilities to FireBox's own.
592 + *
593 + * Before this change anyone with edit_posts could edit campaigns. Granting each role
594 + * the FireBox capability matching the core capability it already holds preserves
595 + * exactly who could do what, so upgrading changes nobody's access.
596 + *
597 + * Note this deliberately does not grant read_fireboxes: that gates the FireBox admin
598 + * screens, was never derived from the post type, and granting it here would hand
599 + * roles access they did not previously have.
600 + *
601 + * Site owners who want to tighten campaign access can now remove these capabilities
602 + * and have it actually take effect, which was not previously the case.
603 + *
604 + * @since 3.1.10
605 + *
606 + * @return void
607 + */
608 + private function preserveCampaignRoleAccess()
609 + {
610 + if (version_compare($this->installedVersion, '3.1.10', '>='))
611 + {
626 612 return;
627 613 }
628 614
629 - // This is an existing installation with campaigns, so skip the onboarding tour.
630 - update_option('firebox_onboarding_completed', \FireBox\Core\Admin\Includes\Onboarding::ONBOARDING_STATUS_SKIPPED);
615 + $map = \FireBox\Core\Admin\Includes\Cpts\Firebox::getPostTypeCapabilities();
631 616
617 + // Only the primitive capabilities are assigned to roles.
618 + unset($map['edit_post'], $map['read_post'], $map['delete_post'], $map['create_posts']);
619 +
620 + // wp_roles() rather than get_editable_roles(): the latter is admin-only and
621 + // undefined on the frontend requests this migration also runs on.
622 + foreach (wp_roles()->role_objects as $role)
623 + {
624 + foreach ($map as $core_cap => $firebox_cap)
625 + {
626 + if (!empty($role->capabilities[$core_cap]))
627 + {
628 + $role->add_cap($firebox_cap);
629 + }
630 + }
631 + }
632 +
632 633 $this->run = true;
633 634 }
634 635
635 636 /**
636 - * Checks whether an index exists in a table.
637 - *
638 - * @param string $index
639 - * @param string $table
640 - *
641 - * @return bool
637 + * Grants the firebox_execute_php capability to administrators.
638 + *
639 + * This capability gates the PHP display condition and PHP Scripts. It is separate
640 + * from the campaign-editing capabilities on purpose, so editing a campaign never
641 + * grants the ability to run PHP. Existing installs get it on administrators here;
642 + * a site owner can grant it to another role deliberately.
643 + *
644 + * @since 3.1.11
645 + *
646 + * @return void
642 647 */
648 + private function grantExecutePHPCapability()
649 + {
650 + if (version_compare($this->installedVersion, '3.1.11', '>='))
651 + {
652 + return;
653 + }
654 +
655 + $cap = 'firebox_execute_php';
656 +
657 + $admin = get_role('administrator');
658 +
659 + if ($admin)
660 + {
661 + if (!$admin->has_cap($cap))
662 + {
663 + $admin->add_cap($cap);
664 + $this->run = true;
665 + }
666 +
667 + return;
668 + }
669 +
670 + // No administrator role on this install: fall back to roles that manage options.
671 + foreach (wp_roles()->role_objects as $role)
672 + {
673 + if (!empty($role->capabilities['manage_options']) && !$role->has_cap($cap))
674 + {
675 + $role->add_cap($cap);
676 + $this->run = true;
677 + }
678 + }
679 + }
680 +
681 + /**
682 + * Grants the firebox_execute_js capability to administrators.
683 + *
684 + * This capability gates campaign-authored JavaScript (the Custom JavaScript
685 + * setting and the "Run Javascript" action) alongside unfiltered_html. It exists
686 + * so administrators keep custom JS where WordPress withholds unfiltered_html
687 + * (multisite site admins, DISALLOW_UNFILTERED_HTML hosts). Like
688 + * firebox_execute_php it is separate from the campaign-editing capabilities on
689 + * purpose, so editing a campaign never grants it; a site owner can grant it to
690 + * another role deliberately.
691 + *
692 + * @since 3.1.11
693 + *
694 + * @return void
695 + */
696 + private function grantExecuteJSCapability()
697 + {
698 + if (version_compare($this->installedVersion, '3.1.11', '>='))
699 + {
700 + return;
701 + }
702 +
703 + $cap = 'firebox_execute_js';
704 +
705 + $admin = get_role('administrator');
706 +
707 + if ($admin)
708 + {
709 + if (!$admin->has_cap($cap))
710 + {
711 + $admin->add_cap($cap);
712 + $this->run = true;
713 + }
714 +
715 + return;
716 + }
717 +
718 + // No administrator role on this install: fall back to roles that manage options.
719 + foreach (wp_roles()->role_objects as $role)
720 + {
721 + if (!empty($role->capabilities['manage_options']) && !$role->has_cap($cap))
722 + {
723 + $role->add_cap($cap);
724 + $this->run = true;
725 + }
726 + }
727 + }
728 +
643 729 private function hasIndex($index = '', $table = '')
644 730 {
645 731 if (empty($index) || empty($table))
646 732 {