1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6declare(strict_types=1);
7
8namespace App\Models;
9
10use App\Libraries\BBCodeForDB;
11use App\Libraries\Uploader;
12use Illuminate\Database\Eloquent\Relations\BelongsTo;
13use Illuminate\Database\Eloquent\Relations\HasMany;
14
15class Team extends Model
16{
17 protected $casts = ['is_open' => 'bool'];
18
19 private Uploader $header;
20 private Uploader $logo;
21
22 public function applications(): HasMany
23 {
24 return $this->hasMany(TeamApplication::class);
25 }
26
27 public function leader(): BelongsTo
28 {
29 return $this->belongsTo(User::class, 'leader_id');
30 }
31
32 public function members(): HasMany
33 {
34 return $this->hasMany(TeamMember::class);
35 }
36
37 public function setHeaderAttribute(?string $value): void
38 {
39 if ($value === null) {
40 $this->header()->delete();
41 } else {
42 $this->header()->store($value);
43 }
44 }
45
46 public function setLogoAttribute(?string $value): void
47 {
48 if ($value === null) {
49 $this->logo()->delete();
50 } else {
51 $this->logo()->store($value);
52 }
53 }
54
55 public function setDefaultRulesetIdAttribute(?int $value): void
56 {
57 $this->attributes['default_ruleset_id'] = Beatmap::MODES[Beatmap::modeStr($value) ?? 'osu'];
58 }
59
60 public function setUrlAttribute(?string $value): void
61 {
62 $this->attributes['url'] = $value === null
63 ? null
64 : (is_http($value)
65 ? $value
66 : "https://{$value}"
67 );
68 }
69
70 public function descriptionHtml(): string
71 {
72 $description = presence($this->description);
73
74 return $description === null
75 ? ''
76 : bbcode((new BBCodeForDB($description))->generate());
77 }
78
79 public function delete()
80 {
81 $this->header()->delete();
82 $this->logo()->delete();
83
84 return $this->getConnection()->transaction(function () {
85 $ret = parent::delete();
86
87 if ($ret) {
88 $this->members()->delete();
89 }
90
91 return $ret;
92 });
93 }
94
95 public function header(): Uploader
96 {
97 return $this->header ??= new Uploader(
98 'teams/header',
99 $this,
100 'header_file',
101 ['image' => ['maxDimensions' => [1000, 250]]],
102 );
103 }
104
105 public function isValid(): bool
106 {
107 $this->validationErrors()->reset();
108
109 if ($this->isDirty('url')) {
110 $url = $this->url;
111 if ($url !== null && !is_http($url)) {
112 $this->validationErrors()->add('url', 'url');
113 }
114 }
115
116 if ($this->isDirty('ruleset_id')) {
117 if (Beatmap::modeStr($this->ruleset_id) === null) {
118 $this->validationErrors()->add('ruleset_id', '.unknown_ruleset_id');
119 }
120 }
121
122 return $this->validationErrors()->isEmpty();
123 }
124
125 public function logo(): Uploader
126 {
127 return $this->logo ??= new Uploader(
128 'teams/logo',
129 $this,
130 'logo_file',
131 ['image' => ['maxDimensions' => [512, 256]]],
132 );
133 }
134}