<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
/**
* Managers converters.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Henrik Bjornskov <henrik@bjrnskov.dk>
*/
class ParamConverterManager
{
/**
* @var array
*/
private $converters = [];
/**
* @var array
*/
private $namedConverters = [];
/**
* Applies all converters to the passed configurations and stops when a
* converter is applied it will move on to the next configuration and so on.
*
* @param array|object $configurations
*/
public function apply(Request $request, $configurations)
{
if (\is_object($configurations)) {
$configurations = [$configurations];
}
foreach ($configurations as $configuration) {
$this->applyConverter($request, $configuration);
}
}
/**
* Applies converter on request based on the given configuration.
*/
private function applyConverter(Request $request, ParamConverter $configuration)
{
$value = $request->attributes->get($configuration->getName());
$className = $configuration->getClass();
// If the value is already an instance of the class we are trying to convert it into
// we should continue as no conversion is required
if (\is_object($value) && $value instanceof $className) {
return;
}
if ($converterName = $configuration->getConverter()) {
if (!isset($this->namedConverters[$converterName])) {
throw new \RuntimeException(sprintf("No converter named '%s' found for conversion of parameter '%s'.", $converterName, $configuration->getName()));
}
$converter = $this->namedConverters[$converterName];
if (!$converter->supports($configuration)) {
throw new \RuntimeException(sprintf("Converter '%s' does not support conversion of parameter '%s'.", $converterName, $configuration->getName()));
}
$converter->apply($request, $configuration);
return;
}
foreach ($this->all() as $converter) {
if ($converter->supports($configuration)) {
if ($converter->apply($request, $configuration)) {
return;
}
}
}
}
/**
* Adds a parameter converter.
*
* Converters match either explicitly via $name or by iteration over all
* converters with a $priority. If you pass a $priority = null then the
* added converter will not be part of the iteration chain and can only
* be invoked explicitly.
*
* @param int $priority the priority (between -10 and 10)
* @param string $name name of the converter
*/
public function add(ParamConverterInterface $converter, $priority = 0, $name = null)
{
if (null !== $priority) {
if (!isset($this->converters[$priority])) {
$this->converters[$priority] = [];
}
$this->converters[$priority][] = $converter;
}
if (null !== $name) {
$this->namedConverters[$name] = $converter;
}
}
/**
* Returns all registered param converters.
*
* @return array An array of param converters
*/
public function all()
{
krsort($this->converters);
$converters = [];
foreach ($this->converters as $all) {
$converters = array_merge($converters, $all);
}
return $converters;
}
}