FunctionInjector.php 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\AppFramework\Bootstrap;
  8. use Closure;
  9. use OCP\AppFramework\QueryException;
  10. use Psr\Container\ContainerInterface;
  11. use ReflectionFunction;
  12. use ReflectionParameter;
  13. use function array_map;
  14. class FunctionInjector {
  15. /** @var ContainerInterface */
  16. private $container;
  17. public function __construct(ContainerInterface $container) {
  18. $this->container = $container;
  19. }
  20. public function injectFn(callable $fn) {
  21. $reflected = new ReflectionFunction(Closure::fromCallable($fn));
  22. return $fn(...array_map(function (ReflectionParameter $param) {
  23. // First we try by type (more likely these days)
  24. if (($type = $param->getType()) !== null) {
  25. try {
  26. return $this->container->get($type->getName());
  27. } catch (QueryException $ex) {
  28. // Ignore and try name as well
  29. }
  30. }
  31. // Second we try by name (mostly for primitives)
  32. try {
  33. return $this->container->get($param->getName());
  34. } catch (QueryException $ex) {
  35. // As a last resort we pass `null` if allowed
  36. if ($type !== null && $type->allowsNull()) {
  37. return null;
  38. }
  39. // Nothing worked, time to bail out
  40. throw $ex;
  41. }
  42. }, $reflected->getParameters()));
  43. }
  44. }