Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
Entry
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
7 / 7
9
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromClass
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fromFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 command
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 opts
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 args
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Celema\Console;
6
7use Closure;
8use ValueError;
9
10/**
11 * A registered command: its metadata plus the factory producing the
12 * runnable instance on first use.
13 *
14 * @internal
15 */
16final class Entry
17{
18    private ?object $command = null;
19
20    /** @param class-string $class */
21    private function __construct(
22        public readonly Command $meta,
23        private readonly string $class,
24        private readonly Closure $factory,
25    ) {}
26
27    public static function fromInstance(object $command): self
28    {
29        return new self(Command::of($command), $command::class, static fn(): object => $command);
30    }
31
32    /** @param class-string $class */
33    public static function fromClass(string $class): self
34    {
35        return new self(Command::of($class), $class, static fn(): object => new $class());
36    }
37
38    /** @param class-string $class */
39    public static function fromFactory(string $class, Closure $factory): self
40    {
41        return new self(Command::of($class), $class, $factory);
42    }
43
44    public function command(): object
45    {
46        if ($this->command === null) {
47            $command = ($this->factory)();
48
49            // The metadata was read from the keyed class; an unrelated
50            // object would be described by one class and run as another.
51            if (!$command instanceof $this->class) {
52                throw new ValueError(
53                    "Factory for command '{$this->meta->full()}' must return a {$this->class}",
54                );
55            }
56
57            $this->command = $command;
58        }
59
60        return $this->command;
61    }
62
63    /** @return list<Opt> */
64    public function opts(): array
65    {
66        return Opt::of($this->class);
67    }
68
69    /** @return list<Arg> */
70    public function args(): array
71    {
72        return Arg::of($this->class);
73    }
74}