ClosureCommand.php 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\Command;
  12. use Closure;
  13. use Hyperf\Crontab\Crontab;
  14. use Hyperf\Crontab\Schedule;
  15. use Hyperf\Stringable\Str;
  16. use Psr\Container\ContainerInterface;
  17. use ReflectionFunction;
  18. use function Hyperf\Tappable\tap;
  19. final class ClosureCommand extends Command
  20. {
  21. private ParameterParser $parameterParser;
  22. public function __construct(
  23. private ContainerInterface $container,
  24. string $signature,
  25. private Closure $closure
  26. ) {
  27. $this->signature = $signature;
  28. $this->parameterParser = $container->get(ParameterParser::class);
  29. parent::__construct();
  30. $options = $this->parameterParser->parseClosureOptions($closure);
  31. $definition = $this->getDefinition();
  32. foreach ($options as $option) {
  33. $name = $option->getName();
  34. $snakeName = Str::snake($option->getName(), '-');
  35. if (
  36. $definition->hasOption($name)
  37. || $definition->hasArgument($name)
  38. || $definition->hasOption($snakeName)
  39. || $definition->hasArgument($snakeName)
  40. ) {
  41. continue;
  42. }
  43. $definition->addOption($option);
  44. }
  45. }
  46. public function handle()
  47. {
  48. $inputs = array_merge($this->input->getArguments(), $this->input->getOptions());
  49. $parameters = $this->parameterParser->parseClosureParameters($this->closure, $inputs);
  50. $ref = new ReflectionFunction($this->closure);
  51. if ($ref->isStatic()) {
  52. ($this->closure)(...$parameters);
  53. return;
  54. }
  55. $this->closure->call($this, ...$parameters);
  56. }
  57. public function describe(string $description): self
  58. {
  59. $this->setDescription($description);
  60. return $this;
  61. }
  62. /**
  63. * @param null|callable(Crontab $crontab):Crontab $callback
  64. */
  65. public function cron(string $rule, array $arguments = [], ?callable $callback = null): self
  66. {
  67. tap(
  68. Schedule::command($this->getName(), $arguments)
  69. ->setName($this->getName())
  70. ->setRule($rule)
  71. ->setMemo($this->getDescription()),
  72. $callback
  73. );
  74. return $this;
  75. }
  76. }