Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
Entry
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
6 / 6
8
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
 signature
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        public 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    /**
33     * @param class-string $class
34     *
35     * @psalm-suppress MixedMethodCall The command class is known only at runtime
36     */
37    public static function fromClass(string $class): self
38    {
39        return new self(Command::of($class), $class, static fn(): object => new $class());
40    }
41
42    /** @param class-string $class */
43    public static function fromFactory(string $class, Closure $factory): self
44    {
45        return new self(Command::of($class), $class, $factory);
46    }
47
48    /**
49     * @psalm-suppress MixedAssignment, MixedReturnStatement Psalm does not narrow the
50     *     factory's result by instanceof against a class-string; PHPStan and Mago do
51     */
52    public function command(): object
53    {
54        if ($this->command === null) {
55            $command = ($this->factory)();
56
57            // The metadata was read from the keyed class; an unrelated
58            // object would be described by one class and run as another.
59            if (!$command instanceof $this->class) {
60                throw new ValueError(
61                    "Factory for command '{$this->meta->full()}' must return a {$this->class}",
62                );
63            }
64
65            $this->command = $command;
66        }
67
68        return $this->command;
69    }
70
71    /**
72     * Reads the command's signature off the keyed class.
73     */
74    public function signature(): Signature
75    {
76        return Signature::of($this->class, $this->meta->full());
77    }
78}

Paths

Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

Entry->__construct
22        public readonly Command $meta,
23        public readonly string $class,
24        private readonly Closure $factory,
25    ) {}
Entry->command
54        if ($this->command === null) {
 
55            $command = ($this->factory)();
56
57            // The metadata was read from the keyed class; an unrelated
58            // object would be described by one class and run as another.
59            if (!$command instanceof $this->class) {
 
60                throw new ValueError(
61                    "Factory for command '{$this->meta->full()}' must return a {$this->class}",
54        if ($this->command === null) {
 
55            $command = ($this->factory)();
56
57            // The metadata was read from the keyed class; an unrelated
58            // object would be described by one class and run as another.
59            if (!$command instanceof $this->class) {
 
65            $this->command = $command;
66        }
67
68        return $this->command;
 
68        return $this->command;
69    }
54        if ($this->command === null) {
 
68        return $this->command;
69    }
Entry->fromClass
37    public static function fromClass(string $class): self
38    {
39        return new self(Command::of($class), $class, static fn(): object => new $class());
40    }
Entry->fromFactory
43    public static function fromFactory(string $class, Closure $factory): self
44    {
45        return new self(Command::of($class), $class, $factory);
46    }
Entry->fromInstance
27    public static function fromInstance(object $command): self
28    {
29        return new self(Command::of($command), $command::class, static fn(): object => $command);
30    }
Entry->signature
76        return Signature::of($this->class, $this->meta->full());
77    }
{closure:/workspace/celema/console/src/Entry.php:29-29}
29        return new self(Command::of($command), $command::class, static fn(): object => $command);
{closure:/workspace/celema/console/src/Entry.php:39-39}
39        return new self(Command::of($class), $class, static fn(): object => new $class());