Passed
Push — develop ( e6f84d...350782 )
by Mikaël
09:01 queued 28s
created

Generator::getOptionSuffix()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace WsdlToPhp\PackageGenerator\Generator;
6
7
use InvalidArgumentException;
8
use JsonSerializable;
9
use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
10
use WsdlToPhp\PackageGenerator\Container\Model\Service as ServiceContainer;
11
use WsdlToPhp\PackageGenerator\Container\Model\Struct as StructContainer;
12
use WsdlToPhp\PackageGenerator\Model\AbstractModel;
13
use WsdlToPhp\PackageGenerator\Model\EmptyModel;
14
use WsdlToPhp\PackageGenerator\Model\Method;
15
use WsdlToPhp\PackageGenerator\Model\Schema;
16
use WsdlToPhp\PackageGenerator\Model\Service;
17
use WsdlToPhp\PackageGenerator\Model\Struct;
18
use WsdlToPhp\PackageGenerator\Model\Wsdl;
19
20
/**
21
 * @method string getOptionCategory()
22
 * @method self   setOptionCategory(string $category)
23
 * @method string getOptionGatherMethods()
24
 * @method self   setOptionGatherMethods(string $gatherMethods)
25
 * @method bool   getOptionGenericConstantsNames()
26
 * @method self   setOptionGenericConstantsNames(bool $genericConstantsNames)
27
 * @method bool   getOptionGenerateTutorialFile()
28
 * @method self   setOptionGenerateTutorialFile(bool $generateTutorialFile)
29
 * @method string getOptionNamespace()
30
 * @method self   setOptionNamespace(string $namespace)
31
 * @method bool   getOptionNamespaceDictatesDirectories()
32
 * @method self   setOptionNamespaceDictatesDirectories(bool $namespaceDictatesDirectories)
33
 * @method array  getOptionAddComments()
34
 * @method self   setOptionAddComments(array $addComments)
35
 * @method bool   getOptionStandalone()
36
 * @method self   setOptionStandalone(bool $standalone)
37
 * @method bool   getOptionValidation()
38
 * @method self   setOptionValidation(bool $validation)
39
 * @method string getOptionStructClass()
40
 * @method self   setOptionStructClass(string $structClass)
41
 * @method string getOptionStructArrayClass()
42
 * @method self   setOptionStructArrayClass(string $structArrayClass)
43
 * @method string getOptionStructEnumClass()
44
 * @method self   setOptionStructEnumClass(string $structEnumClass)
45
 * @method string getOptionSoapClientClass()
46
 * @method self   setOptionSoapClientClass(string $soapClientClass)
47
 * @method self   setOptionPrefix(string $optionPrefix)
48
 * @method self   setOptionSuffix(string $optionSuffix)
49
 * @method string getOptionBasicLogin()
50
 * @method self   setOptionBasicLogin(string $optionBasicLogin)
51
 * @method string getOptionBasicPassword()
52
 * @method self   setOptionBasicPassword(string $optionBasicPassword)
53
 * @method string getOptionProxyHost()
54
 * @method self   setOptionProxyHost(string $optionProxyHost)
55
 * @method string getOptionProxyPort()
56
 * @method self   setOptionProxyPort(string $optionProxyPort)
57
 * @method string getOptionProxyLogin()
58
 * @method self   setOptionProxyLogin(string $optionProxyLogin)
59
 * @method string getOptionProxyPassword()
60
 * @method self   setOptionProxyPassword(string $optionProxyPassword)
61
 * @method string getOptionOrigin()
62
 * @method string getOptionSrcDirname()
63
 * @method self   setOptionSrcDirname(string $optionSrcDirname)
64
 * @method array  getOptionSoapOptions()
65
 * @method string getOptionComposerName()
66
 * @method array  getOptionComposerSettings()
67
 * @method self   setOptionComposerSettings(array $optionComposerSettings)
68
 * @method string getOptionStructsFolder()
69
 * @method self   setOptionStructsFolder(string $optionStructsFolder)
70
 * @method string getOptionArraysFolder()
71
 * @method self   setOptionArraysFolder(string $optionArraysFolder)
72
 * @method string getOptionEnumsFolder()
73
 * @method self   setOptionEnumsFolder(string $optionEnumsFolder)
74
 * @method string getOptionServicesFolder()
75
 * @method self   setOptionServicesFolder(string $optionServicesFolder)
76
 * @method bool   getOptionSchemasSave()
77
 * @method self   setOptionSchemasSave(bool $optionSchemasSave)
78
 * @method string getOptionSchemasFolder()
79
 * @method self   setOptionSchemasFolder(string $optionSchemasFolder)
80
 * @method string getOptionXsdTypesPath()
81
 * @method self   setOptionXsdTypesPath(string $xsdTypesPath)
82
 */
