diff --git a/src/app/Fs/Item.php b/src/app/Fs/Item.php index 6d1438e3..edde2ff3 100644 --- a/src/app/Fs/Item.php +++ b/src/app/Fs/Item.php @@ -1,178 +1,170 @@ The attributes that are mass assignable */ protected $fillable = ['user_id', 'type']; /** @var array The attributes that should be cast */ protected $casts = [ 'created_at' => 'datetime:Y-m-d H:i:s', 'updated_at' => 'datetime:Y-m-d H:i:s', ]; /** @var string Database table name */ protected $table = 'fs_items'; /** * COntent chunks of this item (file). * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function chunks() { return $this->hasMany(Chunk::class); } /** * Getter for the file path (without the filename) in the storage. * * @return \Illuminate\Database\Eloquent\Casts\Attribute */ protected function path(): Attribute { return Attribute::make( get: function ($value) { if (empty($this->id)) { throw new \Exception("Cannot get path for an item without ID"); } $id = substr($this->id, 0, 6); return implode('/', str_split($id, 2)); } ); } /** * Any (additional) properties of this item. * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function properties() { return $this->hasMany(Property::class); } /** * Obtain the value for an item property * * @param string $key Property name * @param mixed $default Default value, to be used if not found * * @return string|null Property value */ public function getProperty(string $key, $default = null) { $attr = $this->properties()->where('key', $key)->first(); return $attr ? $attr->value : $default; } /** * Obtain the values for many properties in one go (for better performance). * * @param array $keys Property names * * @return array Property key=value hash, includes also requested but non-existing properties */ public function getProperties(array $keys): array { $props = array_fill_keys($keys, null); $this->properties()->whereIn('key', $keys)->get() ->each(function ($prop) use (&$props) { $props[$prop->key] = $prop->value; }); return $props; } /** * Remove a property * * @param string $key Property name */ public function removeProperty(string $key): void { $this->setProperty($key, null); } /** * Create or update a property. * * @param string $key Property name * @param string|null $value The new value for the property */ public function setProperty(string $key, $value): void { $this->storeProperty($key, $value); } /** * Create or update multiple properties in one fell swoop. * * @param array $data An associative array of key value pairs. */ public function setProperties(array $data = []): void { foreach ($data as $key => $value) { $this->storeProperty($key, $value); } } /** * Create or update a property. * * @param string $key Property name * @param string|null $value The new value for the property */ private function storeProperty(string $key, $value): void { if ($value === null || $value === '') { // Note: We're selecting the record first, so observers can act if ($prop = $this->properties()->where('key', $key)->first()) { $prop->delete(); } } else { $this->properties()->updateOrCreate( ['key' => $key], ['value' => $value] ); } } - - /** - * The user to which this item belongs. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() - { - return $this->belongsTo(User::class, 'user_id', 'id'); - } } diff --git a/src/app/Mail/PasswordReset.php b/src/app/Mail/PasswordReset.php index 889301be..51338efc 100644 --- a/src/app/Mail/PasswordReset.php +++ b/src/app/Mail/PasswordReset.php @@ -1,86 +1,87 @@ code = $code; } /** * Build the message. * * @return $this */ public function build() { $appName = Tenant::getConfig($this->code->user->tenant_id, 'app.name'); $supportUrl = Tenant::getConfig($this->code->user->tenant_id, 'app.support_url'); $href = Utils::serviceUrl( sprintf('/password-reset/%s-%s', $this->code->short_code, $this->code->code), $this->code->user->tenant_id ); $this->view('emails.html.password_reset') ->text('emails.plain.password_reset') ->subject(\trans('mail.passwordreset-subject', ['site' => $appName])) ->with([ 'site' => $appName, 'code' => $this->code->code, 'short_code' => $this->code->short_code, 'link' => sprintf('%s', $href, $href), 'username' => $this->code->user->name(true) ]); return $this; } /** * Render the mail template with fake data * * @param string $type Output format ('html' or 'text') * * @return string HTML or Plain Text output */ public static function fakeRender(string $type = 'html'): string { $code = new VerificationCode([ 'code' => Str::random(VerificationCode::CODE_LENGTH), 'short_code' => VerificationCode::generateShortCode(), ]); + // @phpstan-ignore-next-line $code->user = new User([ 'email' => 'test@' . \config('app.domain'), ]); $mail = new self($code); return Helper::render($mail, $type); } } diff --git a/src/app/Policy/RateLimit.php b/src/app/Policy/RateLimit.php index 7605da4b..70f2c720 100644 --- a/src/app/Policy/RateLimit.php +++ b/src/app/Policy/RateLimit.php @@ -1,27 +1,25 @@ belongsTo('App\User'); - } - - public function user() - { - $this->belongsTo('App\User'); + $this->belongsTo(\App\User::class); } } diff --git a/src/app/SignupInvitation.php b/src/app/SignupInvitation.php index d5f5ea68..2d353b4c 100644 --- a/src/app/SignupInvitation.php +++ b/src/app/SignupInvitation.php @@ -1,87 +1,78 @@ The attributes that are mass assignable */ protected $fillable = ['email']; /** * Returns whether this invitation process completed (user signed up) * * @return bool */ public function isCompleted(): bool { return ($this->status & self::STATUS_COMPLETED) > 0; } /** * Returns whether this invitation sending failed. * * @return bool */ public function isFailed(): bool { return ($this->status & self::STATUS_FAILED) > 0; } /** * Returns whether this invitation is new. * * @return bool */ public function isNew(): bool { return ($this->status & self::STATUS_NEW) > 0; } /** * Returns whether this invitation has been sent. * * @return bool */ public function isSent(): bool { return ($this->status & self::STATUS_SENT) > 0; } - - /** - * The account to which the invitation was used for. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() - { - return $this->belongsTo(User::class, 'user_id', 'id'); - } } diff --git a/src/app/Traits/BelongsToUserTrait.php b/src/app/Traits/BelongsToUserTrait.php new file mode 100644 index 00000000..25b9e9c8 --- /dev/null +++ b/src/app/Traits/BelongsToUserTrait.php @@ -0,0 +1,16 @@ +belongsTo(\App\User::class); + } +} diff --git a/src/app/UserAlias.php b/src/app/UserAlias.php index 1f744626..d63cb1bf 100644 --- a/src/app/UserAlias.php +++ b/src/app/UserAlias.php @@ -1,38 +1,31 @@ The attributes that are mass assignable */ protected $fillable = ['user_id', 'alias']; /** * Ensure the email address is appropriately cased. * * @param string $alias Email address */ public function setAliasAttribute(string $alias) { $this->attributes['alias'] = \strtolower($alias); } - - /** - * The user to which this alias belongs. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() - { - return $this->belongsTo(User::class, 'user_id', 'id'); - } } diff --git a/src/app/UserPassword.php b/src/app/UserPassword.php index 7766d07b..af004420 100644 --- a/src/app/UserPassword.php +++ b/src/app/UserPassword.php @@ -1,39 +1,32 @@ The attributes that should be cast. */ protected $casts = [ 'created_at' => 'datetime:Y-m-d H:i:s', ]; /** @var array The attributes that are mass assignable. */ protected $fillable = ['user_id', 'password']; /** @var array The attributes that should be hidden for arrays. */ protected $hidden = ['password']; - - /** - * The user to which this entry belongs. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() - { - return $this->belongsTo(User::class, 'user_id', 'id'); - } } diff --git a/src/app/UserSetting.php b/src/app/UserSetting.php index 3d3c2f80..83bf950e 100644 --- a/src/app/UserSetting.php +++ b/src/app/UserSetting.php @@ -1,29 +1,22 @@ The attributes that are mass assignable */ protected $fillable = ['user_id', 'key', 'value']; - - /** - * The user to which this setting belongs. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() - { - return $this->belongsTo(User::class, 'user_id', 'id'); - } } diff --git a/src/app/VerificationCode.php b/src/app/VerificationCode.php index 13544011..6a07ee0c 100644 --- a/src/app/VerificationCode.php +++ b/src/app/VerificationCode.php @@ -1,83 +1,75 @@ Casts properties as type */ protected $casts = [ 'active' => 'boolean', 'expires_at' => 'datetime', ]; /** @var array The attributes that are mass assignable */ protected $fillable = ['user_id', 'code', 'short_code', 'mode', 'expires_at', 'active']; /** * Generate a short code (for human). * * @return string */ public static function generateShortCode(): string { $code_length = env('VERIFICATION_CODE_LENGTH', self::SHORTCODE_LENGTH); return \App\Utils::randStr($code_length); } /** * Check if code is expired. * * @return bool True if code is expired, False otherwise */ public function isExpired() { // @phpstan-ignore-next-line return $this->expires_at ? Carbon::now()->gte($this->expires_at) : false; } - - /** - * The user to which this code belongs. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() - { - return $this->belongsTo(User::class, 'user_id', 'id'); - } } diff --git a/src/tests/Unit/Mail/PasswordResetTest.php b/src/tests/Unit/Mail/PasswordResetTest.php index 95a1bba2..ddc5554b 100644 --- a/src/tests/Unit/Mail/PasswordResetTest.php +++ b/src/tests/Unit/Mail/PasswordResetTest.php @@ -1,47 +1,48 @@ 123456789, 'mode' => 'password-reset', 'code' => 'code', 'short_code' => 'short-code', ]); + // @phpstan-ignore-next-line $code->user = new User([ 'name' => 'User Name', ]); $mail = $this->renderMail(new PasswordReset($code)); $html = $mail['html']; $plain = $mail['plain']; $url = Utils::serviceUrl('/password-reset/' . $code->short_code . '-' . $code->code); $link = "$url"; $appName = \config('app.name'); $this->assertSame("$appName Password Reset", $mail['subject']); $this->assertStringStartsWith('', $html); $this->assertTrue(strpos($html, $link) > 0); $this->assertTrue(strpos($html, $code->user->name(true)) > 0); $this->assertStringStartsWith("Dear " . $code->user->name(true), $plain); $this->assertTrue(strpos($plain, $link) > 0); } }