Skip to content

Commit

Permalink
Refactored code
Browse files Browse the repository at this point in the history
  • Loading branch information
VampireAotD committed Sep 16, 2024
1 parent 3963511 commit b7689e2
Show file tree
Hide file tree
Showing 35 changed files with 873 additions and 486 deletions.
4 changes: 2 additions & 2 deletions docker/mysql/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ARG MYSQL_VERSION=8.0

FROM mysql:${MYSQL_VERSION}

COPY ./conf.d/anilibrary.cnf /etc/mysql/conf.d/
COPY ./docker-entrypoint-initdb.d /docker-entrypoint-initdb.d/
COPY --link ./conf.d/anilibrary.cnf /etc/mysql/conf.d/
COPY --link ./docker-entrypoint-initdb.d /docker-entrypoint-initdb.d/

EXPOSE 3306
6 changes: 3 additions & 3 deletions docker/nginx/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ ARG NGINX_VERSION=1.27

FROM nginx:${NGINX_VERSION}-alpine

COPY ./nginx.conf /etc/nginx
COPY ./conf.d/default.conf /etc/nginx/conf.d/
COPY ./docker-entrypoint.d/logs-to-logstash.sh /docker-entrypoint.d/
COPY --link ./nginx.conf /etc/nginx
COPY --link ./conf.d/default.conf /etc/nginx/conf.d/
COPY --link ./docker-entrypoint.d/logs-to-logstash.sh /docker-entrypoint.d/

RUN chmod +x /docker-entrypoint.d/logs-to-logstash.sh

Expand Down
17 changes: 8 additions & 9 deletions docker/php/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ FROM php:${PHP_VERSION}-cli-alpine
ARG GROUP_ID=1000
ARG USER_ID=1000

RUN apk update \
&& apk add --no-cache libstdc++ libpq libzip-dev gmp-dev oniguruma-dev curl git zip unzip supervisor \
RUN apk add --no-cache libstdc++ libpq libzip-dev gmp-dev oniguruma-dev curl git zip unzip supervisor \
&& apk add --no-cache --virtual .build-deps $PHPIZE_DEPS linux-headers brotli-dev pcre-dev pcre2-dev zlib-dev \
&& pecl install xdebug swoole redis uv \
&& docker-php-ext-install -j$(nproc) \
Expand All @@ -41,15 +40,15 @@ RUN addgroup -g ${GROUP_ID} anilibrary \

USER anilibrary

COPY ./php.ini /usr/local/etc/php/php.ini
COPY ./supervisor/supervisord.conf /etc/supervisor/supervisord.conf
COPY --link ./php.ini /usr/local/etc/php/php.ini
COPY --link ./supervisor/supervisord.conf /etc/supervisor/supervisord.conf

COPY --from=composer /usr/bin/composer /usr/local/bin/composer
COPY --link --from=composer /usr/bin/composer /usr/local/bin/composer

COPY --from=node /usr/lib /usr/lib
COPY --from=node /usr/local/lib /usr/local/lib
COPY --from=node /usr/local/include /usr/local/include
COPY --from=node /usr/local/bin /usr/local/bin
COPY --link --from=node /usr/lib /usr/lib
COPY --link --from=node /usr/local/lib /usr/local/lib
COPY --link --from=node /usr/local/include /usr/local/include
COPY --link --from=node /usr/local/bin /usr/local/bin

WORKDIR /anilibrary

Expand Down
1 change: 0 additions & 1 deletion src/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ CLOUDINARY_URL=
CLOUDINARY_UPLOAD_PRESET=
CLOUDINARY_NOTIFICATION_URL=
CLOUDINARY_DEFAULT_IMAGE=
CLOUDINARY_DEFAULT_FOLDER=

JWT_SECRET=

Expand Down
3 changes: 1 addition & 2 deletions src/.env.testing
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,9 @@ TELEGRAM_LOG_CHANNEL=null
TELEGRAM_WHITELIST=1,2

CLOUDINARY_URL=https://testing.cloudinary.com
CLOUDINARY_UPLOAD_PRESET=
CLOUDINARY_UPLOAD_PRESET=test-preset
CLOUDINARY_NOTIFICATION_URL=
CLOUDINARY_DEFAULT_IMAGE=https://testing.cloudinary.com/test/image.jpg
CLOUDINARY_DEFAULT_FOLDER=test

