Merge parent route with this

@param Route $route The parent route

@return Route mixed route
765400
public function merge($parent)
    {
        $merged = clone $this;
        if ($parent) {
            //Merge with parent route
            ($this->getActionName()) ?
                $merged->setActionName($this->getActionName()) :
                $merged->setActionName($parent->getActioName());

            ($this->getControllerName()) ?
                $merged->setControllerName($this->getControllerName()) :
                $merged->setControllerName($parent->getControllerName());

            $this->addParams(array_merge($parent->getParams(), $this->getParams()));
        }

        return $merged;
    }
1049098
private function target(Route $route)
    {
        $params = $route->getParams();

        $target = new Target($params['controller']);

        unset($params['controller']);

        if (isset($params['action'])) {
            $target->setAction($params['action']);
            unset($params['action']);
        }

        $target->setParams($params);

        return $target;
    }
1342711
public function add(Route $route): self
    {
        if ($route->uri === ""
            || $route->method === 0b0
            || $route->action === null) {
            $this->logger->error("Route incomplete. Unable to add");
            $this->logger->debug("Incomplete Route", [$route]);
            throw new Exception\RouteIncompleteException(
                "Retrieved Route is not complete and can not be stored"
            );
        }

        // store default route
        if ($route->isDefault) {
            if ($this->defaultRoute === null) {
                $this->defaultRoute = $route;
            } else {
                $this->logger->debug(
                    "Default route already added to container, skipping add.",
                    ["route" => $route, "storedDefault" => $this->defaultRoute]
                );
            }
        }

        // store 404 route
        if ($route->is404) {
            if ($this->e404Route === null) {
                $this->e404Route = $route;
                $this->logger->info("404 route added to Route Container");
            } else {
                $this->logger->debug(
                    "404 route already added to container, skipping add.",
                    ["route" => $route, "stored404" => $this->e404Route]
                );
            }

            return $this;
        }

        // store route to regular container
        $this->routes[] = $route;

        $this->logger->info(
            "Route successfully added to Container",
            ["uri" => $route->uri]
        );

        return $this;
    }
724513
public function addRoute(Route $route)
    {
        /**
         * Auto-generate a name from the object's hash
         * This makes it so that we can autogenerate names
         * that ensure duplicate route instances are overridden
         */
        $name = spl_object_hash($route);

        return $this->set($name, $route);
    }
842230
public function gatherRouteMiddlewares($route)
    {
        if (method_exists($this->router, 'gatherRouteMiddleware')) {
            return $this->router->gatherRouteMiddleware($route);
        }

        return $this->router->gatherRouteMiddlewares($route);
    }
823394
protected function runRouteWithinStack(Route $route, Request $request)
    {
        $skipMiddleware = $this->container->bound('middleware.disable') &&
                          ($this->container->make('middleware.disable') === true);

        // Create a Pipeline instance.
        $pipeline = new Pipeline(
            $this->container, $skipMiddleware ? array() : $this->gatherRouteMiddleware($route)
        );

        return $pipeline->handle($request, function ($request) use ($route)
        {
            $response = $route->run($request);

            return $this->prepareResponse($request, $response);
        });
    }
153184
protected function buildRouteAction(Route $route)
    {
        $action = $route->getAction();

        if ($action instanceof \Closure) {

            $controller = new Controller();

            return $action->bindTo($controller, get_class($controller));
        }

        list ($class, $method) = $action;

        $class = new $class;

        return [$class, $method];
    }
1219129
public function create(RouteCollection $routes): Tree
    {
        $routesArray = $routes->all();

        $routesPaths = array_map(function (Route $route) {
            return $this->serializer->serialize($route->getPath());
        }, $routesArray);

        $tree = new Tree();

        /** @var RoutePath[] $pathArray */
        foreach ($routesPaths as $index => $pathArray) {
            $route = $routesArray[$index];

            /** @var TreeNode $treeNode */
            $treeNode = $tree;

            foreach ($pathArray as $path) {
                $treeNode = $this->addPathPartToTree($treeNode, $path, $route, $index);
            }
        }

        return $tree;
    }
