PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.9
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.9
4.1.0 4.0.9 4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 trunk 1.0.0 2.0.0 2.0.1 2.0.2 2.0.3 3.0 3.0.1 3.0.2 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1
superb-blocks / src / data / controllers / class-link-controller.php
superb-blocks / src / data / controllers Last commit date
class-cache-controller.php 2 weeks ago class-css-controller.php 2 weeks ago class-domainshift-controller.php 2 weeks ago class-key-controller.php 2 weeks ago class-link-controller.php 2 weeks ago class-log-controller.php 2 weeks ago class-option-controller.php 2 weeks ago class-rest-controller.php 2 weeks ago
class-link-controller.php
186 lines
1 <?php
2
3 namespace SuperbAddons\Data\Controllers;
4
5 use SuperbAddons\Admin\Utils\AdminLinkSource;
6
7 defined('ABSPATH') || exit();
8
9 class LinkController
10 {
11 // Upsell modal presentation buckets: two independent toggles on the rich
12 // modal layout, reported together as one variant string.
13 // - bonus: a discount line rendered under the modal footer.
14 // - cta: the modal CTA label wording.
15 const VARIANT_GROUP = 'modal-v3';
16 const BONUS_SALT = 'modal-v3-bonus';
17 const CTA_SALT = 'modal-v3-cta';
18
19 const SEED_OPTION = 'superbaddons_pre_activation';
20
21 // Delayed admin notice content buckets
22 // Bucketed independently
23 const NOTICE_GROUP = 'notice-v2';
24 const NOTICE_SALT = 'notice-v2';
25 const NOTICE_VARIANT_DISCOUNT = 'discount';
26 const NOTICE_VARIANT_BENEFITS = 'benefits';
27
28 const NOTICE_FILE_DISCOUNT = 'addons-notice.php';
29 const NOTICE_FILE_BENEFITS = 'addons-notice-benefits.php';
30
31 // Admin navigation CTA buckets: direct link vs opening the upsell modal
32 // Bucketed independently
33 const NAV_GROUP = 'nav-v1';
34 const NAV_SALT = 'nav-v1';
35 const NAV_VARIANT_DIRECT = 'nav-direct';
36 const NAV_VARIANT_MODAL = 'nav-modal';
37
38 private static $cached = null;
39 private static $notice_variant = null;
40 private static $nav_variant = null;
41
42 /**
43 * @return array { active: bool, group: string, variant: string, bonusLine: bool, ctaAll: bool }
44 */
45 public static function GetState()
46 {
47 if (self::$cached !== null) {
48 return self::$cached;
49 }
50
51 $bonus_line = self::Bucket(self::BONUS_SALT) === 1;
52 $cta_all = self::Bucket(self::CTA_SALT) === 1;
53
54 // active is unconditionally true for every install. The JS link builder
55 // reads it to decide whether to append the su_exp/su_var params.
56 self::$cached = array(
57 'active' => true,
58 'group' => self::VARIANT_GROUP,
59 'variant' => ($bonus_line ? 'bonus' : 'plain') . '-' . ($cta_all ? 'all' : 'prem'),
60 'bonusLine' => $bonus_line,
61 'ctaAll' => $cta_all,
62 );
63 return self::$cached;
64 }
65
66 public static function GetVariant()
67 {
68 $state = self::GetState();
69 return $state['variant'];
70 }
71
72 public static function GetLinkExpArgs($experiment = 'upsell')
73 {
74 if ($experiment === 'notice') {
75 return self::GetNoticeExpArgs();
76 }
77 if ($experiment === 'nav') {
78 return self::GetNavExpArgs();
79 }
80
81 $state = self::GetState();
82 if (empty($state['active'])) {
83 return array();
84 }
85 return array(
86 'su_exp' => $state['group'],
87 'su_var' => $state['variant'],
88 );
89 }
90
91 /**
92 * @return array { active, group, variant, bonusLine, ctaAll, sourceExperiments }
93 */
94 public static function GetJsConfig()
95 {
96 $state = self::GetState();
97 // Links built for these sources report their own group/variant instead
98 // of the modal group, so each surface's clicks stay attributable to the
99 // surface they came from.
100 $state['sourceExperiments'] = array(
101 AdminLinkSource::NAVIGATION_CTA => array(
102 'group' => self::NAV_GROUP,
103 'variant' => self::GetNavVariant(),
104 ),
105 );
106 return $state;
107 }
108
109 public static function Localize($handle)
110 {
111 wp_localize_script($handle, 'superbAddonsUpsell', self::GetJsConfig());
112 }
113
114 public static function GetNoticeVariant()
115 {
116 if (self::$notice_variant !== null) {
117 return self::$notice_variant;
118 }
119
120 self::$notice_variant = self::Bucket(self::NOTICE_SALT) === 1
121 ? self::NOTICE_VARIANT_BENEFITS
122 : self::NOTICE_VARIANT_DISCOUNT;
123 return self::$notice_variant;
124 }
125
126 public static function GetNoticeContentFile()
127 {
128 return self::GetNoticeVariant() === self::NOTICE_VARIANT_BENEFITS
129 ? self::NOTICE_FILE_BENEFITS
130 : self::NOTICE_FILE_DISCOUNT;
131 }
132
133 public static function GetNoticeExpArgs()
134 {
135 return array(
136 'su_exp' => self::NOTICE_GROUP,
137 'su_var' => self::GetNoticeVariant(),
138 );
139 }
140
141 public static function GetNavVariant()
142 {
143 if (self::$nav_variant !== null) {
144 return self::$nav_variant;
145 }
146
147 self::$nav_variant = self::Bucket(self::NAV_SALT) === 1
148 ? self::NAV_VARIANT_MODAL
149 : self::NAV_VARIANT_DIRECT;
150 return self::$nav_variant;
151 }
152
153 public static function NavOpensModal()
154 {
155 return self::GetNavVariant() === self::NAV_VARIANT_MODAL;
156 }
157
158 public static function GetNavExpArgs()
159 {
160 return array(
161 'su_exp' => self::NAV_GROUP,
162 'su_var' => self::GetNavVariant(),
163 );
164 }
165
166 // Salted per bucket so each assignment is independent of the other
167 // seed-derived groupings (including earlier salts on the same seed).
168 // abs() is required: crc32() returns a negative int on 32-bit PHP.
169 private static function Bucket($salt)
170 {
171 return abs(crc32($salt . '|' . self::SeedValue())) % 2;
172 }
173
174 private static function SeedValue()
175 {
176 $seed = get_option(self::SEED_OPTION, '');
177 // The seed option can be missing (e.g. removed by a full plugin reset).
178 // Fall back to a stable per-site value rather than writing on a read
179 // path or lumping every seedless install into one bucket.
180 if ($seed === '' || $seed === false) {
181 $seed = home_url();
182 }
183 return (string) $seed;
184 }
185 }
186