Skip to content

Instantly share code, notes, and snippets.

@lionelkouame
Created January 5, 2023 06:57
Show Gist options
  • Save lionelkouame/2c94f722686e586897f5781db00c62a7 to your computer and use it in GitHub Desktop.
Save lionelkouame/2c94f722686e586897f5781db00c62a7 to your computer and use it in GitHub Desktop.
[sylius] - override product repository
# Add "line 8" to change the defaut repository with the own repository
# config/packages/_sylius.yaml
# check the configuration with command:
# symfony console debug:container --parameter=sylius.repository.product.class
sylius_product:
resources:
product:
classes:
model: App\Entity\Product\Product
repository: App\Repository\Product\ProductRepository
<?php
// overrride the ProductRepository of Sylius
//vendor/sylius/sylius/src/Sylius/Bundle/CoreBundle/Doctrine/ORM/ProductRepository.php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Repository\Product;
use App\Entity\User\AdminUser;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\QueryBuilder;
use Sylius\Bundle\ProductBundle\Doctrine\ORM\ProductRepository as BaseProductRepository;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\TaxonInterface;
use SyliusLabs\AssociationHydrator\AssociationHydrator;
final class ProductRepository extends BaseProductRepository
{
private AssociationHydrator $associationHydrator;
public function __construct(EntityManager $entityManager, ClassMetadata $class)
{
parent::__construct($entityManager, $class);
$this->associationHydrator = new AssociationHydrator($entityManager, $class);
}
// add new parameter "$token" to get the current admin user
public function createListQueryBuilder(string $locale, $taxonId = null, $token): QueryBuilder
{
/** @var AdminUser $adminUser */
$adminUser = $token->getuser();
$queryBuilder = $this->createQueryBuilder('o')
->addSelect('translation')
->leftJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
->where('o.isArchived =:isArchived')
->setParameter('locale', $locale)
->setParameter('isArchived', $adminUser->isArchivedMode())
;
if (null !== $taxonId) {
$queryBuilder
->innerJoin('o.productTaxons', 'productTaxon')
->andWhere('productTaxon.taxon = :taxonId')
->setParameter('taxonId', $taxonId)
;
}
return $queryBuilder;
}
public function createShopListQueryBuilder(
ChannelInterface $channel,
TaxonInterface $taxon,
string $locale,
array $sorting = [],
bool $includeAllDescendants = false,
): QueryBuilder {
$queryBuilder = $this->createQueryBuilder('o')
->addSelect('translation')
->addSelect('productTaxon')
->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
->innerJoin('o.productTaxons', 'productTaxon')
;
if ($includeAllDescendants) {
$queryBuilder
->innerJoin('productTaxon.taxon', 'taxon')
->andWhere('taxon.left >= :taxonLeft')
->andWhere('taxon.right <= :taxonRight')
->andWhere('taxon.root = :taxonRoot')
->setParameter('taxonLeft', $taxon->getLeft())
->setParameter('taxonRight', $taxon->getRight())
->setParameter('taxonRoot', $taxon->getRoot())
;
} else {
$queryBuilder
->andWhere('productTaxon.taxon = :taxon')
->setParameter('taxon', $taxon)
;
}
if (empty($sorting)) {
$queryBuilder
->leftJoin('o.productTaxons', 'productTaxons', 'WITH', 'productTaxons.taxon = :taxonId')
->orderBy('productTaxons.position', 'ASC')
->setParameter('taxonId', $taxon->getId())
;
}
$queryBuilder
->andWhere(':channel MEMBER OF o.channels')
->andWhere('o.enabled = :enabled')
->setParameter('locale', $locale)
->setParameter('channel', $channel)
->setParameter('enabled', true)
;
// Grid hack, we do not need to join these if we don't sort by price
if (isset($sorting['price'])) {
// Another hack, the subquery to get the first position variant
$subQuery = $this->createQueryBuilder('m')
->select('min(v.position)')
->innerJoin('m.variants', 'v')
->andWhere('m.id = :product_id')
->andWhere('v.enabled = :enabled')
;
$queryBuilder
->addSelect('variant')
->addSelect('channelPricing')
->innerJoin('o.variants', 'variant')
->innerJoin('variant.channelPricings', 'channelPricing')
->andWhere('channelPricing.channelCode = :channelCode')
->andWhere(
$queryBuilder->expr()->in(
'variant.position',
str_replace(':product_id', 'o.id', $subQuery->getDQL()),
),
)
->setParameter('channelCode', $channel->getCode())
->setParameter('enabled', true)
;
}
return $queryBuilder;
}
public function findLatestByChannel(ChannelInterface $channel, string $locale, int $count): array
{
return $this->createQueryBuilder('o')
->addSelect('translation')
->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
->andWhere(':channel MEMBER OF o.channels')
->andWhere('o.enabled = :enabled')
->addOrderBy('o.createdAt', 'DESC')
->setParameter('channel', $channel)
->setParameter('locale', $locale)
->setParameter('enabled', true)
->setMaxResults($count)
->getQuery()
->getResult()
;
}
public function findOneByChannelAndSlug(ChannelInterface $channel, string $locale, string $slug): ?ProductInterface
{
$product = $this->createQueryBuilder('o')
->addSelect('translation')
->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
->andWhere('translation.slug = :slug')
->andWhere(':channel MEMBER OF o.channels')
->andWhere('o.enabled = :enabled')
->setParameter('channel', $channel)
->setParameter('locale', $locale)
->setParameter('slug', $slug)
->setParameter('enabled', true)
->getQuery()
->getOneOrNullResult()
;
$this->associationHydrator->hydrateAssociations($product, [
'images',
'options',
'options.translations',
'variants',
'variants.channelPricings',
'variants.optionValues',
'variants.optionValues.translations',
]);
return $product;
}
public function findOneByChannelAndCode(ChannelInterface $channel, string $code): ?ProductInterface
{
$product = $this->createQueryBuilder('o')
->where('o.code = :code')
->andWhere(':channel MEMBER OF o.channels')
->andWhere('o.enabled = :enabled')
->setParameter('channel', $channel)
->setParameter('code', $code)
->setParameter('enabled', true)
->getQuery()
->getOneOrNullResult()
;
$this->associationHydrator->hydrateAssociations($product, [
'images',
'options',
'options.translations',
'variants',
'variants.channelPricings',
'variants.optionValues',
'variants.optionValues.translations',
]);
return $product;
}
public function findOneByCode(string $code): ?ProductInterface
{
return $this->createQueryBuilder('o')
->where('o.code = :code')
->setParameter('code', $code)
->getQuery()
->getOneOrNullResult()
;
}
public function findByTaxon(TaxonInterface $taxon): array
{
return $this
->createQueryBuilder('product')
->distinct()
->addSelect('productTaxon')
->innerJoin('product.productTaxons', 'productTaxon')
->andWhere('productTaxon.taxon = :taxon')
->setParameter('taxon', $taxon)
->getQuery()
->getResult()
;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment