PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.10.01
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.10.01
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 1.1.0 All 77 releases
← All changes | app/Functions/Utility.php +110 -3 2.4.012.10.01 View file →
@@ -10,8 +10,9 @@
10 10 use FluentCommunity\App\Services\FeedsHelper;
11 11 use FluentCommunity\App\Services\Helper;
12 12 use FluentCommunity\Framework\Support\Arr;
13 13 use FluentCommunity\Modules\Course\Model\Course;
14 +use FluentCommunity\Modules\PushNotification\PushNotificationModule;
14 15
15 16 class Utility
16 17 {
17 18 public static function isDev()
@@ -116,8 +117,9 @@
116 117 'has_crm_sync' => 'no',
117 118 'content_moderation' => 'no',
118 119 'followers_module' => 'no',
119 120 'custom_profile_fields' => 'no',
121 + 'pwa_module' => 'no',
120 122 ];
121 123
122 124 if (defined('FLUENT_COMMUNITY_CLOUD_STORAGE') && FLUENT_COMMUNITY_CLOUD_STORAGE) {
123 125 $features['cloud_storage'] = 'yes';
@@ -134,8 +136,9 @@
134 136 $features['cloud_storage'] = 'no';
135 137 $features['user_badge'] = 'no';
136 138 $features['followers_module'] = 'no';
137 139 $features['custom_profile_fields'] = 'no';
140 + $features['pwa_module'] = 'no';
138 141 }
139 142
140 143 return $features;
141 144 }
@@ -201,8 +204,9 @@
201 204 }
202 205
203 206 $defaults = [
204 207 'dark_mode' => 'yes',
208 + 'default_theme_mode' => 'light',
205 209 'fixed_page_header' => 'yes',
206 210 'show_powered_by' => 'yes',
207 211 'feed_link_on_sidebar' => 'yes',
208 212 'show_post_modal' => 'yes',
@@ -216,9 +220,11 @@
216 220 'post_title_pref' => 'optional',
217 221 'max_media_per_post' => 4,
218 222 'disable_feed_sort_by' => 'no',
219 223 'default_feed_sort_by' => '',
220 - 'collapse_sidebar_groups' => 'no'
224 + 'collapse_sidebar_groups' => 'no',
225 + 'hide_header_on_scroll' => 'no',
226 + 'enable_sidebar_toggle' => 'no'
221 227 ];
222 228 $settings = self::getOption('customization_settings', $defaults);
223 229
224 230 $settings = wp_parse_args($settings, $defaults);
@@ -227,8 +233,9 @@
227 233 $settings['show_powered_by'] = 'yes';
228 234 $settings['affiliate_id'] = '';
229 235 $settings['rich_post_layout'] = 'classic';
230 236 $settings['member_list_layout'] = 'classic';
237 + $settings['enable_sidebar_toggle'] = 'no';
231 238 }
232 239 return $settings;
233 240 }
234 241
@@ -258,13 +265,15 @@
258 265
259 266 $defaults = [
260 267 'can_customize_username' => 'no',
261 268 'can_change_email' => 'no',
269 + 'can_change_password' => 'yes',
262 270 'show_last_activity' => 'yes',
263 271 'can_deactive_account' => 'no',
264 272 'email_auto_login' => 'yes',
265 273 'enable_gravatar' => 'yes',
266 274 'enable_user_sync' => 'yes',
275 + 'skip_crm_undeliverable_emails' => 'yes',
267 276 'members_page_status' => 'everybody', // everybody, logged_in, admin_only
268 277 'profile_page_visibility' => 'everybody', // everybody, logged_in, admin_only
269 278 'user_space_visibility' => 'everybody', // everybody, logged_in, admin_only
270 279 'leaderboard_members_visibility' => 'everybody', // everybody, logged_in, admin_only
@@ -340,8 +349,12 @@
340 349 {
341 350 $preSettings = self::getPrivacySettings();
342 351 $settings = Arr::only($settings, array_keys($preSettings));
343 352
353 + $settings = array_map(function ($value) {
354 + return is_scalar($value) ? sanitize_text_field($value) : '';
355 + }, $settings);
356 +
344 357 self::updateOption('privacy_settings', $settings);
345 358 self::forgetCache('privacy_settings');
346 359
347 360 return $settings;
@@ -385,8 +398,46 @@
385 398 ], $url);
386 399 }
387 400
388 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 + /**
389 440 * Get the email notification settings.
390 441 *
391 442 * @return array The email notification settings.
392 443 */
@@ -426,8 +477,29 @@
426 477
427 478 return $settings;
428 479 }
429 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 +
430 502 public static function hasEmailAnnouncementEnabled()
431 503 {
432 504 $settings = self::getEmailNotificationSettings();
433 505 return Arr::get($settings, 'mention_mail', 'no') === 'yes';
@@ -478,8 +550,25 @@
478 550 $key = 'fluent_community_post_topics';
479 551 $topics = self::getFromCache($key, function () {
480 552 $topics = Term::where('taxonomy_name', 'post_topic')->orderBy('title', 'ASC')->get();
481 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 +
482 571 /*
483 572 * object_id = term_id
484 573 * meta_key = space_id
485 574 */
@@ -502,8 +591,9 @@
502 591 'title' => $topic->title,
503 592 'description' => $topic->description,
504 593 'slug' => $topic->slug,
505 594 'admin_only' => Arr::get($topic->settings, 'admin_only', 'no'),
595 + 'serial' => Arr::get($topic->settings, 'serial'),
506 596 'space_ids' => isset($relations[$topic->id]) ? $relations[$topic->id] : []
507 597 ];
508 598 }
509 599
@@ -1072,14 +1162,28 @@
1072 1162 $darkCss = self::generateCss(Arr::get($schemas, "darkSkins.$darkName.selectors"), 'html.dark');
1073 1163 return $lightCss . $darkCss;
1074 1164 }
1075 1165
1076 - public static function getThemeColor()
1166 + public static function getThemeColor($scope = 'theme')
1077 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 +
1078 1179 $schemas = self::getColorSchemas();
1079 1180 $lightName = Arr::get(self::getColorConfig('view'), 'light_schema', 'default');
1181 + $color = Arr::get($schemas, "lightSkins.$lightName.selectors.body.{$entry['key']}", $entry['default']);
1080 1182
1081 - return Arr::get($schemas, "lightSkins.$lightName.selectors.body.primary_button", '#2B2E33');
1183 + $cache[$scope] = apply_filters('fluent_community/' . $scope . '_color', $color);
1184 +
1185 + return $cache[$scope];
1082 1186 }
1083 1187
1084 1188 public static function getColorSchemaConfig()
1085 1189 {
@@ -1135,8 +1239,11 @@
1135 1239
1136 1240 public static function slugify($text, $fallback = '')
1137 1241 {
1138 1242 $title = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $text);
1243 +
1244 + $title = Helper::normalizeToAscii($title);
1245 +
1139 1246 $title = remove_accents($title);
1140 1247
1141 1248 $title = strtolower($title);
1142 1249 // only allow alphanumeric, dash, and underscore