PluginProbe
Extendify / trunk
Extendify vtrunk
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | app/PartnerData.php +100 -1 3.1.1 → trunk View file →
@@ -59,8 +59,9 @@
59 59 'showSecondaryDomainRecommendationAgent' => false,
60 60 'domainTLDs' => ['com', 'net'],
61 61 'priorityDomainTLDs' => [],
62 62 'stagingSites' => ['wordpress'],
63 + 'trialDomains' => [],
63 64 'domainSearchURL' => '',
64 65 'showDraft' => false,
65 66 'showChat' => false,
66 67 'showAIPageCreation' => false,
@@ -67,8 +68,9 @@
67 68 'enableImageImports-1-14-6' => false,
68 69 'disableLibraryAutoOpen' => false,
69 70 'enableApexDomain' => false,
70 71 'showLaunch' => false,
72 + 'showLaunchTitle' => false,
71 73 'deactivated' => true,
72 74 'launchRedirectWebsite' => false,
73 75 'showAILogo' => false,
74 76 'showProductRecommendations' => false,
@@ -78,8 +80,9 @@
78 80 'customProducts' => [],
79 81 ],
80 82 'license' => 'active',
81 83 'showAIAgents' => false,
84 + 'agentAbilitiesAllowlist' => [],
82 85 'showQuickEdit' => false,
83 86 // Simple front-end Extendify toolbar (replaces WP core admin
84 87 // bar for editors who prefer it). Default style is Launch-aware
85 88 // (simple post-Launch, full before).
@@ -92,9 +95,20 @@
92 95 'useAgentOnboarding' => false,
93 96 'hidePluginNotifications' => false,
94 97 'hideLaunchExitLink' => false,
95 98 'useAutoUpdate' => false,
99 + 'showLaunchUpdate' => false,
96 100 'activeTests' => [],
101 + 'showExtendifyCode' => false,
102 + 'useComingSoon' => false,
103 + 'extendifyCodeData' => [
104 + 'link' => '',
105 + 'title' => '',
106 + 'message' => '',
107 + 'cta-primary' => '',
108 + ],
109 + 'customDesign' => null,
110 + 'strings' => [],
97 111 ];
98 112
99 113 // phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded
100 114 /**
@@ -119,8 +133,9 @@
119 133 self::$config['domainTLDs'] = ($data['domainTLDs'] ?? self::$config['domainTLDs']);
120 134 self::$config['priorityDomainTLDs'] = ($data['priorityDomainTLDs']
121 135 ?? self::$config['priorityDomainTLDs']);
122 136 self::$config['stagingSites'] = array_map('trim', ($data['stagingSites'] ?? self::$config['stagingSites']));
137 + self::$config['trialDomains'] = array_map('trim', ($data['trialDomains'] ?? self::$config['trialDomains']));
123 138 self::$config['domainSearchURL'] = ($data['domainSearchURL'] ?? self::$config['domainSearchURL']);
124 139 self::$logo = isset($data['logo'][0]['thumbnails']['large']['url'])
125 140 ? $data['logo'][0]['thumbnails']['large']['url']
126 141 : self::$logo;
@@ -139,8 +154,9 @@
139 154 'secondaryColorText' => '#ffffff',
140 155 ];
141 156 self::$config['showAIPageCreation'] = ($data['showAIPageCreation'] ?? self::$config['showAIPageCreation']);
142 157 self::$config['showLaunch'] = ($data['showLaunch'] ?? self::$config['showLaunch']);
158 + self::$config['showLaunchTitle'] = ($data['showLaunchTitle'] ?? self::$config['showLaunchTitle']);
143 159 self::$config['deactivated'] = ($data['deactivated'] ?? self::$config['deactivated']);
144 160 self::$config['launchRedirectWebsite'] = ($data['launchRedirectWebsite']
145 161 ?? self::$config['launchRedirectWebsite']);
146 162 self::$config['showAILogo'] = ($data['showAILogo'] ?? self::$config['showAILogo']);
@@ -157,8 +173,10 @@
157 173 self::$config['license'] = ($data['license'] ?? self::$config['license']);
158 174 self::$config['showImprint'] = ($data['showImprint'] ?? self::$config['showImprint']);
159 175 self::$config['showLaunchQuestions'] = ($data['showLaunchQuestions'] ?? self::$config['showLaunchQuestions']);
160 176 self::$config['showAIAgents'] = ($data['showAIAgents'] ?? self::$config['showAIAgents']);
177 + self::$config['agentAbilitiesAllowlist'] = ($data['agentAbilitiesAllowlist']
178 + ?? self::$config['agentAbilitiesAllowlist']);
161 179 self::$config['showQuickEdit'] = ($data['showQuickEdit'] ?? self::$config['showQuickEdit']);
162 180 self::$config['showSimpleToolbar'] = ($data['showSimpleToolbar']
163 181 ?? self::$config['showSimpleToolbar']);
164 182 self::$config['pluginGroupId'] = ($data['pluginGroup'] ?? self::$config['pluginGroupId']);
@@ -169,9 +187,15 @@
169 187 self::$config['hidePluginNotifications'] = ($data['hidePluginNotifications']
170 188 ?? self::$config['hidePluginNotifications']);
171 189 self::$config['hideLaunchExitLink'] = ($data['hideLaunchExitLink'] ?? self::$config['hideLaunchExitLink']);
172 190 self::$config['useAutoUpdate'] = ($data['useAutoUpdate'] ?? self::$config['useAutoUpdate']);
191 + self::$config['showLaunchUpdate'] = ($data['showLaunchUpdate'] ?? self::$config['showLaunchUpdate']);
173 192 self::$config['activeTests'] = ($data['activeTests'] ?? self::$config['activeTests']);
193 + self::$config['showExtendifyCode'] = ($data['showExtendifyCode'] ?? self::$config['showExtendifyCode']);
194 + self::$config['useComingSoon'] = ($data['useComingSoon'] ?? self::$config['useComingSoon']);
195 + self::$config['extendifyCodeData'] = ($data['extendifyCodeData'] ?? self::$config['extendifyCodeData']);
196 + self::$config['customDesign'] = ($data['customDesign'] ?? self::$config['customDesign']);
197 + self::$config['strings'] = ($data['strings'] ?? self::$config['strings']);
174 198
175 199 // Add the job hook to fetch the partner data.
176 200 \add_action('extendify_fetch_partner_data', [self::class, 'fetchPartnerData']);
177 201 }
@@ -255,9 +279,16 @@
255 279 }
256 280
257 281 $sanitizedData = array_merge(
258 282 Sanitizer::sanitizeUnknown($result['data']),
259 - ['consentTermsCustom' => \sanitize_text_field(htmlentities(($result['data']['consentTermsCustom'] ?? '')))]
283 + [
284 + 'consentTermsCustom' => \sanitize_text_field(htmlentities(
285 + ($result['data']['consentTermsCustom'] ?? ''),
286 + ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401
287 + )),
288 + 'customDesign' => self::sanitizeDesign($result['data']['customDesign'] ?? null),
289 + 'strings' => self::sanitizeStrings($result['data']['strings'] ?? null),
290 + ]
260 291 );
261 292
262 293 // Merge before persisting as this data is accessed directly elsewhere.
263 294 $mergedData = array_merge(self::$config, $sanitizedData);
@@ -263,8 +294,76 @@
263 294 $mergedData = array_merge(self::$config, $sanitizedData);
264 295 \update_option('extendify_partner_data_v2', $mergedData);
265 296
266 297 return $mergedData;
298 + }
299 +
300 + /**
301 + * Partner copy overriding the shipped strings.
302 + *
303 + * Which keys exist is the flow's to know, so only shape and text are checked here.
304 + *
305 + * @param mixed $strings The map as the partner-data response carried it.
306 + * @return array
307 + */
308 + public static function sanitizeStrings($strings)
309 + {
310 + return array_map(
311 + 'sanitize_text_field',
312 + self::designEntries($strings, '/^[a-zA-Z][a-zA-Z0-9]*$/', 'is_string')
313 + );
314 + }
315 +
316 + /**
317 + * A design carries GLSL, which the text sanitizers break, so only its shape is checked.
318 + *
319 + * Empty members are left out rather than kept: json_encode writes an empty
320 + * PHP array as [], and the page reads the design as an object.
321 + *
322 + * @param mixed $design The design as the partner-data response carried it.
323 + * @return array|null
324 + */
325 + private static function sanitizeDesign($design)
326 + {
327 + if (!is_array($design)) {
328 + return null;
329 + }
330 +
331 + $shader = ($design['shader'] ?? null);
332 + $logo = ($design['logo'] ?? null);
333 + $kept = array_filter([
334 + 'vars' => self::designEntries(
335 + ($design['vars'] ?? null),
336 + '/^--ext-(ui|tpl)-[a-z0-9-]+$/',
337 + function ($value) {
338 + // A CSS value is a string, but 0.88 is a natural way to write one.
339 + return is_string($value) || is_int($value) || is_float($value);
340 + }
341 + ),
342 + 'templates' => self::designEntries(($design['templates'] ?? null), '/^[A-Za-z0-9_-]+$/', 'is_string'),
343 + 'shader' => is_string($shader) ? \wp_check_invalid_utf8($shader) : '',
344 + 'logo' => is_string($logo) ? \esc_url_raw($logo) : '',
345 + ]);
346 +
347 + return $kept ?: null;
348 + }
349 +
350 + private static function designEntries($entries, $keyPattern, callable $accepts)
351 + {
352 + if (!is_array($entries)) {
353 + return [];
354 + }
355 +
356 + $kept = [];
357 + foreach ($entries as $key => $value) {
358 + if (!is_string($key) || !preg_match($keyPattern, $key) || !$accepts($value)) {
359 + continue;
360 + }
361 +
362 + $kept[$key] = is_string($value) ? \wp_check_invalid_utf8($value) : $value;
363 + }
364 +
365 + return $kept;
267 366 }
268 367
269 368 /**
270 369 * Return colors mapped as css variables