492445
protected function processRoute($route)
	{
		$routeAction = $route->getAction();

		$this->getParentCommand()->info('Processing route [' . implode('/', $route->methods()) . '] ' . $routeAction['uri']);

		$routeControllerDocBlock = $this->getRouteControllerDocBlock($route);
		$routeControllerOperationTags = $this->getDocBlockOperationTags($routeControllerDocBlock);

		foreach ($route->methods() as $httpMethod) {
			// Ignore HEAD

			if (strtolower($httpMethod) == 'head') {
				continue;
			}

			if (isset($this->openAPI->paths[$routeAction['uri']])) {
				$pathItem = $this->openAPI->paths[$routeAction['uri']];
			} else {
				$pathItem = $this->openAPI->paths[$routeAction['uri']] = new PathItem();

				if (!is_null($routeControllerDocBlock)) {
					$pathItem->summary = $routeControllerDocBlock->getSummary();
					if (empty($pathItem->summary)) {
						$pathItem->summary = null;
					}
					$routeControllerDescriptionDocBlock = $routeControllerDocBlock->getDescription();
					$pathItem->description = $routeControllerDescriptionDocBlock->render();
					if (empty($pathItem->description)) {
						$pathItem->description = null;
					}
				}
			}

			$operation = new Operation();

			$operationTags = $routeControllerOperationTags;

			$routeMethodDocBlock = $this->getRouteMethodDocBlock($route);
			$extraParameterRefTags = [];

			if (!is_null($routeMethodDocBlock)) {
				$operation->summary = $routeMethodDocBlock->getSummary();
				if (empty($operation->summary)) {
					$operation->summary = null;
				}
				$routeMethodDescriptionDocBlock = $routeMethodDocBlock->getDescription();
				$operation->description = $routeMethodDescriptionDocBlock->render();
				if (empty($operation->description)) {
					$operation->description = null;
				}
				$routeMethodOperationTags = $this->getDocBlockOperationTags($routeMethodDocBlock);

				$operationTags = array_merge($routeControllerOperationTags, $routeMethodOperationTags);
				$extraParameterRefTags = $this->getDocBlockExtraParameterRefTags($routeMethodDocBlock);

				$operation->operationId = $this->getDocBlockOperationId($routeMethodDocBlock);
			}

			if (is_null($operation->operationId)) {
				switch (strtolower($httpMethod)) {
					case 'patch':
					case 'put':
						$operation->operationId = strtolower($httpMethod) . ucfirst(array_last(explode('.', $routeAction['as'])));
						break;
					default :
						$operation->operationId = array_last(explode('.', $routeAction['as']));
				}
			}

			if (count($operationTags) > 0) {
				$operation->tags = $operationTags;
			}

			// Try
			$routePathParameters = $this->getRoutePathParameters($route);

			foreach ($routePathParameters as $parameterName => $parameterData) {
				$parameterDescription = isset($parameterData['docDescription']) ? $parameterData['docDescription'] : '';
				if (trim($parameterDescription) == '') {
					$parameterDescription = null;
				}
				$parameter = new Parameter([
					'name' => $parameterName,
					'in' => 'path',
					'description' => $parameterDescription,
					'required' => true,
				]);
				if (isset($parameterData['type'])) {
					$parameter->schema = new Schema([
						'type' => $parameterData['type']
					]);
				}
				if (isset($parameterData['docType'])) {
					$parameter->schema = new Schema([
						'type' => $parameterData['docType']
					]);
				}
				$operation->parameters[] = $parameter;
			}

			// Try to get route validation rules
			$routeValidationRules = $this->getRouteValidationRules($route);

			if (count($routeValidationRules) > 0) {
				switch (strtolower($httpMethod)) {
					case 'get':
					//case 'head':

						foreach ($routeValidationRules as $parameterName => $rulesString) {
							$rules = explode('|', $rulesString);

							$parameter = new Parameter([
								'name' => $parameterName,
								'in' => 'query',
								'description' => null, /* @todo Grab description from phpdoc custom tag ? */
								'required' => in_array('required', $rules),
							]);

							$parameter->schema = $this->getPropertyValidationRulesSchema(
								$rules,
								'Validation rules for parameter "' . $parameterName . '"',
								true
							);
							
							if (is_null($parameter->schema->format)) {
								// ignore this parameter if no type found
								$this->getParentCommand()->warn('  Ignore parameter "' . $parameterName . '"');
								continue;
							}

							// Add if not already added from the "path" parameters
							$find = false;
							if (is_null($operation->parameters)) {
								$operation->parameters = [];
							}
							/** @var Parameter $p */
							foreach ($operation->parameters as $p) {
								if ($p->name == $parameter->name) {
									$find = true;
								}
							}
							if (!$find) {
								$operation->parameters[] = $parameter;
							}
						}

						break;

					case 'put':
					case 'patch':
					case 'post':

						$requestBody = new RequestBody();
						$mediaType = new MediaType();
						$mediaType->schema = new Schema();
						$mediaType->schema->properties = [];

						// Change to multi-part if file in parameters ("string" type and "binary" format)
						$contentType = 'application/json';
						
						foreach ($routeValidationRules as $parameterName => $rulesString) {
							$rules = explode('|', $rulesString);
							$schema = $this->getPropertyValidationRulesSchema(
								$rules,
								'Validation rules for parameter "' . $parameterName . '"',
								true
							);
							
							// ignore this property if no type found
							if (is_null($schema->type)) {
								$this->getParentCommand()->warn('  Ignore parameter "' . $parameterName . '"');
								continue;
							}
							
							// Change to multi-part if file in parameters ("string" type and "binary" format)
							if ($schema->type == 'string' && $schema->format == 'binary') {
								$contentType = 'multipart/form-data';
								// Change mediaType schema type
								$mediaType->schema->type = 'object';
							}
							
							$mediaType->schema->properties[$parameterName] = $schema;
						}

						$mediaType->schema->required = $this->getValidationRulesSchemaRequired($routeValidationRules);

						$requestBody->content[$contentType] = $mediaType;
						$operation->requestBody = $requestBody;

						$operation->responses = [];

						break;
				}
			}

			// Append extra parameter refs

			foreach ($extraParameterRefTags as $extraParameterRefTag) {
				$parameterRef = new Reference([
					'ref' => $extraParameterRefTag
				]);

				if (is_null($operation->parameters)) {
					$operation->parameters = [];
				}

				$operation->parameters[] = $parameterRef;
			}

			// First response

			$response = new Response();
			$responseMediaType = null;

			$apiResponseSchemaRefTags = $routeMethodDocBlock->getTagsByName('OpenApiResponseSchemaRef');
			if (count($apiResponseSchemaRefTags) > 0) {
				if (is_null($responseMediaType)) {
					$responseMediaType = new MediaType();
				}
				$apiResponseSchemaRefTag = $apiResponseSchemaRefTags[0];
				$apiResponseSchemaRef = trim(str_replace('@OpenApiResponseSchemaRef', '', $apiResponseSchemaRefTag->render()));
				$responseMediaType->schema = new Reference([
					'ref' => $apiResponseSchemaRef
				]);
			}
			
			$response->description = '';
			$apiResponseDescriptionTags = $routeMethodDocBlock->getTagsByName('OpenApiResponseDescription');
			if (count($apiResponseDescriptionTags) > 0) {
				$apiResponseDescriptionTag = $apiResponseDescriptionTags[0];
				$apiResponseDescription = trim(str_replace('@OpenApiResponseDescription', '', $apiResponseDescriptionTag->render()));
				$response->description = $apiResponseDescription;
			}

			$apiDocsNoCallTags = $routeMethodDocBlock->getTagsByName('ApiDocsNoCall');
			if (count($apiDocsNoCallTags) == 0) {
				$exampleResponse = $this->getRouteCallExampleResponse($route, $httpMethod);
				if (!is_null($exampleResponse)) {
					if (is_null($responseMediaType)) {
						$responseMediaType = new MediaType();
					}

					$exampleSchemaId = $this->getRouteExampleResponseId($route);

					// Create Example schema in components

					if (is_null($this->openAPI->components)) {
						$this->openAPI->components = new Components();
					}

					$this->openAPI->components->examples[$exampleSchemaId] = new Example([
						'value' => json_decode($exampleResponse, true)
					]);

					$responseMediaType->example = new Reference([
						'ref' => '#/components/examples/' . $exampleSchemaId
					]);
				}
			}

			if (!is_null($responseMediaType)) {
				$response->content['application/json'] = $responseMediaType;
			}
			
			// Excepted HTTP code specified ? "OpenApiResponseExceptedHTTPCode" tag
			
			$apiResponseExceptedHTTPCode = null;
			$apiResponseExceptedHTTPCodeTags = $routeMethodDocBlock->getTagsByName('OpenApiResponseExceptedHTTPCode');
			if (count($apiResponseExceptedHTTPCodeTags) > 0) {
				$apiResponseExceptedHTTPCodeTag = $apiResponseExceptedHTTPCodeTags[0];
				$apiResponseExceptedHTTPCode = trim(str_replace('@OpenApiResponseExceptedHTTPCode', '', $apiResponseExceptedHTTPCodeTag->render()));
			}

			if (!is_null($apiResponseExceptedHTTPCode)) {
				$operation->responses[$apiResponseExceptedHTTPCode] = $response;
			} else {
				switch (strtolower($httpMethod)) {
					case 'get':
						//case 'head':
						$operation->responses['200'] = $response;
						break;
					
					case 'put':
					case 'patch':
						$operation->responses['200'] = $response;
						break;
						
					case 'post':
						$operation->responses['201'] = $response;
						break;
					
					case 'delete':
						$operation->responses['204'] = $response;
						break;
				}
			}

			// Default response (Errors)

			$defaultResponse = new Response();
			$defaultResponseMediaType = null;

			$apiDefaultResponseSchemaRefTags = $routeMethodDocBlock->getTagsByName('OpenApiDefaultResponseSchemaRef');
			if (count($apiDefaultResponseSchemaRefTags) > 0) {
				if (is_null($defaultResponseMediaType)) {
					$defaultResponseMediaType = new MediaType();
				}
				$apiDefaultResponseSchemaRefTag = $apiDefaultResponseSchemaRefTags[0];
				$apiDefaultResponseSchemaRef = trim(str_replace('@OpenApiDefaultResponseSchemaRef', '', $apiDefaultResponseSchemaRefTag->render()));
				$defaultResponseMediaType->schema = new Reference([
					'ref' => $apiDefaultResponseSchemaRef
				]);
			}

			$defaultResponse->description = '';
			$apiDefaultResponseDescriptionTags = $routeMethodDocBlock->getTagsByName('OpenApiDefaultResponseDescription');
			if (count($apiDefaultResponseDescriptionTags) > 0) {
				$apiDefaultResponseDescriptionTag = $apiResponseDescriptionTags[0];
				$apiDefaultResponseDescription = trim(str_replace('@OpenApiDefaultResponseDescription', '', $apiDefaultResponseDescriptionTag->render()));
				$defaultResponse->description = $apiDefaultResponseDescription;
			}

			if (!is_null($defaultResponseMediaType)) {
				$defaultResponse->content['application/json'] = $defaultResponseMediaType;
			}

			$operation->responses['default'] = $defaultResponse;

			$pathItem->{strtolower($httpMethod)} = $operation;
		}
	}
