Reputation: 9465
I want to customize (or fully override if needed) some Symfony workflows which are defined in a vendor package.
With the Symfony configuration merging strategy, it's easy to add some workflow places, transitions, etc... But is it possible to remove them? The most important is to be able to remove transitions, as unreachable places are not a problem.
Let's say we have this vendor workflow:
framework:
workflows:
vendor_workflow:
# ...
places:
- one
- two
- three
transitions:
to_two:
from: [one]
to: two
to_three:
from: [one, two]
to: three
Then how is it possible to:
to_two
,from: one
for transition to_three
,one
,Which would result to this config:
framework:
workflows:
vendor_workflow:
# ...
places:
- two
- three
transitions:
to_three:
from: [two]
to: three
I tried to add a compiler pass to mutate the unmerged Symfony config of the framework
extension, by removing all the $frameworkConfig['workflows']['vendor_workflow']
keys, but the container builder does not allow to mutate the unmerged config (it only allows to prepend configs with $container->prependExtensionConfig()
)
The vendor is Sylius 1.13, by using the Symfony workflow adapter, and I'm trying to simplify the sylius_order_checkout
workflow by removing everything related to shipping:
shipping_selected
and shipping_skipped
;skip_shipping
and select_shipping
.Upvotes: 0
Views: 93
Reputation: 86
Using a CompilerPass
, you can redefine every states or transition by doing this:
<?php
declare(strict_types=1);
namespace App\DependencyInjection\Compiler;
use Sylius\Component\Core\OrderCheckoutStates;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class SyliusOrderCheckoutStateMachineCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
$graph = OrderCheckoutTransitions::GRAPH;
$addressTransition = OrderCheckoutTransitions::TRANSITION_ADDRESS;
// Override the symfony/workflow to reduce the transitions on "addressed" transition from "address" and "cart"
$definition = $container->getDefinition(sprintf('state_machine.%s.definition', $graph));
/** @var Reference[] $transitionReferences */
$transitionReferences = $definition->getArgument(1);
$this->removeTransitionForState(
OrderCheckoutStates::STATE_ADDRESSED,
$container,
$transitionReferences,
$graph,
$addressTransition,
);
$this->removeTransitionForState(
OrderCheckoutStates::STATE_CART,
$container,
$transitionReferences,
$graph,
$addressTransition,
);
$definition->replaceArgument(1, $transitionReferences);
}
protected function removeTransitionForState(
string $targetedState,
ContainerBuilder $container,
array &$transitionReferences,
string $graph,
string $transition,
): void {
$indexFound = null;
foreach ($transitionReferences as $i => $transitionReference) {
$transitionReference = $container->getDefinition((string) $transitionReference);
if ($transition !== $transitionReference->getArgument(0)) {
continue;
}
if ($targetedState !== $transitionReference->getArgument(1)) {
continue;
}
$indexFound = $i;
}
if (null === $indexFound) {
throw new \LogicException(
sprintf(
'Unable to locate the state "%s" into the transition of "%s:%s".',
$targetedState,
$graph,
$transition,
),
);
}
unset($transitionReferences[$indexFound]);
}
}
Upvotes: 1