Commit ccdd18df authored by a.chevordin@iq-adv.ru's avatar a.chevordin@iq-adv.ru
Browse files

Refactoring Repositories

parent 6c4076b4
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -5,14 +5,14 @@ namespace App\Application\Services\Request;
use App\Domain\Request\DTO\PaginationDataDTO;
use App\Domain\Request\DTO\Request\Query\GetRequestsDTO;
use App\Domain\Request\DTO\Request\Response\RequestDTO;
use App\Domain\Request\Interfaces\RequestRepositoryInterface;
use App\Domain\Request\Interfaces\RequestReaderInterface;
use Doctrine\DBAL\Exception;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

final class GetUserRequestService
{
    public function __construct(
        private readonly RequestRepositoryInterface $repository,
        private readonly RequestReaderInterface $repository,
        private readonly TokenStorageInterface $token,
    ) {
    }
+29 −0
Original line number Diff line number Diff line
<?php

namespace App\Domain\Request\Interfaces;

use App\Domain\Request\DTO\PaginateQuery;
use App\Domain\Request\DTO\PaginationDataDTO;
use App\Domain\Request\DTO\Request\Query\GetRequestsDTO;
use App\Domain\Request\DTO\Request\Response\RequestDTO;
use App\Domain\Request\Entity\Request;

interface RequestReaderInterface
{
    /**
     * Все запросы, принадлежащие пользователю
     *
     * @param GetRequestsDTO $request
     * @return mixed
     */
    public function getRequests(GetRequestsDTO $request): PaginationDataDTO;

    /**
     * Получить заявку по идентификатору
     *
     * @param string $id
     * @param string|null $userId
     * @return RequestDTO|null
     */
    public function getRequestById(string $id, ?string $userId = null): ?RequestDTO;
}
+3 −12
Original line number Diff line number Diff line
@@ -19,19 +19,10 @@ interface RequestRepositoryInterface
    public function persist(Request $request): void;

    /**
     * Все запросы, принадлежащие пользователю
     *
     * @param GetRequestsDTO $request
     * @return mixed
     */
    public function getRequests(GetRequestsDTO $request): PaginationDataDTO;

    /**
     * Получить заявку по идентификатору
     * Получить Request
     *
     * @param string $id
     * @param string|null $userId
     * @return RequestDTO|null
     * @return Request|null
     */
    public function getRequestById(string $id, ?string $userId = null): ?RequestDTO;
    public function getById(string $id): ?Request;
}
+184 −0
Original line number Diff line number Diff line
<?php

namespace App\Infrastructure\Request\Reader;

use App\Domain\Request\DTO\PaginateQuery;
use App\Domain\Request\DTO\PaginationDataDTO;
use App\Domain\Request\DTO\Request\Query\GetRequestsDTO;
use App\Domain\Request\DTO\Request\Response\RequestDTO;
use App\Domain\Request\Interfaces\RequestReaderInterface;
use App\Domain\Request\Status\Status;
use DateTime;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;

class RequestReader implements RequestReaderInterface
{
    private const REQUESTS_TABLE_NAME = 'requests';

    public function __construct(private readonly EntityManagerInterface $entityManager)
    {
    }

    /**
     * Все заявки пользователя
     *
     * @param GetRequestsDTO $request
     * @return PaginationDataDTO
     * @throws Exception
     */
    public function getRequests(GetRequestsDTO $request): PaginationDataDTO
    {
        $queryBuilder = $this->getQueryToRequests('r')
            ->leftJoin('r', 'users', 'u', 'u.id = r.user_id');

        $this->parseRequestToQueryCondition($queryBuilder, $request);
        return $this->getPaginateDTO($queryBuilder, $request->pagination);
    }

    /**
     * Получить заявку по идентификатору
     *
     * @param string $id
     * @param string|null $userId
     * @return RequestDTO|null
     * @throws Exception
     * @throws \Exception
     */
    public function getRequestById(string $id, ?string $userId = null): ?RequestDTO
    {
        if (empty($id)) {
            throw new InvalidArgumentException('Id cannot be empty');
        }

        $queryBuilder = $this->getQueryToRequests('r')
            ->leftJoin('r', 'users', 'u', 'u.id = r.user_id')
            ->setMaxResults(1);

        if ($userId !== null) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.user_id', ":userId"))
                ->setParameter('userId', $userId);
        }

