trim($name) ?: self::UNKNOWN_NAME]); } public function albums(): HasMany { return $this->hasMany(Album::class); } public function songs(): HasMany { return $this->hasMany(Song::class); } public function getIsUnknownAttribute(): bool { return $this->id === self::UNKNOWN_ID; } public function getIsVariousAttribute(): bool { return $this->id === self::VARIOUS_ID; } /** * Sometimes the tags extracted from getID3 are HTML entity encoded. * This makes sure they are always sane. */ public function getNameAttribute(string $value): string { return html_entity_decode($value ?: self::UNKNOWN_NAME); } /** * Turn the image name into its absolute URL. */ public function getImageAttribute(?string $value): ?string { return $value ? artist_image_url($value) : null; } public function getImagePathAttribute(): ?string { if (!$this->has_image) { return null; } return artist_image_path(array_get($this->attributes, 'image')); } public function getHasImageAttribute(): bool { $image = array_get($this->attributes, 'image'); if (!$image) { return false; } return file_exists(artist_image_path($image)); } public function scopeIsStandard(Builder $query): Builder { return $query->whereNotIn('artists.id', [self::UNKNOWN_ID, self::VARIOUS_ID]); } public static function withMeta(User $scopedUser): BuilderContract { return static::query() ->leftJoin('songs', 'artists.id', '=', 'songs.artist_id') ->leftJoin('interactions', static function (JoinClause $join) use ($scopedUser): void { $join->on('interactions.song_id', '=', 'songs.id') ->where('interactions.user_id', $scopedUser->id); }) ->groupBy('artists.id') ->select(['artists.*', DB::raw('CAST(SUM(interactions.play_count) AS INTEGER) AS play_count')]) ->withCount('albums AS album_count', 'songs AS song_count') ->withSum('songs AS length', 'length'); } /** @return array */ public function toSearchableArray(): array { return [ 'id' => $this->id, 'name' => $this->name, ]; } }