Generator::getServices()   A
last analyzed

Complexity

Conditions 5
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

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

279
            $wsdl->addSchema(new Schema($wsdl->getGenerator(), $schemaLocation, /** @scrutinizer ignore-type */ $this->getUrlContent($schemaLocation)));
Loading history...
280
        }
281
282 66
        return $this;
283
    }
284
285 156
    public function getServiceName(string $methodName): string
286
    {
287 156
        return ucfirst($this->getGather(new EmptyModel($this, $methodName)));
288
    }
289
290 430
    public function getOptions(): ?GeneratorOptions
291
    {
292 430
        return $this->options;
293
    }
294
295 132
    public function getSoapClient(): GeneratorSoapClient
296
    {
297 132
        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...
298
    }
299
300 462
    public function getUrlContent(string $url): ?string
301
    {
302 462
        if (false !== mb_strpos($url, '://')) {
303 4
            $content = Utils::getContentFromUrl($url, $this->getOptionBasicLogin(), $this->getOptionBasicPassword(), $this->getOptionProxyHost(), $this->getOptionProxyPort(), $this->getOptionProxyLogin(), $this->getOptionProxyPassword(), $this->getSoapClient()->getSoapClientStreamContextOptions());
304 4
            if ($this->getOptionSchemasSave()) {
305 2
                Utils::saveSchemas($this->getOptionDestination(), $this->getOptionSchemasFolder(), $url, $content);
306
            }
307
308 4
            return $content;
309
        }
310 458
        if (is_file($url)) {
311 456
            return file_get_contents($url);
312
        }
313
314 2
        return null;
315
    }
316
317 214
    public function getContainers(): GeneratorContainers
318
    {
319 214
        return $this->containers;
320
    }
321
322 2
    public function jsonSerialize(): array
323
    {
324 2
        return [
325 2
            'containers' => $this->containers,
326 2
            'options' => $this->options,
327 2
        ];
328
    }
329
330 216
    public static function instanceFromSerializedJson(string $json): Generator
331
    {
332 216
        $decodedJson = json_decode($json, true);
333 216
        if (JSON_ERROR_NONE === json_last_error()) {
334
            // load options first
335 214
            $options = GeneratorOptions::instance();
336 214
            foreach ($decodedJson['options'] as $name => $value) {
337 214
                $options->setOptionValue($name, $value);
338
            }
339
            // create generator instance with options
340 214
            $instance = new self($options);
341
            // load services
342 214
            foreach ($decodedJson['containers']['services'] as $service) {
343 214
                $instance->getContainers()->getServices()->add(self::getModelInstanceFromJsonArrayEntry($instance, $service));
344
            }
345
            // load structs
346 214
            foreach ($decodedJson['containers']['structs'] as $struct) {
347 214
                $instance->getContainers()->getStructs()->add(self::getModelInstanceFromJsonArrayEntry($instance, $struct));
348
            }
349
        } else {
350 2
            throw new \InvalidArgumentException(sprintf('Json is invalid, please check error %s', json_last_error()));
351
        }
352
353 214
        return $instance;
354
    }
355
356 460
    protected function initialize(): self
357
    {
358 460
        return $this
359 460
            ->initContainers()
360 460
            ->initParsers()
361 460
            ->initFiles()
362 460
            ->initSoapClient()
363 460
            ->initWsdl()
364 460
        ;
365
    }
366
367 460
    protected function initSoapClient(): self
368
    {
369 460
        if (!isset($this->soapClient)) {
370 460
            $this->soapClient = new GeneratorSoapClient($this);
371
        }
372
373 456
        return $this;
374
    }
375
376 460
    protected function initContainers(): self
377
    {
378 460
        if (!isset($this->containers)) {
379 460
            $this->containers = new GeneratorContainers($this);
380
        }
381
382 460
        return $this;
383
    }
384
385 460
    protected function initParsers(): self
386
    {
387 460
        if (!isset($this->parsers)) {
388 460
            $this->parsers = new GeneratorParsers($this);
389
        }
390
391 460
        return $this;
392
    }
393
394 460
    protected function initFiles(): self
395
    {
396 460
        if (!isset($this->files)) {
397 460
            $this->files = new GeneratorFiles($this);
398
        }
399
400 460
        return $this;
401
    }
402
403 12
    protected function initDirectory(): self
404
    {
405 12
        Utils::createDirectory($this->getOptions()->getDestination());
406 12
        if (!is_writable($this->getOptionDestination())) {
407
            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__);
408
        }
409
410 12
        return $this;
411
    }
412
413 458
    protected function initWsdl(): self
414
    {
415 458
        $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

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