83
class Generator implements JsonSerializable
84
{
85
    protected Wsdl $wsdl;
86
87
    protected GeneratorOptions $options;
88
89
    protected GeneratorParsers $parsers;
90
91
    protected GeneratorFiles $files;
92
93
    protected GeneratorContainers $containers;
94
95
    protected ?GeneratorSoapClient $soapClient = null;
96
97 412
    public function __construct(GeneratorOptions $options)
98
    {
99
        $this
100 412
            ->setOptions($options)
101 412
            ->initialize()
102
        ;
103
    }
104
105 614
    public function __call($name, $arguments)
106
    {
107 614
        if (($prefix = 'getOption') === substr($name, 0, $length = strlen($prefix)) && empty($arguments)) {
108 606
            $getMethod = 'get'.substr($name, $length);
109
110 606
            return $this->options->{$getMethod}();
111
        }
112 125
        if (($prefix = 'setOption') === substr($name, 0, $length = strlen($prefix)) && 1 === count($arguments)) {
113 125
            $setMethod = 'set'.substr($name, $length);
114 125
            $this->options->{$setMethod}(array_shift($arguments));
115
116 125
            return $this;
117
        }
118
119
        throw new \BadMethodCallException(sprintf('Method %s is undefined', $name));
120
    }
121
122 65
    public function getParsers(): GeneratorParsers
123
    {
124 65
        return $this->parsers;
125
    }
126
127 20
    public function getFiles(): GeneratorFiles
128
    {
129 20
        return $this->files;
130
    }
131
132 10
    public function generatePackage(): self
133
    {
134
        return $this
135 10
            ->doSanityChecks()
136 6
            ->parse()
137 6
            ->initDirectory()
138 6
            ->doGenerate()
139
        ;
140
    }
141
142 8
    public function parse(): self
143
    {
144 8
        return $this->doParse();
145
    }
146
147
    /**
148
     * Gets the struct by its name
149
     * Starting from issue #157, we know call getVirtual secondly as structs are now betterly parsed and so is their inheritance/type is detected.
150
     *
151
     * @param string $structName the original struct name
152
     *
153
     * @uses Generator::getStructs()
154
     */
155 348
    public function getStructByName(string $structName): ?Struct
156
    {
157 348
        $struct = $this->getStructs()->getStructByName($structName);
158
159 348
        return $struct ?: $this->getStructs()->getVirtual($structName);
160
    }
161
162 157
    public function getStructByNameAndType(string $structName, string $type): ?Struct
163
    {
164 157
        return $this->getStructs()->getStructByNameAndType($structName, $type);
165
    }
166
167 68
    public function getService(string $serviceName): ?Service
168
    {
169 68
        return $this->getServices()->getServiceByName($serviceName);
170
    }
171
172 64
    public function getServiceMethod(string $methodName): ?Method
173
    {
174 64
        return $this->getService($this->getServiceName($methodName)) instanceof Service ? $this->getService($this->getServiceName($methodName))->getMethod($methodName) : null;
175
    }
176
177 170
    public function getServices(bool $usingGatherMethods = false): ServiceContainer
178
    {
179 170
        $services = $this->containers->getServices();
180 170
        if ($usingGatherMethods && GeneratorOptions::VALUE_NONE === $this->getOptionGatherMethods()) {
181 4
            $serviceContainer = new ServiceContainer($this);
182 4
            $serviceModel = new Service($this, Service::DEFAULT_SERVICE_CLASS_NAME);
183 4
            foreach ($services as $service) {
184 4
                foreach ($service->getMethods() as $method) {
185 4
                    $serviceModel->getMethods()->add($method);
186
                }
187
            }
188 4
            $serviceContainer->add($serviceModel);
189 4
            $services = $serviceContainer;
190
        }
191
192 170
        return $services;
193
    }
194
195 394
    public function getStructs(): StructContainer
196
    {
197 394
        return $this->containers->getStructs();
198
    }
199
200 224
    public function getOptionNamespacePrefix(): string
201
    {
202 224
        return $this->options->getNamespace();
203
    }
204
205 18
    public function setOptionNamespacePrefix(string $namespace): self
206
    {
207 18
        $this->options->setNamespace($namespace);
208
209 18
        return $this;
210
    }
211
212 392
    public function getOptionPrefix(bool $ucFirst = true): string
213
    {
214 392
        return $ucFirst ? ucfirst($this->getOptions()->getPrefix()) : $this->getOptions()->getPrefix();
215
    }
216
217 388
    public function getOptionSuffix(bool $ucFirst = true): string
218
    {
219 388
        return $ucFirst ? ucfirst($this->getOptions()->getSuffix()) : $this->getOptions()->getSuffix();
220
    }
221
222 2
    public function setOptionOrigin(string $optionOrigin): self
223
    {
224 2
        $this->options->setOrigin($optionOrigin);
225 2
        $this->initWsdl();
226
227 2
        return $this;
228
    }
229
230 213
    public function getOptionDestination(): string
231
    {
232 213
        $destination = $this->options->getDestination();
233 213
        if (!empty($destination)) {
234 211
            $destination = rtrim($destination, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
235
        }
236
237 213
        return $destination;
238
    }
239
240 4
    public function setOptionDestination(string $optionDestination): self
241
    {
242 4
        if (!empty($optionDestination)) {
243 2
            $this->options->setDestination(rtrim($optionDestination, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR);
244
        } else {
245 2
            throw new InvalidArgumentException('Package\'s destination can\'t be empty', __LINE__);
246
        }
247
248 2
        return $this;
249
    }
250
251 2
    public function setOptionSoapOptions(array $optionSoapOptions): self
252
    {
253 2
        $this->options->setSoapOptions($optionSoapOptions);
254
255 2
        if ($this->soapClient) {
256 2
            $this->soapClient->initSoapClient();
257
        }
258
259 2
        return $this;
260
    }
261
262 14
    public function setOptionComposerName(string $optionComposerName): self
263
    {
264 14
        if (!empty($optionComposerName)) {
265 12
            $this->options->setComposerName($optionComposerName);
266
        } else {
267 2
            throw new InvalidArgumentException('Package\'s composer name can\'t be empty', __LINE__);
268
        }
269
270 12
        return $this;
271
    }
272
273 228
    public function getWsdl(): ?Wsdl
274
    {
275 228
        return $this->wsdl;
276
    }
277
278 65
    public function addSchemaToWsdl(Wsdl $wsdl, string $schemaLocation): self
279
    {
280 65
        if (!empty($schemaLocation) && !$wsdl->hasSchema($schemaLocation)) {
281 65
            $wsdl->addSchema(new Schema($wsdl->getGenerator(), $schemaLocation, $this->getUrlContent($schemaLocation)));
0 ignored issues
show
Bug introduced by
It seems like $this->getUrlContent($schemaLocation) can also be of type null; however, parameter $content of WsdlToPhp\PackageGenerat...l\Schema::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

281
            $wsdl->addSchema(new Schema($wsdl->getGenerator(), $schemaLocation, /** @scrutinizer ignore-type */ $this->getUrlContent($schemaLocation)));
Loading history...
282
        }
283
284 65
        return $this;
285
    }
286
287 150
    public function getServiceName(string $methodName): string
288
    {
289 150
        return ucfirst($this->getGather(new EmptyModel($this, $methodName)));
290
    }
291
292 396
    public function getOptions(): ?GeneratorOptions
293
    {
294 396
        return $this->options;
295
    }
296
297 126
    public function getSoapClient(): GeneratorSoapClient
298
    {
299 126
        return $this->soapClient;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->soapClient could return the type null which is incompatible with the type-hinted return WsdlToPhp\PackageGenerat...tor\GeneratorSoapClient. Consider adding an additional type-check to rule them out.
Loading history...
300
    }
301
302 414
    public function getUrlContent(string $url): ?string
303
    {
304 414
        if (false !== mb_strpos($url, '://')) {
305 4
            $content = Utils::getContentFromUrl($url, $this->getOptionBasicLogin(), $this->getOptionBasicPassword(), $this->getOptionProxyHost(), $this->getOptionProxyPort(), $this->getOptionProxyLogin(), $this->getOptionProxyPassword(), $this->getSoapClient()->getSoapClientStreamContextOptions());
306 4
            if ($this->getOptionSchemasSave()) {
307 2
                Utils::saveSchemas($this->getOptionDestination(), $this->getOptionSchemasFolder(), $url, $content);
308
            }
309
310 4
            return $content;
311
        }
312 410
        if (is_file($url)) {
313 408
            return file_get_contents($url);
314
        }
315
316 2
        return null;
317
    }
318
319 172
    public function getContainers(): GeneratorContainers
320
    {
321 172
        return $this->containers;
322
    }
323
324 2
    public function jsonSerialize(): array
325
    {
326
        return [
327 2
            'containers' => $this->containers,
328 2
            'options' => $this->options,
329
        ];
330
    }
331
332 174
    public static function instanceFromSerializedJson(string $json): Generator
333
    {
334 174
        $decodedJson = json_decode($json, true);
335 174
        if (JSON_ERROR_NONE === json_last_error()) {
336
            // load options first
337 172
            $options = GeneratorOptions::instance();
338 172
            foreach ($decodedJson['options'] as $name => $value) {
339 172
                $options->setOptionValue($name, $value);
0 ignored issues
show
Bug introduced by
The method setOptionValue() does not exist on WsdlToPhp\PackageGenerat...ader\AbstractYamlReader. It seems like you code against a sub-type of WsdlToPhp\PackageGenerat...ader\AbstractYamlReader such as WsdlToPhp\PackageGenerat...Reader\GeneratorOptions. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

339
                $options->/** @scrutinizer ignore-call */ 
340
                          setOptionValue($name, $value);
Loading history...
340
            }
341
            // create generator instance with options
342 172
            $instance = new self($options);
343
            // load services
344 172
            foreach ($decodedJson['containers']['services'] as $service) {
345 172
                $instance->getContainers()->getServices()->add(self::getModelInstanceFromJsonArrayEntry($instance, $service));
346
            }
347
            // load structs
348 172
            foreach ($decodedJson['containers']['structs'] as $struct) {
349 172
                $instance->getContainers()->getStructs()->add(self::getModelInstanceFromJsonArrayEntry($instance, $struct));
350
            }
351
        } else {
352 2
            throw new InvalidArgumentException(sprintf('Json is invalid, please check error %s', json_last_error()));
353
        }
354
355 172
        return $instance;
356
    }
357
358 412
    protected function initialize(): self
359
    {
360
        return $this
361 412
            ->initContainers()
362 412
            ->initParsers()
363 412
            ->initFiles()
364 412
            ->initSoapClient()
365 408
            ->initWsdl()
366
        ;
367
    }
368
369 412
    protected function initSoapClient(): self
370
    {
371 412
        if (!isset($this->soapClient)) {
372 412
            $this->soapClient = new GeneratorSoapClient($this);
373
        }
374
375 408
        return $this;
376
    }
377
378 412
    protected function initContainers(): self
379
    {
380 412
        if (!isset($this->containers)) {
381 412
            $this->containers = new GeneratorContainers($this);
382
        }
383
384 412
        return $this;
385
    }
386
387 412
    protected function initParsers(): self
388
    {
389 412
        if (!isset($this->parsers)) {
390 412
            $this->parsers = new GeneratorParsers($this);
391
        }
392
393 412
        return $this;
394
    }
395
396 412
    protected function initFiles(): self
397
    {
398 412
        if (!isset($this->files)) {
399 412
            $this->files = new GeneratorFiles($this);
400
        }
401
402 412
        return $this;
403
    }
404
405 6
    protected function initDirectory(): self
406
    {
407 6
        Utils::createDirectory($this->getOptions()->getDestination());
408 6
        if (!is_writable($this->getOptionDestination())) {
409
            throw new InvalidArgumentException(sprintf('Unable to use dir "%s" as dir does not exists, its creation has been impossible or it\'s not writable', $this->getOptionDestination()), __LINE__);
410
        }
411
412 6
        return $this;
413
    }
414
415 410
    protected function initWsdl(): self
416
    {
417 410
        $this->setWsdl(new Wsdl($this, $this->getOptionOrigin(), $this->getUrlContent($this->getOptionOrigin())));
0 ignored issues
show
Bug introduced by
It seems like $this->getUrlContent($this->getOptionOrigin()) can also be of type null; however, parameter $content of WsdlToPhp\PackageGenerat...del\Wsdl::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

417
        $this->setWsdl(new Wsdl($this, $this->getOptionOrigin(), /** @scrutinizer ignore-type */ $this->getUrlContent($this->getOptionOrigin())));
Loading history...
418
419 410
        return $this;
420
    }
421
422 10
    protected function doSanityChecks(): self
423
    {
424 10
        $destination = $this->getOptionDestination();
425 10
        if (empty($destination)) {
426 2
            throw new InvalidArgumentException('Package\'s destination must be defined', __LINE__);
427
        }
428
429 8
        $composerName = $this->getOptionComposerName();
430 8
        if ($this->getOptionStandalone() && empty($composerName)) {
431 2
            throw new InvalidArgumentException('Package\'s composer name must be defined', __LINE__);
432
        }
433
434 6
        return $this;
435
    }
436
437 8
    protected function doParse(): self
438
    {
439 8
        $this->parsers->doParse();
440
441 8
        return $this;
442
    }
443
444 6
    protected function doGenerate(): self
445
    {
446 6
        $this->files->doGenerate();
447
448 6
        return $this;
449
    }
450
451 410
    protected function setWsdl(Wsdl $wsdl): self
452
    {
453 410
        $this->wsdl = $wsdl;
454
455 410
        return $this;
456
    }
457
458 150
    protected function getGather(AbstractModel $model): string
459
    {
460 150
        return Utils::getPart($this->getOptionGatherMethods(), $model->getCleanName());
461
    }
462
463 412
    protected function setOptions(GeneratorOptions $options): self
464
    {
465 412
        $this->options = $options;
466
467 412
        return $this;
468
    }
469
470 172
    protected static function getModelInstanceFromJsonArrayEntry(Generator $generator, array $jsonArrayEntry): AbstractModel
471
    {
472 172
        return AbstractModel::instanceFromSerializedJson($generator, $jsonArrayEntry);
473
    }
474
}
475