PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.1.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.1.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 1.41 All 42 releases
fluent-boards / app / Services / LabelService.php

LabelService.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 2.1.0, at app/Services/LabelService.php

272 lines 9.0 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\Services;
4
5 use FluentBoards\App\Models\Board;
6 use FluentBoards\App\Models\Label;
7 use FluentBoards\App\Models\Relation;
8 use FluentBoards\App\Models\Task;
9
10
11 class LabelService
12 {
13 public function getLabelsByBoard($boardId)
14 {
15 return Label::where('board_id', $boardId)->orderBy('created_at', 'ASC')->get();
16 }
17
18 public function getLabelsByBoardUsedInTasks($boardId)
19 {
20 $boardLabels = Label::where('board_id', $boardId)
21 ->where('type', 'label')
22 ->orderBy('created_at', 'ASC')
23 ->get();
24
25 if ($boardLabels->isEmpty()) {
26 return [];
27 }
28
29 // One relation query for the whole board rather than an exists() per label.
30 $usedIds = Relation::where('object_type', Constant::OBJECT_TYPE_TASK_LABEL)
31 ->whereIn('foreign_id', $boardLabels->pluck('id')->all())
32 ->distinct()
33 ->pluck('foreign_id')
34 ->all();
35
36 $usedIds = array_map('intval', $usedIds);
37
38 $usedLabel = [];
39 foreach ($boardLabels as $label) {
40 if (in_array((int) $label->id, $usedIds, true)) {
41 $usedLabel[] = $label;
42 }
43 }
44
45 return $usedLabel;
46 }
47
48 public function createLabel($labelData, $boardId)
49 {
50 $labelData = $this->normalizeLabelColorData($labelData);
51
52 $label = new Label();
53 $label->board_id = $boardId;
54 $label->title = $labelData['label'] ?? '';
55 $label->bg_color = $labelData['bg_color'] ?? '';
56 $label->color = $labelData['color'] ?? '';
57 if (isset($labelData['settings'])) {
58 $label->settings = $labelData['settings'];
59 }
60 $label->save();
61
62 return $label;
63 }
64
65 public function createDefaultLabel($boardId)
66 {
67 $defaultColors = ['green-bold', 'yellow-bold', 'orange-bold', 'red-bold', 'purple-bold'];
68
69 $data = [];
70
71 foreach ($defaultColors as $presetId)
72 {
73 $preset = Constant::getLabelColorPreset($presetId);
74 $colorName = strtok($presetId, '-');
75 $data[] = [
76 'board_id' => $boardId,
77 // Titles match the create-board modal defaults, otherwise boards created
78 // outside that modal end up with colour chips carrying no text.
79 'title' => ucfirst($colorName),
80 'slug' => $colorName,
81 'type' => 'label',
82 'bg_color' => $preset['light_bg_color'],
83 'color' => $preset['light_text_color'],
84 'settings' => maybe_serialize([Constant::LABEL_COLOR_PRESET_SETTING => $presetId]),
85 'created_at' => current_time('mysql'),
86 'updated_at' => current_time('mysql')
87 ];
88 }
89
90 Label::insert($data);
91 }
92
93 public function createLabelForTask($labelData, $boardId = null)
94 {
95 $task = $boardId ? (new TaskService())->findTaskOnBoard($labelData['task_id'], $boardId) : Task::findOrFail($labelData['task_id']);
96 $label = $this->findLabelOnBoard($labelData['board_term_id'], $boardId ?: $task->board_id);
97
98 $task->labels()->syncWithoutDetaching([$labelData['board_term_id'] => ['object_type' => Constant::OBJECT_TYPE_TASK_LABEL]]);
99
100 $label = $task->labels->find($label->id);
101
102 do_action('fluent_boards/task_label',$task, $label, 'added');
103
104 return $label;
105 }
106
107 public function getLabelsByTask($taskId, $boardId = null)
108 {
109 $task = $boardId ? (new TaskService())->findTaskOnBoard($taskId, $boardId) : Task::findOrFail($taskId);
110 return $task->labels;
111 }
112
113 public function labelsByBoardId($boardId)
114 {
115 return Label::where('board_id', $boardId)->whereNull('archived_at')->get();
116 }
117
118 public function deleteLabelOfTask($taskId, $labelId, $boardId = null)
119 {
120 $task = $boardId ? (new TaskService())->findTaskOnBoard($taskId, $boardId) : Task::findOrFail($taskId);
121 $label = $this->findLabelOnBoard($labelId, $boardId ?: $task->board_id);
122 $task->labels()->detach($labelId);
123 do_action('fluent_boards/task_label',$task, $label, 'removed');
124 }
125
126 public function deleteLabelOfBoard($labelId, $boardId = null)
127 {
128 $label = $boardId ? $this->findLabelOnBoard($labelId, $boardId) : Label::findOrFail($labelId);
129 $label->tasks()->detach();
130 $label->delete();
131
132 do_action('fluent_boards/board_label_deleted', $label);
133 }
134
135 public function editLabelofBoard($labelData, $id, $boardId = null)
136 {
137 $label = $boardId ? $this->findLabelOnBoard($id, $boardId) : Label::findOrFail($id);
138 $labelData = $this->normalizeLabelColorData($labelData, $label);
139 $label->title = $labelData['label'] ?? $label->title;
140
141 // Background and text colour move independently: coupling them dropped a
142 // text-colour-only change on the floor while still reporting success.
143 if (isset($labelData['bg_color']) && $labelData['bg_color'] !== '') {
144 $label->bg_color = $labelData['bg_color'];
145 }
146
147 if (isset($labelData['color']) && $labelData['color'] !== '') {
148 $label->color = $labelData['color'];
149 }
150
151 if (array_key_exists('settings', $labelData)) {
152 if (array_key_exists('color_preset', $labelData) && $labelData['color_preset'] === '') {
153 $label->replaceSettings($labelData['settings']);
154 } else {
155 $label->settings = $labelData['settings'];
156 }
157 }
158
159 $label->save();
160 return $label;
161 }
162
163 /**
164 * Resolve a label only when it belongs to the requested board.
165 *
166 * @param int $labelId
167 * @param int $boardId
168 * @return Label
169 * @throws \Exception
170 */
171 public function findLabelOnBoard($labelId, $boardId)
172 {
173 $label = Label::where('id', absint($labelId))
174 ->where('board_id', absint($boardId))
175 ->where('type', 'label')
176 ->first();
177
178 if (!$label) {
179 throw new \Exception(esc_html__('Label not found', 'fluent-boards'));
180 }
181
182 return $label;
183 }
184
185 public function copyLabelsOfBoard($boardId, $board)
186 {
187 $boardCopyFrom = Board::findOrFail($boardId);
188
189 $labelMap = [];
190
191 foreach($boardCopyFrom->labels as $label)
192 {
193 $labelToSave = array();
194 $labelToSave['title'] = $label->title;
195 $labelToSave['slug'] = $label->slug;
196 $labelToSave['board_id'] = $board->id;
197 $labelToSave['type'] = 'label';
198 $labelToSave['position'] = 0;
199 $labelToSave['color'] = $label->color;
200 $labelToSave['bg_color'] = $label->bg_color;
201 $settings = (array) $label->settings;
202 $presetId = $settings[Constant::LABEL_COLOR_PRESET_SETTING] ?? '';
203 if (Constant::getLabelColorPreset($presetId)) {
204 $labelToSave['settings'] = [Constant::LABEL_COLOR_PRESET_SETTING => $presetId];
205 }
206 $copiedLabel = Label::create($labelToSave);
207
208 $labelMap[$label['id']] = $copiedLabel->id;
209 }
210 return $labelMap;
211 }
212
213 /**
214 * Converts a selected preset into stable light-mode fallback colors.
215 *
216 * @param array $labelData
217 * @param Label|null $label
218 * @return array
219 * @throws \Exception
220 */
221 private function normalizeLabelColorData($labelData, $label = null)
222 {
223 if (!array_key_exists('color_preset', $labelData)) {
224 return $labelData;
225 }
226
227 $presetId = $labelData['color_preset'];
228 $settings = $label ? (array) $label->settings : [];
229
230 // Framework request extraction can represent an omitted optional field
231 // as null. That must preserve an existing preset rather than reject it.
232 if ($presetId === null) {
233 unset($labelData['color_preset']);
234 return $labelData;
235 }
236
237 if ($presetId === '') {
238 unset($settings[Constant::LABEL_COLOR_PRESET_SETTING]);
239 $labelData['settings'] = $settings;
240 return $labelData;
241 }
242
243 $preset = Constant::getLabelColorPreset($presetId);
244 if (!$preset) {
245 throw new \Exception(esc_html__('Invalid label color preset', 'fluent-boards'));
246 }
247
248 $settings[Constant::LABEL_COLOR_PRESET_SETTING] = $preset['id'];
249 $labelData['settings'] = $settings;
250 $labelData['bg_color'] = $preset['light_bg_color'];
251 $labelData['color'] = $preset['light_text_color'];
252
253 return $labelData;
254 }
255 public function getLastOneMinuteUpdatedLabels($boardId, $lastUpdated = null, $includeArchived = true)
256 {
257 if (!$lastUpdated) {
258 $oneMinuteAgoTimestamp = current_time('timestamp') - 60;
259 $lastUpdated = date_i18n('Y-m-d H:i:s', $oneMinuteAgoTimestamp);
260 }
261
262 $labelsQuery = Label::where('board_id', $boardId)
263 ->where('updated_at', '>=', $lastUpdated);
264
265 if (!$includeArchived) {
266 $labelsQuery->whereNull('archived_at');
267 }
268
269 return $labelsQuery->get();
270 }
271 }
272