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
6namespace App\Models\Forum;
7
8use App\Casts\LegacyFilename;
9use App\Libraries\Uploader;
10use App\Models\User;
11use DB;
12use Exception;
13
14/**
15 * @property \Carbon\Carbon|null $created_at
16 * @property string|null $ext
17 * @property string|null $hash
18 * @property int $id
19 * @property Topic $topic
20 * @property int|null $topic_id
21 * @property \Carbon\Carbon|null $updated_at
22 * @property User $user
23 * @property int|null $user_id
24 */
25class TopicCover extends Model
26{
27 const MAX_DIMENSIONS = [2400, 580];
28
29 // To be passed to transformer for generating url for initial cover upload
30 public ?int $newForumId = null;
31
32 protected $casts = [
33 'filename' => LegacyFilename::class,
34 ];
35 protected $table = 'forum_topic_covers';
36
37 private Uploader $file;
38 private $_owner = [false, null];
39
40 public static function findForUse($id, $user)
41 {
42 if ($user === null) {
43 return;
44 }
45
46 $covers = static::select();
47
48 if ($user->isAdmin() === false) {
49 $covers->where('user_id', $user->user_id);
50 }
51
52 return $covers->find($id);
53 }
54
55 public static function upload($filePath, $user, $topic = null)
56 {
57 $cover = new static();
58
59 DB::transaction(function () use ($cover, $filePath, $user, $topic) {
60 $cover->save(); // get id
61 $cover->user()->associate($user);
62 $cover->topic()->associate($topic);
63 $cover->file()->store($filePath);
64 $cover->save();
65 });
66
67 return $cover;
68 }
69
70 public function topic()
71 {
72 return $this->belongsTo(Topic::class, 'topic_id');
73 }
74
75 public function user()
76 {
77 return $this->belongsTo(User::class, 'user_id');
78 }
79
80 public function owner()
81 {
82 if ($this->_owner[0] === false) {
83 $this->_owner[0] = true;
84
85 if ($this->topic !== null) {
86 $this->_owner[1] = User::find($this->topic->topic_poster);
87 }
88
89 if ($this->_owner[1] === null) {
90 $this->_owner[1] = $this->user;
91 }
92 }
93
94 return $this->_owner[1];
95 }
96
97 public function updateFile($filePath, $user)
98 {
99 $this->user()->associate($user);
100 $this->file()->store($filePath);
101 $this->save();
102
103 return $this->fresh();
104 }
105
106 public function defaultFileUrl()
107 {
108 try {
109 return $this->topic->forum->cover->defaultTopicCover->url();
110 } catch (Exception $_e) {
111 // do nothing
112 }
113 }
114
115 public function delete()
116 {
117 $this->file()->delete();
118
119 return parent::delete();
120 }
121
122 public function file(): Uploader
123 {
124 return $this->file ??= new Uploader(
125 'topic-covers',
126 $this,
127 'filename',
128 ['image' => ['maxDimensions' => static::MAX_DIMENSIONS]],
129 );
130 }
131
132 public function getForumId(): ?int
133 {
134 return $this->topic?->forum_id ?? $this->newForumId;
135 }
136}