-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
398 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
name: Repository Pack | ||
|
||
on: | ||
push: | ||
branches-ignore: | ||
- main | ||
release: | ||
types: [ created ] | ||
schedule: | ||
- | ||
cron: "0 1 * * 6" # Run at 1am every Saturday | ||
workflow_dispatch: | ||
|
||
permissions: | ||
actions: write | ||
contents: write | ||
pull-requests: write | ||
|
||
jobs: | ||
cqrs-pack: | ||
runs-on: ubuntu-latest | ||
|
||
name: "Tests (PHP ${{ matrix.php }})" | ||
|
||
strategy: | ||
fail-fast: false | ||
matrix: | ||
php: ["8.3"] | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: "Setup PHP" | ||
uses: shivammathur/setup-php@v2 | ||
with: | ||
php-version: "${{ matrix.php }}" | ||
ini-values: date.timezone=Europe/Warsaw | ||
extensions: intl, gd, mysql, pdo_mysql, :xdebug | ||
tools: symfony | ||
coverage: none | ||
|
||
- name: "Get Composer cache directory" | ||
id: composer-cache | ||
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT | ||
|
||
- name: "Setup cache" | ||
uses: actions/cache@v3 | ||
with: | ||
path: | | ||
${{ steps.composer-cache.outputs.dir }} | ||
key: ${{ github.run_id }}-${{ runner.os }}-${{ hashFiles('composer.json') }}-symfony-${{ matrix.symfony }} | ||
|
||
- name: "Create test application" | ||
run: | | ||
git config --global user.email "[email protected]" | ||
git config --global user.name "Your Name" | ||
(cd tests/Cqrs && make create-test-application) | ||
id: end-of-setup | ||
|
||
- name: "Lint container" | ||
run: (cd tests/Cqrs/app && bin/console lint:container) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"copy-from-recipe": { | ||
"src/": "%SRC_DIR%/" | ||
} | ||
} |
74 changes: 74 additions & 0 deletions
74
monofony/repository-meta/0.1/src/Infrastructure/Doctrine/DoctrinePaginator.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Shared\Infrastructure\Doctrine; | ||
|
||
use App\Shared\Domain\Repository\PaginatorInterface; | ||
use Doctrine\ORM\Tools\Pagination\Paginator; | ||
|
||
/** | ||
* @template T of object | ||
* | ||
* @implements PaginatorInterface<T> | ||
*/ | ||
final readonly class DoctrinePaginator implements PaginatorInterface | ||
{ | ||
private int $firstResult; | ||
private int $maxResults; | ||
|
||
/** | ||
* @param Paginator<T> $paginator | ||
*/ | ||
public function __construct( | ||
private Paginator $paginator, | ||
) { | ||
$firstResult = $paginator->getQuery()->getFirstResult(); | ||
$maxResults = $paginator->getQuery()->getMaxResults(); | ||
|
||
if (null === $maxResults) { | ||
throw new \InvalidArgumentException('Missing maxResults from the query.'); | ||
} | ||
|
||
$this->firstResult = $firstResult; | ||
$this->maxResults = $maxResults; | ||
} | ||
|
||
public function getItemsPerPage(): int | ||
{ | ||
return $this->maxResults; | ||
} | ||
|
||
public function getCurrentPage(): int | ||
{ | ||
if (0 >= $this->maxResults) { | ||
return 1; | ||
} | ||
|
||
return (int) (1 + floor($this->firstResult / $this->maxResults)); | ||
} | ||
|
||
public function getLastPage(): int | ||
{ | ||
if (0 >= $this->maxResults) { | ||
return 1; | ||
} | ||
|
||
return (int) (ceil($this->getTotalItems() / $this->maxResults) ?: 1); | ||
} | ||
|
||
public function getTotalItems(): int | ||
{ | ||
return count($this->paginator); | ||
} | ||
|
||
public function count(): int | ||
{ | ||
return iterator_count($this->getIterator()); | ||
} | ||
|
||
public function getIterator(): \Traversable | ||
{ | ||
return $this->paginator->getIterator(); | ||
} | ||
} |
116 changes: 116 additions & 0 deletions
116
monofony/repository-meta/0.1/src/Infrastructure/Doctrine/DoctrineRepository.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Shared\Infrastructure\Doctrine; | ||
|
||
use App\Shared\Domain\Repository\PaginatorInterface; | ||
use App\Shared\Domain\Repository\RepositoryInterface; | ||
use Doctrine\ORM\EntityManagerInterface; | ||
use Doctrine\ORM\QueryBuilder; | ||
use Doctrine\ORM\Tools\Pagination\Paginator; | ||
use Webmozart\Assert\Assert; | ||
|
||
/** | ||
* @template T of object | ||
* | ||
* @implements RepositoryInterface<T> | ||
*/ | ||
abstract class DoctrineRepository implements RepositoryInterface | ||
{ | ||
private int|null $page = null; | ||
private int|null $itemsPerPage = null; | ||
|
||
private QueryBuilder $queryBuilder; | ||
|
||
public function __construct( | ||
protected EntityManagerInterface $em, | ||
string $entityClass, | ||
string $alias, | ||
) { | ||
$this->queryBuilder = $this->em->createQueryBuilder() | ||
->select($alias) | ||
->from($entityClass, $alias); | ||
} | ||
|
||
public function getIterator(): \Iterator | ||
{ | ||
if (null !== $paginator = $this->paginator()) { | ||
yield from $paginator; | ||
|
||
return; | ||
} | ||
|
||
yield from $this->queryBuilder->getQuery()->getResult(); | ||
} | ||
|
||
public function count(): int | ||
{ | ||
$paginator = $this->paginator() ?? new Paginator(clone $this->queryBuilder); | ||
|
||
return $paginator->count(); | ||
} | ||
|
||
public function paginator(): PaginatorInterface|null | ||
{ | ||
if (null === $this->page || null === $this->itemsPerPage) { | ||
return null; | ||
} | ||
|
||
$firstResult = ($this->page - 1) * $this->itemsPerPage; | ||
$maxResults = $this->itemsPerPage; | ||
|
||
$repository = $this->filter(static function (QueryBuilder $qb) use ($firstResult, $maxResults) { | ||
$qb->setFirstResult($firstResult)->setMaxResults($maxResults); | ||
}); | ||
|
||
/** @var Paginator<T> $paginator */ | ||
$paginator = new Paginator($repository->queryBuilder->getQuery()); | ||
|
||
return new DoctrinePaginator($paginator); | ||
} | ||
|
||
public function withoutPagination(): static | ||
{ | ||
$cloned = clone $this; | ||
$cloned->page = null; | ||
$cloned->itemsPerPage = null; | ||
|
||
return $cloned; | ||
} | ||
|
||
public function withPagination(int $page, int $itemsPerPage): static | ||
{ | ||
Assert::positiveInteger($page); | ||
Assert::positiveInteger($itemsPerPage); | ||
|
||
$cloned = clone $this; | ||
$cloned->page = $page; | ||
$cloned->itemsPerPage = $itemsPerPage; | ||
|
||
return $cloned; | ||
} | ||
|
||
/** | ||
* @return static<T> | ||
* | ||
* @phpstan-ignore-next-line | ||
*/ | ||
protected function filter(callable $filter): static | ||
{ | ||
$cloned = clone $this; | ||
$filter($cloned->queryBuilder); | ||
|
||
return $cloned; | ||
} | ||
|
||
protected function query(): QueryBuilder | ||
{ | ||
return clone $this->queryBuilder; | ||
} | ||
|
||
protected function __clone() | ||
{ | ||
$this->queryBuilder = clone $this->queryBuilder; | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
monofony/repository-meta/0.1/src/Infrastructure/Pagerfanta/PagerfantaPaginator.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Shared\Infrastructure\Pagerfanta; | ||
|
||
use App\Shared\Domain\Repository\PaginatorInterface; | ||
use Pagerfanta\PagerfantaInterface; | ||
|
||
final class PagerfantaPaginator implements PaginatorInterface | ||
{ | ||
public function __construct( | ||
private PagerfantaInterface $pagerfanta, | ||
) { | ||
} | ||
|
||
public function getIterator(): \Traversable | ||
{ | ||
return $this->pagerfanta->getIterator(); | ||
} | ||
|
||
public function count(): int | ||
{ | ||
return iterator_count($this->pagerfanta->getIterator()); | ||
} | ||
|
||
public function getCurrentPage(): int | ||
{ | ||
return $this->pagerfanta->getCurrentPage(); | ||
} | ||
|
||
public function getItemsPerPage(): int | ||
{ | ||
return $this->pagerfanta->getMaxPerPage(); | ||
} | ||
|
||
public function getLastPage(): int | ||
{ | ||
return $this->pagerfanta->getNbPages(); | ||
} | ||
|
||
public function getTotalItems(): int | ||
{ | ||
return $this->pagerfanta->getNbResults(); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
monofony/repository-meta/0.1/src/Shared/Domain/Repository/PaginatorInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Shared\Domain\Repository; | ||
|
||
/** | ||
* @template T of object | ||
* | ||
* @extends \IteratorAggregate<array-key, T> | ||
*/ | ||
interface PaginatorInterface extends \IteratorAggregate, \Countable | ||
{ | ||
public function getCurrentPage(): int; | ||
|
||
public function getItemsPerPage(): int; | ||
|
||
public function getLastPage(): int; | ||
|
||
public function getTotalItems(): int; | ||
} |
32 changes: 32 additions & 0 deletions
32
monofony/repository-meta/0.1/src/Shared/Domain/Repository/RepositoryInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Shared\Domain\Repository; | ||
|
||
/** | ||
* @template T of object | ||
* | ||
* @extends \IteratorAggregate<array-key, T> | ||
*/ | ||
interface RepositoryInterface extends \IteratorAggregate, \Countable | ||
{ | ||
/** | ||
* @return \Iterator<T> | ||
*/ | ||
public function getIterator(): \Iterator; | ||
|
||
public function count(): int; | ||
|
||
/** | ||
* @return PaginatorInterface<T>|null | ||
*/ | ||
public function paginator(): PaginatorInterface|null; | ||
|
||
/** | ||
* @return static<T> | ||
* | ||
* @phpstan-ignore-next-line | ||
*/ | ||
public function withPagination(int $page, int $itemsPerPage): static; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "monofony/repository-meta", | ||
"type": "metapackage", | ||
"license": "MIT", | ||
"description": "A meta package providing recipes for repositories" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "monofony/repository-pack", | ||
"description": "Pack for repositories", | ||
"type": "symfony-pack", | ||
"license": "MIT", | ||
"require": { | ||
"php": "^8.3", | ||
"doctrine/orm": "*", | ||
"monofony/repository-meta": "*", | ||
"pagerfanta/core": "*" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
app |
Oops, something went wrong.