3 namespace Drupal\drupalmoduleupgrader\Routing;
5 use Doctrine\Common\Collections\ArrayCollection;
6 use Drupal\drupalmoduleupgrader\Utility\Path\Drupal7\PathComponent;
7 use Drupal\drupalmoduleupgrader\Utility\Path\Drupal8\PathComponent as PathComponent8x;
8 use Drupal\drupalmoduleupgrader\Utility\Path\PathUtilityInterface;
9 use Symfony\Component\Routing\Route as Drupal8Route;
12 * Represents a set of parameter bindings for a particular path, callback,
13 * and set of arguments.
15 class ParameterMap extends ArrayCollection {
18 * @var \Drupal\drupalmoduleupgrader\Utility\Path\PathUtilityInterface
25 protected $_length = 0;
27 protected $bindings = [];
32 public function __construct(PathUtilityInterface $path, array $parameters, array $arguments = []) {
33 parent::__construct();
35 $this->_length = sizeof($path);
38 $argument = $arguments ? array_shift($arguments) : ParameterBinding::NO_ARGUMENT;
39 $this->addBinding(new ParameterBinding($path, array_shift($parameters), $argument));
46 public function toArray() {
49 foreach ($this->bindings as $key => $bindings) {
50 if (is_integer($key)) {
51 /** @var ParameterBinding[] $bindings */
52 foreach ($bindings as $binding) {
53 $parameter = $binding->getParameter()->getName();
54 $function = $binding->getParameter()->getFunction()->getName()->getText();
55 $output[$function][$parameter]['name'] = $bindings[0]->getParameter()->getName();
57 $value = $bindings[0]->getValue();
58 if ($value instanceof PathComponent && $value->isWildcard()) {
59 $output[$function][$parameter]['type'] = ltrim($value, '%');
69 * Merge another parameter map into this one. Bindings from the incoming map
70 * should 'win', although the specifics are up to the implementing classes.
72 * @param ParameterMap $map
73 * The parameter map to merge.
75 public function merge(ParameterMap $map) {
76 foreach ($map as $binding) {
77 $this->addBinding($binding);
82 * Adds a binding to this map, overwriting the existing one if there is a
85 * @param ParameterBinding $binding
88 public function addBinding(ParameterBinding $binding) {
89 $value = $binding->getValue();
90 // The binding will return a PathComponent if it expects to be physically
91 // represented in the path, whether or not it already is.
92 if ($value instanceof PathComponent) {
93 if ($binding->inPath()) {
94 $key = $binding->getArgument();
97 $key = $this->path->indexOf($value);
99 $key = $this->_length++;
104 $key = $binding->getParameter()->getName();
107 $this->set($key, $binding);
109 if (! isset($this->bindings[$key])) {
110 $this->bindings[$key] = [];
112 array_unshift($this->bindings[$key], $binding);
116 * Applies the parameter map to a path, modifying it as needed.
118 * @param \Drupal\drupalmoduleupgrader\Utility\Path\PathUtilityInterface $path
119 * The path to modify (in-place).
121 public function applyPath(PathUtilityInterface $path) {
122 foreach ($this as $key => $binding) {
123 if (is_integer($key)) {
124 $path[$key] = new PathComponent8x('{' . $binding->getParameter()->getName() . '}');
130 * Apply the parameter map to a Drupal 8 route, modifying it as needed.
132 * @param \Symfony\Component\Routing\Route $route
133 * The route to process.
135 public function applyRoute(Drupal8Route $route) {
136 $this->applyPath($this->path);
138 foreach ($this as $key => $binding) {
139 $parameter = $binding->getParameter();
141 /** @var ParameterBinding $binding */
142 if (is_integer($key)) {
143 if ($parameter->isOptional()) {
144 // @todo Don't use eval().
145 $value = eval('return ' . $parameter->getValue() . ';');
146 $route->setDefault($parameter->getName(), $value);
149 elseif ($binding->hasArgument()) {
150 $route->setDefault($parameter->getName(), $binding->getValue());
153 $route->setPath($this->path->__toString());