Files
kupshop/bundles/KupShop/ComponentsBundle/DependencyInjection/Compiler/ComponentsPass.php
2025-08-02 16:30:27 +02:00

117 lines
4.8 KiB
PHP

<?php
namespace KupShop\ComponentsBundle\DependencyInjection\Compiler;
use KupShop\ComponentsBundle\DependencyInjection\ComponentsExtension;
use KupShop\ComponentsBundle\Twig\ComponentInterface;
use KupShop\ComponentsBundle\Utils\ComponentsLocator;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\UX\Icons\Twig\UXIconComponent;
class ComponentsPass implements CompilerPassInterface
{
public function __construct(
protected ComponentsExtension $extension,
) {
}
public function process(ContainerBuilder $container)
{
$factoryDefinition = $container->findDefinition('ux.twig_component.component_factory');
$componentConfig = $factoryDefinition->getArgument(4);
$shopConfig = $this->extension->getConfig();
$shopComponents = $shopConfig['components'];
$components = [];
$unusedComponents = [];
foreach ($componentConfig as $name => &$config) {
$components[$config['class']] = ['name' => $name, ...$config];
$config['expose_public_props'] = false;
if (isset($shopComponents[$name])) {
$components[$config['class']]['shop'] = $shopComponents[$name];
} elseif (findModule(\Modules::COMPONENTS, \Modules::SUB_STORYBOOK)) {
if ($config['class'] != UXIconComponent::class) {
$components[$config['class']]['shop']['entrypoint'] = 'base';
$components[$config['class']]['shop']['version'] = 1;
}
}
}
unset($config);
foreach ($shopComponents as $name => $config) {
if (!array_key_exists($name, $componentConfig)) {
throw new \LogicException("Unknown component {$name} defined in components.yaml");
}
}
// Find all Wpj Components
foreach ($container->findTaggedServiceIds('wpj.component') as $id => $tags) {
$definition = $container->findDefinition($id);
$component = &$components[$definition->getClass()];
foreach ($tags as $tag) {
$component['latest_version'] = $tag['latestVersion'];
$component['className'] = strtolower(str_replace(':', '-', $component['name']));
// If component is not used on shop, remove it from registered components
if (!isset($component['shop'])) {
$unusedComponents[$component['name']] = $component;
unset($componentConfig[$component['name']]);
continue 2;
}
$component['entrypoints'] = $component['shop']['entrypoint'];
$use_version = $component['shop']['version'];
$version = $this->findVersion($tag, $use_version, $component['name']);
$component['template'] = preg_replace('/\.\d+\.html\.twig/', ".{$version['template']}.html.twig", $component['template']);
$component['shop'] = [...$component['shop'], ...$version];
$componentConfig[$component['name']]['template'] = $component['template'];
if (!is_subclass_of($definition->getClass(), ComponentInterface::class)) {
throw new \LogicException("Component {$definition->getClass()} must inherit from BaseComponent");
}
$definition->addMethodCall('setConfiguration', [$use_version, $component['className']]);
}
}
$factoryDefinition->setArgument(4, $componentConfig);
// Store components info
$locator = $container->getDefinition(ComponentsLocator::class);
$locator->setArgument('$components', $components);
$locator->setArgument('$unusedComponents', $unusedComponents);
// HACK
// override symfony/ux-live-component/src/DependencyInjection/LiveComponentExtension.php
// use constant instead of container.build_hash parameter for template hashing
// when shop is redeployed, container.build_hash changes and cached html still reference old hash, which causes RuntimeException
// The exception: Cannot find a template matching "...". Cache may be corrupt.
$container->getDefinition('ux.live_component.twig.cache_warmer')->setArgument('$secret', '1234');
}
protected function findVersion(array $tag, int $version, string $componentName): ?array
{
if ($version > $tag['latestVersion']) {
throw new \LogicException("Can not find component {$componentName} version {$version}");
}
foreach (array_reverse($tag['versions'], true) as $version_from => $config) {
if ($version_from <= $version) {
return $config;
}
}
throw new \LogicException('This should never happen!');
}
}