        $queryBuilder->where($queryBuilder->expr()->eq('r.id', ':id'))
            ->setParameter('id', $id);


        $response = $queryBuilder->fetchAssociative();

        if (!$response) {
            return null;
        }

        return $this->getRequestDTOByArray($response);
    }

    /**
     * Получить запрос к таблице запросов
     *
     * @param array $select
     * @param string|null $alias
     * @return QueryBuilder
     */
    private function getQueryToRequests(string $alias = null): QueryBuilder
    {
        $select = [
            'r.id',
            'r.message',
            'r.topic',
            'r.user_id',
            'r.created_at',
            'r.status',
            'r.comment',
            'u.email'
        ];
        $queryBuilder = $this->entityManager->getConnection()->createQueryBuilder();

        $queryBuilder
            ->select($select)
            ->from(self::REQUESTS_TABLE_NAME, $alias);

        return $queryBuilder;
    }

    /**
     * Загрузить условия в объект запроса
     *
     * @param QueryBuilder $queryBuilder
     * @param GetRequestsDTO $request
     * @return void
     */
    private function parseRequestToQueryCondition(QueryBuilder $queryBuilder, GetRequestsDTO $request): void
    {
        if (!empty($request->topic)) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.topic', ':topic'));
            $queryBuilder->setParameter('topic', $request->topic);
        }

        if ($request->status !== null) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.status', ":status"));
            $queryBuilder->setParameter('status', $request->status);
        }

        if (!empty($request->userId)) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.user_id', ":user_id"));
            $queryBuilder->setParameter('user_id', $request->userId);
        }
    }

    /**
     * Получить DTO из запроса на чтение
     *
     * @param QueryBuilder $queryBuilder
     * @param PaginateQuery $paginateQuery
     * @return PaginationDataDTO
     * @throws Exception
     * @throws \Exception
     */
    private function getPaginateDTO(QueryBuilder $queryBuilder, PaginateQuery $paginateQuery): PaginationDataDTO
    {
        $items = [];

        $cloneQuery = clone $queryBuilder;

        $queryBuilder->setMaxResults($paginateQuery->perPage);
        $queryBuilder->setFirstResult($paginateQuery->getOffset());

        $cloneQuery->select('COUNT(r.id)');
        $count = $cloneQuery->executeQuery()->fetchOne();
        $result = $queryBuilder->executeQuery()->fetchAllAssociative();

        foreach ($result as $item) {
            $items[] = $this->getRequestDTOByArray($item);
        }
        $lastPage = ceil(($count / $paginateQuery->perPage));

        return new PaginationDataDTO($count, $lastPage, $paginateQuery->page, $items);
    }

    /**
     * Создать dto из массива
     *
     * @param array $item
     * @return RequestDTO
     * @throws \Exception
     */
    private function getRequestDTOByArray(array $item): RequestDTO
    {
        $status = Status::tryFrom($item['status']);
        $dateTime = new DateTime($item['created_at']);

        return new RequestDTO(
            $item['id'],
            $item['topic'],
            $item['message'],
            $item['user_id'],
            $item['email'],
            $dateTime,
            $status,
            $item['comment']
        );
    }
}
 No newline at end of file
+7 −163
Original line number Diff line number Diff line
@@ -2,25 +2,18 @@

namespace App\Infrastructure\Request\Repository;

use App\Domain\Request\DTO\PaginateQuery;
use App\Domain\Request\DTO\PaginationDataDTO;
use App\Domain\Request\DTO\Request\Query\GetRequestsDTO;
use App\Domain\Request\DTO\Request\Response\RequestDTO;
use App\Domain\Request\Entity\Request;
use App\Domain\Request\Interfaces\RequestRepositoryInterface;
use App\Domain\Request\Status\Status;
use DateTime;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Doctrine\ORM\EntityRepository;

class RequestRepository implements RequestRepositoryInterface
{
    private const REQUESTS_TABLE_NAME = 'requests';
    private readonly EntityRepository $repository;

    public function __construct(private readonly EntityManagerInterface $entityManager)
    {
        $this->repository = $this->entityManager->getRepository(Request::class);
    }

