Skip to content

Commit 38cbf7c

Browse files
committed
Create an on sale checker to make the plugin more user-friendly
1 parent 65da8f7 commit 38cbf7c

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

README.md

+34
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,40 @@ class YourFeedProcessor
114114
}
115115
```
116116

117+
## Check if a product is on sale
118+
If you want to check if a product is on sale, e.g. if you want to have a `Sale` category on your store, we have included
119+
a `\Setono\SyliusCatalogPromotionPlugin\Checker\OnSale\OnSaleCheckerInterface` service that checks exactly that:
120+
121+
```php
122+
<?php
123+
124+
use Setono\SyliusCatalogPromotionPlugin\Checker\OnSale\OnSaleCheckerInterface;
125+
use Setono\SyliusCatalogPromotionPlugin\Model\ProductInterface;
126+
127+
class YourFeedProcessor
128+
{
129+
public function __construct(private readonly OnSaleCheckerInterface $onSaleChecker) {
130+
131+
}
132+
133+
public function process(): void
134+
{
135+
/**
136+
* A list of products you are processing
137+
*
138+
* @var list<ProductInterface> $products
139+
*/
140+
$products = [];
141+
142+
foreach ($products as $product) {
143+
if($this->onSaleChecker->onSale($product)) {
144+
// the product is on sale
145+
}
146+
}
147+
}
148+
}
149+
```
150+
117151
[ico-version]: https://poser.pugx.org/setono/sylius-catalog-promotion-plugin/v/stable
118152
[ico-unstable-version]: https://poser.pugx.org/setono/sylius-catalog-promotion-plugin/v/unstable
119153
[ico-license]: https://poser.pugx.org/setono/sylius-catalog-promotion-plugin/license

src/Checker/OnSale/OnSaleChecker.php

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Setono\SyliusCatalogPromotionPlugin\Checker\OnSale;
6+
7+
use Setono\SyliusCatalogPromotionPlugin\Applicator\RuntimePromotionsApplicatorInterface;
8+
use Setono\SyliusCatalogPromotionPlugin\Model\ProductInterface;
9+
use Sylius\Component\Channel\Context\ChannelContextInterface;
10+
use Sylius\Component\Core\Model\ChannelInterface;
11+
use Sylius\Component\Core\Model\ProductVariantInterface;
12+
use Webmozart\Assert\Assert;
13+
14+
final class OnSaleChecker implements OnSaleCheckerInterface
15+
{
16+
public function __construct(
17+
private readonly ChannelContextInterface $channelContext,
18+
private readonly RuntimePromotionsApplicatorInterface $runtimePromotionsApplicator,
19+
) {
20+
}
21+
22+
public function onSale(ProductInterface|ProductVariantInterface $product, ChannelInterface $channel = null): bool
23+
{
24+
$channel = $channel ?? $this->channelContext->getChannel();
25+
Assert::isInstanceOf($channel, ChannelInterface::class);
26+
27+
return match (true) {
28+
$product instanceof ProductInterface => $this->checkProduct($product, $channel),
29+
$product instanceof ProductVariantInterface => $this->checkVariant($product, $channel),
30+
};
31+
}
32+
33+
private function checkProduct(ProductInterface $product, ChannelInterface $channel): bool
34+
{
35+
/** @var ProductVariantInterface $variant */
36+
foreach ($product->getEnabledVariants() as $variant) {
37+
if ($this->checkVariant($variant, $channel)) {
38+
return true;
39+
}
40+
}
41+
42+
return false;
43+
}
44+
45+
private function checkVariant(ProductVariantInterface $variant, ChannelInterface $channel): bool
46+
{
47+
$channelPricing = $variant->getChannelPricingForChannel($channel);
48+
if (null === $channelPricing) {
49+
return false;
50+
}
51+
52+
if ($channelPricing->isPriceReduced()) {
53+
return true;
54+
}
55+
56+
$product = $variant->getProduct();
57+
Assert::isInstanceOf($product, ProductInterface::class);
58+
59+
$appliedPrice = $this->runtimePromotionsApplicator->apply($product, (int) $channelPricing->getPrice(), false);
60+
61+
return $appliedPrice < $channelPricing->getPrice();
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Setono\SyliusCatalogPromotionPlugin\Checker\OnSale;
6+
7+
use Setono\SyliusCatalogPromotionPlugin\Model\ProductInterface;
8+
use Sylius\Component\Core\Model\ChannelInterface;
9+
use Sylius\Component\Core\Model\ProductVariantInterface;
10+
11+
interface OnSaleCheckerInterface
12+
{
13+
/**
14+
* @param ChannelInterface|null $channel if null the channel context will be used
15+
*/
16+
public function onSale(ProductInterface|ProductVariantInterface $product, ChannelInterface $channel = null): bool;
17+
}

src/Resources/config/services/checker.xml

+9
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,14 @@
6868
<service id="Setono\SyliusCatalogPromotionPlugin\Checker\Runtime\EnabledRuntimeChecker">
6969
<tag name="setono_sylius_catalog_promotion.runtime_checker"/>
7070
</service>
71+
72+
<!-- On sale checker -->
73+
<service id="Setono\SyliusCatalogPromotionPlugin\Checker\OnSale\OnSaleCheckerInterface"
74+
alias="Setono\SyliusCatalogPromotionPlugin\Checker\OnSale\OnSaleChecker"/>
75+
76+
<service id="Setono\SyliusCatalogPromotionPlugin\Checker\OnSale\OnSaleChecker">
77+
<argument type="service" id="sylius.context.channel"/>
78+
<argument type="service" id="Setono\SyliusCatalogPromotionPlugin\Applicator\RuntimePromotionsApplicatorInterface"/>
79+
</service>
7180
</services>
7281
</container>

0 commit comments

Comments
 (0)