JWT_SECRET=test

Expand Down
2 changes: 1 addition & 1 deletion src/app/Console/Commands/Lists/Anime/GenerateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function handle(AnimeService $animeService, UserRepositoryInterface $user
new RelationFilter([
'urls:anime_id,url',
'synonyms:anime_id,name',
'image:id,model_id,path,alias',
'image:id,path,name,hash',
'genres:id,name',
'voiceActing:id,name',
]),
Expand Down
67 changes: 67 additions & 0 deletions src/app/Database/Relations/OneOfMorphToMany.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace App\Database\Relations;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Support\Arr;
use Override;

/**
* @template TRelatedModel of Model
*
* @extends MorphToMany<TRelatedModel>
*/
final class OneOfMorphToMany extends MorphToMany
{
use SupportsDefaultModels;

/**
* Match the eagerly loaded results to their parents.
* This method is used when `with` or `load` methods are called.
*/
#[Override]
public function match(array $models, Collection $results, $relation): array
{
$dictionary = $this->buildDictionary($results);

foreach ($models as $model) {
$key = $this->getDictionaryKey($model->{$this->parentKey});

// If there are related entries to model, we need to take only first one and set it
if (isset($dictionary[$key])) {
$model->setRelation($relation, Arr::first($dictionary[$key]));
continue;
}

// If there were no related entries - set default one
$model->setRelation($relation, $this->getDefaultFor($model));
}

return $models;
}

/**
* Get results of the relationship. In the case of `OneOfMorphToMany` it will only get one result.
*/
#[Override]
public function getResults()
{
return $this->query->first() ?: $this->getDefaultFor($this->parent);
}

/**
* Make a new related instance for the given model.
*/
#[Override]
protected function newRelatedInstanceFor(Model $parent): Model
{
return $this->related->newInstance()
->setAttribute($this->getForeignPivotKeyName(), $parent->getKey())
->setAttribute($this->getMorphType(), $this->morphClass);
}
}
2 changes: 1 addition & 1 deletion src/app/Http/Controllers/Anime/AnimeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function store(CreateRequest $request): RedirectResponse
public function show(Anime $anime): Response
{
$anime->load([
'image:model_id,path',
'image:id,path',
'urls:anime_id,url',
'synonyms:anime_id,name',
'voiceActing:name',
Expand Down
2 changes: 1 addition & 1 deletion src/app/Jobs/Image/UploadJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public function __construct(public readonly Anime $anime, public readonly string
*/
public function handle(ImageService $imageService): void
{
$imageService->upsert($this->image, $this->anime);
$imageService->attachEncodedImageToAnime($this->image, $this->anime);
}
}
13 changes: 4 additions & 9 deletions src/app/Models/Anime.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Enums\Anime\StatusEnum;
use App\Enums\Anime\TypeEnum;
use App\Models\Concerns\Filterable;
use App\Models\Concerns\HasImage;
use App\Models\Pivots\AnimeGenre;
use App\Models\Pivots\AnimeVoiceActing;
use App\Observers\AnimeObserver;
Expand All @@ -17,7 +18,6 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
Expand All @@ -28,6 +28,7 @@ class Anime extends Model
{
use HasUuids;
use HasFactory;
use HasImage;
use Filterable;
use SoftDeletes;

Expand All @@ -53,13 +54,6 @@ protected function casts(): array
];
}

public function image(): MorphOne
{
return $this->morphOne(Image::class, 'model')->withDefault([
'path' => config('cloudinary.default_image'),
]);
}

public function urls(): HasMany
{
return $this->hasMany(AnimeUrl::class);
Expand All @@ -86,11 +80,12 @@ public function genres(): BelongsToMany
*/
protected function toTelegramCaption(): Attribute
{
/** @see https://github.com/larastan/larastan/issues/2038 */
return Attribute::make(
get: fn(): string => sprintf(
"Название: %s\nСтатус: %s\nЭпизоды: %s\nОценка: %s\nОзвучки: %s\nЖанры: %s",
$this->title,
$this->status->value,
$this->status->value, // @phpstan-ignore-line Ignored because of parser issues
$this->episodes,
$this->rating,
$this->voiceActing->implode('name', ', '),
Expand Down
42 changes: 42 additions & 0 deletions src/app/Models/Concerns/HasImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace App\Models\Concerns;

use App\Database\Relations\OneOfMorphToMany;
use App\Models\Image;
use Illuminate\Database\Eloquent\Model;

/**
* @mixin Model
* @property-read Image $image
* @infection-ignore-all
* @codeCoverageIgnore
*/
trait HasImage
{
use HasOneOfMorphToManyRelation;

public function image(): OneOfMorphToMany
{
return $this->oneOfMorphToMany(Image::class, 'model', 'has_images')->withTimestamps()->withDefault([
'path' => config('cloudinary.default_image'),
]);
}

public function attachImage(Image $image): void
{
$this->detachImage();
$this->image()->attach($image);
}

public function detachImage(): void
{
if ($this->image->is_default) {
return;
}

$this->image()->detach();
}
}
75 changes: 75 additions & 0 deletions src/app/Models/Concerns/HasOneOfMorphToManyRelation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace App\Models\Concerns;

use App\Database\Relations\OneOfMorphToMany;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

/**
* @mixin Model
* @infection-ignore-all
* @codeCoverageIgnore
*/
trait HasOneOfMorphToManyRelation
{
/**
* Define a polymorphic many-to-many relationship that return only one result.
* Modified version of `morphToMany` method.
*
* @template TRelatedModel of Model
*
* @param class-string<TRelatedModel> $related
* @param string $name
* @param string|null $table
* @param string|null $foreignPivotKey
* @param string|null $relatedPivotKey
* @param string|null $parentKey
* @param string|null $relatedKey
* @param string|null $relation
* @param bool $inverse
* @return OneOfMorphToMany
*/
public function oneOfMorphToMany(
$related,
string $name,
?string $table = null,
?string $foreignPivotKey = null,
?string $relatedPivotKey = null,
?string $parentKey = null,
?string $relatedKey = null,
?string $relation = null,
bool $inverse = false
): OneOfMorphToMany {
$relation = $relation ?: $this->guessBelongsToManyRelation();

$instance = $this->newRelatedInstance($related);

$foreignPivotKey = $foreignPivotKey ?: $name . '_id';

$relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();

if (!$table) {
$words = preg_split('/(_)/u', $name, -1, PREG_SPLIT_DELIM_CAPTURE);

$lastWord = array_pop($words);

$table = implode('', $words) . Str::plural($lastWord);
}

return new OneOfMorphToMany(
query : $instance->newQuery(),
parent : $this,
name : $name,
table : $table,
foreignPivotKey: $foreignPivotKey,
relatedPivotKey: $relatedPivotKey,
parentKey : $parentKey ?: $this->getKeyName(),
relatedKey : $relatedKey ?: $instance->getKeyName(),
relationName : $relation,
inverse : $inverse
);
}
}
15 changes: 5 additions & 10 deletions src/app/Models/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;

/**
* @mixin IdeHelperImage
Expand All @@ -18,23 +18,18 @@ class Image extends Model
use HasUuids;
use HasFactory;

protected $fillable = [
'model_type',
'model_id',
'path',
'alias',
];
protected $fillable = ['path', 'name', 'hash'];

public function anime(): MorphTo
public function animes(): MorphToMany
{
return $this->morphTo(Anime::class);
return $this->morphedByMany(Anime::class, 'model', 'has_images');
}

/**
* @psalm-suppress TooManyTemplateParams Suppressed because PHPStan needs description, but Psalm conflicts with it
* @return Attribute<bool, never>
*/
protected function default(): Attribute
protected function isDefault(): Attribute
{
return Attribute::make(
get: fn(): bool => $this->path === config('cloudinary.default_image'),
Expand Down
2 changes: 1 addition & 1 deletion src/app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
*/
class User extends Authenticatable implements MustVerifyEmail
{
use HasUuids;
use HasApiTokens;
use HasFactory;
use HasRoles;
use HasUuids;
use Notifiable;

protected $fillable = [
Expand Down
Loading

0 comments on commit b7689e2

Please sign in to comment.