PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.5
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.5
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 1.1.1 All 122 releases
firebox / Inc / Core / Helpers / Integrations.php

Integrations.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment 3.1.5, at Inc/Core/Helpers/Integrations.php

1,060 lines 23.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package FireBox
4 * @version 3.1.5
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2026 FirePlugins All Rights Reserved
9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 */
11
12 namespace FireBox\Core\Helpers;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 class Integrations
20 {
21 /**
22 * Global integrations metadata.
23 *
24 * @var array
25 */
26 private static $integrations = [
27 'mailchimp' => [
28 'label' => 'MailChimp',
29 'settings_key' => 'mailchimp_api_key',
30 'class_name' => 'MailChimp',
31 'docs_slug' => 'mailchimp',
32 'logo_file' => 'mailchimp.svg',
33 'connection_type' => 'api_key',
34 'pro_only' => false,
35 'form' => [
36 'legacyApiKeyField' => 'mailchimpAPIKey',
37 'defaults' => [
38 'listId' => '',
39 'doubleOptin' => false,
40 'updateExisting' => true
41 ],
42 'legacyMap' => [
43 'listId' => 'mailchimpListID',
44 'doubleOptin' => 'mailchimpDoubleOptin',
45 'updateExisting' => 'mailchimpUpdateExisting'
46 ],
47 'fields' => [
48 [
49 'type' => 'list',
50 'key' => 'listId',
51 'label' => 'List'
52 ],
53 [
54 'type' => 'toggle',
55 'key' => 'doubleOptin',
56 'label' => 'Double Optin'
57 ],
58 [
59 'type' => 'toggle',
60 'key' => 'updateExisting',
61 'label' => 'Update existing user'
62 ]
63 ]
64 ]
65 ],
66 'brevo' => [
67 'label' => 'Brevo',
68 'settings_key' => 'brevo_api_key',
69 'class_name' => 'Brevo',
70 'docs_slug' => 'brevo',
71 'logo_file' => 'brevo.svg',
72 'connection_type' => 'api_key',
73 'pro_only' => false,
74 'form' => [
75 'legacyApiKeyField' => 'brevoAPIKey',
76 'defaults' => [
77 'listId' => '',
78 'updateExisting' => true
79 ],
80 'legacyMap' => [
81 'listId' => 'brevoListID',
82 'updateExisting' => 'brevoUpdateExisting'
83 ],
84 'fields' => [
85 [
86 'type' => 'list',
87 'key' => 'listId',
88 'label' => 'List'
89 ],
90 [
91 'type' => 'toggle',
92 'key' => 'updateExisting',
93 'label' => 'Update existing user'
94 ]
95 ]
96 ]
97 ]
98
99
100 ];
101
102 /**
103 * Locked integrations metadata for unavailable plans.
104 *
105 * @var array
106 */
107 private static $locked_integrations = [
108
109 'acymailing' => [
110 'label' => 'AcyMailing',
111 'class_name' => 'AcyMailing',
112 'settings_key' => '',
113 'docs_slug' => '',
114 'logo_file' => 'acymailing.png',
115 'connection_type' => 'locked',
116 'required_plan' => 'basic',
117 'form' => [
118 'defaults' => [
119 'listId' => '',
120 'doubleOptin' => false
121 ],
122 'legacyMap' => [
123 'listId' => 'acymailingListID',
124 'doubleOptin' => 'acymailingDoubleOptin'
125 ],
126 'fields' => [
127 [
128 'type' => 'list',
129 'key' => 'listId',
130 'label' => 'List'
131 ],
132 [
133 'type' => 'toggle',
134 'key' => 'doubleOptin',
135 'label' => 'Double Optin'
136 ]
137 ]
138 ]
139 ],
140
141
142 'mailerlite' => [
143 'label' => 'MailerLite',
144 'class_name' => 'MailerLite',
145 'settings_key' => 'mailerlite_api_key',
146 'docs_slug' => 'mailerlite',
147 'logo_file' => 'mailerlite.svg',
148 'connection_type' => 'locked',
149 'required_plan' => 'pro',
150 'form' => [
151 'defaults' => [
152 'listId' => '',
153 'status' => 'active'
154 ],
155 'legacyMap' => [],
156 'fields' => [
157 [
158 'type' => 'list',
159 'key' => 'listId',
160 'label' => 'Group'
161 ],
162 [
163 'type' => 'select',
164 'key' => 'status',
165 'label' => 'Subscriber Status',
166 'options' => [
167 [
168 'value' => 'active',
169 'label' => 'Active'
170 ],
171 [
172 'value' => 'unconfirmed',
173 'label' => 'Unconfirmed'
174 ],
175 [
176 'value' => 'unsubscribed',
177 'label' => 'Unsubscribed'
178 ],
179 [
180 'value' => 'bounced',
181 'label' => 'Bounced'
182 ],
183 [
184 'value' => 'junk',
185 'label' => 'Junk'
186 ]
187 ]
188 ]
189 ]
190 ]
191 ]
192
193 ];
194
195 /**
196 * Returns all integrations with slug in payload.
197 *
198 * @return array
199 */
200 public static function getIntegrations()
201 {
202 $integrations = [];
203
204 foreach (self::$integrations as $slug => $integration)
205 {
206 if (!empty($integration['pro_only']) && !self::isProVersion())
207 {
208 continue;
209 }
210
211 $required_plan = isset($integration['required_plan']) ? trim((string) $integration['required_plan']) : '';
212 if ($required_plan && !self::isRequiredPlanMet($required_plan))
213 {
214 continue;
215 }
216
217 $integrations[$slug] = self::normalizeIntegrationEntry($slug, $integration);
218 }
219
220 return $integrations;
221 }
222
223 /**
224 * Returns locked integrations for unavailable plans.
225 *
226 * @return array
227 */
228 public static function getLockedIntegrations()
229 {
230 $integrations = [];
231
232 foreach (self::$locked_integrations as $slug => $integration)
233 {
234 $required_plan = isset($integration['required_plan']) ? trim((string) $integration['required_plan']) : '';
235 if ($required_plan && self::isRequiredPlanMet($required_plan))
236 {
237 continue;
238 }
239
240 $item = self::normalizeIntegrationEntry($slug, $integration);
241 $item['locked'] = true;
242 $item['connected'] = false;
243
244 $integrations[$slug] = $item;
245 }
246
247 return $integrations;
248 }
249
250 /**
251 * Returns integration metadata by slug or class name.
252 *
253 * @param string $integration
254 *
255 * @return array|null
256 */
257 public static function getIntegration($integration = '')
258 {
259 if (!is_string($integration))
260 {
261 return null;
262 }
263
264 $integration = trim($integration);
265 if (!$integration)
266 {
267 return null;
268 }
269
270 $integrations = array_merge(
271 self::getIntegrations(),
272 self::getLockedIntegrations()
273 );
274 $integration_lc = strtolower($integration);
275
276 if (isset($integrations[$integration_lc]))
277 {
278 return $integrations[$integration_lc];
279 }
280
281 foreach ($integrations as $item)
282 {
283 if (!isset($item['class_name']))
284 {
285 continue;
286 }
287
288 if (strtolower((string) $item['class_name']) === $integration_lc)
289 {
290 return $item;
291 }
292 }
293
294 return null;
295 }
296
297 /**
298 * Resolves a supported integration slug.
299 *
300 * @param string $integration
301 *
302 * @return string|null
303 */
304 public static function getIntegrationSlug($integration = '')
305 {
306 if (!$integration = self::getIntegration($integration))
307 {
308 return null;
309 }
310
311 return $integration['slug'];
312 }
313
314 /**
315 * Returns framework class name for a supported integration.
316 *
317 * @param string $integration
318 *
319 * @return string|null
320 */
321 public static function getFrameworkIntegrationClassName($integration = '')
322 {
323 if (!$integration = self::getIntegration($integration))
324 {
325 return null;
326 }
327
328 return $integration['class_name'];
329 }
330
331 /**
332 * Returns the stored setting key for a given integration.
333 *
334 * @param string $integration
335 *
336 * @return string|null
337 */
338 public static function getIntegrationSettingKey($integration = '')
339 {
340 if (!$integration = self::getIntegration($integration))
341 {
342 return null;
343 }
344
345 $key = isset($integration['settings_key']) ? trim((string) $integration['settings_key']) : '';
346
347 return !empty($key) ? $key : null;
348 }
349
350 /**
351 * Returns integration human label.
352 *
353 * @param string $integration
354 *
355 * @return string
356 */
357 public static function getIntegrationLabel($integration = '')
358 {
359 $integration_input = $integration;
360
361 if (!$integration = self::getIntegration($integration_input))
362 {
363 return trim((string) $integration_input);
364 }
365
366 return $integration['label'];
367 }
368
369 /**
370 * Returns integration docs URL.
371 *
372 * @param string $integration
373 *
374 * @return string
375 */
376 public static function getFindAPIKeyURL($integration = '')
377 {
378 if (!$integration = self::getIntegration($integration))
379 {
380 return '';
381 }
382
383 $docs_slug = isset($integration['docs_slug']) ? trim((string) $integration['docs_slug']) : '';
384 if (!$docs_slug)
385 {
386 return '';
387 }
388
389 return \FPFramework\Base\Functions::getUTMURL(
390 'https://www.fireplugins.com/docs/integrations/' . $docs_slug . '/#find_my_api_key',
391 '',
392 'misc',
393 $docs_slug
394 );
395 }
396
397 /**
398 * Returns settings keys used by integration global API keys.
399 *
400 * @return array
401 */
402 public static function getSettingsKeys()
403 {
404 $keys = array_column(
405 array_merge(self::getIntegrations(), self::getLockedIntegrations()),
406 'settings_key'
407 );
408 $keys = array_filter($keys, function($key) {
409 return is_string($key) && trim($key) !== '';
410 });
411
412 return array_values(array_unique($keys));
413 }
414
415 /**
416 * Returns data used by Settings > Integrations UI.
417 *
418 * @return array
419 */
420 public static function getSettingsManagedIntegrations()
421 {
422 $integrations = [];
423
424 foreach (array_merge(self::getIntegrations(), self::getLockedIntegrations()) as $integration)
425 {
426 $slug = $integration['slug'];
427 $connection_type = self::getConnectionType($slug);
428 $connected = self::isConnected($slug);
429 $is_locked = self::isLocked($slug);
430
431 $item = [
432 'label' => $integration['label'],
433 'slug' => $slug,
434 'connected' => $connected,
435 'locked' => $is_locked,
436 'connection_type' => $connection_type,
437 'status_label' => $is_locked ? __('Locked', 'firebox') : firebox()->_($connected ? 'FB_INTEGRATION_CONNECTED' : 'FB_INTEGRATION_DISCONNECTED'),
438 'logo_url' => !empty($integration['logo_file']) ? FBOX_MEDIA_ADMIN_URL . 'images/integrations/' . $integration['logo_file'] : ''
439 ];
440
441 if ($is_locked)
442 {
443 $required_plan_label = self::getRequiredPlanLabel($slug);
444 /* translators: %s: Required plan label. */
445 $item['locked_message'] = sprintf(__('Upgrade to %s to connect this integration.', 'firebox'), $required_plan_label);
446 $item['upgrade_badge_label'] = sprintf(__('Upgrade to %s', 'firebox'), $required_plan_label);
447 $item['upgrade_label'] = sprintf(fpframework()->_('FPF_UNLOCK_X_FEATURE'), $required_plan_label);
448 $item['upgrade_plan'] = $required_plan_label;
449 $item['current_plan'] = self::getCurrentPlan();
450 $item['upgrade_url'] = self::getUpgradeURL($slug);
451 }
452 else if ($connection_type === 'plugin')
453 {
454 $plugin_state = self::getPluginState($slug);
455
456 if ($plugin_state === 'inactive')
457 {
458 $item['status_label'] = __('Inactive', 'firebox');
459 /* translators: %s: Integration label. */
460 $item['plugin_message'] = sprintf(__('Installed but inactive. Activate %s to use this integration.', 'firebox'), $integration['label']);
461 $item['plugin_action_label'] = __('Activate', 'firebox');
462 $item['plugin_action_url'] = self::getActivatePluginURL($slug);
463 }
464 else if ($plugin_state === 'missing')
465 {
466 $item['status_label'] = __('Not Installed', 'firebox');
467 /* translators: %s: Integration label. */
468 $item['plugin_message'] = sprintf(__('%s is not installed. Install it to use this integration.', 'firebox'), $integration['label']);
469 $item['plugin_action_label'] = __('Install', 'firebox');
470 $item['plugin_action_url'] = self::getInstallPluginURL($slug);
471 }
472 else
473 {
474 /* translators: %s: Integration label. */
475 $item['plugin_message'] = sprintf(__('%s is installed and active.', 'firebox'), $integration['label']);
476 $item['plugin_action_label'] = '';
477 $item['plugin_action_url'] = '';
478 }
479 }
480 else
481 {
482 $item['api_key'] = self::getGlobalAPIKey($slug);
483 $item['docs_url'] = self::getFindAPIKeyURL($slug);
484 }
485
486 $integrations[] = $item;
487 }
488
489 return $integrations;
490 }
491
492 /**
493 * Returns whether integration is connected.
494 *
495 * @param string $integration
496 *
497 * @return bool
498 */
499 public static function isConnected($integration = '')
500 {
501 $connection_type = self::getConnectionType($integration);
502
503 if ($connection_type === 'locked')
504 {
505 return false;
506 }
507
508 if ($connection_type === 'plugin')
509 {
510 return self::getPluginState($integration) === 'active';
511 }
512
513 return self::hasGlobalConnection($integration);
514 }
515
516 /**
517 * Returns integration connection type.
518 *
519 * @param string $integration
520 *
521 * @return string
522 */
523 public static function getConnectionType($integration = '')
524 {
525 if (!$integration = self::getIntegration($integration))
526 {
527 return 'api_key';
528 }
529
530 $type = isset($integration['connection_type']) ? trim((string) $integration['connection_type']) : '';
531
532 return $type ?: 'api_key';
533 }
534
535 /**
536 * Returns plugin state for plugin-based integrations.
537 *
538 * @param string $integration
539 *
540 * @return string active|inactive|missing
541 */
542 public static function getPluginState($integration = '')
543 {
544 if (self::getConnectionType($integration) !== 'plugin')
545 {
546 return 'missing';
547 }
548
549 $plugin_file = self::getPluginFile($integration);
550 if (!$plugin_file)
551 {
552 return 'missing';
553 }
554
555 if (!function_exists('is_plugin_active'))
556 {
557 require_once ABSPATH . 'wp-admin/includes/plugin.php';
558 }
559
560 if (is_plugin_active($plugin_file))
561 {
562 return 'active';
563 }
564
565 $plugins = get_plugins();
566 if (isset($plugins[$plugin_file]))
567 {
568 return 'inactive';
569 }
570
571 return 'missing';
572 }
573
574 /**
575 * Returns plugin install URL for plugin-based integrations.
576 *
577 * @param string $integration
578 *
579 * @return string
580 */
581 public static function getInstallPluginURL($integration = '')
582 {
583 $label = self::getIntegrationLabel($integration);
584
585 return admin_url('plugin-install.php?tab=search&type=term&s=' . rawurlencode($label));
586 }
587
588 /**
589 * Returns plugin activation URL for plugin-based integrations.
590 *
591 * @param string $integration
592 *
593 * @return string
594 */
595 public static function getActivatePluginURL($integration = '')
596 {
597 $plugin_file = self::getPluginFile($integration);
598 if (!$plugin_file)
599 {
600 return '';
601 }
602
603 $url = admin_url('plugins.php?action=activate&plugin=' . rawurlencode($plugin_file));
604
605 return wp_nonce_url($url, 'activate-plugin_' . $plugin_file);
606 }
607
608 /**
609 * Returns integration plugin file.
610 *
611 * @param string $integration
612 *
613 * @return string
614 */
615 public static function getPluginFile($integration = '')
616 {
617 if (!$integration = self::getIntegration($integration))
618 {
619 return '';
620 }
621
622 return isset($integration['plugin_file']) ? trim((string) $integration['plugin_file']) : '';
623 }
624
625 /**
626 * Returns required plan for an integration.
627 *
628 * @param string $integration
629 *
630 * @return string
631 */
632 public static function getRequiredPlan($integration = '')
633 {
634 if (!$integration = self::getIntegration($integration))
635 {
636 return '';
637 }
638
639 return isset($integration['required_plan']) ? strtolower(trim((string) $integration['required_plan'])) : '';
640 }
641
642 /**
643 * Returns required plan label for an integration.
644 *
645 * @param string $integration
646 *
647 * @return string
648 */
649 public static function getRequiredPlanLabel($integration = '')
650 {
651 $required_plan = self::getRequiredPlan($integration);
652
653 return !empty($required_plan) ? ucfirst($required_plan) : __('higher', 'firebox');
654 }
655
656 /**
657 * Returns whether the integration is locked by plan.
658 *
659 * @param string $integration
660 *
661 * @return bool
662 */
663 public static function isLocked($integration = '')
664 {
665 if (!$integration = self::getIntegration($integration))
666 {
667 return false;
668 }
669
670 return !empty($integration['locked']);
671 }
672
673 /**
674 * Returns whether current runtime is Pro.
675 *
676 * @return bool
677 */
678 private static function isProVersion()
679 {
680 return defined('FBOX_LICENSE_TYPE') && FBOX_LICENSE_TYPE === 'pro';
681 }
682
683 /**
684 * Normalizes integration metadata payload.
685 *
686 * @param string $slug
687 * @param array $integration
688 *
689 * @return array
690 */
691 private static function normalizeIntegrationEntry($slug = '', $integration = [])
692 {
693 $integration = is_array($integration) ? $integration : [];
694
695 return array_merge(
696 [
697 'slug' => $slug,
698 'locked' => false
699 ],
700 $integration
701 );
702 }
703
704 /**
705 * Returns current license plan.
706 *
707 * @return string
708 */
709 private static function getCurrentPlan()
710 {
711 if (!defined('FBOX_LICENSE_PLAN'))
712 {
713 return 'free';
714 }
715
716 return strtolower(trim((string) FBOX_LICENSE_PLAN));
717 }
718
719 /**
720 * Returns whether the current plan meets the required plan.
721 *
722 * @param string $required_plan
723 *
724 * @return bool
725 */
726 private static function isRequiredPlanMet($required_plan = '')
727 {
728 $required_plan = strtolower(trim((string) $required_plan));
729 $current_plan = self::getCurrentPlan();
730
731 switch ($required_plan)
732 {
733 case 'growth':
734 return $current_plan === 'growth';
735
736 case 'pro':
737 return in_array($current_plan, ['pro', 'growth'], true);
738
739 case 'basic':
740 return in_array($current_plan, ['basic', 'pro', 'growth'], true);
741
742 default:
743 return true;
744 }
745 }
746
747 /**
748 * Returns upgrade URL for locked integrations.
749 *
750 * @param string $integration
751 *
752 * @return string
753 */
754 private static function getUpgradeURL($integration = '')
755 {
756 if (defined('FBOX_GO_PRO_URL'))
757 {
758 return sprintf(FBOX_GO_PRO_URL, strtolower(trim((string) $integration)) . '-integration');
759 }
760
761 return \FPFramework\Base\Functions::getUTMURL(
762 'https://www.fireplugins.com/upgrade/',
763 '',
764 'feature',
765 strtolower(trim((string) $integration)) . '-integration'
766 );
767 }
768
769 /**
770 * Returns the global API key.
771 *
772 * @param string $integration
773 *
774 * @return string
775 */
776 public static function getGlobalAPIKey($integration = '')
777 {
778 if (!$key = self::getIntegrationSettingKey($integration))
779 {
780 return '';
781 }
782
783 $settings = get_option('firebox_settings', []);
784 if (!is_array($settings))
785 {
786 return '';
787 }
788
789 if (!isset($settings[$key]))
790 {
791 return '';
792 }
793
794 return self::getGlobalAPIKeyEncryption()->decrypt($settings[$key]);
795 }
796
797 /**
798 * Updates an integration global API key.
799 *
800 * @param string $integration
801 * @param string $api_key
802 *
803 * @return bool
804 */
805 public static function setGlobalAPIKey($integration = '', $api_key = '')
806 {
807 if (!$key = self::getIntegrationSettingKey($integration))
808 {
809 return false;
810 }
811
812 $settings = get_option('firebox_settings', []);
813 $settings = is_array($settings) ? $settings : [];
814
815 $settings[$key] = self::getGlobalAPIKeyEncryption()->encrypt($api_key);
816
817 return update_option('firebox_settings', $settings);
818 }
819
820 /**
821 * Returns API key encryption helper.
822 *
823 * @return \FireBox\Core\Helpers\Encryption
824 */
825 private static function getGlobalAPIKeyEncryption()
826 {
827 static $encryption = null;
828 if ($encryption === null)
829 {
830 $encryption = new Encryption();
831 }
832
833 return $encryption;
834 }
835
836 /**
837 * Determines whether there is an active global connection.
838 *
839 * @param string $integration
840 *
841 * @return bool
842 */
843 public static function hasGlobalConnection($integration = '')
844 {
845 return !empty(self::getGlobalAPIKey($integration));
846 }
847
848 /**
849 * Returns legacy action API key from block attributes.
850 *
851 * @param string $integration
852 * @param array $attrs
853 *
854 * @return string
855 */
856 public static function getLegacyActionAPIKey($integration = '', $attrs = [])
857 {
858 $integration = self::getIntegrationSlug($integration);
859 $attrs = is_array($attrs) ? $attrs : [];
860
861 if (!$integration)
862 {
863 return '';
864 }
865
866 switch ($integration)
867 {
868 case 'mailchimp':
869 return isset($attrs['mailchimpAPIKey']) ? trim((string) $attrs['mailchimpAPIKey']) : '';
870
871 case 'brevo':
872 return isset($attrs['brevoAPIKey']) ? trim((string) $attrs['brevoAPIKey']) : '';
873
874 default:
875 return '';
876 }
877 }
878
879 /**
880 * Determines whether the action has a legacy API key.
881 *
882 * @param string $integration
883 * @param array $attrs
884 *
885 * @return bool
886 */
887 public static function hasLegacyActionAPIKey($integration = '', $attrs = [])
888 {
889 return !empty(self::getLegacyActionAPIKey($integration, $attrs));
890 }
891
892 /**
893 * Resolve effective API key used by actions.
894 * Priority: legacy action key -> global key.
895 *
896 * @param string $integration
897 * @param array $attrs
898 * @param string|null $legacy_api_key
899 *
900 * @return string
901 */
902 public static function resolveActionAPIKey($integration = '', $attrs = [], $legacy_api_key = null)
903 {
904 $integration = self::getIntegrationSlug($integration);
905 $attrs = is_array($attrs) ? $attrs : [];
906
907 if (!$integration)
908 {
909 return '';
910 }
911
912 if ($legacy_api_key === null)
913 {
914 $legacy_api_key = self::getLegacyActionAPIKey($integration, $attrs);
915 }
916
917 $legacy_api_key = trim((string) $legacy_api_key);
918 if (!empty($legacy_api_key))
919 {
920 return $legacy_api_key;
921 }
922
923 return self::getGlobalAPIKey($integration);
924 }
925
926 /**
927 * Returns integrations registry used by the Form block editor.
928 *
929 * @return array
930 */
931 public static function getFormEditorIntegrationsRegistry()
932 {
933 $registry = [];
934
935 foreach (array_merge(self::getIntegrations(), self::getLockedIntegrations()) as $integration)
936 {
937 $slug = $integration['slug'];
938 $action = isset($integration['class_name']) ? trim((string) $integration['class_name']) : '';
939 if (!$action)
940 {
941 continue;
942 }
943
944 $registry[$slug] = [
945 'slug' => $slug,
946 'label' => $integration['label'],
947 'action' => $action,
948 'connected' => self::isConnected($slug),
949 'locked' => self::isLocked($slug),
950 'requiredPlan' => self::getRequiredPlan($slug),
951 'requiredPlanLabel' => self::getRequiredPlan($slug) ? self::getRequiredPlanLabel($slug) : '',
952 'connectionType' => self::getConnectionType($slug),
953 'form' => self::getFormSchema($slug)
954 ];
955 }
956
957 $registry = apply_filters('firebox/form/integrations_registry', $registry);
958
959 return is_array($registry) ? $registry : [];
960 }
961
962 /**
963 * Returns normalized Form integration schema for a given integration slug.
964 *
965 * @param string $slug
966 *
967 * @return array
968 */
969 private static function getFormSchema($slug = '')
970 {
971 $integration = self::getIntegration($slug);
972 $integration = is_array($integration) ? $integration : [];
973 $form = isset($integration['form']) && is_array($integration['form']) ? $integration['form'] : [];
974 $form = array_replace_recursive([
975 'legacyApiKeyField' => '',
976 'defaults' => [],
977 'legacyMap' => [],
978 'fields' => []
979 ], $form);
980
981 $legacy_map = [];
982 if (!empty($form['legacyMap']) && is_array($form['legacyMap']))
983 {
984 foreach ($form['legacyMap'] as $setting_key => $legacy_field)
985 {
986 $setting_key = trim((string) $setting_key);
987 $legacy_field = trim((string) $legacy_field);
988 if ($setting_key === '' || $legacy_field === '')
989 {
990 continue;
991 }
992
993 $legacy_map[$setting_key] = $legacy_field;
994 }
995 }
996
997 $fields = [];
998 if (!empty($form['fields']) && is_array($form['fields']))
999 {
1000 foreach ($form['fields'] as $field)
1001 {
1002 if (!is_array($field))
1003 {
1004 continue;
1005 }
1006
1007 $type = strtolower(trim((string) (isset($field['type']) ? $field['type'] : '')));
1008 $key = trim((string) (isset($field['key']) ? $field['key'] : ''));
1009
1010 if (!in_array($type, ['list', 'select', 'toggle'], true) || $key === '')
1011 {
1012 continue;
1013 }
1014
1015 $normalized_field = [
1016 'type' => $type,
1017 'key' => $key,
1018 'label' => !empty($field['label']) ? __((string) $field['label'], 'firebox') : ''
1019 ];
1020
1021 if ($type === 'select')
1022 {
1023 $options = [];
1024 if (!empty($field['options']) && is_array($field['options']))
1025 {
1026 foreach ($field['options'] as $option)
1027 {
1028 if (!is_array($option) || !array_key_exists('value', $option))
1029 {
1030 continue;
1031 }
1032
1033 $options[] = [
1034 'value' => $option['value'],
1035 'label' => !empty($option['label']) ? __((string) $option['label'], 'firebox') : ''
1036 ];
1037 }
1038 }
1039
1040 if (empty($options))
1041 {
1042 continue;
1043 }
1044
1045 $normalized_field['options'] = $options;
1046 }
1047
1048 $fields[] = $normalized_field;
1049 }
1050 }
1051
1052 return [
1053 'legacyApiKeyField' => trim((string) $form['legacyApiKeyField']),
1054 'defaults' => is_array($form['defaults']) ? $form['defaults'] : [],
1055 'legacyMap' => $legacy_map,
1056 'fields' => $fields
1057 ];
1058 }
1059 }
1060