    /**
@@ -37,162 +30,13 @@ class RequestRepository implements RequestRepositoryInterface
    }

    /**
     * Все заявки пользователя
     *
     * @param GetRequestsDTO $request
     * @return PaginationDataDTO
     * @throws Exception
     */
    public function getRequests(GetRequestsDTO $request): PaginationDataDTO
    {
        $queryBuilder = $this->getQueryToRequests('r')
            ->leftJoin('r', 'users', 'u', 'u.id = r.user_id');

        $this->parseRequestToQueryCondition($queryBuilder, $request);
        return $this->getPaginateDTO($queryBuilder, $request->pagination);
    }

    /**
     * Получить заявку по идентификатору
     * Поиск по идентификатору
     *
     * @param string $id
     * @param string|null $userId
     * @return RequestDTO|null
     * @throws Exception
     * @throws \Exception
     */
    public function getRequestById(string $id, ?string $userId = null): ?RequestDTO
    {
        if (empty($id)) {
            throw new InvalidArgumentException('Id cannot be empty');
        }

        $queryBuilder = $this->getQueryToRequests('r')
            ->leftJoin('r', 'users', 'u', 'u.id = r.user_id')
            ->setMaxResults(1);

        if ($userId !== null) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.user_id', ":userId"))
                ->setParameter('userId', $userId);
        }

        $queryBuilder->where($queryBuilder->expr()->eq('r.id', ':id'))
            ->setParameter('id', $id);


        $response = $queryBuilder->fetchAssociative();

        if (!$response) {
            return null;
        }

        return $this->getRequestDTOByArray($response);
    }

    /**
     * Получить запрос к таблице запросов
     *
     * @param array $select
     * @param string|null $alias
     * @return QueryBuilder
     */
    private function getQueryToRequests(string $alias = null): QueryBuilder
    {
        $select = [
            'r.id',
            'r.message',
            'r.topic',
            'r.user_id',
            'r.created_at',
            'r.status',
            'r.comment',
            'u.email'
        ];
        $queryBuilder = $this->entityManager->getConnection()->createQueryBuilder();

        $queryBuilder
            ->select($select)
            ->from(self::REQUESTS_TABLE_NAME, $alias);

        return $queryBuilder;
    }

    /**
     * Загрузить условия в объект запроса
     *
     * @param QueryBuilder $queryBuilder
     * @param GetRequestsDTO $request
     * @return void
     */
    private function parseRequestToQueryCondition(QueryBuilder $queryBuilder, GetRequestsDTO $request): void
    {
        if (!empty($request->topic)) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.topic', ':topic'));
            $queryBuilder->setParameter('topic', $request->topic);
        }

        if ($request->status !== null) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.status', ":status"));
            $queryBuilder->setParameter('status', $request->status);
        }

        if (!empty($request->userId)) {
            $queryBuilder->where($queryBuilder->expr()->eq('r.user_id', ":user_id"));
            $queryBuilder->setParameter('user_id', $request->userId);
        }
    }

    /**
     * Получить DTO из запроса на чтение
     *
     * @param QueryBuilder $queryBuilder
     * @param PaginateQuery $paginateQuery
     * @return PaginationDataDTO
     * @throws Exception
     * @throws \Exception
     */
    private function getPaginateDTO(QueryBuilder $queryBuilder, PaginateQuery $paginateQuery): PaginationDataDTO
    {
        $items = [];

        $cloneQuery = clone $queryBuilder;

        $queryBuilder->setMaxResults($paginateQuery->perPage);
        $queryBuilder->setFirstResult($paginateQuery->getOffset());

        $cloneQuery->select('COUNT(r.id)');
        $count = $cloneQuery->executeQuery()->fetchOne();
        $result = $queryBuilder->executeQuery()->fetchAllAssociative();

        foreach ($result as $item) {
            $items[] = $this->getRequestDTOByArray($item);
        }
        $lastPage = ceil(($count / $paginateQuery->perPage));

        return new PaginationDataDTO($count, $lastPage, $paginateQuery->page, $items);
    }

    /**
     * Создать dto из массива
     *
     * @param array $item
     * @return RequestDTO
     * @throws \Exception
     * @return Request|null
     */
    private function getRequestDTOByArray(array $item): RequestDTO
    public function getById(string $id): ?Request
    {
        $status = Status::tryFrom($item['status']);
        $dateTime = new DateTime($item['created_at']);

        return new RequestDTO(
            $item['id'],
            $item['topic'],
            $item['message'],
            $item['user_id'],
            $item['email'],
            $dateTime,
            $status,
            $item['comment']
        );
        return $this->repository->find($id);
    }
}