<?php
declare(strict_types=1);
namespace Juki\Bundle\AppBundle\EventListener;
use Doctrine\Common\Util\Debug;
use Doctrine\ORM\EntityManagerInterface;
use Faker\Factory;
use Hitso\Bundle\CatalogBundle\Entity\Category;
use Hitso\Bundle\CatalogBundle\Entity\Product;
use Hitso\Bundle\CommonBundle\Doctrine\Event\EntityEvent;
use Hitso\Bundle\CommonBundle\Doctrine\Repository\EntityRepository;
use Hitso\Bundle\CommonBundle\Form\Type\LinkType;
use Juki\Bundle\AppBundle\Entity\Dictionary\FeatureHsm;
use Juki\Bundle\AppBundle\Form\Type\AccessoryType;
use Hitso\Bundle\CommonBundle\Form\Type\KeyValueUnitType;
use Hitso\Bundle\CommonBundle\Form\Type\RepeatableTextCollectionType;
use Hitso\Bundle\CommonBundle\Form\Type\RepeatableTextType;
use Hitso\Bundle\CommonBundle\Form\Type\TableCollectionType;
use Hitso\Bundle\CommonBundle\Helper\Request\RequestHelper;
use Hitso\Bundle\ContentBundle\Entity\Article;
use Hitso\Bundle\FormBundle\Event\FormEvent;
use Hitso\Bundle\FormBundle\Form\Conditions\Equals;
use Hitso\Bundle\FormBundle\Form\Dependencies\Show;
use Hitso\Bundle\FormBundle\Form\Type\ImageType;
use Juki\Bundle\AppBundle\Entity\Dictionary\Device;
use Juki\Bundle\AppBundle\Entity\Dictionary\Feature;
use Juki\Bundle\AppBundle\Entity\Dictionary\ProductAccessory;
use Juki\Bundle\AppBundle\Entity\Dictionary\Shop;
use Juki\Bundle\AppBundle\Event\ProductDisplayEvent;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Count;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Url;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
final class ProductSubscriber implements EventSubscriberInterface
{
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var RequestHelper
*/
private $requestHelper;
/**
* ProductSubscriber constructor.
*
* @param EntityManagerInterface $entityManager
* @param RequestHelper $requestHelper
*/
public function __construct(EntityManagerInterface $entityManager, RequestHelper $requestHelper)
{
$this->entityManager = $entityManager;
$this->requestHelper = $requestHelper;
}
public static function getSubscribedEvents()
{
return [
'product.pre_create' => 'onPreCreate',
'product_type.form_init' => 'onProductFormInit',
'product.display' => 'onProductDisplay',
FormEvents::PRE_SUBMIT => 'onProductFormSubmit',
];
}
public function onPreCreate(EntityEvent $event): void
{
$product = $event->getEntity();
if ($product instanceof Product) {
$categories = $product->getCategories();
if ($categories) {
$category = $categories[0];
if ($category) {
$position = 0;
$result = $this->entityManager->getRepository(Product::class)
->createQueryBuilder('p')
->select('MAX(p.position) AS max_position')
->innerJoin('p.categories', 'c')
->where('c.id = :category')
->setParameter('category', $category->getId())
->orderBy('p.id', 'asc')
->getQuery()
->getSingleResult();
$product->setPosition((int)$result['max_position'] + 1);
}
}
}
}
public function onProductFormSubmit(FormEvent $event)
{
/** @var Product $product */
$product = $event->getBuilder()->getData();
$form = $event->getBuilder()->getForm();
//if ($product->getShopType() === Shop::TYPE_ISM) {
// $product->setShops([Shop::ISM_SYMBOL]);
// $event->getBuilder()->get('shops')->setData([Shop::ISM_SYMBOL]);
//}
}
public function onProductFormInit(FormEvent $event)
{
$builder = $event->getBuilder();
$options = $builder->getOptions();
$product = $builder->getData();
$builder->add(
'shopType',
ChoiceType::class,
[
'label' => 'Typ',
'required' => true,
'choices' => [
'ISM' => Shop::TYPE_ISM,
'HSM' => Shop::TYPE_HSM,
],
'position' => ['before' => 'name'],
// 'source' => $builder->get('series')->getName(),
// 'form' => $builder->getForm()->getName(),
// 'condition' => new Equals(Shop::TYPE_HSM),
]
);
$choices = [];
$result = $this->entityManager->getRepository(Shop::class)->findBy([], ['name' => 'ASC']);
foreach ($result as $shop) {
$choices[$shop->getName() . ' - ' . $shop->getShopNameByType()] = $shop->getSymbol();
}
//if ($builder->get('shopType')->getData() === Shop::TYPE_ISM) {
// $product->setShops([Shop::ISM_SYMBOL]);
//}
$builder->add(
'shops',
ChoiceType::class,
[
'label' => 'Sklepy',
'required' => true,
'translation_domain' => 'admin',
'multiple' => true,
'expanded' => true,
'choices' => $choices,
'empty_data' => Shop::ISM_SYMBOL,
'position' => ['after' => 'shopType'],
'constraints' => [
new Count([
'min' => 1,
'minMessage' => 'Musisz wybrać przynajmniej 1 sklep',
]),
],
/*
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_HSM),
]),
],
*/
]
);
// if ($builder->get('shopType')->getData() === Shop::TYPE_ISM) {
// $builder->get('shops')->setData([Shop::ISM_SYMBOL]);
// }
$builder->add(
'excerpt',
TextareaType::class,
[
'label' => 'Zajawka',
'required' => false,
'empty_data' => '',
'position' => ['before' => 'shortDescription'],
'constraints' => [new Length(['max' => 255])],
]
);
$builder->add(
'series',
CheckboxType::class,
[
'label' => 'Produkt jest serią',
'required' => false,
'position' => ['after' => 'standardAccessories'],
'dependencies' => [],
]
);
$builder->add(
'seriesProducts',
EntityType::class,
[
'class' => Product::class,
'label' => 'Produkty w serii',
'choice_label' => 'name',
'multiple' => true,
'expanded' => false,
'required' => false,
'attr' => ['class' => 'select2-custom'],
'position' => ['after' => 'series'],
'dependencies' => [
new Show([
'source' => $builder->get('series')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(1),
]),
],
'constraints' => [
new Callback([
'callback' => function ($object, ExecutionContextInterface $context) {
$series = $context->getRoot()->get('series')->getData();
if ((bool)$series === true && $object->count() === 0) {
$context->buildViolation('Musisz wybrać minimum 1 produkt w serii.')
->atPath('seriesProducts')
->addViolation();
}
},
]),
],
]
);
$builder->add(
'devices',
EntityType::class,
[
'class' => Device::class,
'label' => 'Powiązane dodatki (ISM only)',
'choice_label' => 'model',
'multiple' => true,
'expanded' => false,
'required' => false,
'attr' => ['class' => 'select2-custom'],
'position' => ['after' => 'photos'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_ISM),
]),
],
]
);
$builder->add(
'features',
EntityType::class,
[
'class' => Feature::class,
'label' => 'Powiązane funkcje',
'choice_label' => 'cmsName',
'multiple' => true,
'expanded' => false,
'required' => false,
'attr' => ['class' => 'select2-custom'],
'position' => ['after' => 'devices'],
]
);
$builder->add(
'relatedProducts',
EntityType::class,
[
'class' => Product::class,
'label' => 'Powiązane produkty',
'choice_label' => 'name',
'multiple' => true,
'expanded' => false,
'required' => false,
'attr' => ['class' => 'select2-custom'],
'position' => ['after' => 'photos'],
]
);
$builder->add(
'relatedArticles',
EntityType::class,
[
'class' => Article::class,
'label' => 'Powiązane artykuły',
'choice_label' => 'title',
'multiple' => true,
'expanded' => false,
'required' => false,
'attr' => ['class' => 'select2-custom'],
'position' => ['after' => 'relatedProducts'],
]
);
$builder->add(
'subTitle',
TextType::class,
[
'label' => 'Podtytuł (ISM only)',
'required' => false,
'empty_data' => '',
'position' => ['after' => 'name'],
'constraints' => [new Length(['max' => 255])],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_ISM),
]),
],
]
);
$builder->add(
'label',
ChoiceType::class,
[
'label' => 'Plakietka (HSM only)',
'required' => false,
'empty_data' => '',
'choices' => [
'---' => '',
'best for start (zielona)' => 'best_for_start',
'advanced (żółta)' => 'advanced',
'best deal (niebieska)' => 'best_deal',
],
'position' => ['after' => 'subTitle'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_HSM),
]),
],
]
);
$builder->add(
'layoutColour',
ChoiceType::class,
[
'label' => 'Wariant kolorystyczny (HSM only)',
'required' => false,
'empty_data' => '',
'choices' => [
'---' => '',
'błękitny' => 'blue',
'żółty' => 'yellow',
'różowy' => 'pink',
],
'position' => ['after' => 'label'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_HSM),
]),
],
]
);
$builder->add(
'accessories',
EntityType::class,
[
'class' => ProductAccessory::class,
'label' => 'Powiązane akcesoria (HSM only)',
'choice_label' => 'cmsName',
'multiple' => true,
'expanded' => false,
'required' => false,
'attr' => ['class' => 'select2-custom'],
'position' => ['after' => 'devices'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_HSM),
]),
],
]
);
$builder->add(
'featuresHsm',
EntityType::class,
[
'class' => FeatureHsm::class,
'label' => 'Powiązane cechy (HSM only)',
'choice_label' => 'name',
'multiple' => true,
'expanded' => false,
'required' => false,
'attr' => ['class' => 'select2-custom'],
'position' => ['after' => 'devices'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_HSM),
]),
],
]
);
$builder->add(
'slogan',
TextType::class,
[
'label' => 'Pogrubiony slogan (ISM only)',
'required' => false,
'empty_data' => '',
'position' => ['after' => 'subTitle'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_ISM),
]),
],
]
);
$builder->add(
'extraProperties',
TableCollectionType::class, [
'label' => 'Cechy produktu (ISM only)',
'entry_type' => KeyValueUnitType::class,
'required' => false,
'allow_add' => true,
'allow_delete' => true,
'row_attr' => [
'class' => 'fb-table',
],
'position' => ['before' => 'seoMetadata'],
'disabled' => $options['disabled'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_ISM),
]),
],
]);
$builder->add(
'videos',
RepeatableTextCollectionType::class,
[
'label' => 'Linki video',
'entry_type' => RepeatableTextType::class,
'allow_add' => true,
'allow_delete' => true,
'empty_data' => [''],
'entry_options' => [
'constraints' => [
new Url(['relativeProtocol' => false]),
],
],
'position' => ['after' => 'extraProperties'],
]
);
$builder->add(
'standardAccessories',
RepeatableTextCollectionType::class,
[
'label' => 'Standardowe akcesoria (HSM only)',
'entry_type' => RepeatableTextType::class,
'allow_add' => true,
'allow_delete' => true,
'empty_data' => [''],
'entry_options' => [
'constraints' => [
new NotNull(),
],
],
'position' => ['after' => 'description'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_HSM),
]),
],
]
);
$builder->add(
'published',
CheckboxType::class,
[
'label' => 'Opublikowany',
'required' => false,
'position' => ['after' => 'slogan'],
'disabled' => $options['disabled'],
]
);
$builder->remove('brand');
$builder->remove('taxRate');
$builder->remove('netAmount');
$builder->remove('currencyCode');
$builder->remove('enabled');
$builder->setRequired(false);
$builder->remove('photo');
$builder->add(
'photo',
ImageType::class,
[
'label' => 'Zdjęcie',
'config_name' => 'product_image',
'required' => false,
'hotspot_enabled' => $product->getId() > 0,
'hotspot_resource_name' => 'product',
'hotspot_resource_id' => $product->getId(),
'position' => ['after' => 'seriesProducts'],
'constraints' => [
new Callback([
'callback' => function ($object, ExecutionContextInterface $context) {
$series = $context->getRoot()->get('series')->getData();
if ((bool)$series === true && is_null($object)) {
$context->buildViolation('Zdjęcie jest wymagane, gdyż produkt jest serią')
->addViolation();
}
},
]),
],
]
);
$builder
->remove('photos')
->add(
'photos',
ImageType::class,
[
'label' => 'Zdjęcia dodatkowe (ISM only)',
'config_name' => 'product_images',
'multiple' => true,
'disabled' => $options['disabled'],
'hotspot_enabled' => $product->getId() > 0,
'hotspot_resource_name' => 'product',
'hotspot_resource_id' => $product->getId(),
'position' => ['after' => 'photo'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_ISM),
]),
],
]
);
$builder
->remove('category')
->add(
'category',
EntityType::class,
[
'class' => Category::class,
'label' => 'Kategoria główna',
'choice_label' => 'pathAsString',
'multiple' => false,
'expanded' => false,
'attr' => ['class' => 'select2-custom'],
'query_builder' => function (EntityRepository $repo) {
return $repo->createQueryBuilder('c')->andWhere('c.parent IS NULL');
},
'position' => ['before' => 'categories'],
]
);
$builder
->remove('categories')
->add(
'categories',
EntityType::class,
[
'class' => Category::class,
'label' => 'Kategorie dodatkowe (ISM only)',
'choice_label' => 'name',
'required' => false,
'multiple' => true,
'expanded' => false,
'attr' => ['class' => 'select2-custom'],
// 'choices' => $product->getCategory()->getChildren(),
'query_builder' => function (\Doctrine\ORM\EntityRepository $repo) {
return $repo->createQueryBuilder('c')->andWhere('c.parent IS NOT NULL');
},
'position' => ['before' => 'extraProperties'],
'dependencies' => [
new Show([
'source' => $builder->get('shopType')->getName(),
'form' => $builder->getForm()->getName(),
'condition' => new Equals(Shop::TYPE_ISM),
]),
],
]
);
if ($product->getId()) {
$builder->get('actions')->add('edit_files', LinkType::class, [
'label' => 'Edytuj pliki',
'position' => ['after' => 'edit_attributes'],
'route' => 'juki_product_attachment_admin_index',
'route_params' => ['id' => $product->getId()],
'target' => '_blank',
'attr' => [
'class' => 'btn-right',
],
]);
}
if ($builder->get('shopType')->getData() === Shop::TYPE_ISM) {
$product->setShops([Shop::ISM_SYMBOL]);
}
}
public function onProductDisplay(ProductDisplayEvent $event)
{
$product = $event->getProduct();
if (false === $this->requestHelper->getSessionAttribute('product_display_' . $product->getId(), false)) {
$product->setDisplayCounter($product->getDisplayCounter() + 1);
$this->entityManager->persist($product);
$this->entityManager->flush();
$this->requestHelper->setSessionAttribute('product_display_' . $product->getId(), true);
}
// if ($product->getShopType() === Shop::TYPE_ISM) {
// $product->setShops([Shop::ISM_SYMBOL]);
// }
}
}