PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.10.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.10.0
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
← All changes | app/Functions/Utility.php +944 -77 1.0.952.10.0 View file →
@@ -1,8 +1,9 @@
1 1 <?php
2 2
3 3 namespace FluentCommunity\App\Functions;
4 4
5 +use FluentCommunity\App\App;
5 6 use FluentCommunity\App\Models\Meta;
6 7 use FluentCommunity\App\Models\Space;
7 8 use FluentCommunity\App\Models\SpaceGroup;
8 9 use FluentCommunity\App\Models\Term;
@@ -9,17 +10,34 @@
9 10 use FluentCommunity\App\Services\FeedsHelper;
10 11 use FluentCommunity\App\Services\Helper;
11 12 use FluentCommunity\Framework\Support\Arr;
12 13 use FluentCommunity\Modules\Course\Model\Course;
14 +use FluentCommunity\Modules\PushNotification\PushNotificationModule;
13 15
14 16 class Utility
15 17 {
18 + public static function isDev()
19 + {
20 + static $isDev = null;
21 + if ($isDev !== null) {
22 + return $isDev;
23 + }
16 24
25 + $config = App::getInstance()->config;
26 + $isDev = $config->get('app.env') === 'dev';
27 + return $isDev;
28 + }
29 +
17 30 public static function getApp($instance = null)
18 31 {
19 32 return \FluentCommunity\App\App::getInstance($instance);
20 33 }
21 34
35 + public static function extender()
36 + {
37 + return new FluentExtendApi();
38 + }
39 +
22 40 /**
23 41 * Get Global Fluent Community Option
24 42 * @param string $key The option name
25 43 * @param mixed $default the default value of the option if option is not available
@@ -39,8 +57,45 @@
39 57 return $default;
40 58 });
41 59 }
42 60
61 + /**
62 + * Update Global Fluent Community Option
63 + * @param string $key The option name
64 + * @param mixed $value the value of the option
65 + * @return \FluentCommunity\App\Models\Meta
66 + */
67 + public static function updateOption($key, $value)
68 + {
69 + $exist = \FluentCommunity\App\Models\Meta::where('object_type', 'option')
70 + ->where('meta_key', $key)
71 + ->first();
72 + if ($exist) {
73 + $exist->value = $value;
74 + $exist->save();
75 +
76 + } else {
77 + $exist = \FluentCommunity\App\Models\Meta::create([
78 + 'meta_key' => $key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
79 + 'object_type' => 'option',
80 + 'value' => $value
81 + ]);
82 + }
83 +
84 + self::setCache('option_' . $key, $value);
85 +
86 + return $exist;
87 + }
88 +
89 + public static function deleteOption($key)
90 + {
91 + \FluentCommunity\App\Models\Meta::where('object_type', 'option')
92 + ->where('meta_key', $key)
93 + ->delete();
94 +
95 + self::forgetCache('option_' . $key);
96 + }
97 +
43 98 public static function getFeaturesConfig()
44 99 {
45 100 static $features = null;
46 101
@@ -50,19 +105,23 @@
50 105
51 106 $features = self::getOption('fluent_community_features', []);
52 107
53 108 $defaults = [
54 - 'leader_board_module' => 'yes',
55 - 'course_module' => 'yes',
56 - 'giphy_module' => 'no',
57 - 'giphy_api_key' => '',
58 - 'emoji_module' => 'yes',
59 - 'cloud_storage' => 'no',
60 - 'invitation' => 'yes',
61 - 'user_badge' => 'yes',
109 + 'leader_board_module' => 'yes',
110 + 'course_module' => 'yes',
111 + 'giphy_module' => 'no',
112 + 'giphy_api_key' => '',
113 + 'emoji_module' => 'yes',
114 + 'cloud_storage' => 'no',
115 + 'invitation' => 'yes',
116 + 'user_badge' => 'yes',
117 + 'has_crm_sync' => 'no',
118 + 'content_moderation' => 'no',
119 + 'followers_module' => 'no',
120 + 'custom_profile_fields' => 'no',
121 + 'pwa_module' => 'no',
62 122 ];
63 123
64 -
65 124 if (defined('FLUENT_COMMUNITY_CLOUD_STORAGE') && FLUENT_COMMUNITY_CLOUD_STORAGE) {
66 125 $features['cloud_storage'] = 'yes';
67 126 }
68 127
@@ -68,8 +127,9 @@
68 127
69 128 $features = wp_parse_args($features, $defaults);
70 129
71 130 $hasPro = defined('FLUENT_COMMUNITY_PRO') && FLUENT_COMMUNITY_PRO;
131 +
72 132 if (!$hasPro) {
73 133 $features['leader_board_module'] = 'no';
74 134 $features['giphy_module'] = 'no';
75 135 $features['emoji_module'] = 'no';
@@ -74,8 +134,11 @@
74 134 $features['giphy_module'] = 'no';
75 135 $features['emoji_module'] = 'no';
76 136 $features['cloud_storage'] = 'no';
77 137 $features['user_badge'] = 'no';
138 + $features['followers_module'] = 'no';
139 + $features['custom_profile_fields'] = 'no';
140 + $features['pwa_module'] = 'no';
78 141 }
79 142
80 143 return $features;
81 144 }
@@ -80,36 +143,8 @@
80 143 return $features;
81 144 }
82 145
83 146 /**
84 - * Update Global Fluent Community Option
85 - * @param string $key The option name
86 - * @param mixed $value the value of the option
87 - * @return \FluentCommunity\App\Models\Meta
88 - */
89 - public static function updateOption($key, $value)
90 - {
91 - $exist = \FluentCommunity\App\Models\Meta::where('object_type', 'option')
92 - ->where('meta_key', $key)
93 - ->first();
94 - if ($exist) {
95 - $exist->value = $value;
96 - $exist->save();
97 -
98 - } else {
99 - $exist = \FluentCommunity\App\Models\Meta::create([
100 - 'meta_key' => $key,
101 - 'object_type' => 'option',
102 - 'value' => $value
103 - ]);
104 - }
105 -
106 - self::setCache('option_' . $key, $value);
107 -
108 - return $exist;
109 - }
110 -
111 - /**
112 147 * @param $key
113 148 * @param $callback
114 149 * @param $expire
115 150 * @return false|mixed
@@ -168,30 +203,40 @@
168 203 return $settings;
169 204 }
170 205
171 206 $defaults = [
172 - 'dark_mode' => 'yes',
173 - 'fixed_page_header' => 'yes',
174 - 'show_powered_by' => 'yes',
175 - 'feed_link_on_sidebar' => 'yes',
176 - 'fixed_sidebar' => 'no',
177 - 'icon_on_header_menu' => 'no',
178 - 'affiliate_id' => '',
179 - 'rich_post_layout' => 'classic',
180 - 'post_title_pref' => 'optional',
181 - 'a11y_enhancement_style' => 'no',
207 + 'dark_mode' => 'yes',
208 + 'default_theme_mode' => 'light',
209 + 'fixed_page_header' => 'yes',
210 + 'show_powered_by' => 'yes',
211 + 'feed_link_on_sidebar' => 'yes',
212 + 'show_post_modal' => 'yes',
213 + 'fixed_sidebar' => 'no',
214 + 'icon_on_header_menu' => 'no',
215 + 'affiliate_id' => '',
216 + 'rich_post_layout' => 'classic',
217 + 'member_list_layout' => 'classic', // grid, classic
218 + 'default_feed_layout' => 'timeline', // list, timeline
219 + 'disable_feed_layout' => 'no',
220 + 'post_title_pref' => 'optional',
221 + 'max_media_per_post' => 4,
222 + 'disable_feed_sort_by' => 'no',
223 + 'default_feed_sort_by' => '',
224 + 'collapse_sidebar_groups' => 'no',
225 + 'hide_header_on_scroll' => 'no',
226 + 'enable_sidebar_toggle' => 'no'
182 227 ];
183 -
184 228 $settings = self::getOption('customization_settings', $defaults);
185 229
186 230 $settings = wp_parse_args($settings, $defaults);
187 -
231 + $settings = apply_filters('fluent_community/customization_settings', $settings);
188 232 if (!defined('FLUENT_COMMUNITY_PRO')) {
189 233 $settings['show_powered_by'] = 'yes';
190 234 $settings['affiliate_id'] = '';
191 235 $settings['rich_post_layout'] = 'classic';
236 + $settings['member_list_layout'] = 'classic';
237 + $settings['enable_sidebar_toggle'] = 'no';
192 238 }
193 -
194 239 return $settings;
195 240 }
196 241
197 242 public static function getCustomizationSetting($key)
@@ -217,27 +262,34 @@
217 262 if ($settings) {
218 263 return $settings;
219 264 }
220 265
221 - $settings = self::getFromCache('privacy_settings', function () {
222 - $defaults = [
223 - 'members_page_status' => 'everybody', // everybody, logged_in, admin_only
224 - 'can_customize_username' => 'no',
225 - 'show_last_activity' => 'yes',
226 - 'user_space_visibility' => 'everybody', // everybody, logged_in, admin_only
227 - ];
266 + $defaults = [
267 + 'can_customize_username' => 'no',
268 + 'can_change_email' => 'no',
269 + 'can_change_password' => 'yes',
270 + 'show_last_activity' => 'yes',
271 + 'can_deactive_account' => 'no',
272 + 'email_auto_login' => 'yes',
273 + 'enable_gravatar' => 'yes',
274 + 'enable_user_sync' => 'yes',
275 + 'skip_crm_undeliverable_emails' => 'yes',
276 + 'members_page_status' => 'everybody', // everybody, logged_in, admin_only
277 + 'profile_page_visibility' => 'everybody', // everybody, logged_in, admin_only
278 + 'user_space_visibility' => 'everybody', // everybody, logged_in, admin_only
279 + 'leaderboard_members_visibility' => 'everybody', // everybody, logged_in, admin_only
280 + ];
228 281
229 - $settings = self::getOption('privacy_settings', $defaults);
282 + $settings = self::getOption('privacy_settings', $defaults);
230 283
231 - $settings = wp_parse_args($settings, $defaults);
284 + $settings = wp_parse_args($settings, $defaults);
232 285
233 - if (!defined('FLUENT_COMMUNITY_PRO')) {
234 - $settings['can_customize_username'] = 'no';
235 - }
286 + if (!defined('FLUENT_COMMUNITY_PRO')) {
287 + $settings['can_customize_username'] = 'no';
288 + $settings['can_change_email'] = 'no';
289 + $settings['email_auto_login'] = 'no';
290 + }
236 291
237 - return $settings;
238 - });
239 -
240 292 return $settings;
241 293 }
242 294
243 295 public static function canViewMembersPage()
@@ -254,8 +306,40 @@
254 306
255 307 return apply_filters('fluent_community/can_view_members_page', Helper::isModerator(), $pageStatus);
256 308 }
257 309
310 + public static function canViewLeaderboardMembers()
311 + {
312 + $pageStatus = self::getPrivacySetting('leaderboard_members_visibility');
313 +
314 + if ($pageStatus == 'everybody') {
315 + return apply_filters('fluent_community/can_view_leaderboard_members', true, $pageStatus);
316 + }
317 +
318 + if ($pageStatus == 'logged_in') {
319 + return apply_filters('fluent_community/can_view_leaderboard_members', is_user_logged_in(), $pageStatus);
320 + }
321 +
322 + return apply_filters('fluent_community/can_view_leaderboard_members', Helper::isModerator(), $pageStatus);
323 + }
324 +
325 + public static function canViewUserProfile($targetUserId = null)
326 + {
327 + $pageStatus = self::getPrivacySetting('profile_page_visibility');
328 +
329 + if ($pageStatus == 'everybody') {
330 + return apply_filters('fluent_community/can_view_user_profile', true, $pageStatus, $targetUserId);
331 + }
332 +
333 + if ($pageStatus == 'logged_in') {
334 + return apply_filters('fluent_community/can_view_user_profile', is_user_logged_in(), $pageStatus, $targetUserId);
335 + }
336 +
337 + $isOwn = $targetUserId && (get_current_user_id() === $targetUserId);
338 +
339 + return apply_filters('fluent_community/can_view_user_profile', ($isOwn || Helper::isModerator()), $pageStatus, $targetUserId);
340 + }
341 +
258 342 public static function getPrivacySetting($key)
259 343 {
260 344 $settings = self::getPrivacySettings();
261 345 return Arr::get($settings, $key);
@@ -265,8 +349,12 @@
265 349 {
266 350 $preSettings = self::getPrivacySettings();
267 351 $settings = Arr::only($settings, array_keys($preSettings));
268 352
353 + $settings = array_map(function ($value) {
354 + return is_scalar($value) ? sanitize_text_field($value) : '';
355 + }, $settings);
356 +
269 357 self::updateOption('privacy_settings', $settings);
270 358 self::forgetCache('privacy_settings');
271 359
272 360 return $settings;
@@ -271,8 +359,13 @@
271 359
272 360 return $settings;
273 361 }
274 362
363 + public static function showLastActivity()
364 + {
365 + return self::getPrivacySetting('show_last_activity') === 'yes' || Helper::isModerator();
366 + }
367 +
275 368 public static function isCustomizationEnabled($key, $matchingValue = 'yes')
276 369 {
277 370 $settings = self::getCustomizationSettings();
278 371 return isset($settings[$key]) && $settings[$key] === $matchingValue;
@@ -277,17 +370,19 @@
277 370 $settings = self::getCustomizationSettings();
278 371 return isset($settings[$key]) && $settings[$key] === $matchingValue;
279 372 }
280 373
281 - public static function getProductUrl($isPowered = false)
374 + public static function getProductUrl($isPowered = false, $params = [])
282 375 {
283 376 $url = 'https://fluentcommunity.co/';
284 377 if ($isPowered) {
285 - $params = [
378 + $defaultParams = [
286 379 'utm_source' => 'power_footer',
287 380 'utm_medium' => 'site',
288 381 'utm_campaign' => 'powered_by'
289 382 ];
383 + $params = wp_parse_args($params, $defaultParams);
384 +
290 385 $settings = self::getCustomizationSettings();
291 386 $affId = Arr::get($settings, 'affiliate_id');
292 387 if ($affId) {
293 388 $params['ref'] = $affId;
@@ -292,19 +387,57 @@
292 387 if ($affId) {
293 388 $params['ref'] = $affId;
294 389 }
295 390
296 - $url = add_query_arg($params, $url);
391 + return add_query_arg($params, $url);
297 392 }
298 393
299 394 return add_query_arg([
300 395 'utm_source' => 'plugin',
301 396 'utm_medium' => 'site',
302 - 'utm_campaign' => 'pligin_ui'
397 + 'utm_campaign' => 'plugin_ui'
303 398 ], $url);
304 399 }
305 400
306 401 /**
402 + * Build a spec-compliant "Upgrade to Pro" URL.
403 + *
404 + * Follows the shared Fluent* UTM spec:
405 + * utm_source = fluent-community (fixed vocabulary, never the wp.org slug)
406 + * utm_medium = free_plugin | pro_plugin (acquisition vs cross-sell)
407 + * utm_campaign= upgrade_pro (override for xsell_<target> / license_* )
408 + * utm_content = the exact placement, e.g. feature_lock_moderation, upgrade_page
409 + * utm_term = plugin version that generated the link
410 + * utm_id = promo id, blank normally (omit unless passed)
411 + *
412 + * @param string $content The utm_content placement.
413 + * @param array $overrides Override any utm_* param (e.g. utm_campaign for cross-sell).
414 + * @return string
415 + */
416 + public static function getProUpgradeUrl($content = 'upgrade_page', $overrides = [])
417 + {
418 + $baseUrl = apply_filters(
419 + 'fluent_community/pro_upgrade_base_url',
420 + 'https://fluentcommunity.co/pricing/'
421 + );
422 +
423 + $params = wp_parse_args($overrides, [
424 + 'utm_source' => 'fluent-community',
425 + 'utm_medium' => defined('FLUENT_COMMUNITY_PRO_VERSION') ? 'pro_plugin' : 'free_plugin',
426 + 'utm_campaign' => 'upgrade_pro',
427 + 'utm_content' => $content,
428 + 'utm_term' => FLUENT_COMMUNITY_PLUGIN_VERSION,
429 + ]);
430 +
431 + // Drop any blank params (e.g. an unset utm_id) so they never hit the URL.
432 + $params = array_filter($params, function ($value) {
433 + return $value !== '' && $value !== null;
434 + });
435 +
436 + return add_query_arg($params, $baseUrl);
437 + }
438 +
439 + /**
307 440 * Get the email notification settings.
308 441 *
309 442 * @return array The email notification settings.
310 443 */
@@ -325,13 +458,14 @@
325 458 'send_from_email' => '',
326 459 'send_from_name' => '',
327 460 'reply_to_email' => '',
328 461 'reply_to_name' => '',
329 - 'email_footer' => 'You are getting this email because you are a member of {{site_name_with_url}}.\n\n{{manage_email_notification_url|Manage Your Email Notifications Preference}}.',
462 + 'email_footer' => 'You are getting this email because you are a member of {{site_name_with_url}}.' . PHP_EOL . PHP_EOL . '{{manage_email_notification_url|Manage Your Email Notifications Preference}}.',
330 463 'disable_powered_by' => 'no',
464 + 'logo' => ''
331 465 ];
332 466
333 - $settings = self::getOption('global_email_settings', $default);
467 + $settings = array_filter(self::getOption('global_email_settings', $default));
334 468 $settings = wp_parse_args($settings, $default);
335 469
336 470 if (!defined('FLUENT_COMMUNITY_PRO')) {
337 471 $settings['disable_powered_by'] = 'no';
@@ -343,8 +477,35 @@
343 477
344 478 return $settings;
345 479 }
346 480
481 + public static function getPushNotificationSettings()
482 + {
483 + static $settings;
484 + if ($settings) return $settings;
485 +
486 + $default = [
487 + 'push_enabled' => 'yes',
488 + 'com_my_post_push' => 'yes',
489 + 'reply_my_com_push' => 'yes',
490 + 'mention_push' => 'yes',
491 + 'co_com_push' => 'yes',
492 + 'prompt_placements' => PushNotificationModule::PROMPT_PLACEMENTS
493 + ];
494 +
495 + $settings = self::getOption('global_push_settings', $default);
496 +
497 + $settings = wp_parse_args($settings, $default);
498 +
499 + return $settings;
500 + }
501 +
502 + public static function hasEmailAnnouncementEnabled()
503 + {
504 + $settings = self::getEmailNotificationSettings();
505 + return Arr::get($settings, 'mention_mail', 'no') === 'yes';
506 + }
507 +
347 508 public static function postTitlePref()
348 509 {
349 510 $pref = self::getCustomizationSetting('post_title_pref');
350 511
@@ -360,9 +521,9 @@
360 521 if ($byGroups) {
361 522 return SpaceGroup::orderBy('serial', 'ASC')->with('spaces', function ($q) {
362 523 $q->orderBy('serial', 'ASC')
363 524 ->where('type', 'community');
364 - })->all();
525 + })->get();
365 526 }
366 527
367 528 return Space::where('type', 'community')->orderBy('serial', 'ASC')->get();
368 529 }
@@ -372,9 +533,9 @@
372 533 if ($byGroups) {
373 534 return SpaceGroup::orderBy('serial', 'ASC')->with('spaces', function ($q) {
374 535 $q->orderBy('serial', 'ASC')
375 536 ->where('type', 'course');
376 - })->all();
537 + })->get();
377 538 }
378 539
379 540 return Course::orderBy('serial', 'ASC')->get();
380 541 }
@@ -389,8 +550,25 @@
389 550 $key = 'fluent_community_post_topics';
390 551 $topics = self::getFromCache($key, function () {
391 552 $topics = Term::where('taxonomy_name', 'post_topic')->orderBy('title', 'ASC')->get();
392 553
554 + // Respect the admin-defined order (settings.serial) when present;
555 + // topics without a serial fall back to the alphabetical order above.
556 + $topics = $topics->sort(function ($a, $b) {
557 + $serialA = Arr::get($a->settings, 'serial');
558 + $serialB = Arr::get($b->settings, 'serial');
559 + if ($serialA === null && $serialB === null) {
560 + return 0;
561 + }
562 + if ($serialA === null) {
563 + return 1;
564 + }
565 + if ($serialB === null) {
566 + return -1;
567 + }
568 + return (int) $serialA <=> (int) $serialB;
569 + })->values();
570 +
393 571 /*
394 572 * object_id = term_id
395 573 * meta_key = space_id
396 574 */
@@ -413,8 +591,9 @@
413 591 'title' => $topic->title,
414 592 'description' => $topic->description,
415 593 'slug' => $topic->slug,
416 594 'admin_only' => Arr::get($topic->settings, 'admin_only', 'no'),
595 + 'serial' => Arr::get($topic->settings, 'serial'),
417 596 'space_ids' => isset($relations[$topic->id]) ? $relations[$topic->id] : []
418 597 ];
419 598 }
420 599
@@ -426,14 +605,12 @@
426 605
427 606 public static function getTopicsBySpaceId($spaceId)
428 607 {
429 608 $topics = self::getTopics();
430 -
431 609 $topics = array_filter($topics, function ($topic) use ($spaceId) {
432 610 return in_array($spaceId, $topic['space_ids']);
433 611 });
434 -
435 - return $topics;
612 + return array_values($topics);
436 613 }
437 614
438 615 public static function getMaxRunTime()
439 616 {
@@ -441,8 +618,13 @@
441 618 $maxRunTime = (int)ini_get('max_execution_time');
442 619 if ($maxRunTime === 0) {
443 620 $maxRunTime = 60;
444 621 }
622 + // If set to 0 (unlimited) or a negative value, return a large number
623 + if ($maxRunTime <= 0) {
624 + return PHP_INT_MAX;
625 + }
626 +
445 627 } else {
446 628 $maxRunTime = 30;
447 629 }
448 630
@@ -451,8 +633,693 @@
451 633 }
452 634
453 635 $maxRunTime = $maxRunTime - 3;
454 636
455 - return apply_filters('fluent_communutt/max_execution_time', $maxRunTime);
637 + return apply_filters('fluent_community/max_execution_time', $maxRunTime);
456 638 }
457 639
640 + public static function getColorSchemas()
641 + {
642 + $defaultCustom = [
643 + 'title' => __('Custom', 'fluent-community'),
644 + 'selectors' => [
645 + 'body' => [],
646 + 'fcom_top_menu' => [],
647 + 'spaces' => []
648 + ],
649 + ];
650 + $shemas = apply_filters('fluent-community/color_schemas', [
651 + 'lightSkins' => [
652 + 'default' => [
653 + 'title' => __('Default', 'fluent-community'),
654 + 'selectors' => [
655 + 'body' => [
656 + 'primary_bg' => '#ffffff',
657 + 'secondary_bg' => '#f0f2f5',
658 + 'secondary_content_bg' => '#f0f3f5',
659 + 'active_bg' => '#f0f3f5',
660 + 'light_bg' => '#E1E4EA',
661 + 'deep_bg' => '#222530',
662 + 'menu_text' => '#545861',
663 + 'primary_text' => '#19283a',
664 + 'secondary_text' => '#525866',
665 + 'text_off' => '#959595',
666 + 'primary_button' => '#2B2E33',
667 + 'primary_button_text' => '#ffffff',
668 + 'primary_border' => '#e3e8ee',
669 + 'secondary_border' => '#9CA3AF',
670 + 'highlight_bg' => '#fffce3',
671 + 'text_link' => '#2271b1',
672 + ],
673 + 'fcom_top_menu' => [
674 + 'primary_bg' => '#ffffff',
675 + 'primary_border' => '#e3e8ee',
676 + 'menu_text' => '#545861',
677 + 'menu_text_active' => '#545861',
678 + 'active_bg' => '#f0f3f5',
679 + 'menu_text_hover' => '#545861',
680 + 'menu_bg_hover' => '#f0f3f5',
681 + ],
682 + 'spaces' => [
683 + 'primary_bg' => '#ffffff',
684 + 'primary_border' => '#e3e8ee',
685 + 'menu_text' => '#545861',
686 + 'menu_text_active' => '#545861',
687 + 'menu_text_hover' => '#545861',
688 + 'menu_bg_hover' => '#f0f3f5',
689 + 'active_bg' => '#f0f3f5',
690 + ]
691 + ],
692 + ],
693 + 'sunset_sands' => [
694 + 'title' => __('Sunset Sands', 'fluent-community'),
695 + 'selectors' => [
696 + 'body' => [
697 + 'primary_bg' => '#FFFFFF',
698 + 'secondary_bg' => '#FDF6F0',
699 + 'secondary_content_bg' => '#FDF6F0',
700 + 'active_bg' => '#FCF0E6',
701 + 'light_bg' => '#FAE5D3',
702 + 'deep_bg' => '#2D2D2D',
703 + 'menu_text' => '#5D5D5D',
704 + 'primary_text' => '#333333',
705 + 'secondary_text' => '#666666',
706 + 'text_off' => '#999999',
707 + 'text_link' => '#E67E22',
708 + 'primary_button' => '#E67E22',
709 + 'primary_button_text' => '#FFFFFF',
710 + 'primary_border' => '#EADDD3',
711 + 'secondary_border' => '#E0D0C3',
712 + 'highlight_bg' => '#FFF5EC',
713 + ],
714 + 'fcom_top_menu' => [
715 + 'primary_bg' => '#FFFFFF',
716 + 'primary_border' => '#EADDD3',
717 + 'menu_text' => '#5D5D5D',
718 + 'menu_text_active' => '#E67E22',
719 + 'active_bg' => '#FFF5EC',
720 + 'menu_text_hover' => '#E67E22',
721 + 'menu_bg_hover' => '#FFF5EC',
722 + ],
723 + 'spaces' => [
724 + 'primary_bg' => '#FFFFFF',
725 + 'primary_border' => '#EADDD3',
726 + 'menu_text' => '#5D5D5D',
727 + 'menu_text_hover' => '#E67E22',
728 + 'menu_bg_hover' => '#FFF5EC',
729 + 'menu_text_active' => '#FFFFFF',
730 + 'active_bg' => '#E67E22',
731 + ]
732 + ]
733 + ],
734 + 'ocean_blue' => [
735 + 'title' => __('Ocean Blue', 'fluent-community'),
736 + 'selectors' => [
737 + 'body' => [
738 + 'primary_bg' => '#FFFFFF',
739 + 'secondary_bg' => '#F0F2F5',
740 + 'secondary_content_bg' => '#f0f3f5',
741 + 'active_bg' => '#E7F3FF',
742 + 'light_bg' => '#F6F9FA',
743 + 'deep_bg' => '#18191A',
744 + 'menu_text' => '#65676B',
745 + 'primary_text' => '#050505',
746 + 'secondary_text' => '#65676B',
747 + 'text_off' => '#8A8D91',
748 + 'text_link' => '#216FDB',
749 + 'primary_button' => '#1877F2',
750 + 'primary_button_text' => '#FFFFFF',
751 + 'primary_border' => '#DADDE1',
752 + 'secondary_border' => '#CED0D4',
753 + 'highlight_bg' => '#E7F3FF'
754 + ],
755 + 'fcom_top_menu' => [
756 + 'primary_bg' => '#FFFFFF',
757 + 'primary_border' => '#DADDE1',
758 + 'menu_text' => '#65676B',
759 + 'menu_text_active' => '#1877F2',
760 + 'active_bg' => '#E7F3FF',
761 + 'menu_text_hover' => '#1877F2',
762 + 'menu_bg_hover' => '#E7F3FF',
763 + ],
764 + 'spaces' => [
765 + 'primary_bg' => '#FFFFFF',
766 + 'primary_border' => '#DADDE1',
767 + 'menu_text' => '#65676B',
768 + 'menu_text_hover' => '#1877F2',
769 + 'menu_bg_hover' => '#E7F3FF',
770 + 'menu_text_active' => '#FFFFFF',
771 + 'active_bg' => '#1877F2'
772 + ]
773 + ]
774 + ],
775 + 'sky_blue' => [
776 + 'title' => __('Sky Blue', 'fluent-community'),
777 + 'selectors' => [
778 + 'body' => [
779 + 'primary_bg' => '#FFFFFF',
780 + 'secondary_bg' => '#F7F9FA',
781 + 'secondary_content_bg' => '#f0f3f5',
782 + 'active_bg' => '#E8F5FD',
783 + 'light_bg' => '#F7F9FA',
784 + 'deep_bg' => '#15202B',
785 + 'menu_text' => '#536471',
786 + 'primary_text' => '#0F1419',
787 + 'secondary_text' => '#536471',
788 + 'text_off' => '#8899A6',
789 + 'text_link' => '#1D9BF0',
790 + 'primary_button' => '#1D9BF0',
791 + 'primary_button_text' => '#FFFFFF',
792 + 'primary_border' => '#EFF3F4',
793 + 'secondary_border' => '#CFD9DE',
794 + 'highlight_bg' => '#E8F5FD'
795 + ],
796 + 'fcom_top_menu' => [
797 + 'primary_bg' => '#FFFFFF',
798 + 'primary_border' => '#EFF3F4',
799 + 'menu_text' => '#536471',
800 + 'menu_text_active' => '#1D9BF0',
801 + 'active_bg' => '#E8F5FD',
802 + 'menu_bg_hover' => '#E8F5FD',
803 + 'menu_text_hover' => '#536471',
804 + ],
805 + 'spaces' => [
806 + 'primary_bg' => '#FFFFFF',
807 + 'primary_border' => '#EFF3F4',
808 + 'menu_text' => '#536471',
809 + 'menu_text_hover' => '#1D9BF0',
810 + 'menu_bg_hover' => '#E8F5FD',
811 + 'menu_text_active' => '#FFFFFF',
812 + 'active_bg' => '#1D9BF0'
813 + ]
814 + ]
815 + ],
816 + 'emerald_essence' => [
817 + 'title' => __('Emerald Essence', 'fluent-community'),
818 + 'selectors' => [
819 + 'body' => [
820 + 'primary_bg' => '#FFFFFF',
821 + 'secondary_bg' => '#F0F7F4',
822 + 'secondary_content_bg' => '#f0f3f5',
823 + 'active_bg' => '#E3F2ED',
824 + 'light_bg' => '#F7FAFA',
825 + 'deep_bg' => '#1A2B32',
826 + 'menu_text' => '#4A5D5E',
827 + 'primary_text' => '#1F2937',
828 + 'secondary_text' => '#4B5563',
829 + 'text_off' => '#9CA3AF',
830 + 'text_link' => '#059669',
831 + 'primary_button' => '#10B981',
832 + 'primary_button_text' => '#FFFFFF',
833 + 'primary_border' => '#D1E7DD',
834 + 'secondary_border' => '#A7C4BC',
835 + 'highlight_bg' => '#ECFDF5'
836 + ],
837 + 'fcom_top_menu' => [
838 + 'primary_bg' => '#FFFFFF',
839 + 'primary_border' => '#D1E7DD',
840 + 'menu_text' => '#4A5D5E',
841 + 'menu_text_active' => '#059669',
842 + 'active_bg' => '#ECFDF5',
843 + 'menu_bg_hover' => '#ECFDF5',
844 + 'menu_text_hover' => '#4A5D5E',
845 + ],
846 + 'spaces' => [
847 + 'primary_bg' => '#FFFFFF',
848 + 'primary_border' => '#D1E7DD',
849 + 'menu_text' => '#4A5D5E',
850 + 'menu_text_hover' => '#059669',
851 + 'menu_bg_hover' => '#ECFDF5',
852 + 'menu_text_active' => '#FFFFFF',
853 + 'active_bg' => '#10B981'
854 + ]
855 + ]
856 + ]
857 + ],
858 + 'darkSkins' => [
859 + 'default' => [
860 + 'title' => __('Default (Dark)', 'fluent-community'),
861 + 'selectors' => [
862 + 'body' => [
863 + 'primary_bg' => '#2B2E33',
864 + 'secondary_bg' => '#191B1F',
865 + 'secondary_content_bg' => '#42464D',
866 + 'active_bg' => '#42464D',
867 + 'light_bg' => '#2B303B',
868 + 'deep_bg' => '#E1E4EA',
869 + 'menu_text' => '#E4E7EB',
870 + 'menu_text_active' => '#E4E7EB',
871 + 'primary_text' => '#F0F3F5',
872 + 'secondary_text' => '#99A0AE',
873 + 'menu_bg_hover' => '#E1E4EA',
874 + 'text_off' => '#A5A9AD',
875 + 'text_link' => '#60a5fa',
876 + 'primary_button' => '#FFFFFF',
877 + 'primary_button_text' => '#2B2E33',
878 + 'primary_border' => '#42464D',
879 + 'secondary_border' => '#A5A9AD',
880 + 'highlight_bg' => '#2c2c1a',
881 + ],
882 + 'fcom_top_menu' => [
883 + 'primary_bg' => '#2B2E33',
884 + 'primary_border' => '#42464D',
885 + 'menu_text' => '#E4E7EB',
886 + 'menu_text_active' => '#E4E7EB',
887 + 'active_bg' => '#42464D',
888 + 'menu_bg_hover' => '#42464D',
889 + 'menu_text_hover' => '#E4E7EB',
890 + ],
891 + 'spaces' => [
892 + 'primary_bg' => '#2B2E33',
893 + 'primary_border' => '#42464D',
894 + 'menu_text' => '#E4E7EB',
895 + 'menu_text_active' => '#E4E7EB',
896 + 'active_bg' => '#42464D',
897 + 'menu_bg_hover' => '#42464D',
898 + 'menu_text_hover' => '#fff',
899 + ]
900 + ],
901 + ],
902 + 'sunset_sands' => [
903 + 'title' => __('Sunset Sands (Dark)', 'fluent-community'),
904 + 'selectors' => [
905 + 'body' => [
906 + 'primary_bg' => '#1A1A1A',
907 + 'secondary_bg' => '#222222',
908 + 'secondary_content_bg' => '#222222',
909 + 'active_bg' => '#2A2420',
910 + 'light_bg' => '#33302E',
911 + 'deep_bg' => '#111111',
912 + 'menu_text' => '#B0B0B0',
913 + 'primary_text' => '#E0E0E0',
914 + 'secondary_text' => '#A0A0A0',
915 + 'text_off' => '#707070',
916 + 'text_link' => '#F39C12',
917 + 'primary_button' => '#F39C12',
918 + 'primary_border' => '#3A3632',
919 + 'primary_button_text' => '#1A1A1A',
920 + 'secondary_border' => '#4C4D4F',
921 + 'highlight_bg' => '#2A2420',
922 + ],
923 + 'fcom_top_menu' => [
924 + 'primary_bg' => '#1A1A1A',
925 + 'primary_border' => '#3A3632',
926 + 'menu_text' => '#B0B0B0',
927 + 'menu_text_active' => '#F39C12',
928 + 'active_bg' => '#2A2420',
929 + 'menu_text_hover' => '#F39C12',
930 + 'menu_bg_hover' => '#2A2420',
931 + ],
932 + 'spaces' => [
933 + 'primary_bg' => '#1A1A1A',
934 + 'primary_border' => '#3A3632',
935 + 'menu_text' => '#B0B0B0',
936 + 'menu_text_hover' => '#F39C12',
937 + 'menu_bg_hover' => '#2A2420',
938 + 'menu_text_active' => '#1A1A1A',
939 + 'active_bg' => '#F39C12',
940 + ]
941 + ]
942 + ],
943 + 'ocean_blue' => [
944 + 'title' => __('Ocean Blue (Dark)', 'fluent-community'),
945 + 'selectors' => [
946 + 'body' => [
947 + 'primary_border' => '#3E4042',
948 + 'menu_text' => '#B0B3B8',
949 + 'menu_text_active' => '#2D88FF',
950 + 'active_bg' => '#263951',
951 + 'menu_text_hover' => '#2D88FF',
952 + 'menu_bg_hover' => '#263951',
953 + 'primary_bg' => '#2B2E33',
954 + 'secondary_content_bg' => '#42464D',
955 + 'secondary_bg' => '#191B1F',
956 + 'light_bg' => '#2B303B',
957 + 'deep_bg' => '#E1E4EA',
958 + 'primary_text' => '#F0F3F5',
959 + 'secondary_text' => '#99A0AE',
960 + 'text_off' => '#A5A9AD',
961 + 'primary_button' => '#FFFFFF',
962 + 'primary_button_text' => '#191B1F',
963 + 'secondary_border' => '#A5A9AD',
964 + 'highlight_bg' => '#2c2c1a',
965 + 'text_link' => '#2d88ff',
966 + ],
967 + 'fcom_top_menu' => [
968 + 'primary_bg' => '#242526',
969 + 'primary_border' => '#3E4042',
970 + 'menu_text' => '#B0B3B8',
971 + 'menu_text_active' => '#fff',
972 + 'active_bg' => '#263951',
973 + 'menu_text_hover' => '#fff',
974 + 'menu_bg_hover' => '#263951',
975 + ],
976 + 'spaces' => [
977 + 'primary_bg' => '#242526',
978 + 'primary_border' => '#3E4042',
979 + 'menu_text' => '#B0B3B8',
980 + 'menu_text_hover' => '#2D88FF',
981 + 'menu_bg_hover' => '#263951',
982 + 'menu_text_active' => '#FFFFFF',
983 + 'active_bg' => '#2D88FF'
984 + ]
985 + ]
986 + ],
987 + 'sky_blue' => [
988 + 'title' => __('Sky Blue (Dark)', 'fluent-community'),
989 + 'selectors' => [
990 + 'body' => [
991 + 'primary_bg' => '#15202B',
992 + 'secondary_bg' => '#1E2732',
993 + 'secondary_content_bg' => '#2C3640',
994 + 'active_bg' => '#1D2F41',
995 + 'light_bg' => '#22303C',
996 + 'deep_bg' => '#E7E9EA',
997 + 'menu_text' => '#8B98A5',
998 + 'primary_text' => '#E7E9EA',
999 + 'secondary_text' => '#8B98A5',
1000 + 'text_off' => '#536471',
1001 + 'text_link' => '#1D9BF0',
1002 + 'primary_button' => '#1D9BF0',
1003 + 'primary_button_text' => '#15202B',
1004 + 'primary_border' => '#38444D',
1005 + 'secondary_border' => '#536471',
1006 + 'highlight_bg' => '#1D2F41'
1007 + ],
1008 + 'fcom_top_menu' => [
1009 + 'primary_bg' => '#15202B',
1010 + 'primary_border' => '#38444D',
1011 + 'menu_text' => '#8B98A5',
1012 + 'menu_text_active' => '#1D9BF0',
1013 + 'active_bg' => '#1D2F41',
1014 + 'menu_bg_hover' => '#1D2F41',
1015 + 'menu_text_hover' => '#E7E9EA',
1016 + ],
1017 + 'spaces' => [
1018 + 'primary_bg' => '#15202B',
1019 + 'primary_border' => '#38444D',
1020 + 'menu_text' => '#8B98A5',
1021 + 'menu_text_hover' => '#1D9BF0',
1022 + 'menu_bg_hover' => '#1D2F41',
1023 + 'menu_text_active' => '#FFFFFF',
1024 + 'active_bg' => '#1D9BF0'
1025 + ]
1026 + ]
1027 + ],
1028 + 'emerald_essence' => [
1029 + 'title' => __('Emerald Essence (Dark)', 'fluent-community'),
1030 + 'selectors' => [
1031 + 'body' => [
1032 + 'primary_bg' => '#1A2B32',
1033 + 'secondary_bg' => '#243B43',
1034 + 'secondary_content_bg' => '#2C464F',
1035 + 'active_bg' => '#1E3A31',
1036 + 'light_bg' => '#2A3F48',
1037 + 'deep_bg' => '#E2E8F0',
1038 + 'menu_text' => '#A7BCBF',
1039 + 'primary_text' => '#E2E8F0',
1040 + 'secondary_text' => '#A7BCBF',
1041 + 'text_off' => '#64748B',
1042 + 'text_link' => '#34D399',
1043 + 'primary_button' => '#10B981',
1044 + 'primary_border' => '#2F4C41',
1045 + 'primary_button_text' => '#1A2B32',
1046 + 'secondary_border' => '#3D5C52',
1047 + 'highlight_bg' => '#064E3B'
1048 + ],
1049 + 'fcom_top_menu' => [
1050 + 'primary_bg' => '#1A2B32',
1051 + 'primary_border' => '#2F4C41',
1052 + 'menu_text' => '#A7BCBF',
1053 + 'menu_text_active' => '#34D399',
1054 + 'active_bg' => '#064E3B',
1055 + 'menu_bg_hover' => '#064E3B',
1056 + 'menu_text_hover' => '#E2E8F0',
1057 + ],
1058 + 'spaces' => [
1059 + 'primary_bg' => '#1A2B32',
1060 + 'primary_border' => '#2F4C41',
1061 + 'menu_text' => '#A7BCBF',
1062 + 'menu_text_hover' => '#34D399',
1063 + 'menu_bg_hover' => '#064E3B',
1064 + 'menu_text_active' => '#FFFFFF',
1065 + 'active_bg' => '#10B981'
1066 + ]
1067 + ]
1068 + ]
1069 + ]
1070 + ]);
1071 +
1072 + $customSchemaConfig = self::getColorConfig('edit');
1073 +
1074 + $shemas['lightSkins']['custom'] = [
1075 + 'title' => __('Custom', 'fluent-community'),
1076 + 'selectors' => $customSchemaConfig['light_config'] ?? $defaultCustom
1077 + ];
1078 +
1079 + $shemas['darkSkins']['custom'] = [
1080 + 'title' => __('Custom', 'fluent-community'),
1081 + 'selectors' => $customSchemaConfig['dark_config'] ?? $defaultCustom
1082 + ];
1083 +
1084 + return $shemas;
1085 + }
1086 +
1087 + public static function generateCss($sectors, $prefix = '')
1088 + {
1089 + if (!$sectors) {
1090 + return '';
1091 + }
1092 +
1093 + $bodyPrefix = 'body';
1094 + if ($prefix) {
1095 + $bodyPrefix = $prefix . ' body';
1096 + }
1097 +
1098 + $elementPlusMap = [
1099 + 'primary_text' => '--el-color-primary',
1100 + 'secondary_bg' => '--el-color-white'
1101 + ];
1102 +
1103 + $css = '';
1104 + foreach ($sectors as $selector => $props) {
1105 + $isBody = $selector === 'body';
1106 + $prefix = $isBody ? $bodyPrefix : $bodyPrefix . ' .' . $selector;
1107 + $prefix .= '{';
1108 +
1109 + $css .= $prefix;
1110 +
1111 + foreach ($props as $prop => $value) {
1112 + $cssVar = '--fcom-' . str_replace('_', '-', $prop);
1113 + $css .= $cssVar . ':' . $value . ';';
1114 +
1115 + if ($isBody && isset($elementPlusMap[$prop])) {
1116 + $css .= $elementPlusMap[$prop] . ':' . $value . ';';
1117 + }
1118 + }
1119 + $css .= '} ';
1120 + }
1121 +
1122 + return $css;
1123 + }
1124 +
1125 + public static function getColorConfig($context = 'view')
1126 + {
1127 + return apply_filters('fluent_community/color_schmea_config', [
1128 + 'light_schema' => 'default',
1129 + 'dark_schema' => 'default',
1130 + 'light_config' => [
1131 + 'body' => [],
1132 + 'fcom_top_menu' => [],
1133 + 'spaces' => []
1134 + ],
1135 + 'dark_config' => [
1136 + 'body' => [],
1137 + 'fcom_top_menu' => [],
1138 + 'spaces' => []
1139 + ],
1140 + 'version' => FLUENT_COMMUNITY_PLUGIN_VERSION
1141 + ], $context);
1142 + }
1143 +
1144 + public static function getColorCssVariables()
1145 + {
1146 + $customSchemaConfig = self::getColorConfig('view');
1147 +
1148 + if (!empty($customSchemaConfig['cached_css'])) {
1149 + if ($customSchemaConfig['version'] != FLUENT_COMMUNITY_PLUGIN_VERSION) {
1150 + do_action('fluent_community/recache_color_schema');
1151 + }
1152 +
1153 + return (string)$customSchemaConfig['cached_css'];
1154 + }
1155 +
1156 + $schemas = self::getColorSchemas();
1157 +
1158 + $lightName = Arr::get($customSchemaConfig, 'light_schema', 'default');
1159 + $darkName = Arr::get($customSchemaConfig, 'dark_schema', 'default');
1160 +
1161 + $lightCss = self::generateCss(Arr::get($schemas, "lightSkins.$lightName.selectors"));
1162 + $darkCss = self::generateCss(Arr::get($schemas, "darkSkins.$darkName.selectors"), 'html.dark');
1163 + return $lightCss . $darkCss;
1164 + }
1165 +
1166 + public static function getThemeColor($scope = 'theme')
1167 + {
1168 + static $cache = [];
1169 + if (isset($cache[$scope])) {
1170 + return $cache[$scope];
1171 + }
1172 +
1173 + $map = [
1174 + 'theme' => ['key' => 'primary_button', 'default' => '#2B2E33'],
1175 + 'theme_button_text' => ['key' => 'primary_button_text', 'default' => '#ffffff'],
1176 + ];
1177 + $entry = Arr::get($map, $scope, ['key' => $scope, 'default' => '']);
1178 +
1179 + $schemas = self::getColorSchemas();
1180 + $lightName = Arr::get(self::getColorConfig('view'), 'light_schema', 'default');
1181 + $color = Arr::get($schemas, "lightSkins.$lightName.selectors.body.{$entry['key']}", $entry['default']);
1182 +
1183 + $cache[$scope] = apply_filters('fluent_community/' . $scope . '_color', $color);
1184 +
1185 + return $cache[$scope];
1186 + }
1187 +
1188 + public static function getColorSchemaConfig()
1189 + {
1190 + $customSchemaConfig = self::getColorConfig('view');
1191 + $lightName = Arr::get($customSchemaConfig, 'light_schema', 'default');
1192 + $darkName = Arr::get($customSchemaConfig, 'dark_schema', 'default');
1193 + $schemas = self::getColorSchemas();
1194 +
1195 + return [
1196 + 'dark' => Arr::get($schemas, "lightSkins.$darkName.selectors"),
1197 + 'light' => Arr::get($schemas, "darkSkins.$lightName.selectors"),
1198 + ];
1199 + }
1200 +
1201 + public static function getSuggestedColors()
1202 + {
1203 + $pallets = current((array)get_theme_support('editor-color-palette'));
1204 +
1205 + $colors = [];
1206 +
1207 + if ($pallets && is_array($pallets)) {
1208 + $colors = array_map(function ($color) {
1209 + $colorString = Arr::get($color, 'color');
1210 + // Trim any whitespace
1211 + $colorString = trim($colorString);
1212 + // Check if it's a CSS variable
1213 + if (strpos($colorString, 'var(') === 0) {
1214 + // Extract the fallback color if present
1215 + preg_match('/var\(.*,\s*(#[A-Fa-f0-9]{6})\)/', $colorString, $matches);
1216 + if (!empty($matches[1])) {
1217 + return $matches[1];
1218 + }
1219 + // If no fallback color, return an empty string
1220 + return '';
1221 + }
1222 +
1223 + if (preg_match('/#[A-Fa-f0-9]{6}/', $colorString, $matches)) {
1224 + return $matches[0];
1225 + }
1226 +
1227 + return $colorString;
1228 + }, $pallets);
1229 +
1230 + $colors = array_filter($colors);
1231 + }
1232 +
1233 + if (!$colors) {
1234 + $colors = ['#000000', '#abb8c3', '#ffffff', '#f78da7', '#ff6900', '#fcb900', '#7bdcb5', '#00d084', '#8ed1fc', '#0693e3', '#9b51e0'];
1235 + }
1236 +
1237 + return apply_filters('fluent_community/suggested_colors', $colors);
1238 + }
1239 +
1240 + public static function slugify($text, $fallback = '')
1241 + {
1242 + $title = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $text);
1243 +
1244 + $title = Helper::normalizeToAscii($title);
1245 +
1246 + $title = remove_accents($title);
1247 +
1248 + $title = strtolower($title);
1249 + // only allow alphanumeric, dash, and underscore
1250 + $title = trim(preg_replace('/[^a-z0-9-_]/', ' ', $title));
1251 +
1252 + if (!$title) {
1253 + $title = $fallback;
1254 + }
1255 +
1256 + if (!$title) {
1257 + return $title;
1258 + }
1259 +
1260 + return sanitize_title($title, $fallback);
1261 + }
1262 +
1263 + public static function hasAnalyticsEnabled()
1264 + {
1265 + $defaultSettings = ['status' => 'no'];
1266 +
1267 + $settings = apply_filters('fluent_community/features/analytics', $defaultSettings);
1268 +
1269 + $status = Arr::get($settings, 'status');
1270 +
1271 + return $status === 'yes';
1272 + }
1273 +
1274 + public static function getPortalSidebarData($scope = 'sidebar')
1275 + {
1276 + $userModel = Helper::getCurrentUser();
1277 + $spaceGroups = Helper::getCommunityMenuGroups($userModel);
1278 + $settingsMenu = apply_filters('fluent_community/settings_menu', [], $userModel);
1279 + $menuGroups = Helper::getMenuItemsGroup('view');
1280 + $topInlines = Arr::get($menuGroups, 'beforeCommunityMenuItems', []);
1281 + $bottomLinkGroups = Arr::get($menuGroups, 'afterCommunityLinkGroups', []);
1282 + $primaryMenuItems = Arr::get($menuGroups, 'mainMenuItems', []);
1283 + $primaryMenuItems = apply_filters('fluent_community/main_menu_items', $primaryMenuItems, $scope);
1284 +
1285 + return apply_filters('fluent_community/sidebar_menu_groups_config', [
1286 + 'primaryItems' => $primaryMenuItems,
1287 + 'spaceGroups' => $spaceGroups,
1288 + 'settingsItems' => $settingsMenu,
1289 + 'topInlineLinks' => $topInlines,
1290 + 'bottomLinkGroups' => $bottomLinkGroups,
1291 + 'is_admin' => Helper::isSiteAdmin(null, $userModel),
1292 + 'has_color_scheme' => Helper::hasColorScheme(),
1293 + 'context' => $scope,
1294 + ], $userModel);
1295 + }
1296 +
1297 + public static function getVerifiedSenders()
1298 + {
1299 + $verifiedSenders = [];
1300 +
1301 + if (defined('FLUENTMAIL')) {
1302 + $smtpSettings = get_option('fluentmail-settings', []);
1303 + if ($smtpSettings && count($smtpSettings['mappings'])) {
1304 + $verifiedSenders = array_keys($smtpSettings['mappings']);
1305 + }
1306 + }
1307 +
1308 + return apply_filters('fluent_community/verified_email_senders', $verifiedSenders);
1309 + }
1310 +
1311 + public static function safeUnserialize($data)
1312 + {
1313 + if (!$data) {
1314 + return $data;
1315 + }
1316 +
1317 + if (is_serialized($data)) { // Don't attempt to unserialize data that wasn't serialized going in.
1318 + return @unserialize(trim($data), [
1319 + 'allowed_classes' => false,
1320 + ]);
1321 + }
1322 +
1323 + return $data;
1324 + }
458 1325 }