class CallableResolver

Same name in other branches
  1. 10 core/lib/Drupal/Core/Utility/CallableResolver.php \Drupal\Core\Utility\CallableResolver

Resolves PHP callables.

The callable resolver service aims to provide a standardized approach to how callables are resolved and invoked from various subsystems. The callable resolver will return or invoke a callable defined in any of the following definition formats:

  • Service notation:
'some.service:method';
  • Static methods:
'\\FooClass::staticMethod';
  • Non-static methods, instantiated with the class resolver:
'\\DependencyInjectedClass::method';
  • Object calls:
[
    $object,
    'method',
];
  • Classes with an __invoke method:
'\\ClassWithInvoke';
  • Closures.

Hierarchy

Expanded class hierarchy of CallableResolver

12 files declare their use of CallableResolver
CallableResolverTest.php in core/tests/Drupal/Tests/Core/Utility/CallableResolverTest.php
ControllerResolver.php in core/lib/Drupal/Core/Controller/ControllerResolver.php
ControllerResolverTest.php in core/tests/Drupal/Tests/Core/Controller/ControllerResolverTest.php
CustomAccessCheck.php in core/lib/Drupal/Core/Access/CustomAccessCheck.php
CustomAccessCheckTest.php in core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php

... See full list

File

core/lib/Drupal/Core/Utility/CallableResolver.php, line 37

Namespace

Drupal\Core\Utility
View source
class CallableResolver {
    
    /**
     * Constructs a CallableResolver object.
     *
     * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $classResolver
     *   The class resolver.
     */
    public function __construct(ClassResolverInterface $classResolver) {
    }
    
    /**
     * Gets a callable from a definition.
     *
     * @param callable|array|string $definition
     *   A callable definition.
     *
     * @return callable
     *   A callable.
     *
     * @throws \InvalidArgumentException
     *   Thrown when no valid callable could be resolved from the definition.
     */
    public function getCallableFromDefinition(callable|array|string $definition) : callable {
        // If the definition is natively a callable, we can return it immediately.
        if (is_callable($definition)) {
            return $definition;
        }
        if (is_array($definition)) {
            throw new \InvalidArgumentException(sprintf('The callable definition provided "[%s]" is not a valid callable.', implode(",", $definition)));
        }
        if (!is_string($definition)) {
            throw new \InvalidArgumentException(sprintf('The callable definition provided was invalid. Illegal format of type: %s', gettype($definition)));
        }
        // Callable with __invoke().
        if (!str_contains($definition, ':')) {
            $instance = $this->classResolver
                ->getInstanceFromDefinition($definition);
            if (!is_callable($instance)) {
                throw new \InvalidArgumentException(sprintf('The callable definition provided was invalid. Class "%s" does not have a method "__invoke" and is not callable.', $instance::class));
            }
            return $instance;
        }
        // Callable in the service:method notation.
        $class_or_service = NULL;
        $method = NULL;
        $count = substr_count($definition, ':');
        if ($count == 1) {
            [
                $class_or_service,
                $method,
            ] = explode(':', $definition, 2);
        }
        // Callable in the class::method notation.
        if (str_contains($definition, '::')) {
            [
                $class_or_service,
                $method,
            ] = explode('::', $definition, 2);
        }
        if (empty($class_or_service) || empty($method)) {
            throw new \InvalidArgumentException(sprintf('The callable definition provided was invalid. Could not get class and method from definition "%s".', $definition));
        }
        $instance = $this->classResolver
            ->getInstanceFromDefinition($class_or_service);
        if (!is_callable([
            $instance,
            $method,
        ])) {
            throw new \InvalidArgumentException(sprintf('The callable definition provided was invalid. Either class "%s" does not have a method "%s", or it is not callable.', $instance::class, $method));
        }
        return [
            $instance,
            $method,
        ];
    }

}

Members

Title Sort descending Modifiers Object type Summary
CallableResolver::getCallableFromDefinition public function Gets a callable from a definition.
CallableResolver::__construct public function Constructs a CallableResolver object.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.