silpo-tech/odm-bundle

Common ODM bundle

Installs: 41

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

Type:symfony-bundle

pkg:composer/silpo-tech/odm-bundle

v2.0.0 2025-10-03 09:06 UTC

This package is auto-updated.

Last update: 2025-10-03 09:08:32 UTC


README

CI codecov License: MIT

About

The ODM Bundle contains common used ODM classes (e.g. Validators)

Installation

Require the bundle and its dependencies with composer:

$ composer require silpo-tech/odm-bundle

Register the bundle:

// project/config/bundles.php

return [
    ODMBundle\ODMBundle::class => ['all' => true],
];

Examples

FilterValueResolver

Add converter annotation to argument for your dto

     public function __invoke(#[OdmFilterMapper] ExternalCategoryFilterDto $dto)
class ExternalCategoryFilterDto
{
    public $externalId;
    public $title;
    public $mappings;

    /**
     * @Assert\Type("array")
     * @Assert\Choice(multiple=true, choices={"title", "-title", "createdAt", "-createdAt"})
     *
     * @var array
     */
    public $sort = ['title'];
}

AbstractBuilderAwareFilter

Extend your filter class with AbstractBuilderAwareFilter and implement filtration methods. Sorting implementation is defined in AbstractBuilderAwareFilter and will be called if $dto->sort is not empty

class ExternalCategoryFilter extends AbstractBuilderAwareFilter
{
    protected function aggregationTitle(MatchStage $match, $value): void
    {
        $match->field('title')->equals(new Regex(sprintf('^.*%s.*$', $value), 'i'));
    }

    protected function aggregationExternalId(MatchStage $match, string $value): void
    {
        $match->field('externalId')->equals($value);
    }
    
    protected function aggregationCreatedAt(MatchStage $match, array $value): void
    {
        $this->aggregationFilterDate($match, $value, 'createdAt', true);
    }

    protected function aggregationMappings(MatchStage $match, bool $value): void
    {
        $field = $match->lookup('mappings')->match()->field('mappings');
        $value ? $field->not($match->expr()->size(0)) : $field->size(0);
    }
    
    protected function queryTitle(QueryBuilder $qb, $value): void
    {
        $qb->field('title')->equals(new Regex(sprintf('^.*%s.*$', $value), 'i'));
    }

    protected function queryExternalId(QueryBuilder $qb, string $value): void
    {
        $qb->field('externalId')->equals($value);
    }
    
    protected function queryCreatedAt(QueryBuilder $qb, array $value): void
    {
        $this->queryFilterDate($qb, $value, 'createdAt', true);
    }
}

Call filtration from repository

        //$qb = $this->createQueryBuilder();
        $qb = $this->createAggregationBuilder()->hydrate(ExternalCategory::class);

        (new ExternalCategoryFilter())->filter($qb, $filterDto);

Paginator

        //$qb = $this->createQueryBuilder();
        $qb = $this->createAggregationBuilder()->hydrate(ExternalCategory::class);

        return (new BuilderAwarePaginator())->paginate($qb, $paginationDto);
    public function listAction(OffsetPaginator $paginationDto): Response
    {
        $result = $this->repository->paginate($paginationDto);

        return $this->createPaginatedCollectionResponse(
            $result->total,
            $this->mapper->convertCollection($result->items, ResponseExternalCategoryDto::class),
            $paginationDto
        );
    }

Validator

/**
 * @Assert\GroupSequence({"ExternalCategoryMappingDto", "ODM"})
 * @OdmExists(
 *     documentClass="App\Document\ExternalCategory",
 *     fields={"externalCategoryId":"_id"},
 *     errorPath="externalCategory"
 * )
 * @OdmNotExists(
 *     documentClass="App\Document\ExternalCategoryMapping",
 *     fields={
 *      "categoryId":"categoryId",
 *      "externalCategoryId":"externalCategory",
 *      "externalBrandId":"externalBrand"
 *     },
 *     ignoreNull=false,
 *     errorPath="externalCategoryMapping"
 * )
 *
 */
class ExternalCategoryMappingDto {
    /**
     * @ValidDateRange(format="Y-m-d", allowEqual=true),
     *
     * @var array with keys ['from', 'to']
     */
    public $createdAt;
}