PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.95
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.95
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 / Modules / MCP / Tools / BoardTools.php

BoardTools.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.95, at app/Modules/MCP/Tools/BoardTools.php

199 lines 6.8 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\Modules\MCP\Tools;
4
5 use FluentBoards\App\Models\Board;
6 use FluentBoards\App\Modules\MCP\Helpers\MCPHelper;
7 use FluentBoards\App\Services\BoardService;
8 use FluentBoards\App\Services\Helper;
9 use FluentBoards\App\Services\LabelService;
10 use FluentBoards\App\Services\PermissionManager;
11 use FluentBoards\App\Services\StageService;
12
13 /**
14 * Board read/write tools and board permission helpers.
15 */
16 class BoardTools
17 {
18 public static function canReadBoard($params = [])
19 {
20 $boardId = isset($params['board_id']) ? absint($params['board_id']) : 0;
21 return $boardId && MCPHelper::canReadBoard($boardId);
22 }
23
24 public static function canWriteBoard($params = [])
25 {
26 $boardId = isset($params['board_id']) ? absint($params['board_id']) : 0;
27 return $boardId && MCPHelper::canWriteBoard($boardId);
28 }
29
30 public static function listBoards($params = [])
31 {
32 $pagination = MCPHelper::normalizePagination($params);
33 $userId = get_current_user_id();
34 $boardIds = PermissionManager::getBoardIdsForUser($userId);
35
36 if (!$boardIds) {
37 return [
38 'items' => [],
39 'pagination' => self::paginationMeta(null, $pagination),
40 ];
41 }
42
43 $query = Board::with(['stages', 'labels', 'users'])
44 ->whereIn('id', $boardIds);
45
46 if (empty($params['include_archived'])) {
47 $query->whereNull('archived_at');
48 }
49
50 if (!empty($params['type'])) {
51 $query->where('type', sanitize_text_field($params['type']));
52 }
53
54 if (!empty($params['search'])) {
55 $search = sanitize_text_field($params['search']);
56 $query->where('title', 'like', '%' . $search . '%');
57 }
58
59 $allowedSort = ['id', 'title', 'created_at', 'updated_at'];
60 $sortBy = !empty($params['sort_by']) && in_array($params['sort_by'], $allowedSort, true)
61 ? $params['sort_by']
62 : 'created_at';
63 $sortType = !empty($params['sort_type']) && strtoupper($params['sort_type']) === 'ASC' ? 'ASC' : 'DESC';
64
65 $paginated = $query->orderBy($sortBy, $sortType)
66 ->paginate($pagination['per_page'], ['*'], 'page', $pagination['page']);
67
68 $items = [];
69 foreach ($paginated->items() as $board) {
70 $items[] = MCPHelper::formatBoardSummary($board);
71 }
72
73 return [
74 'items' => $items,
75 'pagination' => self::paginationMeta($paginated, $pagination),
76 ];
77 }
78
79 public static function getBoard($params = [])
80 {
81 $board = MCPHelper::resolveBoard($params);
82 if (is_wp_error($board)) {
83 return $board;
84 }
85
86 if (!MCPHelper::canReadBoard($board->id)) {
87 return MCPHelper::error('forbidden', __('You do not have access to this board', 'fluent-boards'));
88 }
89
90 return [
91 'board' => MCPHelper::formatBoard($board, !empty($params['include_tasks'])),
92 ];
93 }
94
95 public static function createBoard($params = [])
96 {
97 if (!PermissionManager::userHasBoardCreationPermission()) {
98 return MCPHelper::error('forbidden', __('You do not have permission to create boards', 'fluent-boards'));
99 }
100
101 $title = isset($params['title']) ? sanitize_text_field($params['title']) : '';
102 if ($title === '') {
103 return MCPHelper::error('invalid_param', __('Board title is required', 'fluent-boards'));
104 }
105
106 $type = !empty($params['type']) ? sanitize_text_field($params['type']) : 'to-do';
107 if (!in_array($type, ['to-do', 'roadmap'], true)) {
108 return MCPHelper::error('invalid_param', __('Invalid board type', 'fluent-boards'), [
109 'allowed' => ['to-do', 'roadmap'],
110 ]);
111 }
112
113 $boardData = Helper::sanitizeBoard([
114 'title' => $title,
115 'description' => isset($params['description']) ? wp_kses_post($params['description']) : '',
116 'type' => $type,
117 'currency' => !empty($params['currency']) ? sanitize_text_field($params['currency']) : 'USD',
118 'crm_contact_id' => !empty($params['crm_contact_id']) ? absint($params['crm_contact_id']) : 0,
119 ]);
120
121 $boardService = new BoardService();
122 $labelService = new LabelService();
123 $stageService = new StageService();
124
125 $board = $boardService->createBoard($boardData);
126 $labelService->createDefaultLabel($board->id);
127
128 if ($type === 'roadmap') {
129 $stageService->createRoadmapStages($board, self::sanitizeRoadmapStages($params['stages'] ?? []));
130 } else {
131 $stageService->createDefaultStages($board);
132 }
133
134 if (!empty($boardData['crm_contact_id'])) {
135 $boardService->updateAssociateMember($boardData['crm_contact_id'], $board->id);
136 }
137
138 do_action('fluent_boards/board_created', $board);
139
140 if (defined('FLUENT_BOARDS_PRO') && !empty($params['folder_id']) && class_exists('FluentBoardsPro\App\Services\FolderService')) {
141 (new \FluentBoardsPro\App\Services\FolderService())->addBoardToFolder(absint($params['folder_id']), [$board->id]);
142 }
143
144 $board = Board::with(['stages', 'labels', 'users'])->find($board->id);
145
146 return [
147 'board' => MCPHelper::formatBoard($board),
148 'message' => __('Board has been created successfully', 'fluent-boards'),
149 ];
150 }
151
152 private static function paginationMeta($paginated, $fallback)
153 {
154 if (!$paginated) {
155 return [
156 'total' => 0,
157 'current_page' => (int) $fallback['page'],
158 'per_page' => (int) $fallback['per_page'],
159 'last_page' => 0,
160 ];
161 }
162
163 return [
164 'total' => (int) $paginated->total(),
165 'current_page' => (int) $paginated->currentPage(),
166 'per_page' => (int) $paginated->perPage(),
167 'last_page' => (int) $paginated->lastPage(),
168 ];
169 }
170
171 private static function sanitizeRoadmapStages($stages)
172 {
173 $items = [];
174
175 if (!is_array($stages)) {
176 return $items;
177 }
178
179 foreach ($stages as $index => $stage) {
180 if (!is_array($stage)) {
181 continue;
182 }
183
184 $title = isset($stage['title']) ? sanitize_text_field($stage['title']) : '';
185 if ($title === '') {
186 continue;
187 }
188
189 $items[] = [
190 'title' => $title,
191 'slug' => !empty($stage['slug']) ? sanitize_title($stage['slug']) : sanitize_title($title),
192 'position' => !empty($stage['position']) ? absint($stage['position']) : $index + 1,
193 ];
194 }
195
196 return $items;
197 }
198 }
199