Skip to content

Commit

Permalink
feat: added /all endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
benborla committed Nov 18, 2023
1 parent 7e5b73d commit 63901aa
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 22 deletions.
24 changes: 14 additions & 10 deletions api/src/Controller/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use App\Repository\FruitRepository;
use Symfony\Component\Routing\Annotation\Route;
use App\Service\FruitAggregator;
use App\Service\FruitDecomulator;

final class IndexController extends AbstractController
{
#[Route('/sync', name: 'fruits_get_all', methods: ['GET'])]
public function all(FruitAggregator $fruit)
#[Route('/', name: 'fruits_get_all', methods: ['GET'])]
public function all(Request $request, FruitRepository $fruits): JsonResponse
{
dd($fruit->sync());
}
$page = (int) $request->get('page');
$orderBy = $request->get('order_by', 'name');
$search = $request->get('search');
$direction = $request->get('direction', 'ASC');

#[Route('/clear', name: 'fruits_clear_all', methods: ['GET'])]
public function clear(FruitDecomulator $fruit)
{
dd($fruit->__invoke());
/** @var \ArrayIterator $result **/
$result = $fruits->all($page, $orderBy, $direction, $search)
->getResults();

return new JsonResponse($result->getArrayCopy());
}
}
113 changes: 113 additions & 0 deletions api/src/Pagination/Paginator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

namespace App\Pagination;

use Doctrine\ORM\QueryBuilder as DoctrineQueryBuilder;
use Doctrine\ORM\Tools\Pagination\CountWalker;
use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator;

final class Paginator
{
final public const PAGE_SIZE = 10;

private int $currentPage;
private int $numResults;

/**
* @var \Traversable<int, object>
*/
private \Traversable $results;

public function __construct(
private readonly DoctrineQueryBuilder $queryBuilder,
private readonly int $pageSize = self::PAGE_SIZE
) {
}

public function paginate(int $page = 1): self
{
$this->currentPage = max(1, $page);
$firstResult = ($this->currentPage - 1) * $this->pageSize;

$query = $this->queryBuilder
->setFirstResult($firstResult)
->setMaxResults($this->pageSize)
->getQuery();

// @INFO: Set Hydration to Array, to fit on JSON response
$query->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);

/** @var array<string, mixed> $joinDqlParts */
$joinDqlParts = $this->queryBuilder->getDQLPart('join');

if (0 === \count($joinDqlParts)) {
$query->setHint(CountWalker::HINT_DISTINCT, false);
}

$paginator = new DoctrinePaginator($query, true);

/** @var array<string, mixed> $havingDqlParts */
$havingDqlParts = $this->queryBuilder->getDQLPart('having');

$useOutputWalkers = \count($havingDqlParts ?: []) > 0;
$paginator->setUseOutputWalkers($useOutputWalkers);

$this->results = $paginator->getIterator();
$this->numResults = $paginator->count();

return $this;
}

public function getCurrentPage(): int
{
return $this->currentPage;
}

public function getLastPage(): int
{
return (int) ceil($this->numResults / $this->pageSize);
}

public function getPageSize(): int
{
return $this->pageSize;
}

public function hasPreviousPage(): bool
{
return $this->currentPage > 1;
}

public function getPreviousPage(): int
{
return max(1, $this->currentPage - 1);
}

public function hasNextPage(): bool
{
return $this->currentPage < $this->getLastPage();
}

public function getNextPage(): int
{
return min($this->getLastPage(), $this->currentPage + 1);
}

public function hasToPaginate(): bool
{
return $this->numResults > $this->pageSize;
}

public function getNumResults(): int
{
return $this->numResults;
}

/**
* @return \Traversable<int, object>
*/
public function getResults(): \Traversable
{
return $this->results;
}
}
32 changes: 20 additions & 12 deletions api/src/Repository/FruitRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
use App\Entity\Fruit;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\ORM\Query;
use App\Pagination\Paginator;

/**
* @extends ServiceEntityRepository<Fruit>
*
* @method \App\Pagination\Paginator all()
* @method Fruit|null find($id, $lockMode = null, $lockVersion = null)
* @method Fruit|null findOneBy(array $criteria, array $orderBy = null)
* @method Fruit[] findAll()
Expand All @@ -22,19 +25,24 @@ public function __construct(ManagerRegistry $registry)
}

/**
* @return Fruit[] Returns an array of Fruit objects
* @return \App\Paginator\Paginator Returns a paginated results of Fruits[]
*/
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('f')
// ->andWhere('f.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('f.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
public function all(
int $page = 1,
string $orderBy = 'name',
string $direction = 'ASC',
string $search = '',
): Paginator {
$qb = $this->createQueryBuilder('f')
->orWhere('f.name LIKE :search')
->orWhere('f.family LIKE :search')
->orWhere('f.genus LIKE :search')
->orWhere('f.fruitOrder LIKE :search')
->orderBy("f.$orderBy", $direction)
->setParameter('search', "%$search%");

return (new Paginator($qb))->paginate($page);
}

/**
* @param string $field The name of the field that you would like to refer to
Expand Down

0 comments on commit 63901aa

Please sign in to comment.