<?php
/**
* Part of the Joomla Framework Application Package
*
* @copyright Copyright (C) 2005 - 2021 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
namespace Joomla\Application\Controller;
use Joomla\Controller\ControllerInterface;
use Joomla\Router\ResolvedRoute;
/**
* Resolves a controller for the given route.
*
* @since 2.0.0
*/
class ControllerResolver implements ControllerResolverInterface
{
/**
* Resolve the controller for a route
*
* @param ResolvedRoute $route The route to resolve the controller for
*
* @return callable
*
* @since 2.0.0
* @throws \InvalidArgumentException
*/
public function resolve(ResolvedRoute $route): callable
{
$controller = $route->getController();
// Try to resolve a callable defined as an array
if (\is_array($controller))
{
if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1]))
{
if (!class_exists($controller[0]))
{
throw new \InvalidArgumentException(sprintf('Cannot resolve controller for URI `%s`', $route->getUri()));
}
try
{
$controller[0] = $this->instantiateController($controller[0]);
}
catch (\ArgumentCountError $error)
{
throw new \InvalidArgumentException(
sprintf(
'Controller `%s` has required constructor arguments, cannot instantiate the class', $controller[0]
),
0,
$error
);
}
}
if (!\is_callable($controller))
{
throw new \InvalidArgumentException(sprintf('Cannot resolve controller for URI `%s`', $route->getUri()));
}
return $controller;
}
// Try to resolve an invokable object
if (\is_object($controller))
{
if (!\is_callable($controller))
{
throw new \InvalidArgumentException(sprintf('Cannot resolve controller for URI `%s`', $route->getUri()));
}
return $controller;
}
// Try to resolve a known function
if (\function_exists($controller))
{
return $controller;
}
// Try to resolve a class name if it implements our ControllerInterface
if (\is_string($controller) && interface_exists(ControllerInterface::class))
{
if (!class_exists($controller))
{
throw new \InvalidArgumentException(sprintf('Cannot resolve controller for URI `%s`', $route->getUri()));
}
try
{
return [$this->instantiateController($controller), 'execute'];
}
catch (\ArgumentCountError $error)
{
throw new \InvalidArgumentException(
sprintf(
'Controller `%s` has required constructor arguments, cannot instantiate the class', $controller
),
0,
$error
);
}
}
// Unsupported resolution
throw new \InvalidArgumentException(sprintf('Cannot resolve controller for URI `%s`', $route->getUri()));
}
/**
* Instantiate a controller class
*
* @param string $class The class to instantiate
*
* @return object Controller class instance
*
* @since 2.0.0
*/
protected function instantiateController(string $class): object
{
return new $class;
}
}