Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
99.28% covered (success)
99.28%
275 / 277
91.67% covered (success)
91.67%
11 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
GeneratePackageCommand
99.28% covered (success)
99.28%
275 / 277
91.67% covered (success)
91.67%
11 / 12
24
0.00% covered (danger)
0.00%
0 / 1
 getGenerator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGeneratorOptionsConfigOption
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 resolveGeneratorOptionsConfigPath
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getGeneratorOptionsPossibilities
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 setGenerator
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 initGenerator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 configure
100.00% covered (success)
100.00%
197 / 197
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
2
 getPackageGenerationCommandLineOptions
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
1 / 1
1
 initGeneratorOptions
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 formatOptionValue
60.00% covered (warning)
60.00%
3 / 5
0.00% covered (danger)
0.00%
0 / 1
10.14
 formatArrayForConsole
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace WsdlToPhp\PackageGenerator\Command;
6
7use Symfony\Component\Console\Input\InputInterface;
8use Symfony\Component\Console\Input\InputOption;
9use Symfony\Component\Console\Output\OutputInterface;
10use WsdlToPhp\PackageBase\AbstractSoapClientBase;
11use WsdlToPhp\PackageBase\AbstractStructArrayBase;
12use WsdlToPhp\PackageBase\AbstractStructBase;
13use WsdlToPhp\PackageBase\AbstractStructEnumBase;
14use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
15use WsdlToPhp\PackageGenerator\Generator\Generator;
16
17final class GeneratePackageCommand extends AbstractCommand
18{
19    public const GENERATOR_OPTIONS_CONFIG_OPTION = 'config';
20    public const PROPER_USER_CONFIGURATION = 'wsdltophp.yml';
21    public const DEFAULT_CONFIGURATION_FILE = 'wsdltophp.yml.dist';
22
23    protected Generator $generator;
24
25    protected GeneratorOptions $generatorOptions;
26
27    public function getGenerator(): Generator
28    {
29        return $this->generator;
30    }
31
32    public function getGeneratorOptionsConfigOption()
33    {
34        return $this->getOptionValue(self::GENERATOR_OPTIONS_CONFIG_OPTION);
35    }
36
37    public function resolveGeneratorOptionsConfigPath(): ?string
38    {
39        $path = null;
40        $possibilities = $this->getGeneratorOptionsPossibilities();
41        foreach ($possibilities as $possibility) {
42            if (!empty($possibility) && is_file($possibility)) {
43                $path = $possibility;
44
45                break;
46            }
47        }
48
49        return $path;
50    }
51
52    public function getGeneratorOptionsPossibilities(): array
53    {
54        return [
55            $this->getGeneratorOptionsConfigOption(),
56            sprintf('%s/%s', getcwd(), self::PROPER_USER_CONFIGURATION),
57            sprintf('%s/%s', getcwd(), self::DEFAULT_CONFIGURATION_FILE),
58            GeneratorOptions::getDefaultConfigurationPath(),
59        ];
60    }
61
62    protected function setGenerator(Generator $generator): self
63    {
64        $this->generator = $generator;
65
66        return $this;
67    }
68
69    protected function initGenerator(): self
70    {
71        return $this->setGenerator(new Generator($this->generatorOptions));
72    }
73
74    protected function configure(): void
75    {
76        parent::configure();
77        $this
78            ->setName('generate:package')
79            ->setDescription('Generate package based on options')
80            ->addOption(
81                'urlorpath',
82                null,
83                InputOption::VALUE_REQUIRED,
84                'Url or path to WSDL'
85            )
86            ->addOption(
87                'destination',
88                null,
89                InputOption::VALUE_REQUIRED,
90                'Path to destination directory, where the package will be generated'
91            )
92            ->addOption(
93                'login',
94                null,
95                InputOption::VALUE_OPTIONAL,
96                'Basic authentication login required to access the WSDL url, can be avoided mot of the time'
97            )
98            ->addOption(
99                'password',
100                null,
101                InputOption::VALUE_OPTIONAL,
102                'Basic authentication password required to access the WSDL url, can be avoided mot of the time'
103            )
104            ->addOption(
105                'proxy-host',
106                null,
107                InputOption::VALUE_OPTIONAL,
108                'Use proxy url'
109            )
110            ->addOption(
111                'proxy-port',
112                null,
113                InputOption::VALUE_OPTIONAL,
114                'Use proxy port'
115            )
116            ->addOption(
117                'proxy-login',
118                null,
119                InputOption::VALUE_OPTIONAL,
120                'Use proxy login'
121            )
122            ->addOption(
123                'proxy-password',
124                null,
125                InputOption::VALUE_OPTIONAL,
126                'Use proxy password'
127            )
128            ->addOption(
129                'prefix',
130                null,
131                InputOption::VALUE_REQUIRED,
132                'Prepend generated classes'
133            )
134            ->addOption(
135                'suffix',
136                null,
137                InputOption::VALUE_REQUIRED,
138                'Append generated classes'
139            )
140            ->addOption(
141                'namespace',
142                null,
143                InputOption::VALUE_OPTIONAL,
144                'Package classes\' namespace'
145            )
146            ->addOption(
147                'namespace-directories',
148                null,
149                InputOption::VALUE_OPTIONAL,
150                'Should the directories match the namespace path or not? True by default'
151            )
152            ->addOption(
153                'category',
154                null,
155                InputOption::VALUE_OPTIONAL,
156                'First level directory name generation mode (start, end, cat, none)'
157            )
158            ->addOption(
159                'gathermethods',
160                null,
161                InputOption::VALUE_OPTIONAL,
162                'Gather methods based on operation name mode (start, end)'
163            )
164            ->addOption(
165                'gentutorial',
166                null,
167                InputOption::VALUE_OPTIONAL,
168                'Enable/Disable tutorial file, you should enable this option only on dev'
169            )
170            ->addOption(
171                'genericconstants',
172                null,
173                InputOption::VALUE_OPTIONAL,
174                'Enable/Disable usage of generic constants name (ex : ENUM_VALUE_0, ENUM_VALUE_1, etc) or contextual values (ex : VALUE_STRING, VALUE_YES, VALUES_NO, etc)'
175            )
176            ->addOption(
177                'addcomments',
178                null,
179                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
180                'Set comments to be used within each generated file'
181            )
182            ->addOption(
183                'standalone',
184                null,
185                InputOption::VALUE_OPTIONAL,
186                'By default, the generated package can be used as a standalone. Otherwise, you must add wsdltophp/packagebase:dev-master to your main composer.json.'
187            )
188            ->addOption(
189                'validation',
190                null,
191                InputOption::VALUE_OPTIONAL,
192                'Enable/Disable the generation of validation rules in every generated setter.'
193            )
194            ->addOption(
195                'struct',
196                null,
197                InputOption::VALUE_OPTIONAL,
198                sprintf('Use this class as parent class for any StructType class. Default class is %s from wsdltophp/packagebase package', AbstractStructBase::class)
199            )
200            ->addOption(
201                'structarray',
202                null,
203                InputOption::VALUE_OPTIONAL,
204                sprintf('Use this class as parent class for any StructArrayType class. Default class is %s from wsdltophp/packagebase package', AbstractStructArrayBase::class)
205            )
206            ->addOption(
207                'structenum',
208                null,
209                InputOption::VALUE_OPTIONAL,
210                sprintf('Use this class as parent class for any StructEnumType class. Default class is %s from wsdltophp/packagebase package', AbstractStructEnumBase::class)
211            )
212            ->addOption(
213                'soapclient',
214                null,
215                InputOption::VALUE_OPTIONAL,
216                sprintf('Use this class as parent class for any ServiceType class. Default class is %s from wsdltophp/packagebase package', AbstractSoapClientBase::class)
217            )
218            ->addOption(
219                'composer-name',
220                null,
221                InputOption::VALUE_REQUIRED,
222                'Composer name of the generated package'
223            )
224            ->addOption(
225                'composer-settings',
226                null,
227                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
228                'Composer settings of the generated package'
229            )
230            ->addOption(
231                'structs-folder',
232                null,
233                InputOption::VALUE_OPTIONAL,
234                'Structs folder name (default: SructType)'
235            )
236            ->addOption(
237                'arrays-folder',
238                null,
239                InputOption::VALUE_OPTIONAL,
240                'Arrays folder name (default: ArrayType)'
241            )
242            ->addOption(
243                'enums-folder',
244                null,
245                InputOption::VALUE_OPTIONAL,
246                'Enumerations folder name (default: EnumType)'
247            )
248            ->addOption(
249                'services-folder',
250                null,
251                InputOption::VALUE_OPTIONAL,
252                'Services class folder name (default: ServiceType)'
253            )
254            ->addOption(
255                'src-dirname',
256                null,
257                InputOption::VALUE_OPTIONAL,
258                'Source directory subfolder oof destination directory (default: src)'
259            )
260            ->addOption(
261                'xsd-types-path',
262                null,
263                InputOption::VALUE_OPTIONAL,
264                'Path to the xsd types configuration file to load'
265            )
266            ->addOption(
267                self::GENERATOR_OPTIONS_CONFIG_OPTION,
268                null,
269                InputOption::VALUE_OPTIONAL,
270                'Path to the generator\'s configuration file to load'
271            )
272        ;
273    }
274
275    protected function execute(InputInterface $input, OutputInterface $output): int
276    {
277        parent::execute($input, $output);
278        $start = new \DateTime();
279        $this->writeLn(sprintf(' Start at %s', $start->format('Y-m-d H:i:s')));
280        $this->initGeneratorOptions();
281        if ($this->canExecute()) {
282            $this->initGenerator()->getGenerator()->generatePackage();
283        } else {
284            $this->writeLn('  Generation not launched, use "--force" option to force generation');
285            $this->writeLn(sprintf("  Generator's option file used: %s", $this->resolveGeneratorOptionsConfigPath()));
286            $this->writeLn("  Used generator's options:");
287            $this->writeLn('    '.implode(PHP_EOL.'    ', $this->formatArrayForConsole($this->generatorOptions->toArray())));
288        }
289        $end = new \DateTime();
290        $this->writeLn(sprintf(' End at %s, duration: %s', $end->format('Y-m-d H:i:s'), $start->diff($end)->format('%H:%I:%S')));
291
292        return self::EXIT_OK;
293    }
294
295    protected function getPackageGenerationCommandLineOptions(): array
296    {
297        return [
298            'addcomments' => GeneratorOptions::ADD_COMMENTS,
299            'arrays-folder' => GeneratorOptions::ARRAYS_FOLDER,
300            'composer-name' => GeneratorOptions::COMPOSER_NAME,
301            'composer-settings' => GeneratorOptions::COMPOSER_SETTINGS,
302            'category' => GeneratorOptions::CATEGORY,
303            'destination' => GeneratorOptions::DESTINATION,
304            'enums-folder' => GeneratorOptions::ENUMS_FOLDER,
305            'gathermethods' => GeneratorOptions::GATHER_METHODS,
306            'genericconstants' => GeneratorOptions::GENERIC_CONSTANTS_NAME,
307            'gentutorial' => GeneratorOptions::GENERATE_TUTORIAL_FILE,
308            'login' => GeneratorOptions::BASIC_LOGIN,
309            'namespace' => GeneratorOptions::NAMESPACE_PREFIX,
310            'namespace-directories' => GeneratorOptions::NAMESPACE_DICTATES_DIRECTORIES,
311            'password' => GeneratorOptions::BASIC_PASSWORD,
312            'prefix' => GeneratorOptions::PREFIX,
313            'proxy-host' => GeneratorOptions::PROXY_HOST,
314            'proxy-login' => GeneratorOptions::PROXY_LOGIN,
315            'proxy-password' => GeneratorOptions::PROXY_PASSWORD,
316            'proxy-port' => GeneratorOptions::PROXY_PORT,
317            'services-folder' => GeneratorOptions::SERVICES_FOLDER,
318            'src-dirname' => GeneratorOptions::SRC_DIRNAME,
319            'structarray' => GeneratorOptions::STRUCT_ARRAY_CLASS,
320            'structenum' => GeneratorOptions::STRUCT_ENUM_CLASS,
321            'structs-folder' => GeneratorOptions::STRUCTS_FOLDER,
322            'soapclient' => GeneratorOptions::SOAP_CLIENT_CLASS,
323            'struct' => GeneratorOptions::STRUCT_CLASS,
324            'standalone' => GeneratorOptions::STANDALONE,
325            'suffix' => GeneratorOptions::SUFFIX,
326            'urlorpath' => GeneratorOptions::ORIGIN,
327            'validation' => GeneratorOptions::VALIDATION,
328            'xsd-types-path' => GeneratorOptions::XSD_TYPES_PATH,
329        ];
330    }
331
332    protected function initGeneratorOptions(): self
333    {
334        /** @var GeneratorOptions $generatorOptions */
335        $generatorOptions = GeneratorOptions::instance($this->resolveGeneratorOptionsConfigPath());
336
337        foreach ($this->getPackageGenerationCommandLineOptions() as $optionName => $generatorOptionName) {
338            if (is_null($optionValue = $this->formatOptionValue($this->input->getOption($optionName)))) {
339                continue;
340            }
341            $generatorOptions->setOptionValue($generatorOptionName, $optionValue);
342        }
343        $this->generatorOptions = $generatorOptions;
344
345        return $this;
346    }
347
348    protected function formatOptionValue($optionValue)
349    {
350        if ('true' === $optionValue || (is_numeric($optionValue) && 1 === (int) $optionValue)) {
351            return true;
352        }
353        if ('false' === $optionValue || (is_numeric($optionValue) && 0 === (int) $optionValue)) {
354            return false;
355        }
356
357        return $optionValue;
358    }
359
360    /**
361     * Utility method to return readable array based on "key: value".
362     */
363    protected function formatArrayForConsole(array $array): array
364    {
365        array_walk($array, function (&$value, $index) {
366            $value = sprintf('%s: %s', $index, json_encode($value, JSON_THROW_ON_ERROR));
367        });
368
369        return $array;
370    }
371}