-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from monsieurbiz/feature/multiple-coupons
Manage multiple coupons in order
- Loading branch information
Showing
18 changed files
with
654 additions
and
3 deletions.
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,33 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Monsieur Biz' Advanced Promotion plugin for Sylius. | ||
* (c) Monsieur Biz <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE.txt | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Entity\Order; | ||
|
||
use Doctrine\ORM\Mapping as ORM; | ||
use MonsieurBiz\SyliusAdvancedPromotionPlugin\Entity\PromotionCouponsAwareTrait; | ||
use Sylius\Component\Core\Model\Order as BaseOrder; | ||
|
||
/** | ||
* @ORM\Entity | ||
* @ORM\Table(name="sylius_order") | ||
*/ | ||
#[ORM\Entity] | ||
#[ORM\Table(name: 'sylius_order')] | ||
class Order extends BaseOrder implements OrderInterface | ||
{ | ||
use PromotionCouponsAwareTrait; | ||
|
||
public function __construct() | ||
{ | ||
parent::__construct(); | ||
$this->initializePromotionCoupons(); | ||
} | ||
} |
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,19 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Monsieur Biz' Advanced Promotion plugin for Sylius. | ||
* (c) Monsieur Biz <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE.txt | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Entity\Order; | ||
|
||
use MonsieurBiz\SyliusAdvancedPromotionPlugin\Entity\PromotionCouponsAwareInterface; | ||
use Sylius\Component\Core\Model\OrderInterface as BaseOrderInterface; | ||
|
||
interface OrderInterface extends BaseOrderInterface, PromotionCouponsAwareInterface | ||
{ | ||
} |
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,42 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Monsieur Biz' Advanced Promotion plugin for Sylius. | ||
* (c) Monsieur Biz <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE.txt | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace App\Migrations; | ||
|
||
use Doctrine\DBAL\Schema\Schema; | ||
use Doctrine\Migrations\AbstractMigration; | ||
|
||
/** | ||
* Auto-generated Migration: Please modify to your needs! | ||
*/ | ||
final class Version20231218092305 extends AbstractMigration | ||
{ | ||
public function getDescription(): string | ||
{ | ||
return ''; | ||
} | ||
|
||
public function up(Schema $schema): void | ||
{ | ||
// this up() migration is auto-generated, please modify it to your needs | ||
$this->addSql('CREATE TABLE monsieurbiz_advanced_promotion_order_promotion_coupon (order_id INT NOT NULL, promotion_coupon_id INT NOT NULL, INDEX IDX_5C4132AF8D9F6D38 (order_id), INDEX IDX_5C4132AF17B24436 (promotion_coupon_id), PRIMARY KEY(order_id, promotion_coupon_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); | ||
$this->addSql('ALTER TABLE monsieurbiz_advanced_promotion_order_promotion_coupon ADD CONSTRAINT FK_5C4132AF8D9F6D38 FOREIGN KEY (order_id) REFERENCES sylius_order (id)'); | ||
$this->addSql('ALTER TABLE monsieurbiz_advanced_promotion_order_promotion_coupon ADD CONSTRAINT FK_5C4132AF17B24436 FOREIGN KEY (promotion_coupon_id) REFERENCES sylius_promotion_coupon (id)'); | ||
} | ||
|
||
public function down(Schema $schema): void | ||
{ | ||
// this down() migration is auto-generated, please modify it to your needs | ||
$this->addSql('ALTER TABLE monsieurbiz_advanced_promotion_order_promotion_coupon DROP FOREIGN KEY FK_5C4132AF8D9F6D38'); | ||
$this->addSql('ALTER TABLE monsieurbiz_advanced_promotion_order_promotion_coupon DROP FOREIGN KEY FK_5C4132AF17B24436'); | ||
$this->addSql('DROP TABLE monsieurbiz_advanced_promotion_order_promotion_coupon'); | ||
} | ||
} |
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,27 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Monsieur Biz' Advanced Promotion plugin for Sylius. | ||
* (c) Monsieur Biz <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE.txt | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MonsieurBiz\SyliusAdvancedPromotionPlugin\Entity; | ||
|
||
use Doctrine\Common\Collections\Collection; | ||
use Sylius\Component\Core\Model\PromotionCouponInterface; | ||
|
||
interface PromotionCouponsAwareInterface | ||
{ | ||
/** @return Collection<array-key, ?PromotionCouponInterface> */ | ||
public function getPromotionCoupons(): Collection; | ||
|
||
public function hasPromotionCoupon(PromotionCouponInterface $promotionCoupon): bool; | ||
|
||
public function addPromotionCoupon(PromotionCouponInterface $promotionCoupon): void; | ||
|
||
public function removePromotionCoupon(PromotionCouponInterface $promotionCoupon): void; | ||
} |
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,65 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Monsieur Biz' Advanced Promotion plugin for Sylius. | ||
* (c) Monsieur Biz <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE.txt | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MonsieurBiz\SyliusAdvancedPromotionPlugin\Entity; | ||
|
||
use Doctrine\Common\Collections\ArrayCollection; | ||
use Doctrine\Common\Collections\Collection; | ||
use Doctrine\ORM\Mapping as ORM; | ||
use Sylius\Component\Core\Model\PromotionCouponInterface; | ||
|
||
trait PromotionCouponsAwareTrait | ||
{ | ||
/** | ||
* @ORM\ManyToMany(targetEntity=PromotionCouponInterface::class) | ||
* @ORM\JoinTable(name="monsieurbiz_advanced_promotion_order_promotion_coupon", | ||
* joinColumns={@ORM\JoinColumn(name="order_id", referencedColumnName="id")}, | ||
* inverseJoinColumns={@ORM\JoinColumn(name="promotion_coupon_id", referencedColumnName="id")} | ||
* ) | ||
* | ||
* @var Collection<array-key, PromotionCouponInterface> | ||
*/ | ||
#[ORM\ManyToMany(targetEntity: PromotionCouponInterface::class)] | ||
#[ORM\JoinTable(name: 'monsieurbiz_advanced_promotion_order_promotion_coupon')] | ||
#[ORM\JoinColumn(name: 'order_id', referencedColumnName: 'id')] | ||
#[ORM\InverseJoinColumn(name: 'promotion_coupon_id', referencedColumnName: 'id')] | ||
private $promotionCoupons; | ||
|
||
private function initializePromotionCoupons(): void | ||
{ | ||
$this->promotionCoupons = new ArrayCollection(); | ||
} | ||
|
||
/** @return Collection<array-key, ?PromotionCouponInterface> */ | ||
public function getPromotionCoupons(): Collection | ||
{ | ||
return $this->promotionCoupons; | ||
} | ||
|
||
public function hasPromotionCoupon(PromotionCouponInterface $promotionCoupon): bool | ||
{ | ||
return $this->promotionCoupons->contains($promotionCoupon); | ||
} | ||
|
||
public function addPromotionCoupon(PromotionCouponInterface $promotionCoupon): void | ||
{ | ||
if (!$this->hasPromotionCoupon($promotionCoupon)) { | ||
$this->promotionCoupons->add($promotionCoupon); | ||
} | ||
} | ||
|
||
public function removePromotionCoupon(PromotionCouponInterface $promotionCoupon): void | ||
{ | ||
if ($this->hasPromotionCoupon($promotionCoupon)) { | ||
$this->promotionCoupons->removeElement($promotionCoupon); | ||
} | ||
} | ||
} |
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,126 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Monsieur Biz' Advanced Promotion plugin for Sylius. | ||
* (c) Monsieur Biz <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE.txt | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MonsieurBiz\SyliusAdvancedPromotionPlugin\Form\Extension; | ||
|
||
use MonsieurBiz\SyliusAdvancedPromotionPlugin\Entity\PromotionCouponsAwareInterface; | ||
use Sylius\Bundle\OrderBundle\Form\Type\CartType; | ||
use Sylius\Bundle\PromotionBundle\Form\Type\PromotionCouponToCodeType; | ||
use Sylius\Component\Core\Model\PromotionCouponInterface; | ||
use Symfony\Component\Form\AbstractTypeExtension; | ||
use Symfony\Component\Form\Extension\Core\Type\CollectionType; | ||
use Symfony\Component\Form\FormBuilderInterface; | ||
use Symfony\Component\Form\FormEvent; | ||
use Symfony\Component\Form\FormEvents; | ||
use Symfony\Component\Form\FormInterface; | ||
use Symfony\Component\OptionsResolver\Options; | ||
use Symfony\Component\OptionsResolver\OptionsResolver; | ||
use Symfony\Component\Validator\Constraints as Assert; | ||
use Symfony\Component\Validator\Context\ExecutionContextInterface; | ||
|
||
final class CartTypeExtension extends AbstractTypeExtension | ||
{ | ||
/** | ||
* @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||
*/ | ||
public function buildForm(FormBuilderInterface $builder, array $options): void | ||
{ | ||
$builder | ||
->add('promotionCoupons', CollectionType::class, [ | ||
'entry_type' => PromotionCouponToCodeType::class, | ||
'entry_options' => [ | ||
'attr' => [ | ||
'form' => 'sylius_cart', | ||
], | ||
'constraints' => [ | ||
new Assert\Callback( | ||
[$this, 'validatePromotionEntry'], | ||
['monsieurbiz_advanced_promotion_coupon'] | ||
), | ||
], | ||
], | ||
'required' => false, | ||
'allow_add' => true, | ||
'allow_delete' => true, | ||
'button_add_label' => 'monsieurbiz_sylius_advanced_promotion.coupons.add_coupon', | ||
'attr' => [ | ||
'class' => 'monsieurbiz-coupons', | ||
], | ||
]) | ||
->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'removeEmptyCouponsOnPreSubmit']) | ||
; | ||
} | ||
|
||
public function validatePromotionEntry(?PromotionCouponInterface $entry, ExecutionContextInterface $context): void | ||
{ | ||
if (null !== $entry) { | ||
return; | ||
} | ||
|
||
$context | ||
->buildViolation('sylius.promotion_coupon.is_invalid') | ||
->addViolation() | ||
; | ||
} | ||
|
||
/** | ||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||
*/ | ||
public function removeEmptyCouponsOnPreSubmit(FormEvent $event): void | ||
{ | ||
$formData = $event->getData(); | ||
if (!\is_array($formData)) { | ||
return; | ||
} | ||
|
||
$promotionCoupons = $formData['promotionCoupons'] ?? []; | ||
if (!empty($promotionCoupons)) { | ||
return; | ||
} | ||
|
||
$order = $event->getForm()->getNormData(); | ||
if (!$order instanceof PromotionCouponsAwareInterface) { | ||
return; | ||
} | ||
|
||
foreach ($order->getPromotionCoupons() as $promotionCoupon) { | ||
if (!$promotionCoupon) { | ||
continue; | ||
} | ||
$order->removePromotionCoupon($promotionCoupon); | ||
} | ||
} | ||
|
||
/** | ||
* @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||
*/ | ||
public function configureOptions(OptionsResolver $resolver): void | ||
{ | ||
$resolver->setNormalizer('validation_groups', fn (Options $options, array $validationGroups) => function (FormInterface $form) use ($validationGroups) { | ||
foreach ($form->get('promotionCoupons') as $promotionCoupon) { | ||
if ((bool) $promotionCoupon->getNormData()) { // Validate the coupon if it was sent | ||
$validationGroups[] = 'monsieurbiz_advanced_promotion_coupon'; | ||
|
||
break; | ||
} | ||
} | ||
|
||
return $validationGroups; | ||
}); | ||
} | ||
|
||
public static function getExtendedTypes(): iterable | ||
{ | ||
return [ | ||
CartType::class, | ||
]; | ||
} | ||
} |
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,33 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Monsieur Biz' Advanced Promotion plugin for Sylius. | ||
* (c) Monsieur Biz <[email protected]> | ||
* For the full copyright and license information, please view the LICENSE.txt | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace MonsieurBiz\SyliusAdvancedPromotionPlugin\Form\Type; | ||
|
||
use Sylius\Bundle\PromotionBundle\Form\Type\PromotionCouponToCodeType; | ||
use Symfony\Component\Form\AbstractType; | ||
use Symfony\Component\Form\FormBuilderInterface; | ||
|
||
final class PromotionCouponType extends AbstractType | ||
{ | ||
/** | ||
* @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||
*/ | ||
public function buildForm(FormBuilderInterface $builder, array $options): void | ||
{ | ||
$builder | ||
->add('promotionCoupon', PromotionCouponToCodeType::class, [ | ||
'label' => 'sylius.form.cart.coupon', | ||
'required' => false, | ||
'by_reference' => false, | ||
]) | ||
; | ||
} | ||
} |
Oops, something went wrong.