PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.2.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.2.0
2.2.0 2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 All 43 releases
← All changes | app/Functions/helpers.php +71 -1 1.95.2 → 2.2.0 View file →
@@ -1,7 +1,8 @@
1 1 <?php
2 2
3 3 use FluentBoards\App\App;
4 +use FluentBoards\App\Services\Constant;
4 5
5 6 // $app is available
6 7
7 8 if (!function_exists('fluentBoards')) {
@@ -18,8 +19,42 @@
18 19 return is_null($key) ? $api : $api->{$key};
19 20 }
20 21 }
21 22
23 +if (!function_exists('fluent_boards_sanitize_description')) {
24 + function fluent_boards_sanitize_description($description): string
25 + {
26 + $description = preg_replace_callback('/<((?:https?:\/\/)[^<>\s]+)>/i', function ($matches) {
27 + $url = esc_url_raw(html_entity_decode($matches[1], ENT_QUOTES | ENT_HTML5, 'UTF-8'));
28 +
29 + return $url ? '[' . $url . '](' . str_replace(')', '%29', $url) . ')' : $matches[0];
30 + }, (string) $description);
31 +
32 + // Markdown email autolinks otherwise look like disallowed HTML to KSES.
33 + $description = preg_replace_callback('/<(?:mailto:)?([^<>\s]+@[^<>\s]+)>/i', function ($matches) {
34 + $email = html_entity_decode($matches[1], ENT_QUOTES | ENT_HTML5, 'UTF-8');
35 + if (!is_email($email)) {
36 + return $matches[0];
37 + }
38 +
39 + $label = str_replace(['*', '_', '`'], ['\\*', '\\_', '\\`'], $email);
40 + return '[' . $label . '](mailto:' . $email . ')';
41 + }, $description);
42 +
43 + // KSES encodes standalone > characters, which breaks Markdown quotes.
44 + // Protect only quote prefixes; all HTML still passes through KSES.
45 + $quotePrefix = 'fbs-quote-' . wp_generate_uuid4() . '-';
46 + $quotes = [];
47 + $description = preg_replace_callback('/^[ \t]*(?:>[ \t]*)+/m', function ($matches) use (&$quotes, $quotePrefix) {
48 + $key = $quotePrefix . count($quotes);
49 + $quotes[$key] = $matches[0];
50 + return $key;
51 + }, $description);
52 +
53 + return strtr(wp_kses_post($description), $quotes);
54 + }
55 +}
56 +
22 57 if (!function_exists('fluent_boards_user_avatar')) {
23 58 function fluent_boards_user_avatar($email, $name = '')
24 59 {
25 60 $user = get_user_by('email', $email);
@@ -24,9 +59,9 @@
24 59 {
25 60 $user = get_user_by('email', $email);
26 61
27 62 if ($user) {
28 - $photo_url = get_user_meta($user->ID, 'fbs_profile_photo', true);
63 + $photo_url = get_user_meta($user->ID, Constant::PROFILE_PHOTO_META_KEY, true);
29 64 if ($photo_url) {
30 65 return apply_filters('fluent_boards/get_avatar', $photo_url, $email);
31 66 }
32 67
@@ -82,8 +117,20 @@
82 117 return apply_filters('fluent_boards/app_url', admin_url('admin.php?page=fluent-boards#/'));
83 118 }
84 119 }
85 120
121 +if (!function_exists('fluent_boards_is_rtl')) {
122 + /**
123 + * Determine if Fluent Boards should render right-to-left UI.
124 + *
125 + * @return bool
126 + */
127 + function fluent_boards_is_rtl(): bool
128 + {
129 + return is_rtl();
130 + }
131 +}
132 +
86 133 function fluent_boards_get_pref_settings($cached = true)
87 134 {
88 135 static $pref = null;
89 136
@@ -280,5 +327,28 @@
280 327 }
281 328
282 329 // Fallback: return original value if not recognized
283 330 return $value;
331 +}
332 +
333 +/**
334 + * Builds the canonical Fluent Boards Upgrade-to-Pro URL.
335 + *
336 + * @param string $utmContent Exact in-plugin CTA placement.
337 + * @return string
338 + */
339 +function fluent_boards_get_upgrade_url($utmContent = '')
340 +{
341 + $queryArgs = [
342 + 'utm_source' => 'fluent-boards',
343 + 'utm_medium' => 'free_plugin',
344 + 'utm_campaign' => 'upgrade_pro',
345 + 'utm_term' => FLUENT_BOARDS_PLUGIN_VERSION,
346 + ];
347 +
348 + $utmContent = sanitize_key($utmContent);
349 + if ($utmContent) {
350 + $queryArgs['utm_content'] = $utmContent;
351 + }
352 +
353 + return add_query_arg($queryArgs, 'https://fluentboards.com/pricing/');
284 354 }