42993
public function addRoute(Route $route, $name = null)
    {
        if (null === $name) {
            // used as a flag to know which routes will need a name later
            $name = '_unnamed_route_'.spl_object_hash($route);
        }

        $this->routes[$name] = $route;

        return $this;
    }
612457
public function getRouteMiddleware($route)
    {
        return collect($route->gatherMiddleware())->map(function ($middleware) {
            return $middleware instanceof Closure ? 'Closure' : $middleware;
        })->implode(',');
    }
1050404
public static function delete(Route $route)
    {
        $routeWithoutSlash = $route;
        $routeWithSlash = $route->getWithSlash();

        // exception_if(! check(self::$register[$routeWithoutSlash->getName()]), RouteNotFoundInRoutesRegisterException::class , $routeWithoutSlash);
        // exception_if(! check(self::$register[$routeWithSlash->getName()]), RouteNotFoundInRoutesRegisterException::class , $routeWithSlash);

        if (check(self::$register[$routeWithoutSlash->getName()])) {
            unset(self::$register[$routeWithoutSlash->getName()]);
        }

        if (check(self::$register[$routeWithSlash->getName()])) {
            unset(self::$register[$routeWithSlash->getName()]);
        }
    }
516781
public function dispatch(\Parable\Routing\Route $route)
    {
        $this->dispatchedRoute = $route;

        $this->hook->trigger(self::HOOK_DISPATCH_BEFORE, $route);
        $controller = null;

        // Start output buffering and set $returnContent to null
        $returnContent = null;
        $this->response->startOutputBuffer();

        // Build the parameters array
        $parameters = [];
        foreach ($route->getValues() as $value) {
            $parameters[] = $value;
        }

        // Call the relevant code
        if ($route->hasControllerAndAction()) {
            $controller = \Parable\DI\Container::get($route->getController());
            $returnContent = $controller->{$route->getAction()}(...$parameters);
        } elseif ($route->hasCallable()) {
            $callable = $route->getCallable();
            $returnContent = $callable(...$parameters);
        }

        $this->hook->trigger(self::HOOK_DISPATCH_TEMPLATE_BEFORE, $route);

        // If the route has no template path, attempt to build one based on controller/action.phtml
        if (!$route->hasTemplatePath() && $route->hasControllerAndAction()) {
            $reflection = new \ReflectionClass($controller);
            $controllerName = str_replace('\\', '/', $reflection->getName());
            $controllerName = str_replace('Controller/', '', $controllerName);

            $templatePathGenerated = $this->path->getDir(
                "app/View/{$controllerName}/{$route->getAction()}.phtml"
            );

            if (file_exists($templatePathGenerated)) {
                $route->setTemplatePath($templatePathGenerated);
            }
        }

        // And check again, now that we might have a magic template path
        if ($route->hasTemplatePath()) {
            $templatePath = $this->path->getDir($route->getTemplatePath());
            $this->view->setTemplatePath($templatePath);
            $this->view->render();
        }

        // If the callback or controller/action returned content, we need to handle it
        if ($returnContent) {
            if ($this->response->getOutput()->acceptsContent($returnContent)) {
                $this->response->setContent($returnContent);
            } else {
                $type   = gettype($returnContent);
                $output = get_class($this->response->getOutput());

                // Stop the output buffer we've started above and throw
                $this->response->stopOutputBuffer();
                throw new \Parable\Framework\Exception(
                    "Route returned value of type '{$type}', which output class '{$output}' cannot handle."
                );
            }
        }

        // Any rendered content was from before the returnContent was set, so we prepend it if there's any
        $renderedContent = $this->response->returnOutputBuffer();
        if ($renderedContent) {
            $this->response->prependContent($renderedContent);
        }

        $this->hook->trigger(self::HOOK_DISPATCH_TEMPLATE_AFTER, $route);
        $this->hook->trigger(self::HOOK_DISPATCH_AFTER, $route);
        return $this;
    }
1242159
public function add( Route $route ){
		$routeId	= $route->getId();
		if( array_key_exists( $routeId, $this->routes ) ){
			throw new \DomainException( sprintf(
				'A route for pattern and method is already registered: %2$s %1$s',
				$route->getPattern(),
				$route->getMethod()
			) );
		}
		$this->routes[$routeId]	= $route;
		return $routeId;
	}
1323918
public static function fromRoute(Route $route, array $params = []): self
    {
        $result = new self();
        $result->success = true;
        $result->route = $route;
        $result->matchedParams = $params;

        return $result;
    }
1034501
protected function addWhereClausesToRoute( $route )
	{
		$where = isset( $route->getAction()['where'] ) ? $route->getAction()['where'] : [];
		$route->where( array_merge( $this->patterns, $where ) );

		return $route;
	}
151646
public function mapRoute(Route $route)
    {
        $optionsRoute = clone $route;
        $optionsRoute->setMethods(array('OPTIONS'));
        $optionsRoute->setDefault(
            '_controller',
            'ezpublish_rest.controller.options:getRouteOptions'
        );

        $optionsRoute->setDefault(
            'allowedMethods',
            implode(',', $route->getMethods())
        );

        return $optionsRoute;
    }