<?php
declare(strict_types=1);
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\CoreBundle\Form\Extension;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\Exception\InvalidArgumentException;
use Symfony\Component\Form\FormExtensionInterface;
use Symfony\Component\Form\FormTypeGuesserChain;
use Symfony\Component\Form\FormTypeGuesserInterface;
use Symfony\Component\Form\FormTypeInterface;
/**
* This proxy class help to keep BC code with < SF2.8 form behavior by restoring
* the type as a code and not as a class.
*
* @deprecated since 3.7, to be removed in 4.0, the form mapping feature should be disabled.
*/
class DependencyInjectionExtension implements FormExtensionInterface
{
/**
* @var FormExtensionInterface
*/
protected $extension;
/**
* @var array
*/
protected $mappingTypes;
/**
* @var array
*/
protected $extensionTypes;
/**
* @var ContainerInterface
*/
private $container;
/**
* @var string[]
*/
private $typeServiceIds;
/**
* @var string[]
*/
private $typeExtensionServiceIds;
/**
* @var string[]
*/
private $guesserServiceIds;
/**
* @var FormTypeGuesserInterface
*/
private $guesser;
/**
* @var bool
*/
private $guesserLoaded = false;
public function __construct(
ContainerInterface $container,
array $typeServiceIds,
array $typeExtensionServiceIds,
array $guesserServiceIds,
array $mappingTypes = [],
array $extensionTypes = []
) {
$this->container = $container;
$this->typeServiceIds = $typeServiceIds;
$this->typeExtensionServiceIds = $typeExtensionServiceIds;
$this->guesserServiceIds = $guesserServiceIds;
$this->mappingTypes = $mappingTypes;
$this->mappingExtensionTypes = $extensionTypes;
$this->reverseMappingTypes = array_flip($mappingTypes);
}
public function getType($name)
{
// resolve code to FQCN
$name = self::findClass($this->mappingTypes, $name);
if (!isset($this->typeServiceIds[$name])) {
if (class_exists($name) && \in_array(FormTypeInterface::class, class_implements($name), true)) {
return new $name();
}
throw new InvalidArgumentException(
sprintf('The field type "%s" is not registered with the service container.', $name)
);
}
$type = $this->container->get($this->typeServiceIds[$name]);
if ($name !== \get_class($type) && (method_exists($type, 'getName') && $type->getName() !== $name)) {
throw new InvalidArgumentException(sprintf(
'The type name specified for the service "%s" does not match the actual name.'
.' Expected "%s", given "%s"',
$this->typeServiceIds[$name],
$name,
\get_class($type)
));
}
return $type;
}
public function hasType($name)
{
return isset($this->mappingTypes[$name]) || isset($this->typeServiceIds[$name]);
}
public function getTypeExtensions($name)
{
// lookup inside the extension mapping
$serviceIdx = [];
if (isset($this->reverseMappingTypes[$name])) {
$code = $this->reverseMappingTypes[$name];
if (isset($this->mappingExtensionTypes[$code])) {
$serviceIdx = array_merge($serviceIdx, $this->mappingExtensionTypes[$code]);
}
}
$serviceIdx = array_unique(array_merge(isset($this->typeExtensionServiceIds[$name]) ? $this->typeExtensionServiceIds[$name] : [], $serviceIdx));
$extensions = [];
foreach ($serviceIdx as $serviceId) {
if ($this->container->has($serviceId)) {
$extensions[] = $this->container->get($serviceId);
}
}
return $extensions;
}
public function hasTypeExtensions($name)
{
return isset($this->reverseMappingTypes[$name]) || isset($this->typeExtensionServiceIds[$name]);
}
public function getTypeGuesser()
{
if (!$this->guesserLoaded) {
$this->guesserLoaded = true;
$guessers = [];
foreach ($this->guesserServiceIds as $serviceId) {
if ($this->container->has($serviceId)) {
$guessers[] = $this->container->get($serviceId);
}
}
if ($guessers) {
$this->guesser = new FormTypeGuesserChain($guessers);
}
}
return $this->guesser;
}
/**
* @param string $type
*
* @return string
*/
protected static function findClass($mapping, $type)
{
if (strpos($type, '\\')) {
return $type;
}
if (!isset($mapping[$type])) {
return $type;
}
return $mapping[$type];
}
}