| @@ -1,14 +1,12 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace FluentBoards\App\Models; |
| 4 | 4 | |
| 5 | -use FluentBoards\App\Services\BoardService; | |
| 6 | 5 | use FluentBoards\App\Services\Constant; |
| 7 | 6 | use FluentBoards\App\Services\PermissionManager; |
| 8 | 7 | use FluentBoards\App\Services\UserService; |
| 9 | 8 | use FluentBoards\Framework\Database\Orm\Builder; |
| 10 | -use FluentBoards\Framework\Support\Arr; | |
| 11 | 9 | use FluentBoardsPro\App\Models\CustomField; |
| 12 | 10 | |
| 13 | 11 | class Board extends Model |
| 14 | 12 | { |
| @@ -32,20 +30,24 @@ | ||
| 32 | 30 | 'created_by', |
| 33 | 31 | 'archived_at', |
| 34 | 32 | ]; |
| 35 | 33 | |
| 34 | + protected $appends = ['meta', 'isUserOnlyViewer']; | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * Boot board defaults while preserving empty backgrounds for newly created boards. | |
| 38 | + */ | |
| 36 | 39 | public static function boot() |
| 37 | 40 | { |
| 38 | 41 | static::creating(function ($model) { |
| 39 | 42 | $model->created_by = $model->created_by ?: get_current_user_id(); |
| 40 | 43 | $model->type = $model->type ?: 'to-do'; // default board type is to-do |
| 41 | - $model->background = $model->background ?: $model->randomBackground(); | |
| 44 | + $model->background = $model->background ?: ''; | |
| 42 | 45 | }); |
| 43 | 46 | /* global scope for board type which means only type = to-do will be fetched from everywhere */ |
| 44 | 47 | parent::boot(); |
| 45 | 48 | static::addGlobalScope('type', function (Builder $builder) { |
| 46 | - $builder = $builder->whereNull('archived_at'); | |
| 47 | - $builder->where('type', '=', 'to-do') | |
| 49 | + $builder = $builder->where('type', '=', 'to-do') | |
| 48 | 50 | ->orWhere('type', '=', 'roadmap'); |
| 49 | 51 | }); |
| 50 | 52 | } |
| 51 | 53 | |
| @@ -77,8 +79,13 @@ | ||
| 77 | 79 | { |
| 78 | 80 | return \maybe_unserialize($settings); |
| 79 | 81 | } |
| 80 | 82 | |
| 83 | + public function getMetaAttribute() | |
| 84 | + { | |
| 85 | + return $this->getMeta(); | |
| 86 | + } | |
| 87 | + | |
| 81 | 88 | public function setBackgroundAttribute($background) |
| 82 | 89 | { |
| 83 | 90 | $this->attributes['background'] = \maybe_serialize($background); |
| 84 | 91 | } |
| @@ -100,13 +107,8 @@ | ||
| 100 | 107 | ->where('parent_id', null) |
| 101 | 108 | ->where('status', 'closed'); |
| 102 | 109 | } |
| 103 | 110 | |
| 104 | - public function boardTerm() | |
| 105 | - { | |
| 106 | - return $this->hasMany(BoardTerm::class, 'board_id'); | |
| 107 | - } | |
| 108 | - | |
| 109 | 111 | public function stages() |
| 110 | 112 | { |
| 111 | 113 | return $this->hasMany(Stage::class, 'board_id') |
| 112 | 114 | ->whereNull('archived_at') |
| @@ -126,9 +128,9 @@ | ||
| 126 | 128 | User::class, |
| 127 | 129 | 'fbs_relations', |
| 128 | 130 | 'object_id', |
| 129 | 131 | 'foreign_id' |
| 130 | - )->withPivot('settings') | |
| 132 | + )->withPivot('settings','preferences') | |
| 131 | 133 | ->wherePivot('object_type', Constant::OBJECT_TYPE_BOARD_USER) |
| 132 | 134 | ->withTimestamps(); |
| 133 | 135 | } |
| 134 | 136 | |
| @@ -217,21 +219,49 @@ | ||
| 217 | 219 | } |
| 218 | 220 | |
| 219 | 221 | return $query->whereIn('id', $boardIds); |
| 220 | 222 | } |
| 221 | - private function randomBackground() | |
| 223 | + | |
| 224 | + /** | |
| 225 | + * Exclude template boards (settings['is_template'] === true). | |
| 226 | + * The settings column is serialized text, so both the PHP-serialized | |
| 227 | + * and JSON representations of the flag are matched. | |
| 228 | + */ | |
| 229 | + public function scopeExcludeTemplates($query) | |
| 222 | 230 | { |
| 223 | - $solids = Constant::BOARD_BACKGROUND_DEFAULT_SOLID_COLORS; | |
| 224 | - $solid = $solids[wp_rand(0, count($solids) - 1)]; | |
| 231 | + return $query->where(function ($query) { | |
| 232 | + $query->whereNull('settings') | |
| 233 | + ->orWhere(function ($subQuery) { | |
| 234 | + $subQuery->where('settings', 'NOT LIKE', '%"is_template";b:1%') | |
| 235 | + ->where('settings', 'NOT LIKE', '%"is_template":true%'); | |
| 236 | + }); | |
| 237 | + }); | |
| 238 | + } | |
| 225 | 239 | |
| 226 | - return [ | |
| 227 | - 'id' => $solid['id'], | |
| 228 | - 'is_image' => false, | |
| 229 | - 'image_url' => null, | |
| 230 | - 'color' => $solid['value'] | |
| 231 | - ]; | |
| 240 | + /** | |
| 241 | + * Limit boards to types supported by the currently loaded plugins. | |
| 242 | + */ | |
| 243 | + public function scopeAvailableInCurrentInstall($query) | |
| 244 | + { | |
| 245 | + if (!defined('FLUENT_ROADMAP')) { | |
| 246 | + return $query->where('type', 'to-do'); | |
| 247 | + } | |
| 248 | + | |
| 249 | + return $query; | |
| 232 | 250 | } |
| 233 | 251 | |
| 252 | + /** | |
| 253 | + * Only template boards (inverse of scopeExcludeTemplates). | |
| 254 | + */ | |
| 255 | + public function scopeOnlyTemplates($query) | |
| 256 | + { | |
| 257 | + return $query->whereNotNull('settings') | |
| 258 | + ->where(function ($subQuery) { | |
| 259 | + $subQuery->where('settings', 'LIKE', '%"is_template";b:1%') | |
| 260 | + ->orWhere('settings', 'LIKE', '%"is_template":true%'); | |
| 261 | + }); | |
| 262 | + } | |
| 263 | + | |
| 234 | 264 | public function getUsers() |
| 235 | 265 | { |
| 236 | 266 | return (new UserService())->allFluentBoardsUsers($this->id); |
| 237 | 267 | } |
| @@ -240,7 +270,91 @@ | ||
| 240 | 270 | { |
| 241 | 271 | return $this->hasMany(CustomField::class, 'board_id') |
| 242 | 272 | ->whereNull('archived_at') |
| 243 | 273 | ->orderBy('position', 'asc'); |
| 274 | + } | |
| 275 | + | |
| 276 | + public function getMeta() // get Board Meta only | |
| 277 | + { | |
| 278 | + $meta = Meta::where('object_id', $this->id) | |
| 279 | + ->where('object_type', Constant::OBJECT_TYPE_BOARD) | |
| 280 | + ->get(); | |
| 281 | + | |
| 282 | + $formattedMeta = []; | |
| 283 | + | |
| 284 | + foreach ($meta as $m) { | |
| 285 | + $formattedMeta[$m->key] = $m->value; | |
| 286 | + } | |
| 287 | + | |
| 288 | + return $formattedMeta; | |
| 289 | + } | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + public function getMetaByKey($key) // get Board Meta only | |
| 294 | + { | |
| 295 | + $meta = Meta::where('object_id', $this->id) | |
| 296 | + ->where('object_type', Constant::OBJECT_TYPE_BOARD) | |
| 297 | + ->where('key', $key) | |
| 298 | + ->first(); | |
| 299 | + | |
| 300 | + return $meta->value ?? null; | |
| 301 | + } | |
| 302 | + | |
| 303 | + public function updateMeta($key, $value) | |
| 304 | + { | |
| 305 | + $meta = Meta::where('object_id', $this->id) | |
| 306 | + ->where('object_type', Constant::OBJECT_TYPE_BOARD) | |
| 307 | + ->where('key', $key) | |
| 308 | + ->first(); | |
| 309 | + | |
| 310 | + if ($meta) { | |
| 311 | + $meta->value = $value; | |
| 312 | + $meta->save(); | |
| 313 | + } else { | |
| 314 | + $meta = Meta::create([ | |
| 315 | + 'object_id' => $this->id, | |
| 316 | + 'object_type' => Constant::OBJECT_TYPE_BOARD, | |
| 317 | + 'key' => $key, | |
| 318 | + 'value' => $value, | |
| 319 | + ]); | |
| 320 | + } | |
| 321 | + | |
| 322 | + return $meta; | |
| 323 | + | |
| 324 | + } | |
| 325 | + | |
| 326 | + | |
| 327 | + public function activities() | |
| 328 | + { | |
| 329 | + return $this->hasMany(Activity::class, 'object_id') | |
| 330 | + ->where('object_type', Constant::ACTIVITY_BOARD); | |
| 331 | + } | |
| 332 | + | |
| 333 | + public function getisUserOnlyViewerAttribute() | |
| 334 | + { | |
| 335 | + $userId = get_current_user_id(); | |
| 336 | + if(PermissionManager::isAdmin()) { | |
| 337 | + return false; | |
| 338 | + } | |
| 339 | + $boardPermissions = Relation::where('object_id', $this->id) | |
| 340 | + ->where('foreign_id', $userId) | |
| 341 | + ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER) | |
| 342 | + ->first(); | |
| 343 | + | |
| 344 | + return $boardPermissions->settings['is_viewer_only'] ?? false; | |
| 345 | + } | |
| 346 | + | |
| 347 | + public function removeBoardFromFolder() | |
| 348 | + { | |
| 349 | + $relation = Relation::where('object_type', Constant::OBJECT_TYPE_FOLDER_BOARD) | |
| 350 | + ->where('foreign_id', $this->id) | |
| 351 | + ->first(); | |
| 352 | + | |
| 353 | + if (!$relation) { | |
| 354 | + return; | |
| 355 | + } | |
| 356 | + $relation->delete(); | |
| 357 | + | |
| 244 | 358 | } |
| 245 | 359 | |
| 246 | 360 | } |