Rulebuilder - Eigene Felder erstellen

Guten Tag liebe Shopware-Community,

Ich bin am entwickeln eines eigenen Plugins, welches die Rulebuilder-Felder um mein eigenes Erweitern soll.

Mein Feld wird mir auch im Backend bei den Rules erfolgreich angezeigt und speichern lässt sich das ganze auch, nur leider scheine ich irgendwo noch einen Fehler zu haben, da meine Regel nicht greift.

Ich bin leider in diesem Bereich noch etwas neu und freue mich über jede Hilfe.

Ich habe die Regel „LineItemWithQuantityRule.php“ und „LineItemInProductStream.php“ von Shopware als Basis genommen.
Pfade (Shopware/src/Core/Checkout/Cart/Rule/LineItemWithQuantityRule.php), (Shopware/src/Core/Checkout/Cart/Rule/LineItemInProductStream.php)

Ich möchte, dass meine Regel am Ende zählt wie viele Produkte im Warenkorb in einer bestimmten Dynamischen Produktgruppe sind.

Also ungefähr so:
mind. eine Größer/gleich <2>

Das soll später für Staffelrabatte funktionieren, sodass man sagen kann, wenn mehr als 2 Produkte in der Dynamischen Produktgruppe XY sind (dieser Teil ist der, der mir noch fehlt), dann greift → Staffelrabatt XY

Ich glaube das meine Datei …CartProcessor.php noch fehlerhaft ist und eventuell sogar auch die Regel ansich…

Hat da vielleicht jemand einen Tipp für mich? Ich würde mich riesig um ein wenig Hilfe freuen.

Hier der aktuelle Code aus meinen Dateien.

…CartProcessor.php

<?php declare(strict_types=1);

namespace Bergmann\MoreRules\Core\Content\Product\Cart;

use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartBehavior;
use Shopware\Core\Checkout\Cart\CartDataCollectorInterface;
use Shopware\Core\Checkout\Cart\CartProcessorInterface;
use Shopware\Core\Checkout\Cart\Delivery\Struct\DeliveryInformation;
use Shopware\Core\Checkout\Cart\Delivery\Struct\DeliveryTime;
use Shopware\Core\Checkout\Cart\Exception\MissingLineItemPriceException;
use Shopware\Core\Checkout\Cart\LineItem\CartDataCollection;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
use Shopware\Core\Checkout\Cart\LineItem\QuantityInformation;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\ReferencePriceDefinition;
use Shopware\Core\Content\Product\SalesChannel\Price\AbstractProductPriceCalculator;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\AndFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\OrFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\Feature;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\System\SalesChannel\SalesChannelContext;

class BergmannMoreRulesCartProcessor implements CartProcessorInterface, CartDataCollectorInterface
{
    public const LINE_ITEM_ALLOWED_TYPE = [
        LineItem::PRODUCT_LINE_ITEM_TYPE,
    ];

    private ProductGatewayInterface $productGateway;

    private QuantityPriceCalculator $calculator;

    private ProductFeatureBuilder $featureBuilder;

    private AbstractProductPriceCalculator $priceCalculator;

    private EntityCacheKeyGenerator $generator;

    private SalesChannelRepositoryInterface $repository;

    public function __construct(
        ProductGatewayInterface $productGateway,
        QuantityPriceCalculator $calculator,
        ProductFeatureBuilder $featureBuilder,
        AbstractProductPriceCalculator $priceCalculator,
        EntityCacheKeyGenerator $generator,
        SalesChannelRepositoryInterface $repository
    ) {
        $this->productGateway = $productGateway;
        $this->calculator = $calculator;
        $this->featureBuilder = $featureBuilder;
        $this->priceCalculator = $priceCalculator;
        $this->generator = $generator;
        $this->repository = $repository;
    }

