PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 1.0.99
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v1.0.99
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 / Hooks / Handlers / PortalHandler.php

PortalHandler.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 1.0.99, at app/Hooks/Handlers/PortalHandler.php

1,067 lines 54.7 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\Hooks\Handlers;
4
5 use FluentCommunity\App\App;
6 use FluentCommunity\App\Functions\Utility;
7 use FluentCommunity\App\Models\Space;
8 use FluentCommunity\App\Models\Feed;
9 use FluentCommunity\App\Models\BaseSpace;
10 use FluentCommunity\App\Models\SpaceGroup;
11 use FluentCommunity\App\Models\User;
12 use FluentCommunity\App\Models\XProfile;
13 use FluentCommunity\App\Services\CustomSanitizer;
14 use FluentCommunity\App\Services\Helper;
15 use FluentCommunity\App\Services\LockscreenService;
16 use FluentCommunity\App\Services\ProfileHelper;
17 use FluentCommunity\App\Services\TransStrings;
18 use FluentCommunity\App\Vite;
19 use FluentCommunity\Framework\Support\Arr;
20 use FluentCommunity\App\Services\FeedsHelper;
21 use FluentCommunity\Modules\Auth\AuthHelper;
22
23 class PortalHandler
24 {
25 protected $currentPath = '';
26
27 protected $slug = null;
28
29 public function register()
30 {
31 /**
32 * Register the portal route
33 */
34 add_action('init', function () {
35 $this->slug = Helper::getPortalSlug();
36 if ($this->slug !== '') {
37 add_rewrite_rule('^' . $this->slug . '/?$', 'index.php?fcom_route=portal_home', 'top'); // For /hooks
38 add_rewrite_rule('^' . $this->slug . '/(.+)/?', 'index.php?fcom_route=$matches[1]', 'top');
39 }
40 });
41
42 add_filter('query_vars', function ($vars) {
43 $vars[] = 'fcom_route';
44 return $vars;
45 });
46
47 add_action('template_redirect', function () {
48 $hook_path = get_query_var('fcom_route');
49 if ($hook_path) {
50 $this->currentPath = $hook_path;
51 $this->renderFullApp();
52 }
53
54 if ($this->slug === '') {
55 global $wp;
56 $currentRequest = $wp->request;
57 if ($hookPath = Helper::getPortalRequestPath($currentRequest)) {
58 $this->currentPath = $hookPath;
59 $this->renderFullApp();
60 }
61 }
62 }, 1);
63
64 add_action('fluent_community/portal_html', function () {
65 App::make('view')->render('portal.portal');
66 });
67
68 add_action('fluent_community/portal_header', function ($context) {
69 $this->getPortalHeader(true, $context);
70 });
71
72 add_action('fluent_community/portal_sidebar', function ($context) {
73 $this->getPortalSidebar(true, $context);
74 });
75
76 // add a link to admin menu which will redirect to /portal
77 add_action('admin_menu', function () {
78 add_menu_page(
79 __('FluentCommunity', 'fluent-community'),
80 __('FluentCommunity', 'fluent-community'),
81 'edit_posts',
82 'fluent-community',
83 [$this, 'showAdminPage'],
84 $this->getMenuIcon(),
85 130
86 );
87 });
88
89 add_action('fluent_community/enqueue_global_assets', function ($useDefaultTheme = true) {
90 wp_enqueue_style('fluent_community_global', Vite::getDynamicSrcUrl('global.scss'), [], time(), 'screen');
91 if ($useDefaultTheme) {
92 wp_enqueue_style('fluent_community_default_theme', Vite::getDynamicSrcUrl('theme-default.scss'), [], FLUENT_COMMUNITY_PLUGIN_VERSION, 'screen');
93 }
94
95 $css = Utility::getColorCssVariables();
96
97 wp_add_inline_style('fluent_community_global', $css);
98
99 wp_enqueue_script('portal_general', Vite::getStaticSrcUrl('portal_general.js'), [], FLUENT_COMMUNITY_PLUGIN_VERSION, true);
100
101 wp_localize_script('portal_general', 'fcom_portal_general', [
102 'is_wp' => true
103 ]);
104 });
105
106 add_action('admin_bar_menu', function ($wp_admin_bar) {
107 if (!\FluentCommunity\App\Services\Helper::canAccessPortal()) {
108 return;
109 }
110
111 // Add custom link within site name dropdown
112 $wp_admin_bar->add_node(array(
113 'id' => 'fluent-community-link',
114 'title' => __('Visit Community Portal', 'fluent-community'),
115 'href' => \FluentCommunity\App\Services\Helper::baseUrl('/'),
116 'parent' => 'site-name'
117 ));
118 }, 99);
119
120 add_action('fluent_community/top_menu_right_items', [$this, 'renderTopMenuRightItems']);
121
122 add_action('fluent_community/after_portal_sidebar', function () {
123
124 if (did_action('fluent_community/after_header_right_menu_items')) {
125 echo '<div role="region" aria-label="Portal Settings" class="fcom_side_footer">';
126 if (Helper::isSiteAdmin()) {
127 ?>
128 <div style="display: flex;justify-content: space-between;" class="fcom_admin_menu">
129 <?php if (!defined('FLUENT_COMMUNITY_PRO')): ?>
130 <a title="Upgrade to Pro" target="_blank" rel="noopener" class="fcom_inline_icon_link_item"
131 href="<?php echo esc_url(Utility::getProductUrl(true)) ?>">
132 <span class="el-icon">
133 <svg width="126" height="125" viewBox="0 0 126 125" fill="none">
134 <rect x="0.22139" width="125" height="125" rx="17.8571" fill="#4A5FE0"/>
135 <path
136 d="M47.9424 75.1832L61.6888 67.2467L69.6253 80.9931C62.0334 85.3763 52.3256 82.7751 47.9424 75.1832Z"
137 fill="white"/>
138 <path fill-rule="evenodd" clip-rule="evenodd"
139 d="M75.4348 59.3101L61.6884 67.2466L69.6249 80.993L83.3713 73.0565L75.4348 59.3101ZM89.1821 51.3734L75.4356 59.3099L83.3721 73.0564L97.1186 65.1199L89.1821 51.3734Z"
140 fill="white"/>
141 <path
142 d="M89.182 51.3736C92.978 49.182 97.8319 50.4826 100.023 54.2786L103.992 61.1518L97.1185 65.12L89.182 51.3736Z"
143 fill="white"/>
144 <path
145 d="M64.593 56.4052L50.8466 64.3417L42.9101 50.5953L56.6565 42.6588L64.593 56.4052Z"
146 fill="white"/>
147 <path
148 d="M78.3397 48.4683L64.5933 56.4048L56.6568 42.6584C64.2487 38.2752 73.9565 40.8764 78.3397 48.4683Z"
149 fill="white"/>
150 <path
151 d="M50.847 64.3418L37.1006 72.2783L29.1641 58.5318L42.9105 50.5953L50.847 64.3418Z"
152 fill="white"/>
153 <path
154 d="M37.1011 72.2783C33.3051 74.4699 28.4512 73.1693 26.2596 69.3733L22.2913 62.5001L29.1646 58.5319L37.1011 72.2783Z"
155 fill="white"/>
156 </svg>
157 </span>
158 <span>Upgrade</span>
159 </a>
160 <?php else: ?>
161 <a title="Go to /wp-admin" class="fcom_inline_icon_link_item fcom_wp_admin_link"
162 href="<?php echo esc_url(admin_url()); ?>">
163 <span class="el-icon">
164 <svg viewBox="0 0 122.52 122.523"><g fill="currentColor"><path
165 d="m8.708 61.26c0 20.802 12.089 38.779 29.619 47.298l-25.069-68.686c-2.916 6.536-4.55 13.769-4.55 21.388z"/><path
166 d="m96.74 58.608c0-6.495-2.333-10.993-4.334-14.494-2.664-4.329-5.161-7.995-5.161-12.324 0-4.831 3.664-9.328 8.825-9.328.233 0 .454.029.681.042-9.35-8.566-21.807-13.796-35.489-13.796-18.36 0-34.513 9.42-43.91 23.688 1.233.037 2.395.063 3.382.063 5.497 0 14.006-.667 14.006-.667 2.833-.167 3.167 3.994.337 4.329 0 0-2.847.335-6.015.501l19.138 56.925 11.501-34.493-8.188-22.434c-2.83-.166-5.511-.501-5.511-.501-2.832-.166-2.5-4.496.332-4.329 0 0 8.679.667 13.843.667 5.496 0 14.006-.667 14.006-.667 2.835-.167 3.168 3.994.337 4.329 0 0-2.853.335-6.015.501l18.992 56.494 5.242-17.517c2.272-7.269 4.001-12.49 4.001-16.989z"/><path
167 d="m62.184 65.857-15.768 45.819c4.708 1.384 9.687 2.141 14.846 2.141 6.12 0 11.989-1.058 17.452-2.979-.141-.225-.269-.464-.374-.724z"/><path
168 d="m107.376 36.046c.226 1.674.354 3.471.354 5.404 0 5.333-.996 11.328-3.996 18.824l-16.053 46.413c15.624-9.111 26.133-26.038 26.133-45.426.001-9.137-2.333-17.729-6.438-25.215z"/><path
169 d="m61.262 0c-33.779 0-61.262 27.481-61.262 61.26 0 33.783 27.483 61.263 61.262 61.263 33.778 0 61.265-27.48 61.265-61.263-.001-33.779-27.487-61.26-61.265-61.26zm0 119.715c-32.23 0-58.453-26.223-58.453-58.455 0-32.23 26.222-58.451 58.453-58.451 32.229 0 58.45 26.221 58.45 58.451 0 32.232-26.221 58.455-58.45 58.455z"/></g></svg>
170 </span>
171 </a>
172 <?php endif; ?>
173 <a title="Portal Settings" class="fcom_inline_icon_link_item"
174 href="<?php echo esc_url(Helper::baseUrl('admin/settings')); ?>">
175 <span class="el-icon">
176 <svg viewBox="0 0 1024 1024" data-v-d2e47025=""><path fill="currentColor"
177 d="M600.704 64a32 32 0 0 1 30.464 22.208l35.2 109.376c14.784 7.232 28.928 15.36 42.432 24.512l112.384-24.192a32 32 0 0 1 34.432 15.36L944.32 364.8a32 32 0 0 1-4.032 37.504l-77.12 85.12a357.12 357.12 0 0 1 0 49.024l77.12 85.248a32 32 0 0 1 4.032 37.504l-88.704 153.6a32 32 0 0 1-34.432 15.296L708.8 803.904c-13.44 9.088-27.648 17.28-42.368 24.512l-35.264 109.376A32 32 0 0 1 600.704 960H423.296a32 32 0 0 1-30.464-22.208L357.696 828.48a351.616 351.616 0 0 1-42.56-24.64l-112.32 24.256a32 32 0 0 1-34.432-15.36L79.68 659.2a32 32 0 0 1 4.032-37.504l77.12-85.248a357.12 357.12 0 0 1 0-48.896l-77.12-85.248A32 32 0 0 1 79.68 364.8l88.704-153.6a32 32 0 0 1 34.432-15.296l112.32 24.256c13.568-9.152 27.776-17.408 42.56-24.64l35.2-109.312A32 32 0 0 1 423.232 64H600.64zm-23.424 64H446.72l-36.352 113.088-24.512 11.968a294.113 294.113 0 0 0-34.816 20.096l-22.656 15.36-116.224-25.088-65.28 113.152 79.68 88.192-1.92 27.136a293.12 293.12 0 0 0 0 40.192l1.92 27.136-79.808 88.192 65.344 113.152 116.224-25.024 22.656 15.296a294.113 294.113 0 0 0 34.816 20.096l24.512 11.968L446.72 896h130.688l36.48-113.152 24.448-11.904a288.282 288.282 0 0 0 34.752-20.096l22.592-15.296 116.288 25.024 65.28-113.152-79.744-88.192 1.92-27.136a293.12 293.12 0 0 0 0-40.256l-1.92-27.136 79.808-88.128-65.344-113.152-116.288 24.96-22.592-15.232a287.616 287.616 0 0 0-34.752-20.096l-24.448-11.904L577.344 128zM512 320a192 192 0 1 1 0 384 192 192 0 0 1 0-384m0 64a128 128 0 1 0 0 256 128 128 0 0 0 0-256"></path></svg>
178 </span>
179 <span><?php esc_html_e('Settings', 'fluent-community'); ?></span>
180 </a>
181 </div>
182 <?php
183 } else if (Utility::isCustomizationEnabled('show_powered_by')) {
184 ?>
185 <a target="_blank" rel="noopener" style="font-size: 80%; cursor: pointer;"
186 class="fcom_inline_icon_link_item" href="<?php echo esc_url(Utility::getProductUrl(true)) ?>">
187 <?php echo esc_html('Powered by FluentCommunity', 'fluent-community'); ?>
188 </a>
189 <?php
190 }
191 echo '</div>';
192 return;
193 }
194
195 if (Helper::isSiteAdmin()) {
196 add_action('fluent_community/before_header_menu_items', function () {
197 ?>
198 <li class="top_menu_item fcom_icon_link">
199 <a href="<?php echo esc_url(Helper::baseUrl('admin/settings')); ?>">
200 <span class="el-icon">
201 <svg viewBox="0 0 1024 1024" data-v-d2e47025=""><path fill="currentColor"
202 d="M600.704 64a32 32 0 0 1 30.464 22.208l35.2 109.376c14.784 7.232 28.928 15.36 42.432 24.512l112.384-24.192a32 32 0 0 1 34.432 15.36L944.32 364.8a32 32 0 0 1-4.032 37.504l-77.12 85.12a357.12 357.12 0 0 1 0 49.024l77.12 85.248a32 32 0 0 1 4.032 37.504l-88.704 153.6a32 32 0 0 1-34.432 15.296L708.8 803.904c-13.44 9.088-27.648 17.28-42.368 24.512l-35.264 109.376A32 32 0 0 1 600.704 960H423.296a32 32 0 0 1-30.464-22.208L357.696 828.48a351.616 351.616 0 0 1-42.56-24.64l-112.32 24.256a32 32 0 0 1-34.432-15.36L79.68 659.2a32 32 0 0 1 4.032-37.504l77.12-85.248a357.12 357.12 0 0 1 0-48.896l-77.12-85.248A32 32 0 0 1 79.68 364.8l88.704-153.6a32 32 0 0 1 34.432-15.296l112.32 24.256c13.568-9.152 27.776-17.408 42.56-24.64l35.2-109.312A32 32 0 0 1 423.232 64H600.64zm-23.424 64H446.72l-36.352 113.088-24.512 11.968a294.113 294.113 0 0 0-34.816 20.096l-22.656 15.36-116.224-25.088-65.28 113.152 79.68 88.192-1.92 27.136a293.12 293.12 0 0 0 0 40.192l1.92 27.136-79.808 88.192 65.344 113.152 116.224-25.024 22.656 15.296a294.113 294.113 0 0 0 34.816 20.096l24.512 11.968L446.72 896h130.688l36.48-113.152 24.448-11.904a288.282 288.282 0 0 0 34.752-20.096l22.592-15.296 116.288 25.024 65.28-113.152-79.744-88.192 1.92-27.136a293.12 293.12 0 0 0 0-40.256l-1.92-27.136 79.808-88.128-65.344-113.152-116.288 24.96-22.592-15.232a287.616 287.616 0 0 0-34.752-20.096l-24.448-11.904L577.344 128zM512 320a192 192 0 1 1 0 384 192 192 0 0 1 0-384m0 64a128 128 0 1 0 0 256 128 128 0 0 0 0-256"></path></svg>
203 </a>
204 </li>
205 <?php
206 });
207 }
208
209 echo '<div class="fcom_side_footer">';
210 $this->renderTopMenuRightItems();
211 echo '</div>';
212 });
213
214 }
215
216 public function renderTopMenuRightItems()
217 {
218 $auth_url = $this->getAuthUrl();
219 $auth = Helper::getCurrentProfile();
220 $has_color_scheme = Helper::hasColorScheme();
221 $profileLinks = $this->getProfileLinks($auth);
222 ?>
223 <ul class="fcom_user_context_menu_items">
224 <?php do_action('fluent_community/before_header_right_menu_items', $auth); ?>
225 <?php if ($has_color_scheme): ?>
226 <li>
227 <span class="fcom_color_mode_core">
228 <span class="fcom_color_mode_action fcom_mode_switch el-icon">
229 <svg class="show_on_light" width="20" height="20" viewBox="0 0 20 20" fill="none"
230 xmlns="http://www.w3.org/2000/svg">
231 <path
232 d="M17.9163 11.7317C16.9166 12.2654 15.7748 12.5681 14.5623 12.5681C10.6239 12.5681 7.43128 9.37543 7.43128 5.43705C7.43128 4.22456 7.73388 3.08274 8.2677 2.08301C4.72272 2.91382 2.08301 6.09562 2.08301 9.89393C2.08301 14.3246 5.67476 17.9163 10.1054 17.9163C13.9038 17.9163 17.0855 15.2767 17.9163 11.7317Z"
233 stroke="#525866" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
234 </svg>
235 <svg class="show_on_dark" width="20" height="20" viewBox="0 0 20 20" fill="none"
236 xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_2906_20675)">
237 <path
238 d="M14.1663 10.0007C14.1663 12.3018 12.3009 14.1673 9.99967 14.1673C7.69849 14.1673 5.83301 12.3018 5.83301 10.0007C5.83301 7.69946 7.69849 5.83398 9.99967 5.83398C12.3009 5.83398 14.1663 7.69946 14.1663 10.0007Z"
239 stroke="currentColor" stroke-width="1.5"/><path
240 d="M9.99984 1.66699V2.91699M9.99984 17.0837V18.3337M15.8922 15.8931L15.0083 15.0092M4.99089 4.99137L4.107 4.10749M18.3332 10.0003H17.0832M2.9165 10.0003H1.6665M15.8926 4.10758L15.0087 4.99147M4.99129 15.0093L4.10741 15.8932"
241 stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></g><defs><clipPath
242 id="clip0_2906_20675"><rect width="20" height="20"
243 fill="correntColor"/></clipPath></defs>
244 </svg>
245 </span>
246 </span>
247 </li>
248 <?php endif; ?>
249 <li class="top_menu_item fcom_search_holder"></li>
250 <li class="top_menu_item fcom_notification_holder"></li>
251 <?php do_action('fluent_community/before_header_menu_items', $auth); ?>
252 <?php if ($auth): ?>
253 <li class="top_menu_item fcom_menu_item_user">
254 <div class="fcom_user_menu_item">
255 <div class="fcom_profile_extend">
256 <div class="fcom_profile_menu">
257 <div class="user_avatar">
258 <img alt="User Photo" src="<?php echo esc_url($auth->avatar); ?>"/>
259 <span class="avatar_icon">
260 <svg xmlns="http://www.w3.org/2000/svg" height="8" width="8"
261 viewBox="0 0 1024 1024" data-v-d2e47025="">
262 <path fill="currentColor"
263 d="M104.704 338.752a64 64 0 0 1 90.496 0l316.8 316.8 316.8-316.8a64 64 0 0 1 90.496 90.496L557.248 791.296a64 64 0 0 1-90.496 0L104.704 429.248a64 64 0 0 1 0-90.496z"></path>
264 </svg>
265 </span>
266 </div>
267 <span class="user_name">
268 <?php echo esc_html($auth->display_name); ?>
269 </span>
270 <ul class="fcom_profile_sub_menu">
271 <li class="fcom_profile_block">
272 <a href="<?php echo esc_url(Helper::baseUrl('/u/' . $auth->username)); ?>">
273 <div class="fcom_profile_avatar">
274 <img src="<?php echo esc_url($auth->avatar); ?>"
275 alt="<?php echo esc_attr($auth->display_name); ?>">
276 </div>
277 <div class="fcom_user_info">
278 <p class="fcom_user_name"><?php echo esc_html($auth->display_name); ?></p>
279 <p class="fcom_user_email"><?php echo esc_html($auth->user->user_email); ?></p>
280 </div>
281 </a>
282 </li>
283 <?php foreach ($profileLinks as $link): ?>
284 <li>
285 <?php Helper::renderLink($link, 'fcom_menu_link', ''); ?>
286 </li>
287 <?php endforeach; ?>
288 </ul>
289 </div>
290 </div>
291 </li>
292 <?php else: ?>
293 <li class="top_menu_item fcom_login_li">
294 <a class="fcom_login_btn" href="<?php echo esc_url($auth_url); ?>">
295 <span><?php esc_html_e('Login', 'fluent-community'); ?></span>
296 </a>
297 </li>
298 <?php endif; ?>
299 <?php do_action('fluent_community/after_header_right_menu_items', $auth); ?>
300 </ul>
301 <?php
302 }
303
304 protected function appVars()
305 {
306 $userModel = User::where('ID', get_current_user_id())->first();
307 $xprofile = null;
308
309 if ($userModel) {
310 $xprofile = XProfile::where('user_id', get_current_user_id())->first();
311 if (!$xprofile) {
312 $xprofile = $userModel->syncXProfile();
313 }
314 }
315
316 $authData = null;
317 $spaceSlugs = [];
318 $spaceGroups = [];
319
320 if ($userModel && $xprofile) {
321 $wpUser = get_user_by('ID', $userModel->ID);
322
323 if ($userModel->isCommunityModerator()) {
324 $userSpaces = Space::orderBy('serial', 'ASC')->get();
325 $spaceGroups = SpaceGroup::orderBy('serial', 'ASC')
326 ->select(['id', 'title', 'slug', 'settings'])
327 ->get();
328 } else {
329 $userSpaces = Space::orderBy('serial', 'ASC')
330 ->whereHas('members', function ($q) {
331 $q->where('user_id', get_current_user_id())
332 ->where('status', 'active');
333 })
334 ->get();
335
336 $userSpaceParentIds = $userSpaces->pluck('parent_id')->filter()->unique()->toArray();
337
338 $spaceGroups = SpaceGroup::orderBy('serial', 'ASC')
339 ->select(['id', 'title', 'slug', 'settings'])
340 ->whereIn('id', $userSpaceParentIds)
341 ->get();
342 }
343
344 $userSpaces->each(function ($space) use ($userModel) {
345 $userId = get_current_user_id();
346 $space->permissions = $space->getUserPermissions($userModel);
347 $space->membership = $space->getMembership($userId);
348 $space->description_rendered = FeedsHelper::mdToHtml($space->description);
349 if (!$space->membership) {
350 $space->lockscreen_config = LockscreenService::getLockscreenConfig($space, $space->membership);
351 }
352 $space->topics = Utility::getTopicsBySpaceId($space->id);
353 do_action_ref_array('fluent_community/space', [&$space]);
354 });
355
356 $userSpaces = $userSpaces->keyBy('slug');
357
358 $userModel->cacheAccessSpaces();
359
360 $spaceSlugs = $userSpaces->pluck('slug')->toArray();
361
362 $authData = [
363 'id' => $xprofile->user_id,
364 'user_id' => $xprofile->user_id,
365 'username' => $xprofile->username,
366 'display_name' => $xprofile->display_name,
367 'first_name' => $wpUser->first_name ? $wpUser->first_name : $xprofile->getFirstName(),
368 'avatar' => $xprofile->avatar,
369 'total_points' => $xprofile->total_points,
370 'last_activity' => $xprofile->last_activity,
371 'email' => $userModel->user_email,
372 'spaces' => $userSpaces,
373 'community_roles' => $userModel->getCommunityRoles(),
374 'is_verified' => $xprofile->is_verified,
375 'compilation_score' => $xprofile->getCompletionScore(),
376 'meta' => $xprofile->meta
377 ];
378 } else {
379 $authData = [
380 'id' => 0,
381 'user_id' => 0,
382 'spaces' => (object)[],
383 'community_roles' => [],
384 'compilation_score' => 100
385 ];
386 }
387
388 $settings = Helper::generalSettings();
389
390 $onboardSettings = Helper::getOnboardingSettings();
391
392 global $wp_version;
393
394 $isRtl = Helper::isRtl();
395
396 $isAbsoluteUrl = defined('FLUENT_COMMUNITY_PORTAL_SLUG') && FLUENT_COMMUNITY_PORTAL_SLUG == '';
397
398 $portalVars = apply_filters('fluent_community/portal_vars', [
399 'portal_notices' => apply_filters('fluent_community/portal_notices', []),
400 'i18n' => TransStrings::getStrings(),
401 'auth' => $authData,
402 'ajaxurl' => admin_url('admin-ajax.php'),
403 'slug' => 'fluent-community',
404 'rest' => $this->getRestInfo(),
405 'user_id' => $userModel ? $userModel->ID : null,
406 'assets_url' => FLUENT_COMMUNITY_PLUGIN_URL . 'assets/',
407 'permissions' => $userModel ? $userModel->getPermissions() : ['read' => true],
408 'logo' => Arr::get($settings, 'logo'),
409 'site_title' => Arr::get($settings, 'site_title'),
410 'user_membership_slugs' => $spaceSlugs,
411 'block_editor_assets' => [
412 'scripts' => [
413 'react' => Vite::getStaticSrcUrl('libs/isolated-editor/react.production.min.js'),
414 'react-dom' => Vite::getStaticSrcUrl(
415 'libs/isolated-editor/react-dom.production.min.js'
416 ),
417 'isolated-block-editor' => Vite::getStaticSrcUrl('libs/isolated-editor/isolated-block-editor.js')
418 ],
419 'styles' => [
420 $isRtl ? Vite::getStaticSrcUrl('libs/isolated-editor/core.rtl.css') : Vite::getStaticSrcUrl('libs/isolated-editor/core.css'),
421 $isRtl ? Vite::getStaticSrcUrl('libs/isolated-editor/isolated-block-editor.rtl.css') : Vite::getStaticSrcUrl('libs/isolated-editor/isolated-block-editor.css'),
422 includes_url('css/dist/block-editor/content.min.css?ver=' . $wp_version),
423 ]
424 ],
425 'features' => [
426 'disable_global_posts' => Arr::get($settings, 'disable_global_posts', '') == 'yes',
427 'has_survey_poll' => true,
428 'is_onboarding_enabled' => Arr::get($onboardSettings, 'is_onboarding_enabled', 'no') == 'yes',
429 'can_switch_layout' => true,
430 'max_media_per_post' => apply_filters('fluent_community/max_media_per_post', 4),
431 'has_post_title' => Utility::postTitlePref(),
432 'has_course' => Helper::isFeatureEnabled('course_module'),
433 'skicky_sidebar' => Utility::isCustomizationEnabled('fixed_sidebar'),
434 'post_layout' => Utility::getCustomizationSetting('rich_post_layout'),
435 'video_embeder' => apply_filters('fluent_community/has_video_embeder', true),
436 'has_topics' => !!Utility::getTopics()
437 ],
438 'route_classes' => array_filter([
439 'fcom_sticky_header' => Utility::isCustomizationEnabled('fixed_page_header'),
440 'fcom_sticky_sidebar' => Utility::isCustomizationEnabled('fixed_sidebar'),
441 'fcom_has_icon_on_header_menu' => Utility::isCustomizationEnabled('icon_on_header_menu')
442 ]),
443 'urls' => [
444 'site_url' => site_url(),
445 'portal_base' => Helper::baseUrl('/'),
446 'global_search' => Helper::baseUrl(),
447 ],
448 'last_feed_id' => FeedsHelper::getLastFeedId(),
449 'unread_notification_count' => $userModel ? $userModel->getUnreadNotificationCount() : 0,
450 'unread_feed_ids' => $userModel ? $userModel->getUnreadNotificationFeedIds() : [],
451 'date_offset' => time() - current_time('timestamp'),
452 'portal_slug' => Helper::getPortalSlug(true),
453 'mobileMenuItems' => apply_filters('fluent_community/mobile_menu', [
454 [
455 'route' => [
456 'name' => 'all_feeds'
457 ],
458 'icon_svg' => '<svg width="20" height="18" viewBox="0 0 20 18" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M10 13.166H10.0075H10Z" fill="currentColor"></path><path d="M10 13.166H10.0075" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M16.6666 6.08301V10.2497C16.6666 13.3924 16.6666 14.9637 15.6903 15.94C14.714 16.9163 13.1426 16.9163 9.99992 16.9163C6.85722 16.9163 5.28587 16.9163 4.30956 15.94C3.33325 14.9637 3.33325 13.3924 3.33325 10.2497V6.08301" stroke="currentColor" stroke-width="1.5"></path><path d="M18.3333 7.74967L14.714 4.27925C12.4918 2.14842 11.3807 1.08301 9.99996 1.08301C8.61925 1.08301 7.50814 2.14842 5.28592 4.27924L1.66663 7.74967" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path></svg>'
459 ],
460 [
461 'route' => [
462 'name' => 'spaces'
463 ],
464 'icon_svg' => '<svg version="1.1" viewBox="0 0 128 128" xml:space="preserve"><g><path d="M64,42c-13.2,0-24,10.8-24,24s10.8,24,24,24s24-10.8,24-24S77.2,42,64,42z M64,82c-8.8,0-16-7.2-16-16s7.2-16,16-16 s16,7.2,16,16S72.8,82,64,82z"></path><path d="M64,100.8c-14.9,0-29.2,6.2-39.4,17.1l-2.7,2.9l5.8,5.5l2.7-2.9c8.8-9.4,20.7-14.6,33.6-14.6s24.8,5.2,33.6,14.6l2.7,2.9 l5.8-5.5l-2.7-2.9C93.2,107.1,78.9,100.8,64,100.8z"></path><path d="M97,47.9v8c9.4,0,18.1,3.8,24.6,10.7l5.8-5.5C119.6,52.7,108.5,47.9,97,47.9z"></path><path d="M116.1,20c0-10.5-8.6-19.1-19.1-19.1S77.9,9.5,77.9,20S86.5,39.1,97,39.1S116.1,30.5,116.1,20z M85.9,20 c0-6.1,5-11.1,11.1-11.1s11.1,5,11.1,11.1s-5,11.1-11.1,11.1S85.9,26.1,85.9,20z"></path><path d="M31,47.9c-11.5,0-22.6,4.8-30.4,13.2l5.8,5.5c6.4-6.9,15.2-10.7,24.6-10.7V47.9z"></path><path d="M50.1,20C50.1,9.5,41.5,0.9,31,0.9S11.9,9.5,11.9,20S20.5,39.1,31,39.1S50.1,30.5,50.1,20z M31,31.1 c-6.1,0-11.1-5-11.1-11.1S24.9,8.9,31,8.9s11.1,5,11.1,11.1S37.1,31.1,31,31.1z"></path></g></svg>'
465 ]
466 ]),
467 'socialLinkProviders' => ProfileHelper::socialLinkProviders(),
468 'space_groups' => $spaceGroups,
469 'feed_links' => Helper::getEnabledFeedLinks(),
470 'routing_system' => Helper::getPortalRouteType(),
471 'portal_url' => Helper::baseUrl('/'),
472 'upgrade_url' => 'https://fluentcommunity.co/discount-deal/?utm_source=wp&utm_medium=upgrade&utm_campaign=upgrade',
473 'dateTime18n' => apply_filters('fluent_community/date_time_i18n', [
474 /* translators: weekday. Please keep the serial and format */
475 'weekdays' => __('Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday', 'fluent-community'),
476 /* translators: Months Please keep the serial and format*/
477 'months' => __('January_February_March_April_May_June_July_August_September_October_November_December', 'fluent-community'),
478 /* translators: weekday short Please keep the serial and format*/
479 'weekdaysShort' => __('Sun_Mon_Tue_Wed_Thu_Fri_Sat', 'fluent-community'),
480 /* translators: Months short Please keep the serial and format*/
481 'monthsShort' => __('Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec', 'fluent-community'),
482 /* translators: weekday min Please keep the serial and format*/
483 'weekdaysMin' => __('Su_Mo_Tu_We_Th_Fr_Sa', 'fluent-community'),
484 'relativeTime' => [
485 /* translators: Relative Date Formats. Please do not alter %s*/
486 'future' => __('in %s', 'fluent-community'),
487 /* translators: Relative Date Formats. Please do not alter %s*/
488 'past' => __('%s ago', 'fluent-community'),
489 /* translators: Relative Date Formats.*/
490 's' => __('a few seconds', 'fluent-community'),
491 /* translators: Relative Date Formats.*/
492 'm' => __('a minute', 'fluent-community'),
493 /* translators: Relative Date Formats. Don't alter %d*/
494 'mm' => __('%d minutes', 'fluent-community'),
495 /* translators: Relative Date Formats*/
496 'h' => __('an hour', 'fluent-community'),
497 /* translators: Relative Date Formats. Don't alter %d*/
498 'hh' => __('%d hours', 'fluent-community'),
499 /* translators: Relative Date Formats*/
500 'd' => __('a day', 'fluent-community'),
501 /* translators: Relative Date Formats. Don't alter %d*/
502 'dd' => __('%d days', 'fluent-community'),
503 /* translators: Relative Date Formats*/
504 'M' => __('a month', 'fluent-community'),
505 /* translators: Relative Date Formats. Don't alter %d*/
506 'MM' => __('%d months', 'fluent-community'),
507 /* translators: Relative Date Formats*/
508 'y' => __('a year', 'fluent-community'),
509 /* translators: Relative Date Formats. Don't alter %d*/
510 'yy' => __('%d years', 'fluent-community')
511 ],
512 'relativeTimeMobile' => [
513 /* translators: Relative Date Formats. Please do not alter %s*/
514 'future' => __('in %s', 'fluent-community'),
515 /* translators: Relative Date Formats. Please do not alter %s*/
516 'past' => __('%s ago', 'fluent-community'),
517 /* translators: Relative Date Formats.*/
518 's' => __('few sec', 'fluent-community'),
519 /* translators: Relative Date Formats.*/
520 'm' => __('1min', 'fluent-community'),
521 /* translators: Relative Date Formats. Don't alter %d*/
522 'mm' => __('%dmin', 'fluent-community'),
523 /* translators: Relative Date Formats*/
524 'h' => __('1h', 'fluent-community'),
525 /* translators: Relative Date Formats. Don't alter %d*/
526 'hh' => __('%dh', 'fluent-community'),
527 /* translators: Relative Date Formats*/
528 'd' => __('1d', 'fluent-community'),
529 /* translators: Relative Date Formats. Don't alter %d*/
530 'dd' => __('%dd', 'fluent-community'),
531 /* translators: Relative Date Formats*/
532 'M' => __('1m', 'fluent-community'),
533 /* translators: Relative Date Formats. Don't alter %d*/
534 'MM' => __('%dm', 'fluent-community'),
535 /* translators: Relative Date Formats*/
536 'y' => __('1y', 'fluent-community'),
537 /* translators: Relative Date Formats. Don't alter %d*/
538 'yy' => __('%dy', 'fluent-community')
539 ]
540 ]),
541 'topicsConfig' => Helper::getTopicsConfig(),
542 'is_absolute_url' => $isAbsoluteUrl,
543 'portal_paths' => $isAbsoluteUrl ? Helper::portalRoutePaths() : [],
544 'suggestedColors' => Utility::getSuggestedColors()
545 ]);
546
547 if ($xprofile) {
548 $portalVars['mobileMenuItems'][] = [
549 'route' => [
550 'name' => 'user_profile',
551 'params' => [
552 'username' => $xprofile->username
553 ]
554 ],
555 'icon' => 'Avatar'
556 ];
557 }
558
559 $portalVars['welcome_banner'] = Helper::getWelcomeBanner($userModel ? 'login' : 'logout');
560
561 if (!$xprofile) {
562 $portalVars['auth_url'] = $this->getAuthUrl();
563 $portalVars['allow_signup'] = !!AuthHelper::isRegistrationEnabled();
564 }
565
566 return $portalVars;
567 }
568
569 protected function getRestInfo()
570 {
571 $app = fluentCommunityApp();
572 $ns = $app->config->get('app.rest_namespace');
573 $v = $app->config->get('app.rest_version');
574
575 return [
576 'base_url' => esc_url_raw(rest_url()),
577 'url' => rest_url($ns . '/' . $v),
578 'nonce' => wp_create_nonce('wp_rest'),
579 'namespace' => $ns,
580 'version' => $v,
581 ];
582 }
583
584 protected function renderFullApp()
585 {
586 if (isset($_REQUEST['fcom_action'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
587 $action = sanitize_text_field(wp_unslash($_REQUEST['fcom_action'])); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
588 do_action('fluent_community/portal_action_' . $action, $_GET); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
589 }
590
591 $userId = get_current_user_id();
592
593 if (!$userId) {
594 if (!Helper::isPublicAccessible()) {
595 $url = home_url(add_query_arg($_REQUEST, $GLOBALS['wp']->request)); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
596 $settings = Helper::generalSettings();
597 $authUrl = Arr::get($settings, 'auth_url', '');
598 if ($authUrl) {
599 $authUrl = add_query_arg([
600 'redirect_to' => $url
601 ], $authUrl);
602 } else {
603 $authUrl = $this->getAuthUrl();
604 }
605
606 do_action('fluent_community/portal/not_logged_in', $authUrl);
607 wp_redirect($authUrl);
608 exit();
609 }
610 }
611
612 do_action('fluent_community/portal/viewed');
613 $xprofile = Helper::getCurrentProfile();
614
615 if ($xprofile && $xprofile->status != 'active') {
616 if ($xprofile->status == 'pending') {
617 $this->viewErrorPage('You request is on pending', 'An admin need to approve your join request. Please contact with an admin to get approval');
618 } else {
619 $this->viewErrorPage('Access denied', 'Sorry, You can not access to this portal');
620 }
621 }
622
623 if ($xprofile) {
624 if (!Helper::canAccessPortal()) {
625 $generalSettings = Helper::generalSettings();
626 $this->viewErrorPage('Access Denied', Arr::get($generalSettings, 'restricted_role_content'));
627 }
628 if ($xprofile->user) {
629 $xprofile->user->cacheAccessSpaces();
630 }
631
632 /*
633 * Just in case if username is not sanitized
634 */
635 if ($xprofile->username != CustomSanitizer::sanitizeUserName($xprofile->username)) {
636 $xprofile->username = ProfileHelper::generateUserName($xprofile->user_id);
637 $xprofile->save();
638 }
639
640 do_action('fluent_community/portal_render_for_user', $xprofile);
641 do_action('fluent_communit/track_activity');
642 }
643
644 $data = $this->getAppData();
645 $data = $this->maybePushDynamicMetaData($data);
646
647 $data['isHeadless'] = Helper::isHeadless();
648
649 if (!$data['isHeadless']) {
650 $this->loadClassicPortalAssets($data);
651 } else {
652 do_action('fluent_community/rendering_headless_portal', $data);
653 }
654
655 do_action('fluent_community/before_portal_rendered', $data);
656
657 status_header(200);
658 App::make('view')->render('portal_page', $data);
659 exit(200);
660 }
661
662 public function loadClassicPortalAssets($data)
663 {
664 $cssFiles = $data['css_files'];
665
666 unset($cssFiles['fcom_theme_default']);
667
668 foreach ($cssFiles as $fileName => $cssFile) {
669 wp_enqueue_style($fileName, $cssFile['url'], [], FLUENT_COMMUNITY_PLUGIN_VERSION, 'screen');
670 }
671
672 $jsFiles = $data['js_files'];
673 $jsTags = array_keys($jsFiles);
674 add_filter('script_loader_tag', function ($tag, $handle) use ($jsTags) {
675 if (!in_array($handle, $jsTags)) {
676 return $tag;
677 }
678 $tag = str_replace(' src', ' type="module" src', $tag);
679 return $tag;
680 }, 10, 2);
681 foreach ($jsFiles as $fileName => $jsFile) {
682 wp_enqueue_script($fileName, $jsFile['url'], $jsFile['deps'], FLUENT_COMMUNITY_PLUGIN_VERSION, [
683 'in_footer' => true,
684 'strategy' => 'defer',
685 'type' => 'module'
686 ]);
687 }
688
689 foreach ($data['js_vars'] as $varKey => $values) {
690 wp_localize_script('fcom_strat', $varKey, $values);
691 }
692 }
693
694 public function getAppData()
695 {
696
697 $isRtl = Helper::isRtl();
698
699 $userId = get_current_user_id();
700 $url = home_url(add_query_arg($_REQUEST, $GLOBALS['wp']->request)); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
701
702 $appVars = $this->appVars();
703 $generalSettings = Helper::generalSettings();
704
705 $dataVars = [
706 'title' => Arr::get($generalSettings, 'site_title'),
707 'description' => get_bloginfo('description'),
708 'featured_image' => Arr::get($generalSettings, 'featured_image', ''),
709 'js_files' => [
710 'fcom_strat' => [
711 'url' => Vite::getStaticSrcUrl('start.js'),
712 'deps' => []
713 ],
714 'fcom_app' => [
715 'url' => Vite::getStaticSrcUrl('app.js'),
716 'deps' => []
717 ],
718 'fcom_general' => [
719 'url' => Vite::getStaticSrcUrl('portal_general.js'),
720 'deps' => []
721 ]
722 ],
723 'js_vars' => [
724 'fluentComAdmin' => $appVars,
725 ],
726 'css_files' => array_filter([
727 'fcom_theme_default' => [
728 'url' => Vite::getDynamicSrcUrl('theme-default.scss', $isRtl)
729 ],
730 'fcom_global' => [
731 'url' => Vite::getDynamicSrcUrl('global.scss', $isRtl)
732 ]
733 ]),
734 'url' => $url,
735 'current_route' => $this->currentPath,
736 'contact' => $appVars['auth'],
737 'user' => $userId ? get_user_by('ID', $userId) : null,
738 'route_group' => Helper::getRouteNameByRequestPath($this->currentPath)
739 ];
740
741 if (!Utility::isDev()) {
742
743 if($isRtl) {
744 $fileName = 'app.rtl.css';
745 } else {
746 $fileName = 'app.css';
747 }
748
749 $dataVars['css_files']['fcom_vendor'] = [
750 'url' => Vite::getStaticSrcUrl($fileName)
751 ];
752 } else {
753 $dataVars['css_files']['fcom_vendor'] = [
754 'url' => Vite::getDynamicSrcUrl('app_css.scss')
755 ];
756 }
757
758 return apply_filters('fluent_community/portal_data_vars', $dataVars);
759 }
760
761 protected function maybePushDynamicMetaData($data)
762 {
763 $dynamicRoute = Arr::get($data, 'route_group');
764 $validGroups = [
765 'user_profile',
766 'community_view',
767 'course_view',
768 'feed_view'
769 ];
770
771 if (!in_array($dynamicRoute, $validGroups)) {
772 return $data;
773 }
774
775 if ($dynamicRoute == 'user_profile') {
776 $uriParts = explode('/', $this->currentPath);
777 if (count($uriParts) >= 2) {
778 $userName = $uriParts[1];
779 $xProfile = XProfile::where('username', $userName)->first();
780 if ($xProfile) {
781 $data['title'] = esc_html($xProfile->display_name) . ' - ' . $data['title'];
782 if ($xProfile->short_description) {
783 $data['description'] = Helper::getHumanExcerpt($xProfile->short_description, 100);
784 }
785 if ($coverPhoto = Arr::get($xProfile->meta, 'cover_photo')) {
786 $data['featured_image'] = $coverPhoto;
787 }
788 }
789 }
790 return $data;
791 }
792
793 if ($dynamicRoute == 'community_view' || $dynamicRoute == 'course_view') {
794 $uriParts = explode('/', $this->currentPath);
795 if (count($uriParts) >= 2) {
796 $paceSlug = $uriParts[1];
797
798 $space = BaseSpace::query()->withoutGlobalScopes()->where('slug', $paceSlug)->first();
799
800 if ($space && $space->privacy != 'secret') {
801
802 if ($dynamicRoute == 'course_view') {
803 $data['title'] = sprintf(__('Enroll %s', 'fluent-community'), esc_html($space->title) . ' - ' . $data['title']);
804 } else {
805 $data['title'] = sprintf(__('Join %s', 'fluent-community'), esc_html($space->title) . ' - ' . $data['title']);
806 }
807
808 if ($space->description) {
809 $data['description'] = Helper::getHumanExcerpt($space->description, 100);
810 }
811 if ($ogImage = Arr::get($space->settings, 'og_image')) {
812 $data['featured_image'] = $ogImage;
813 } else if ($space->cover_photo) {
814 $data['featured_image'] = $space->cover_photo;
815 }
816 }
817 }
818 return $data;
819 }
820
821 if ($dynamicRoute == 'feed_view') {
822 $uriParts = explode('/', $this->currentPath);
823
824 if (count($uriParts) >= 2) {
825 $postSlug = end($uriParts);
826 $feed = Feed::where('slug', $postSlug)
827 ->with([
828 'xprofile' => function ($q) {
829 $q->select(ProfileHelper::getXProfilePublicFields());
830 },
831 'space'
832 ])
833 ->byUserAccess(get_current_user_id())
834 ->first();
835
836 if (!$feed) {
837 return $data;
838 }
839
840 if ($feed->title) {
841 $data['title'] = esc_html($feed->title) . ' - ' . $data['title'];
842 } else {
843 $data['title'] = esc_html($feed->xprofile->display_name) . ' posted at ' . $data['title'];
844 }
845
846 if ($feed->message) {
847 $data['description'] = esc_html(Helper::getHumanExcerpt($feed->message, 100));
848 }
849
850 if ($mediaPreview = Arr::get($feed->meta, 'media_preview.image')) {
851 $data['featured_image'] = esc_url($mediaPreview);
852 } else if ($feed->space) {
853 $space = $feed->space;
854 if ($ogImage = Arr::get($space->settings, 'og_image')) {
855 $data['featured_image'] = $ogImage;
856 } else if ($space->cover_photo) {
857 $data['featured_image'] = $space->cover_photo;
858 }
859 }
860 }
861
862 return $data;
863 }
864
865 return $data;
866 }
867
868 protected function getMainMenuItems($scope = 'sidebar')
869 {
870 $menuGroups = Helper::getMenuItemsGroup('view');
871
872 $items = Arr::get($menuGroups, 'mainMenuItems', []);
873
874 return apply_filters('fluent_community/main_menu_items', $items, $scope);
875 }
876
877 public function getPortalHeader($echo = false, $context = 'headless')
878 {
879 $settings = Helper::generalSettings();
880 $userId = get_current_user_id();
881
882 if ($userId) {
883 $xprofile = XProfile::where('user_id', get_current_user_id())
884 ->first();
885 } else {
886 $xprofile = null;
887 }
888
889
890 $authUrl = $this->getAuthUrl();
891
892 if ($xprofile) {
893 $xprofile->logout_url = wp_logout_url(Helper::baseUrl());
894 }
895
896 $logo = Arr::get($settings, 'logo', '');
897 $whiteLogo = Arr::get($settings, 'white_logo', '');
898 if (!$whiteLogo) {
899 $whiteLogo = $logo;
900 }
901
902 $data = apply_filters('fluent_community/header_vars', [
903 'portal_url' => Helper::baseUrl('/'),
904 'logo' => $logo,
905 'white_logo' => $whiteLogo,
906 'site_title' => Arr::get($settings, 'site_title'),
907 'profile_url' => $userId ? Helper::baseUrl('u/' . $xprofile->username . '/') : '',
908 'auth' => $xprofile ? $xprofile : null,
909 'auth_url' => $authUrl,
910 'menuItems' => $this->getMainMenuItems('header')
911 ]);
912
913 if ($echo) {
914 App::make('view')->render('portal.header', $data);
915 return;
916 }
917
918 return (string)App::make('view')->make('portal.header', $data);
919 }
920
921 private function getProfileLinks($xprofile = null)
922 {
923 if (!$xprofile) {
924 $xprofile = Helper::getCurrentProfile();
925 }
926
927 $profileLinks = [];
928 $menuGroups = Helper::getMenuItemsGroup('view');
929 if ($xprofile) {
930 $profileLinks = Arr::get($menuGroups, 'profileDropdownItems', []);
931
932 $replaces = [
933 '#{{user_url}}' => Helper::baseUrl('u/' . $xprofile->username),
934 '#user_url' => Helper::baseUrl('u/' . $xprofile->username),
935 '#{{logout_url}}' => wp_logout_url(Helper::baseUrl()),
936 '#logout_url' => wp_logout_url(Helper::baseUrl())
937 ];
938
939 foreach ($profileLinks as &$link) {
940 $slug = Arr::get($link, 'slug', '');
941
942 if ($slug == 'my_spaces') {
943 $link['permalink'] = Helper::baseUrl('u/' . $xprofile->username . '/spaces');
944 } else if ($slug == 'logout') {
945 $link['permalink'] = wp_logout_url(Helper::baseUrl());
946 } else if ($slug == 'profile') {
947 $link['permalink'] = Helper::baseUrl('u/' . $xprofile->username);
948 }
949
950 $link['permalink'] = str_replace(array_keys($replaces), array_values($replaces), $link['permalink']);
951 }
952 }
953
954 return $profileLinks;
955 }
956
957 public function getPortalSidebar($echo = false, $context = 'headless')
958 {
959 $primaryMenuItems = $this->getMainMenuItems('sidebar');
960
961 $userModel = Helper::getCurrentUser();
962 $spaceGroups = Helper::getCommunityMenuGroups($userModel);
963
964 $settingsMenu = apply_filters('fluent_community/settings_menu', [], $userModel);
965
966 $menuGroups = Helper::getMenuItemsGroup('view');
967 $topInlines = Arr::get($menuGroups, 'beforeCommunityMenuItems', []);
968 $bottomLinkGroups = Arr::get($menuGroups, 'afterCommunityLinkGroups', []);
969
970 $data = [
971 'primaryItems' => $primaryMenuItems,
972 'spaceGroups' => $spaceGroups,
973 'settingsItems' => $settingsMenu,
974 'topInlineLinks' => $topInlines,
975 'bottomLinkGroups' => $bottomLinkGroups,
976 'is_admin' => Helper::isSiteAdmin(),
977 'has_color_scheme' => Helper::hasColorScheme(),
978 'context' => $context
979 ];
980
981 if ($echo) {
982 App::make('view')->render('portal.main_sidebar', $data);
983 return;
984 }
985
986 return (string)App::make('view')->make('portal.main_sidebar', $data);
987 }
988
989 protected function getAuthUrl()
990 {
991 return apply_filters('fluent_community/auth/login_url', Helper::getAuthUrl());
992 }
993
994 protected function viewErrorPage($title, $message = '', $showBtn = true)
995 {
996 $data = [
997 'title' => $title,
998 'description' => $message,
999 'btn_txt' => 'Go to home page',
1000 'url' => site_url()
1001 ];
1002
1003 if (!$showBtn) {
1004 $data['btn_txt'] = '';
1005 }
1006
1007 status_header(200);
1008 App::make('view')->render('error_page', $data);
1009 exit();
1010 }
1011
1012 public function showAdminPage()
1013 {
1014 $jsTags = ['fluent_community_onboarding'];
1015
1016 add_filter('script_loader_tag', function ($tag, $handle) use ($jsTags) {
1017 if (!in_array($handle, $jsTags)) {
1018 return $tag;
1019 }
1020 $tag = str_replace(' src', ' type="module" src', $tag);
1021 return $tag;
1022 }, 10, 2);
1023
1024 wp_enqueue_script('fluent_community_onboarding', Vite::getDynamicSrcUrl('Onboarding/onboarding.js'), ['jquery'], FLUENT_COMMUNITY_PLUGIN_VERSION, [
1025 'in_footer' => true,
1026 'strategy' => 'defer',
1027 'type' => 'module'
1028 ]);
1029
1030 wp_localize_script('fluent_community_onboarding', 'fluentComAdmin', [
1031 'ajaxurl' => admin_url('admin-ajax.php'),
1032 'rest' => $this->getRestInfo(),
1033 'urls' => [
1034 'site_url' => site_url('/'),
1035 'portal_base' => Helper::baseUrl('/'),
1036 'permalink_url' => admin_url('options-permalink.php')
1037 ],
1038 'logo' => Helper::assetUrl('images/logo.png'),
1039 'is_onboarded' => !!Utility::getOption('onboarding_sub_settings'),
1040 'permalink_structure' => get_option('permalink_structure'),
1041 'is_slug_defined' => defined('FLUENT_COMMUNITY_PORTAL_SLUG'),
1042 'has_pro' => defined('FLUENT_COMMUNITY_PRO_VERSION'),
1043 'upgrade_url' => Utility::getProductUrl(false),
1044 'settings_page_url' => admin_url('admin.php?page=fluent-community'),
1045 'is_license_page' => isset($_GET['license']) && $_GET['license'] === 'yes',
1046 'license_url_page' => defined('FLUENT_COMMUNITY_PRO_VERSION') ? admin_url('admin.php?page=fluent-community&license=yes') : '',
1047 ]);
1048
1049 echo '<div class="wrap"><div id="fcom_onboarding_app"></div></div>';
1050 }
1051
1052 private function getMenuIcon()
1053 {
1054 return 'data:image/svg+xml;base64,' . base64_encode('<svg width="82" height="71" viewBox="0 0 82 71" fill="none" xmlns="http://www.w3.org/2000/svg">
1055 <path d="M25.9424 49.1832L39.6888 41.2467L47.6253 54.9931C40.0334 59.3763 30.3256 56.7751 25.9424 49.1832Z" fill="white"/>
1056 <path fill-rule="evenodd" clip-rule="evenodd" d="M53.4348 33.3101L39.6884 41.2466L47.6249 54.993L61.3713 47.0565L53.4348 33.3101ZM67.1821 25.3734L53.4356 33.3099L61.3721 47.0564L75.1186 39.1199L67.1821 25.3734Z" fill="white"/>
1057 <path d="M67.182 25.3736C70.978 23.182 75.8319 24.4826 78.0235 28.2786L81.9917 35.1518L75.1185 39.12L67.182 25.3736Z" fill="white"/>
1058 <path d="M42.593 30.4052L28.8466 38.3417L20.9101 24.5953L34.6565 16.6588L42.593 30.4052Z" fill="white"/>
1059 <path d="M56.3397 22.4683L42.5933 30.4048L34.6568 16.6584C42.2487 12.2752 51.9565 14.8764 56.3397 22.4683Z" fill="white"/>
1060 <path d="M28.847 38.3418L15.1006 46.2783L7.16409 32.5318L20.9105 24.5953L28.847 38.3418Z" fill="white"/>
1061 <path d="M15.1011 46.2783C11.3051 48.4699 6.4512 47.1693 4.25959 43.3733L0.291343 36.5001L7.16456 32.5319L15.1011 46.2783Z" fill="white"/>
1062 </svg>');
1063
1064 }
1065
1066 }
1067