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
fluent-boards / app / Models / Board.php

Board.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 2.2.0, at app/Models/Board.php

391 lines 10.6 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\Models;
4
5 use FluentBoards\App\Services\Constant;
6 use FluentBoards\App\Services\PermissionManager;
7 use FluentBoards\App\Services\UserService;
8 use FluentBoards\Framework\Database\Orm\Builder;
9 use FluentBoards\App\Models\CustomField;
10
11 class Board extends Model
12 {
13 protected $table = 'fbs_boards';
14
15 protected $guarded = ['id'];
16
17 protected $hidden = [
18 'created_at',
19 'updated_at',
20 'boardMeta',
21 'viewerMembership',
22 ];
23
24 protected $fillable = [
25 'parent_id',
26 'title',
27 'description',
28 'type',
29 'currency',
30 'background',
31 'settings',
32 'created_by',
33 'archived_at',
34 ];
35
36 protected $appends = ['meta', 'isUserOnlyViewer'];
37
38 /**
39 * Boot board defaults while preserving empty backgrounds for newly created boards.
40 */
41 public static function boot()
42 {
43 static::creating(function ($model) {
44 $model->created_by = $model->created_by ?: get_current_user_id();
45 $model->type = $model->type ?: 'to-do'; // default board type is to-do
46 $model->background = $model->background ?: '';
47 });
48 /* global scope for board type which means only type = to-do will be fetched from everywhere */
49 parent::boot();
50 static::addGlobalScope('type', function (Builder $builder) {
51 $builder = $builder->where('type', '=', 'to-do')
52 ->orWhere('type', '=', 'roadmap');
53 });
54 }
55
56 public static function getColor()
57 {
58 $colors = [
59 '#673AB7', // deep purple
60 '#3F51B5', // indigo
61 '#14508C', // blue
62 '#009688', // teal
63 '#519839', // green
64 '#795548', // brown
65 '#607D8B', // blue grey
66 '#03A9F4', // light blue
67 '#00BCD4', // cyan
68 '#CDDC39', // lime
69 '#838c91', // grey
70 ];
71
72 return $colors[array_rand($colors)];
73 }
74
75 public function setSettingsAttribute($settings)
76 {
77 $this->attributes['settings'] = \maybe_serialize($settings);
78 }
79
80 public function getSettingsAttribute($settings)
81 {
82 return \maybe_unserialize($settings);
83 }
84
85 public function getMetaAttribute()
86 {
87 if (!$this->relationLoaded('boardMeta')) {
88 return $this->getMeta();
89 }
90
91 $meta = [];
92 foreach ($this->getRelation('boardMeta') as $item) {
93 $meta[$item->key] = $item->value;
94 }
95 return $meta;
96 }
97
98 /** Internal eager-loaded metadata for board-list serialization. */
99 public function boardMeta()
100 {
101 return $this->hasMany(Meta::class, 'object_id')
102 ->where('object_type', Constant::OBJECT_TYPE_BOARD);
103 }
104
105 /** Internal membership snapshot for the current board-list reader. */
106 public function viewerMembership()
107 {
108 return $this->hasOne(Relation::class, 'object_id')
109 ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
110 ->where('foreign_id', get_current_user_id());
111 }
112
113 public function setBackgroundAttribute($background)
114 {
115 $this->attributes['background'] = \maybe_serialize($background);
116 }
117
118 public function getBackgroundAttribute($background)
119 {
120 return \maybe_unserialize($background);
121 }
122
123 public function tasks()
124 {
125 return $this->hasMany(Task::class, 'board_id');
126 }
127
128 public function completedTasks()
129 {
130 return $this->hasMany(Task::class, 'board_id')
131 ->whereNull('archived_at')
132 ->where('parent_id', null)
133 ->where('status', 'closed');
134 }
135
136 public function stages()
137 {
138 return $this->hasMany(Stage::class, 'board_id')
139 ->whereNull('archived_at')
140 ->orderBy('position', 'asc');
141 }
142
143 public function labels()
144 {
145 return $this->hasMany(Label::class, 'board_id')
146 ->whereNull('archived_at')
147 ->orderBy('position', 'asc');
148 }
149
150 public function users()
151 {
152 return $this->belongsToMany(
153 User::class,
154 'fbs_relations',
155 'object_id',
156 'foreign_id'
157 )->withPivot('settings','preferences')
158 ->wherePivot('object_type', Constant::OBJECT_TYPE_BOARD_USER)
159 ->withTimestamps();
160 }
161
162
163 public function boardUserEmailNotificationSettings()
164 {
165 return $this->belongsToMany(
166 User::class,
167 'fbs_relations',
168 'object_id',
169 'foreign_id'
170 )->withTimestamps()
171 ->withPivot('settings')
172 ->wherePivot('object_type', Constant::OBJECT_TYPE_BOARD_USER_EMAIL_NOTIFICATION);
173 }
174
175 public function boardUserNotificationSettings() //will delete later
176 {
177 return $this->belongsToMany(
178 User::class,
179 'fbs_relations',
180 'object_id',
181 'foreign_id'
182 )->withTimestamps()
183 ->withPivot('settings')
184 ->wherePivot('object_type', Constant::OBJECT_TYPE_BOARD_USER_NOTIFICATION);
185 }
186
187 public function syncUsers($userIds)
188 {
189 $exists = $this->users;
190 $existIds = [];
191 foreach ($exists as $exist) {
192 $existIds[] = $exist->ID;
193 }
194
195 $newIds = array_diff($userIds, $existIds);
196
197 if ($newIds) {
198 $this->users()->attach(
199 $newIds,
200 [
201 'object_type' => Constant::OBJECT_TYPE_BOARD_USER,
202 'settings' => maybe_serialize(Constant::BOARD_USER_SETTINGS),
203 'preferences' => maybe_serialize(Constant::BOARD_NOTIFICATION_TYPES)
204 ]
205 );
206 }
207
208 return $newIds;
209 }
210
211 public static function isBoardExists($boardId)
212 {
213 return self::where('id', $boardId)->exists();
214 }
215
216 public function notifications()
217 {
218 return $this->hasMany(Notification::class, 'object_id', 'id')
219 ->where('object_type', Constant::OBJECT_TYPE_BOARD_NOTIFICATION);
220 }
221
222 public function comments()
223 {
224 return $this->hasMany(Comment::class, 'board_id', 'id');
225 }
226
227 public function owner()
228 {
229 return $this->belongsTo(User::class, 'created_by');
230 }
231
232 public function scopeByAccessUser($query, $userId)
233 {
234 if (PermissionManager::isAdmin($userId)) {
235 return $query;
236 }
237
238 $user = User::find($userId);
239
240 $boardIds = $user->whichBoards()->pluck('object_id')->toArray();
241
242 if (!$boardIds) {
243 return $query->where('id', 0);
244 }
245
246 return $query->whereIn('id', $boardIds);
247 }
248
249 /**
250 * Exclude template boards (settings['is_template'] === true).
251 * The settings column is serialized text, so both the PHP-serialized
252 * and JSON representations of the flag are matched.
253 */
254 public function scopeExcludeTemplates($query)
255 {
256 return $query->where(function ($query) {
257 $query->whereNull('settings')
258 ->orWhere(function ($subQuery) {
259 $subQuery->where('settings', 'NOT LIKE', '%"is_template";b:1%')
260 ->where('settings', 'NOT LIKE', '%"is_template":true%');
261 });
262 });
263 }
264
265 /**
266 * Limit boards to types supported by the currently loaded plugins.
267 */
268 public function scopeAvailableInCurrentInstall($query)
269 {
270 if (!defined('FLUENT_ROADMAP')) {
271 return $query->where('type', 'to-do');
272 }
273
274 return $query;
275 }
276
277 /**
278 * Only template boards (inverse of scopeExcludeTemplates).
279 */
280 public function scopeOnlyTemplates($query)
281 {
282 return $query->whereNotNull('settings')
283 ->where(function ($subQuery) {
284 $subQuery->where('settings', 'LIKE', '%"is_template";b:1%')
285 ->orWhere('settings', 'LIKE', '%"is_template":true%');
286 });
287 }
288
289 public function getUsers()
290 {
291 return (new UserService())->allFluentBoardsUsers($this->id);
292 }
293
294 public function customFields()
295 {
296 return $this->hasMany(CustomField::class, 'board_id')
297 ->whereNull('archived_at')
298 ->orderBy('position', 'asc');
299 }
300
301 public function getMeta() // get Board Meta only
302 {
303 $meta = Meta::where('object_id', $this->id)
304 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
305 ->get();
306
307 $formattedMeta = [];
308
309 foreach ($meta as $m) {
310 $formattedMeta[$m->key] = $m->value;
311 }
312
313 return $formattedMeta;
314 }
315
316
317
318 public function getMetaByKey($key) // get Board Meta only
319 {
320 $meta = Meta::where('object_id', $this->id)
321 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
322 ->where('key', $key)
323 ->first();
324
325 return $meta->value ?? null;
326 }
327
328 public function updateMeta($key, $value)
329 {
330 $this->unsetRelation('boardMeta');
331 $meta = Meta::where('object_id', $this->id)
332 ->where('object_type', Constant::OBJECT_TYPE_BOARD)
333 ->where('key', $key)
334 ->first();
335
336 if ($meta) {
337 $meta->value = $value;
338 $meta->save();
339 } else {
340 $meta = Meta::create([
341 'object_id' => $this->id,
342 'object_type' => Constant::OBJECT_TYPE_BOARD,
343 'key' => $key,
344 'value' => $value,
345 ]);
346 }
347
348 return $meta;
349
350 }
351
352
353 public function activities()
354 {
355 return $this->hasMany(Activity::class, 'object_id')
356 ->where('object_type', Constant::ACTIVITY_BOARD);
357 }
358
359 public function getisUserOnlyViewerAttribute()
360 {
361 $userId = get_current_user_id();
362 if(PermissionManager::isAdmin()) {
363 return false;
364 }
365 $boardPermissions = $this->relationLoaded('viewerMembership') ? $this->getRelation('viewerMembership') : null;
366 // Never reuse another user's eagerly loaded membership.
367 if (!$boardPermissions || (int) $boardPermissions->foreign_id !== (int) $userId) {
368 $boardPermissions = Relation::where('object_id', $this->id)
369 ->where('foreign_id', $userId)
370 ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
371 ->first();
372 }
373
374 return $boardPermissions->settings['is_viewer_only'] ?? false;
375 }
376
377 public function removeBoardFromFolder()
378 {
379 $relation = Relation::where('object_type', Constant::OBJECT_TYPE_FOLDER_BOARD)
380 ->where('foreign_id', $this->id)
381 ->first();
382
383 if (!$relation) {
384 return;
385 }
386 $relation->delete();
387
388 }
389
390 }
391