PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.45
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.45
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 1.41 1.45 All 41 releases
fluent-boards / app / Http / Controllers / OptionsController.php

OptionsController.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.45, at app/Http/Controllers/OptionsController.php

923 lines 34.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\App\Http\Controllers;
4
5 use FluentBoards\App\App;
6 use FluentBoards\App\Models\Meta;
7 use FluentBoards\App\Models\Task;
8 use FluentBoards\App\Models\User;
9 use FluentBoards\App\Models\Board;
10 use FluentBoards\App\Models\Relation;
11 use FluentBoards\App\Services\BoardService;
12 use FluentBoards\App\Services\Helper;
13 use FluentBoards\App\Services\OptionService;
14 use FluentBoards\App\Services\Constant;
15 use FluentBoards\App\Services\PermissionManager;
16 use FluentBoards\Framework\Http\Request\Request;
17 use FluentBoards\Framework\Support\Arr;
18 use FluentBoardsPro\App\Hooks\Handlers\ProScheduleHandler;
19
20 class OptionsController extends Controller
21 {
22 private $boardService;
23 private $optionService;
24
25 public function __construct(BoardService $boardService, OptionService $optionService)
26 {
27 parent::__construct();
28 $this->boardService = $boardService;
29 $this->optionService = $optionService;
30 }
31
32 public function selectorOptions(Request $request)
33 {
34 try {
35 $optionKey = $request->getSafe('option_key');
36 $search = $request->getSafe('search');
37 $includedIds = $request->getSafe('values');
38 $boardId = $request->getSafe('board_id');
39
40 $options = [];
41 if ('users' === $optionKey || 'task_assignees' === $optionKey) { // no ajax/code is designed to handle this eventually will goto else
42
43 if (!PermissionManager::isBoardManager($boardId)) {
44 throw new \Exception('You do not have permission to access this route');
45 }
46
47 if (!defined('FLUENT_BOARDS_PRO')) {
48 // get who has 'manage_options' capability
49 $users = PermissionManager::getAll_WP_Admins($search);
50
51 } else {
52 // Search by user login, email, and nicename, first_name , last_name
53 $users = Helper::searchWordPressUsers($search);
54 $users = Helper::sanitizeUsersArray($users, $boardId);
55
56 }
57
58 $options = $this->addUserDataAsSelectorOption($users);
59
60 } elseif ('boards' === $optionKey) {
61 $boards = Board::query()
62 ->when($search, function ($query) use ($search) {
63 return $query->where('title', 'LIKE', '%' . $search . '%');
64 })->take(20)->get();
65
66 foreach ($boards as $board) {
67 $options[] = [
68 'id' => $board->id,
69 'title' => $board->title,
70 'left_side_value' => $board->title,
71 'right_side_value' => $board->slug,
72 ];
73 }
74 } elseif ('tasks' === $optionKey) {
75 $tasks = Task::where('board_id', $boardId)
76 ->whereNull('archived_at')
77 ->whereNull('parent_id')
78 ->when($search, function ($query) use ($search) {
79 return $query->where('title', 'LIKE', '%' . $search . '%');
80 })->take(20)->get();
81
82 foreach ($tasks as $task) {
83 $options[] = [
84 'id' => $task->id,
85 'title' => $task->title,
86 'board_id' => $task->board_id
87 ];
88 }
89
90 } elseif ('assigned_in_task' == $optionKey) {
91 $users = (new BoardService())->getAssigneesByBoard($boardId, $search);
92 $options = $this->addUserDataAsSelectorOption($users);
93 } else {
94 $options = apply_filters('fluent_boards/ajax_options_' . $optionKey, [], $search, $includedIds);
95 }
96
97 return $this->sendSuccess([
98 'options' => $options,
99 ], 200);
100 } catch (\Exception $e) {
101 return $this->sendError($e->getMessage(), 404);
102 }
103 }
104
105 private function addUserDataAsSelectorOption($users)
106 {
107 $options = [];
108 foreach ($users as $user) {
109 $options[] = [
110 'id' => $user->ID,
111 'email' => $user->user_email,
112 'name' => $user->display_name ?? $user->user_email,
113 'title' => $user->display_name . ' (' . $user->user_email . ')',
114 'photo' => get_avatar_url($user->user_email),
115 ];
116 }
117 return $options;
118 }
119
120 public function getCurrentUserPermissions()
121 {
122 try {
123 $currentUserBoards = Relation::query()
124 ->where('user_id', get_current_user_id())
125 ->whereNotNull('board_id')
126 ->where('status', 'ACTIVE')
127 ->get();
128 foreach ($currentUserBoards as &$currentUserBoardPermission) {
129 $currentUserBoardPermission->permissions = \maybe_unserialize($currentUserBoardPermission->permissions);
130 }
131
132 return $this->sendSuccess(
133 $currentUserBoards, 200
134 );
135 } catch (\Exception $e) {
136 return $this->sendError($e->getMessage(), 404);
137 }
138 }
139
140 public function getUserPermission(Request $request)
141 {
142 try {
143 $boardId = $request->getSafe('boardId');
144 $userId = $request->getSafe('userId');
145
146 $boardUser = Relation::where('board_id', $boardId)
147 ->where('user_id', $userId)
148 ->where('status', 'ACTIVE')->first();
149 if (!$boardUser->is_admin) {
150 $boardUser->permissions = \maybe_unserialize($boardUser->permissions);
151 }
152
153 return $this->sendSuccess(
154 $boardUser, 200
155 );
156 } catch (\Exception $e) {
157 return $this->sendError($e->getMessage(), 404);
158 }
159 }
160
161 public function updatedUserPermission(Request $request)
162 {
163 try {
164 $permission = $request->getSafe('userPermission');
165 $updateType = $request->getSafe('updateType');
166 $boardId = $request->getSafe('boardId');
167 $userId = $request->getSafe('userId');
168
169 $boardUser = Relation::where('board_id', $boardId)->where('user_id', $userId)->status('ACTIVE')->first();
170
171 if ('Board Admin' == $permission) {
172 $boardUser->is_admin = 'add' == $updateType ? 1 : 0;
173 $boardUser->save();
174 } else {
175 if (0 == $boardUser->is_admin) {
176 $permissionsAlreadyHave = maybe_unserialize($boardUser->permissions);
177 if (!in_array($permission, $permissionsAlreadyHave) && 'add' == $updateType) {
178 array_push($permissionsAlreadyHave, $permission);
179 } elseif (in_array($permission, $permissionsAlreadyHave) && 'remove' == $updateType) {
180 if (($key = array_search($permission, $permissionsAlreadyHave)) !== false) {
181 unset($permissionsAlreadyHave[$key]);
182 }
183 }
184 $boardUser->permissions = serialize($permissionsAlreadyHave);
185 $boardUser->save();
186 }
187 }
188
189 $boardUser->permissions = maybe_unserialize($boardUser->permissions);
190
191 return $this->sendSuccess(
192 $boardUser, 200
193 );
194 } catch (\Exception $e) {
195 return $this->sendError($e->getMessage(), 404);
196 }
197 }
198
199 public function SetUserSuperAdmin($userId)
200 {
201 try {
202 $this->optionService->createSuperAdmin($userId);
203 return $this->sendSuccess([
204 'message' => __('Member has been set super admin successfully!', 'fluent-boards')
205 ], 200);
206
207 } catch (\Exception $e) {
208 return $this->sendError($e->getMessage(), 404);
209 }
210 }
211
212 public function removeUserSuperAdmin($userId)
213 {
214 try {
215 $this->optionService->removeUserSuperAdmin($userId);
216
217 return $this->sendSuccess([
218 'message' => __('User has been removed as super admin successfully!', 'fluent-boards'),
219 ], 200);
220 } catch (\Exception $e) {
221 return $this->sendError($e->getMessage(), 404);
222 }
223 }
224
225 public function IsUserAllBoardAdmin(Request $request)
226 {
227 try {
228 $userId = $request->getSafe('id');
229 $isSuperAdmin = false;
230 $superAdmin = Relation::where('board_id', null)->where('user_id', $userId)->where('status', 'ACTIVE')->first();
231 $totalSuperAdmin = Relation::where('board_id', null)->where('status', 'ACTIVE')->count();
232 $permissions = [];
233 if ($superAdmin) {
234 $isSuperAdmin = true;
235 $permissions = \maybe_unserialize($superAdmin->permissions);
236 }
237
238 return $this->sendSuccess([
239 'allBoardAdmin' => $isSuperAdmin,
240 'permissions' => $permissions,
241 'numberOfSuperAdmin' => $totalSuperAdmin,
242 ], 200);
243 } catch (\Exception $e) {
244 return $this->sendError($e->getMessage(), 404);
245 }
246 }
247
248 public function RemoveUserFromSuperAdmin(Request $request, $id)
249 {
250 try {
251 $userId = $request->getSafe('id');
252
253 $superAdmin = Relation::where('board_id', null)->where('user_id', $userId)->first();
254 $superAdmin->status = 'INACTIVE';
255 $superAdmin->save();
256
257 return $this->sendSuccess([
258 'message' => __('User removed as super admin', 'fluent-boards'),
259 ], 201);
260 } catch (\Exception $e) {
261 return $this->sendError($e->getMessage(), 404);
262 }
263 }
264
265 public function removeUserFromBoard(Request $request)
266 {
267 try {
268 $boardId = $request->getSafe('boardId');
269 $userId = $request->getSafe('userId');
270
271 $this->boardService->removeUserFromBoard($boardId, $userId);
272
273 if (!PermissionManager::isAdmin($userId)) {
274 $this->boardService->removeFromRecentlyOpened($boardId, $userId);
275 }
276
277 return $this->sendSuccess([
278 'message' => __('User Removed from Board successfully!', 'fluent-boards'),
279 ], 201);
280 } catch (\Exception $e) {
281 return $this->sendError($e->getMessage(), 404);
282 }
283 }
284
285 public function addAsSuperAdmin(Request $request)
286 {
287 try {
288 $userIds = $request->getSafe('memberIds');
289 foreach ($userIds as $userId) {
290 $this->createSuperAdmin($userId);
291 }
292
293 return $this->sendSuccess([
294 'message' => __('Fluent boards admin added', 'fluent-boards'),
295 ], 201);
296 } catch (\Exception $e) {
297 return $this->sendError($e->getMessage(), 404);
298 }
299 }
300
301 private function createSuperAdmin($userId)
302 {
303 try {
304 $existUser = Meta::where('object_id', $userId)->first();
305 if (!$existUser) {
306 $meta = new Meta();
307 $meta->object_id = $userId;
308 $meta->object_type = Constant::FLUENT_BOARD_ADMIN;
309 $meta->save();
310 }
311 } catch (\Exception $e) {
312 return $this->sendError($e->getMessage(), 404);
313 }
314 }
315
316 public function addMembersInBoards(Request $request)
317 {
318 try {
319 $userIds = $request->getSafe('memberIds');
320 $boardIds = $request->getSafe('boardIds');
321
322 foreach ($userIds as $userId) {
323 foreach ($boardIds as $boardId) {
324 $this->boardService->addMembersInBoard($boardId, $userId);
325 }
326 }
327
328 return $this->sendSuccess([
329 'message' => __('Members added to boards', 'fluent-boards'),
330 ], 201);
331 } catch (\Exception $e) {
332 return $this->sendError($e->getMessage(), 404);
333 }
334 }
335
336
337 public function updateGlobalNotificationSettings(Request $request)
338 {
339 try {
340 $newSettings = $request->getSafe('updatedSettings');
341
342 $this->optionService->updateGlobalNotificationSettings($newSettings);
343
344 return $this->sendSuccess([
345 'message' => __("Notification settings are updated", 'fluent-boards'),
346 ], 201);
347 } catch (\Exception $e) {
348 return $this->sendError($e->getMessage(), 404);
349 }
350 }
351
352 public function getGlobalNotificationSettings()
353 {
354 try {
355 $globalSettings = $this->optionService->getGlobalNotificationSettings();
356 if ($globalSettings->value)
357 $currentSettings = maybe_unserialize($globalSettings->value);
358
359 return $this->sendSuccess([
360 'currentSettings' => $currentSettings,
361 ], 200);
362 } catch (\Exception $e) {
363 return $this->sendError($e->getMessage(), 404);
364 }
365 }
366
367 public function getBoardMembers(Request $request)
368 {
369 if (!PermissionManager::userHasAnyBoardAccess()) {
370 return $this->sendError([
371 'message' => __('You do not have permission to access this route', 'fluent-boards')
372 ]);
373 }
374
375 $boardId = $request->getSafe('boardId', 'intval');
376
377 $memberUserIds = Relation::where('object_type', 'board_user')
378 ->select(['foreign_id'])
379 ->groupBy('foreign_id');
380
381 if ($boardId) {
382 $memberUserIds = $memberUserIds->where('object_id', $boardId);
383 }
384
385 $members = [];
386
387 $memberUserIds = $memberUserIds->get()
388 ->pluck('foreign_id')->toArray();
389
390
391 if ($memberUserIds) {
392 $memberUsers = get_users([
393 'include' => $memberUserIds
394 ]);
395
396
397 foreach ($memberUsers as $memberUser) {
398 $name = trim($memberUser->first_name . ' ' . $memberUser->last_name);
399 if (!$name) {
400 $name = $memberUser->display_name;
401 }
402
403 $members[$memberUser->ID] = [
404 'ID' => $memberUser->ID,
405 'display_name' => $name,
406 'photo' => get_avatar_url($memberUser->user_email)
407 ];
408 }
409
410 }
411
412 $adminUsers = get_users([
413 'role' => 'administrator',
414 'exclude' => $memberUserIds
415 ]);
416
417 foreach ($adminUsers as $user) {
418 $name = trim($user->first_name . ' ' . $user->last_name);
419 if (!$name) {
420 $name = $user->display_name;
421 }
422 $members[$user->ID] = [
423 'ID' => $user->ID,
424 'display_name' => $name,
425 'photo' => get_avatar_url($user->user_email)
426 ];
427 }
428
429 $members = array_values($members);
430
431 // sort members by name
432 usort($members, function ($a, $b) {
433 return strcmp($a['display_name'], $b['display_name']);
434 });
435
436 return [
437 'members' => $members
438 ];
439 }
440
441 public function quickSearch()
442 {
443 $currentUserId = get_current_user_id();
444
445 $query = sanitize_text_field($_REQUEST['query']);
446 $query = strtolower($query);
447 $scope = sanitize_text_field($_REQUEST['scope']);
448
449 $firstThreeChars = substr($query, 0, 3);
450 $firstNineChars = substr($query, 0, 9);
451
452 if($firstThreeChars == 'id:') {
453 $idPart = substr($query, 3);
454 $idPart = preg_replace('/[^a-zA-Z0-9]/', '', $idPart);
455 $tasksQuery = Task::query()->where('parent_id', null)->whereRaw('id LIKE ?', ['%' . $idPart . '%']);
456 }elseif($firstNineChars == 'archived:') {
457 $archivedPart = substr($query, 9);
458 $archivedPart = trim($archivedPart);
459 $tasksQuery = Task::query()->where('parent_id', null)->whereNotNull('archived_at')->whereRaw('LOWER(title) LIKE ?', ['%' . $archivedPart . '%']);
460 } else {
461 $tasksQuery = Task::query()->where('parent_id', null)->whereRaw('LOWER(title) LIKE ?', ['%' . $query . '%']);
462 }
463
464 $isUserAdmin = PermissionManager::isAdmin($currentUserId);
465
466 // This is a check for deleted tasks to be excluded from search results
467 $allActiveBoardsIds = Board::query()->where('archived_at', null)->pluck('id')->toArray();
468
469 if ($scope == 'all') {
470 if($firstThreeChars == 'id:'){
471 $idPart = substr($query, 3);
472 $idPart = preg_replace('/[^a-zA-Z0-9]/', '', $idPart);
473 $boardQuery = Board::query()->whereRaw('id LIKE ?', ['%' . $idPart . '%']);
474 }elseif ($firstNineChars == 'archived:') {
475 $archivedPart = substr($query, 9);
476 $archivedPart = trim($archivedPart);
477 $boardQuery = Board::query()->whereNotNull('archived_at')->whereRaw('LOWER(title) LIKE ?', ['%' . $archivedPart . '%']);
478 } else {
479 $boardQuery = Board::query()->whereRaw('LOWER(title) LIKE ?', ['%' . $query . '%']);
480 }
481 if ($isUserAdmin) {
482 $boards = $boardQuery->limit(10)->get();
483 $tasks = $tasksQuery->limit(10)->get();
484 } else {
485 $boardIds = PermissionManager::getBoardIdsForUser($currentUserId);
486 $boards = $boardQuery->whereIn('id', $boardIds)->limit(10)->get();
487 $tasks = $tasksQuery->whereIn('board_id', $boardIds)->limit(10)->get();
488 }
489 } else {
490 $boards = []; // boards results is not needed in scoped search
491 $inBoard = (int)$scope;
492 if ($isUserAdmin || in_array($inBoard, $boardIds = PermissionManager::getBoardIdsForUser($currentUserId))) {
493 $tasks = $tasksQuery->where('board_id', $inBoard)->limit(10)->get();
494 } else {
495 // Out of permission scope search
496 $tasks = [];
497 }
498 }
499
500
501 $formattedTasks = [];
502 $formattedBoards = [];
503 foreach ($boards as $board) {
504 $formattedBoards[] = [
505 'type' => 'board',
506 'id' => $board->id,
507 'title' => $board->title,
508 'description' => $board->description,
509 ];
510 }
511 foreach ($tasks as $task) {
512
513 if (!in_array($task->board_id, $allActiveBoardsIds)) {
514 // if the task is not in an active board, skip it
515 continue;
516 }
517
518 $board = $task->board;
519
520 $formattedTasks[] = [
521 'type' => 'task',
522 'id' => $task->id,
523 'title' => $task->title,
524 'description' => $task->description,
525 'board_id' => $task->board_id,
526 'board' => [
527 'id' => $board->id,
528 'title' => $board->title,
529 'url' => Helper::getBoardUrl($board->id)
530 ],
531 'stage' => [
532 'id' => $task->stage_id,
533 'title' => $task->stage->title ?? '',
534 ],
535
536 ];
537 }
538 return $this->sendSuccess([
539 'tasks' => $formattedTasks,
540 'boards' => $formattedBoards
541 ], 200);
542
543 }
544
545 public function getDashboardViewSettings()
546 {
547 try {
548 $globalSettings = $this->optionService->getDashboardViewSettings();
549 if ($globalSettings->value)
550 $currentSettings = maybe_unserialize($globalSettings->value);
551
552 return $this->sendSuccess([
553 'currentSettings' => $currentSettings,
554 ], 200);
555 } catch (\Exception $e) {
556 return $this->sendError($e->getMessage(), 404);
557 }
558 }
559
560 public function updateDashboardViewSettings(Request $request)
561 {
562 try {
563 $newSettings = $request->getSafe('updatedSettings');
564
565 $this->optionService->updateDashboardViewSettings($newSettings);
566
567 return $this->sendSuccess([
568 'message' => __("Dashboard view settings are updated", 'fluent-boards'),
569 ], 201);
570 } catch (\Exception $e) {
571 return $this->sendError($e->getMessage(), 404);
572 }
573 }
574
575
576 public function getAddonsSettings()
577 {
578 $addOns = [
579 'fluent-crm' => [
580 'title' => __('FluentCRM', 'fluent-boards'),
581 'logo' => fluent_boards_mix('images/addons/fluent-crm.svg'),
582 'is_installed' => defined('FLUENTCRM'),
583 'learn_more_url' => 'https://fluentcrm.com/',
584 'associate_doc' => 'https://fluentboards.com/docs/fluentboards-integration-with-fluentcrm/',
585 'action_text' => $this->isPluginInstalled('fluent-crm/fluent-crm.php') ? __('Activate FluentCRM', 'fluent-boards') : __('Install FluentCRM', 'fluent-boards'),
586 'description' => __('FluentCRM is a Self Hosted Email Marketing Automation Plugin for WordPress. Manage your leads and customers, email campaigns, automated email sequencing and many more', 'fluent-boards'),
587 'short_desc' => __('Email marketing automation', 'fluent-boards')
588 ],
589 'fluentform' => [
590 'title' => __('Fluent Forms', 'fluent-boards'),
591 'logo' => fluent_boards_mix('images/addons/fluentform.png'),
592 'is_installed' => defined('FLUENTFORM'),
593 'learn_more_url' => 'https://wordpress.org/plugins/fluentform/',
594 'associate_doc' => 'https://fluentboards.com/docs/fluentboards-integration-with-fluent-forms/',
595 'action_text' => $this->isPluginInstalled('fluent-form/fluent-form.php') ? __('Activate Fluent Forms', 'fluent-boards') : __('Install Fluent Forms', 'fluent-boards'),
596 'description' => __('Collect leads and build any type of forms, accept payments, connect with your CRM with the Fastest Contact Form Builder Plugin for WordPress', 'fluent-boards'),
597 'short_desc' => __('Create forms and accept payments', 'fluent-boards')
598 ],
599 'fluent-support' => [
600 'title' => __('Fluent Support', 'fluent-boards'),
601 'logo' => fluent_boards_mix('images/addons/fluent-support.svg'),
602 'is_installed' => defined('FLUENT_SUPPORT_VERSION'),
603 'learn_more_url' => 'https://wordpress.org/plugins/fluent-connect/',
604 'settings_url' => admin_url('admin.php?page=fluent-support#/'),
605 'associate_doc' => 'https://fluentboards.com/docs/fluentboards-integration-with-fluentsupport/',
606 'action_text' => $this->isPluginInstalled('fluent-support/fluent-support.php') ? __('Activate Fluent Support', 'fluent-boards') : __('Install Fluent Support', 'fluent-boards'),
607 'description' => __('WordPress Helpdesk and Customer Support Ticket Plugin. Provide awesome support and manage customer queries right from your WordPress dashboard.', 'fluent-boards'),
608 'short_desc' => __('Customer support ticketing', 'fluent-boards')
609 ],
610 'fluent-smtp' => [
611 'title' => __('Fluent SMTP', 'fluent-boards'),
612 'logo' => fluent_boards_mix('images/addons/fluent-smtp.svg'),
613 'is_installed' => defined('FLUENTMAIL'),
614 'learn_more_url' => 'https://wordpress.org/plugins/fluent-smtp/',
615 'associate_doc' => admin_url('options-general.php?page=fluent-mail#/'),
616 'action_text' => $this->isPluginInstalled('fluent-smtp/fluent-smtp.php') ? __('Activate Fluent SMTP', 'fluent-boards') : __('Install Fluent SMTP', 'fluent-boards'),
617 'description' => __('The Ultimate SMTP and SES Plugin for WordPress. Connect with any SMTP, SendGrid, Mailgun, SES, Sendinblue, PepiPost, Google, Microsoft and more.', 'fluent-boards'),
618 'short_desc' => __('Reliable email delivery with SMTP', 'fluent-boards')
619 ],
620 ];
621
622 $addOns = apply_filters('fluent_boards/addons_settings', $addOns);
623
624 $modules = fluent_boards_get_pref_settings(false);
625
626 if (empty($modules['frontend']['render_type'])) {
627 $modules['frontend']['render_type'] = 'standalone';
628 }
629
630 $modules['panel_url'] = fluent_boards_page_url();
631
632 return [
633 'addons' => $addOns,
634 'featureModules' => $modules
635 ];
636 }
637
638 public function saveAddonsSettings(Request $request)
639 {
640 if (!defined('FLUENT_BOARDS_PRO')) {
641 return $this->sendError([
642 'message' => __('This feature is only available in Fluent Boards Pro', 'fluent-boards')
643 ]);
644 }
645
646 $settings = $request->get('settings', []);
647
648 $prefSettings = fluent_boards_get_pref_settings(false);
649
650 $settings = wp_parse_args($settings, $prefSettings);
651
652 $settings = Arr::only($settings, array_keys($prefSettings));
653 $settings['frontend']['slug'] = sanitize_title($settings['frontend']['slug']);
654
655 if (empty($settings['frontend']['slug'])) {
656 $settings['frontend']['slug'] = 'projects';
657 }
658
659 if (defined('FLUENT_BOARDS_SLUG') && FLUENT_BOARDS_SLUG) {
660 $settings['frontend']['slug'] = FLUENT_BOARDS_SLUG;
661 }
662
663 do_action('fluent_boards/saving_addons', $settings, $prefSettings);
664
665 update_option('fluent_boards_modules', $settings, 'yes');
666
667 if (isset($settings['recurring_task']['enabled']) && $settings['recurring_task']['enabled'] == 'no') {
668 do_action('fluent_boards/recurring_task_disabled');
669 }
670
671 return $this->sendSuccess([
672 'message' => __('Settings are saved', 'fluent-boards'),
673 'featureModules' => $settings
674 ]);
675 }
676
677 public function installPlugin(Request $request)
678 {
679 if (!current_user_can('install_plugins')) {
680 return $this->sendError([
681 'message' => __('Sorry! you do not have permission to install plugin', 'fluent-boards')
682 ]);
683 }
684
685 $plugin = $request->getSafe('plugin', 'sanitize_text_field');
686
687 $acceptedFreePlugins = [
688 'fluent-crm' => 'fluent-crm.php',
689 'fluentform' => 'fluentform.php',
690 'fluent-support' => 'fluent-support.php',
691 'fluent-smtp' => 'fluent-smtp.php'
692 ];
693
694 $acceptedPlugins = apply_filters('fluent_boards/accepted_plugins', $acceptedFreePlugins);
695
696 if (!isset($acceptedPlugins[$plugin])) {
697 return $this->sendError([
698 'message' => __('Invalid plugin', 'fluent-boards')
699 ]);
700 }
701
702 $pluginToInstall = [
703 'name' => __('Fluent Plugin', 'fluent-boards'),
704 'repo-slug' => $plugin,
705 'file' => $acceptedPlugins[$plugin],
706 ];
707
708 // if plugin in free list then run background intaller otherwise call an action to install
709 if (isset($acceptedFreePlugins[$plugin])) {
710 $this->backgroundInstaller($pluginToInstall, $plugin);
711 } else {
712 do_action('fluent_boards/install_plugin', $pluginToInstall, $plugin);
713 }
714
715 return $this->sendSuccess([
716 'message' => __('Plugin is being installed', 'fluent-boards')
717 ]);
718 }
719
720 private function isPluginInstalled($plugin)
721 {
722 return file_exists(WP_PLUGIN_DIR . '/' . $plugin);
723 }
724
725 private function backgroundInstaller($plugin_to_install, $plugin_id)
726 {
727 if (!empty($plugin_to_install['repo-slug'])) {
728 require_once ABSPATH . 'wp-admin/includes/file.php';
729 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
730 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
731 require_once ABSPATH . 'wp-admin/includes/plugin.php';
732
733 WP_Filesystem();
734
735 $skin = new \Automatic_Upgrader_Skin();
736 $upgrader = new \WP_Upgrader($skin);
737 $installed_plugins = array_reduce(array_keys(\get_plugins()), array($this, 'associate_plugin_file'), array());
738 $plugin_slug = $plugin_to_install['repo-slug'];
739 $plugin_file = isset($plugin_to_install['file']) ? $plugin_to_install['file'] : $plugin_slug . '.php';
740 $installed = false;
741 $activate = false;
742
743 // See if the plugin is installed already.
744 if (isset($installed_plugins[$plugin_file])) {
745 $installed = true;
746 $activate = !is_plugin_active($installed_plugins[$plugin_file]);
747 }
748
749 // Install this thing!
750 if (!$installed) {
751 // Suppress feedback.
752 ob_start();
753
754 try {
755 $plugin_information = plugins_api(
756 'plugin_information',
757 array(
758 'slug' => $plugin_slug,
759 'fields' => array(
760 'short_description' => false,
761 'sections' => false,
762 'requires' => false,
763 'rating' => false,
764 'ratings' => false,
765 'downloaded' => false,
766 'last_updated' => false,
767 'added' => false,
768 'tags' => false,
769 'homepage' => false,
770 'donate_link' => false,
771 'author_profile' => false,
772 'author' => false,
773 ),
774 )
775 );
776
777 if (is_wp_error($plugin_information)) {
778 throw new \Exception($plugin_information->get_error_message());
779 }
780
781 $package = $plugin_information->download_link;
782 $download = $upgrader->download_package($package);
783
784 if (is_wp_error($download)) {
785 throw new \Exception($download->get_error_message());
786 }
787
788 $working_dir = $upgrader->unpack_package($download, true);
789
790 if (is_wp_error($working_dir)) {
791 throw new \Exception($working_dir->get_error_message());
792 }
793
794 $result = $upgrader->install_package(
795 array(
796 'source' => $working_dir,
797 'destination' => WP_PLUGIN_DIR,
798 'clear_destination' => false,
799 'abort_if_destination_exists' => false,
800 'clear_working' => true,
801 'hook_extra' => array(
802 'type' => 'plugin',
803 'action' => 'install',
804 ),
805 )
806 );
807
808 if (is_wp_error($result)) {
809 throw new \Exception($result->get_error_message());
810 }
811
812 $activate = true;
813
814 } catch (\Exception $e) {
815 }
816
817 // Discard feedback.
818 ob_end_clean();
819 }
820
821 wp_clean_plugins_cache();
822
823 // Activate this thing.
824 if ($activate) {
825 try {
826 $result = activate_plugin($installed ? $installed_plugins[$plugin_file] : $plugin_slug . '/' . $plugin_file);
827
828 if (is_wp_error($result)) {
829 throw new \Exception($result->get_error_message());
830 }
831 } catch (\Exception $e) {
832 }
833 }
834 }
835 }
836
837 private function associate_plugin_file($plugins, $key)
838 {
839 $path = explode('/', $key);
840 $filename = end($path);
841 $plugins[$filename] = $key;
842 return $plugins;
843 }
844
845 public function getBoards(Request $request)
846 {
847 $boards = Board::select(['id', 'title', 'type'])
848 ->byAccessUser(get_current_user_id())
849 ->orderBy('title', 'ASC')
850 ->get();
851
852 return $this->sendSuccess([
853 'boards' => $boards
854 ]);
855 }
856
857 public function getPages(Request $request)
858 {
859
860 $db = App::getInstance('db');
861
862 $allPages = $db->table('posts')->where('post_type', 'page')
863 ->where('post_status', 'publish')
864 ->select(['ID', 'post_title'])
865 ->orderBy('post_title', 'ASC')
866 ->get();
867
868 $pages = [];
869 foreach ($allPages as $page) {
870 $pages[] = [
871 'id' => $page->ID,
872 'title' => $page->post_title ? $page->post_title : __('(no title)', 'fluent-boards')
873 ];
874 }
875
876 return $this->sendSuccess([
877 'pages' => $pages
878 ]);
879 }
880
881 public function getGeneralSettings()
882 {
883 $settings = fluent_boards_get_option('general_settings', []);
884
885 return $this->sendSuccess([
886 'settings' => $settings,
887 'server_timezone' => \wp_timezone_string()
888 ]);
889
890 }
891
892 public function saveGeneralSettings(Request $request)
893 {
894 // check for pro version
895 if (!defined('FLUENT_BOARDS_PRO')) {
896 return $this->sendError([
897 'message' => __('This feature is only available in Fluent Boards Pro. Please upgrade.', 'fluent-boards')
898 ]);
899 }
900 $settings = $request->getSafe('updatedSettings', []);
901
902 $settings = apply_filters('fluent_boards/save_general_settings', $settings);
903
904 $savedSettings = fluent_boards_update_option('general_settings', $settings);
905 $savedGeneralSettings = \maybe_unserialize($savedSettings->value);
906
907 $scheduleHandler = new ProScheduleHandler();
908
909 if ($savedGeneralSettings['daily_reminder_enabled'] || $savedGeneralSettings['daily_reminder_enabled'] == 'true') {
910 // force schedule from this settings update
911 $scheduleHandler->clearDailyTaskReminderScheduler();
912 $scheduleHandler->scheduleDailyTaskReminder();
913 }
914
915 return $this->sendSuccess([
916 'settings' => $savedGeneralSettings,
917 'message' => __('Settings are saved', 'fluent-boards')
918 ]);
919
920 }
921
922 }
923