InfluxOW/laravel_ddd_ecommerce

View on GitHub
app/Domains/Common/Services/Repositories/ConfirmationTokenRepository.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace App\Domains\Common\Services\Repositories;

use App\Domains\Common\Enums\ConfirmationTokenType;
use App\Domains\Common\Exceptions\InvalidConfirmationTokenException;
use App\Domains\Common\Models\ConfirmationToken;
use App\Domains\Users\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Str;

final class ConfirmationTokenRepository
{
    public function create(ConfirmationTokenType $type, User $user, Carbon $expiresAt): ConfirmationToken
    {
        return $user->confirmationTokens()->create(['type' => $type->name, 'token' => $this->createToken($type), 'expires_at' => $expiresAt]);
    }

    /**
     * @throws InvalidConfirmationTokenException
     */
    public function consume(User $user, ConfirmationTokenType $type, string $token): void
    {
        $confirmationToken = $this->find($user, $type, $token);

        if ($confirmationToken === null || $confirmationToken->isExpired() || $confirmationToken->isUsed()) {
            throw new InvalidConfirmationTokenException($confirmationToken);
        }

        $confirmationToken->update(['used_at' => Carbon::now()]);
    }

    private function find(User $user, ConfirmationTokenType $type, string $token): ?ConfirmationToken
    {
        $latestToken = ConfirmationToken::query()->whereBelongsTo($user)->where('type', $type->name)->latest()->first();

        return isset($latestToken) && strtolower($latestToken->token) === strtolower($token) ? $latestToken : null;
    }

    private function createToken(ConfirmationTokenType $type): string
    {
        return match ($type) {
            ConfirmationTokenType::EMAIL_VERIFICATION => $this->generateShortStringToken(),
        };
    }

    private function generateShortStringToken(): string
    {
        return Str::of(Str::random(6))->upper()->toString();
    }
}