    public function collect(
        CartDataCollection $data,
        Cart $original,
        SalesChannelContext $context,
        CartBehavior $behavior
    ): void {
        $lineItems = $original
            ->getLineItems();
            ->filterFlatByType(LineItem::PRODUCT_LINE_ITEM_TYPE);

        foreach ($lineItems as $lineItem) {
            $id = $lineItem->getReferencedId() && $lineItem->getPayloadValue('parentId');

            $streamIds = $lineItem->getPayloadValue('streamIds');

            $quantity = $lineItem->getQuantity();
        }
    }
    
}


…Rule.php

<?php declare(strict_types=1);

namespace Bergmann\MoreRules\Core\Checkout\Cart\Rule;

use Shopware\Core\Checkout\Cart\Exception\PayloadKeyNotFoundException;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Framework\Rule\Exception\UnsupportedOperatorException;
use Shopware\Core\Framework\Rule\Rule;
use Shopware\Core\Framework\Rule\RuleScope;
use Shopware\Core\Framework\Validation\Constraint\ArrayOfUuid;
use Shopware\Core\Framework\Validation\Constraint\Uuid;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Type;

class CartLineItemGroupCountRule extends Rule
{
    /**
     * @var string[]
     */
    protected array $streamIds;

    protected ?int $quantity;

    protected string $operator;

    public function __construct(string $operator = self::OPERATOR_EQ, array $streamIds = [], ?int $quantity = null)
    {
        parent::__construct();

        $this->operator = $operator;
        $this->streamIds = $streamIds;
        $this->quantity = $quantity;
    }

    /**
     * @throws UnsupportedOperatorException
     */
    public function match(RuleScope $scope): bool
    {
        if ($scope instanceof LineItemScope) {
            return $this->matchesOneOfProductStream($scope->getLineItem());
        }

        if (!$scope instanceof CartRuleScope) {
            return false;
        }

        foreach ($scope->getCart()->getLineItems()->getFlat() as $lineItem) {
            if ($this->matchesOneOfProductStream($lineItem)) {
                return true;
            }
        }

        return false;
    }

    public function getConstraints(): array
    {
        $constraints = [
            'quantity' => [new NotBlank(), new Type('int')],
            'operator' => [
                new NotBlank(),
                new Choice(
                    [
                        self::OPERATOR_EQ,
                        self::OPERATOR_LTE,
                        self::OPERATOR_GTE,
                        self::OPERATOR_NEQ,
                        self::OPERATOR_GT,
                        self::OPERATOR_LT,
                    ]
                ),
            ],
        ];

        if ($this->operator === self::OPERATOR_EMPTY) {
            return $constraints;
        }

        $constraints['streamIds'] = [new NotBlank(), new ArrayOfUuid()];

        return $constraints;
    }

    public function getName(): string
    {
        return 'cartLineItemGroupCountRule';
    }

    /**
     * @throws UnsupportedOperatorException
     * @throws PayloadKeyNotFoundException
     */
    private function matchesOneOfProductStream(LineItem $lineItem): bool
    {
        $streamIds = (array) $lineItem->getPayloadValue('streamIds');

        $matches = array_intersect($streamIds, $this->streamIds);

        if ($lineItem->getReferencedId() !== $this->id && $lineItem->getPayloadValue('parentId') !== $this->id) {
            return false;
        }

        if ($this->quantity === null) {
            return true;
        }

        switch ($this->operator) {
            case self::OPERATOR_GTE:
                return $quantity >= $this->quantity;

            case self::OPERATOR_LTE:
                return $quantity <= $this->quantity;

            case self::OPERATOR_GT:
                return $quantity > $this->quantity;

            case self::OPERATOR_LT:
                return $quantity < $this->quantity;

            case self::OPERATOR_EQ:
                return $quantity === $this->quantity;

            case self::OPERATOR_NEQ:
                return $quantity !== $this->quantity;

            default:
                throw new UnsupportedOperatorException($this->operator, self::class);
        }
    }
}