• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

elie29 / zend-di-config / 19967829054

05 Dec 2025 03:34PM UTC coverage: 95.0% (-5.0%) from 100.0%
19967829054

push

github

web-flow
Feature/v10: Major version updated (#62)

* Upgrade PHP version support, update dependencies, modify CI workflow, and refactor test cases in preparation for PHP 8.2+ compatibility #61

* 🤖 Upgrade to version 10.0.0, adding PHP 8.2 and PHPUnit 10 support, with an updated dependency stack.

* 🤖 Refactor AutowiresConfigDumperCommandTest for improved readability by aligning variable assignments and array structures.

* Refactor Psalm configuration, improve type handling in Config and AutowiresConfigDumper, and clean up related tests #61

---------

Co-authored-by: Elie NEHME <elie.nehme@soprasterianext.com>

9 of 9 new or added lines in 3 files covered. (100.0%)

9 existing lines in 1 file now uncovered.

171 of 180 relevant lines covered (95.0%)

6.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.0
/src/Tool/AutowiresConfigDumperCommand.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Elie\PHPDI\Config\Tool;
6

7
use InvalidArgumentException;
8
use Laminas\Stdlib\ConsoleHelper;
9
use stdClass;
10

11
use function array_shift;
12
use function class_exists;
13
use function count;
14
use function dirname;
15
use function file_exists;
16
use function file_put_contents;
17
use function in_array;
18
use function is_array;
19
use function is_writable;
20
use function sprintf;
21

22
use const STDERR;
23
use const STDOUT;
24

25
class AutowiresConfigDumperCommand
26
{
27
    private const COMMAND_DUMP  = 'dump';
28
    private const COMMAND_ERROR = 'error';
29
    private const COMMAND_HELP  = 'help';
30

31
    private const HELP_TEMPLATE = <<<EOH
32
<info>Usage:</info>
33

34
  %s [-h|--help|help] <configFile> <className>
35

36
<info>Arguments:</info>
37

38
  <info>-h|--help|help</info>          This usage message
39
  <info><configFile></info>            Path to a config file for which to generate
40
                          configuration. If the file does not exist, it will
41
                          be created. If it does exist, it must return an
42
                          array, and the file will be updated with new
43
                          configuration.
44
  <info><className></info>             Name of the class to reflect and to be added
45
                          in as a new entry in the autowires configuration.
46

47
Reads the provided configuration file (creating it if it does not exist),
48
and adds the provided class name in the autowires array, writing the changes
49
back to the file. The class name is added once.
50
EOH;
51

52
    private ConsoleHelper $helper;
53

54
    public function __construct(private readonly string $scriptName = self::class, ?ConsoleHelper $helper = null)
55
    {
56
        $this->helper = $helper ?? new ConsoleHelper();
10✔
57
    }
58

59
    /**
60
     * @param array $args Argument list, minus script name
61
     * @return int Exit status
62
     */
63
    public function __invoke(array $args): int
64
    {
65
        $arguments = $this->parseArgs($args);
10✔
66

67
        switch ($arguments->command) {
10✔
68
            case self::COMMAND_HELP:
69
                $this->help();
4✔
70
                return 0;
4✔
71
            case self::COMMAND_ERROR:
72
                $this->helper->writeErrorMessage($arguments->message);
4✔
73
                $this->help(STDERR);
4✔
74
                return 1;
4✔
75
            case self::COMMAND_DUMP:
76
                // fall-through
77
            default:
78
                break;
2✔
79
        }
80

81
        $dumper = new AutowiresConfigDumper();
2✔
82

83
        try {
84
            /** @var array<array-key, mixed> $config */
85
            $config = $arguments->config;
2✔
86
            /** @var string $class */
87
            $class  = $arguments->class;
2✔
88
            $config = $dumper->createDependencyConfig($config, $class);
2✔
UNCOV
89
        } catch (InvalidArgumentException $e) {
×
UNCOV
90
            $this->helper->writeErrorMessage(sprintf(
×
UNCOV
91
                'Unable to create config for "%s": %s',
×
UNCOV
92
                $arguments->class,
×
UNCOV
93
                $e->getMessage()
×
UNCOV
94
            ));
×
UNCOV
95
            $this->help(STDERR);
×
UNCOV
96
            return 1;
×
97
        }
98

99
        file_put_contents($arguments->configFile, $dumper->dumpConfigFile($config));
2✔
100

101
        $this->helper->writeLine(sprintf(
2✔
102
            '<info>[DONE]</info> Changes written to %s',
2✔
103
            $arguments->configFile
2✔
104
        ));
2✔
105

106
        return 0;
2✔
107
    }
108

109
    private function parseArgs(array $args): stdClass
110
    {
111
        if (! count($args)) {
10✔
112
            return $this->createHelpArgument();
1✔
113
        }
114

115
        /** @var string|int|null $arg1 */
116
        $arg1 = array_shift($args);
9✔
117

118
        if (in_array($arg1, ['-h', '--help', 'help'], true)) {
9✔
119
            return $this->createHelpArgument();
3✔
120
        }
121

122
        if (! count($args)) {
6✔
123
            return $this->createErrorArgument('Missing class name');
1✔
124
        }
125

126
        $configFile = (string) $arg1;
5✔
127
        switch (file_exists($configFile)) {
5✔
128
            case true:
129
                $config = require $configFile;
1✔
130

131
                if (! is_array($config)) {
1✔
132
                    return $this->createErrorArgument(sprintf(
1✔
133
                        'Configuration at path "%s" does not return an array.',
1✔
134
                        $configFile
1✔
135
                    ));
1✔
136
                }
137

UNCOV
138
                break;
×
139
            case false:
4✔
140
                // fall-through
141
            default:
142
                if (! is_writable(dirname($configFile))) {
4✔
143
                    return $this->createErrorArgument(sprintf(
1✔
144
                        'Cannot create configuration at path "%s"; not writable.',
1✔
145
                        $configFile
1✔
146
                    ));
1✔
147
                }
148

149
                $config = [];
3✔
150
                break;
3✔
151
        }
152

153
        $class = (string) array_shift($args);
3✔
154

155
        if (! class_exists($class)) {
3✔
156
            return $this->createErrorArgument(sprintf(
1✔
157
                'Class "%s" does not exist or could not be autoloaded.',
1✔
158
                $class
1✔
159
            ));
1✔
160
        }
161

162
        return $this->createArguments($configFile, $config, $class);
2✔
163
    }
164

165
    /**
166
     * @param bool|resource $resource Defaults to STDOUT
167
     */
168
    private function help(mixed $resource = STDOUT): void
169
    {
170
        $this->helper->writeLine(sprintf(
8✔
171
            self::HELP_TEMPLATE,
8✔
172
            $this->scriptName
8✔
173
        ), true, $resource);
8✔
174
    }
175

176
    /** @psalm-suppress LessSpecificReturnStatement */
177
    private function createArguments(string $configFile, array $config, string $class): stdClass
178
    {
179
        return (object) [
2✔
180
            'command'    => self::COMMAND_DUMP,
2✔
181
            'configFile' => $configFile,
2✔
182
            'config'     => $config,
2✔
183
            'class'      => $class,
2✔
184
        ];
2✔
185
    }
186

187
    /** @psalm-suppress LessSpecificReturnStatement */
188
    private function createErrorArgument(string $message): stdClass
189
    {
190
        return (object) [
4✔
191
            'command' => self::COMMAND_ERROR,
4✔
192
            'message' => $message,
4✔
193
        ];
4✔
194
    }
195

196
    /** @psalm-suppress LessSpecificReturnStatement */
197
    private function createHelpArgument(): stdClass
198
    {
199
        return (object) [
4✔
200
            'command' => self::COMMAND_HELP,
4✔
201
        ];
4✔
202
    }
203
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc