PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.4.01
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.4.01
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
fluent-community / app / Functions / Utility.php

Utility.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.4.01, at app/Functions/Utility.php

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