Completed
Push — 2.x ( 043669...4fa139 )
by Mikaël
65:52 queued 32:03
created

AbstractModel::getDocSubPackages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace WsdlToPhp\PackageGenerator\Model;
4
5
use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
6
use WsdlToPhp\PackageGenerator\ConfigurationReader\PhpReservedKeyword;
7
use WsdlToPhp\PackageGenerator\ConfigurationReader\AbstractReservedWord;
8
use WsdlToPhp\PackageGenerator\Generator\Generator;
9
use WsdlToPhp\PackageGenerator\Generator\Utils as GeneratorUtils;
10
use WsdlToPhp\PackageGenerator\Generator\AbstractGeneratorAware;
11
12
/**
13
 * Class AbstractModel defines the basic properties and methods to operations and structs extracted from the WSDL
14
 */
15
abstract class AbstractModel extends AbstractGeneratorAware
16
{
17
    /**
18
     * Constant used to define the key to store documentation value in meta
19
     * @var string
20
     */
21
    const META_DOCUMENTATION = 'documentation';
22
    /**
23
     * Original name od the element
24
     * @var string
25
     */
26
    private $name = '';
27
    /**
28
     * Values associated to the operation
29
     * @var string[]
30
     */
31
    private $meta = array();
32
    /**
33
     * Define the inheritance of a struct by the name of the parent struct or type
34
     * @var string
35
     */
36
    private $inheritance = '';
37
    /**
38
     * Store the object which owns the current model
39
     * @var AbstractModel
40
     */
41
    private $owner = null;
42
    /**
43
     * Indicates that the current elemen is an abstract element.
44
     * It allows to generated an abstract class.
45
     * This will happen for element/complexType that are defined with abstract="true"
46
     * @var bool
47
     */
48
    private $isAbstract = false;
49
    /**
50
     * Replaced keywords time in order to generate unique new keyword
51
     * @var array
52
     */
53
    private static $replacedPhpReservedKeywords = array();
54
    /**
55
     * Replaced methods time in order to generate unique new method
56
     * @var array
57
     */
58
    private $replacedReservedMethods = array();
59
    /**
60
     * Unique name generated in order to ensure unique naming (for struct constructor and setters/getters even for different case attribute name whith same value)
61
     * @var array
62
     */
63
    private static $uniqueNames = array();
64
    /**
65
     * Main constructor
66
     * @uses AbstractModel::setName()
67
     * @param Generator $generator
68
     * @param string $name the original name
69
     */
70 752
    public function __construct(Generator $generator, $name)
71
    {
72 752
        parent::__construct($generator);
73 752
        $this->setName($name);
74 752
    }
75
    /**
76
     * @uses AbstractModel::getInheritedMoel()
77
     * @uses AbstractModel::getPackagedName()
78
     * @uses AbstractModel::getExtends()
79
     * @uses Struct::getIsStruct()
80
     * @return string
81
     */
82 216
    public function getExtendsClassName()
83
    {
84 216
        $extends = '';
85 216
        if (($model = $this->getInheritedMoel()) instanceof Struct && $model->getIsStruct()) {
86 20
            $extends = $model->getPackagedName();
87 15
        }
88 216
        if (empty($extends)) {
89 204
            $extends = $this->getExtends(true);
90 153
        }
91 216
        return $extends;
92
    }
93
    /**
94
     * Returns the name of the class the current class inherits from
95
     * @return string
96
     */
97 276
    public function getInheritance()
98
    {
99 276
        return $this->inheritance;
100
    }
101
    /**
102
     * Sets the name of the class the current class inherits from
103
     * @param string $inheritance
104
     * @return AbstractModel
105
     */
106 180
    public function setInheritance($inheritance = '')
107
    {
108 180
        $this->inheritance = $inheritance;
109 180
        return $this;
110
    }
111
    /**
112
     * @uses AbstractGeneratorAware::getGenerator()
113
     * @uses Generator::getStruct()
114
     * @uses AbstractModel::getInheritance()
115
     * @return Struct
116
     */
117 216
    public function getInheritedMoel()
118
    {
119 216
        return $this->getGenerator()->getStruct($this->getInheritance());
120
    }
121
    /**
122
     * Returns the meta
123
     * @return string[]
124
     */
125 296
    public function getMeta()
126
    {
127 296
        return $this->meta;
128
    }
129
    /**
130
     * Sets the meta
131
     * @param string[] $meta
132
     * @return AbstractModel
133
     */
134 4
    public function setMeta(array $meta = array())
135
    {
136 4
        $this->meta = $meta;
137 4
        return $this;
138
    }
139
    /**
140
     * Add meta information to the operation
141
     * @uses AbstractModel::getMeta()
142
     * @throws \InvalidArgumentException
143
     * @param string $metaName
144
     * @param mixed $metaValue
145
     * @return AbstractModel
146
     */
147 372
    public function addMeta($metaName, $metaValue)
148
    {
149 372
        if (!is_scalar($metaName) || (!is_scalar($metaValue) && !is_array($metaValue))) {
150 8
            throw new \InvalidArgumentException(sprintf('Invalid meta name "%s" or value "%s". Please provide scalar meta name and scalar or array meta value.', gettype($metaName), gettype($metaValue)), __LINE__);
151
        }
152 364
        $metaValue = is_scalar($metaValue) ? trim($metaValue) : $metaValue;
153 364
        if ((is_scalar($metaValue) && $metaValue !== '') || is_array($metaValue)) {
154 364
            if (!array_key_exists($metaName, $this->meta)) {
155 360
                $this->meta[$metaName] = $metaValue;
156 294
            } elseif (is_array($this->meta[$metaName]) && is_array($metaValue)) {
157 64
                $this->meta[$metaName] = array_merge($this->meta[$metaName], $metaValue);
158 68
            } elseif (is_array($this->meta[$metaName])) {
159 4
                array_push($this->meta[$metaName], $metaValue);
160 3
            } else {
161 16
                $this->meta[$metaName] = $metaValue;
162
            }
163 364
            ksort($this->meta);
164 273
        }
165 364
        return $this;
166
    }
167
    /**
168
     * Sets the documentation meta value.
169
     * Documentation is set as an array so if multiple documentation nodes are set for an unique element, it will gather them.
170
     * @uses AbstractModel::META_DOCUMENTATION
171
     * @uses AbstractModel::addMeta()
172
     * @param string $documentation the documentation from the WSDL
173
     * @return AbstractModel
174
     */
175 112
    public function setDocumentation($documentation)
176
    {
177 112
        return $this->addMeta(self::META_DOCUMENTATION, is_array($documentation) ? $documentation : array(
178 112
            $documentation,
179 84
        ));
180
    }
181
    /**
182
     * Returns a meta value according to its name
183
     * @uses AbstractModel::getMeta()
184
     * @param string $metaName the meta information name
185
     * @param mixed $fallback the fallback value if unset
186
     * @return mixed the meta information value
187
     */
188 240
    public function getMetaValue($metaName, $fallback = null)
189
    {
190 240
        $meta = $this->getMeta();
191 240
        return array_key_exists($metaName, $meta) ? $meta[$metaName] : $fallback;
192
    }
193
    /**
194
     * Returns the value of the first meta value assigned to the name
195
     * @param array $names the meta names to check
196
     * @param mixed $fallback the fallback value if anyone is set
197
     * @return mixed the meta information value
198
     */
199 104
    public function getMetaValueFirstSet(array $names, $fallback = null)
200
    {
201 104
        $meta = $this->getMeta();
202 104
        foreach ($names as $name) {
203 104
            if (array_key_exists($name, $meta)) {
204 86
                return $meta[$name];
205
            }
206 57
        }
207 76
        return $fallback;
208
    }
209
    /**
210
     * Returns the original name extracted from the WSDL
211
     * @return string
212
     */
213 652
    public function getName()
214
    {
215 652
        return $this->name;
216
    }
217
    /**
218
     * Sets the original name extracted from the WSDL
219
     * @param string $name
220
     * @return AbstractModel
221
     */
222 752
    public function setName($name)
223
    {
224 752
        $this->name = $name;
225 752
        return $this;
226
    }
227
    /**
228
     * Returns a valid clean name for PHP
229
     * @uses AbstractModel::getName()
230
     * @uses AbstractModel::cleanString()
231
     * @param bool $keepMultipleUnderscores optional, allows to keep the multiple consecutive underscores
232
     * @return string
233
     */
234 524
    public function getCleanName($keepMultipleUnderscores = true)
235
    {
236 524
        return self::cleanString($this->getName(), $keepMultipleUnderscores);
237
    }
238
    /**
239
     * Returns the owner model object
240
     * @return AbstractModel
241
     */
242 524
    public function getOwner()
243
    {
244 524
        return $this->owner;
245
    }
246
    /**
247
     * Sets the owner model object
248
     * @param AbstractModel $owner object the owner of the current model
249
     * @return AbstractModel
250
     */
251 572
    public function setOwner(AbstractModel $owner)
252
    {
253 572
        $this->owner = $owner;
254 572
        return $this;
255
    }
256
    /**
257
     * @return bool
258
     */
259 220
    public function getIsAbstract()
260
    {
261 220
        return $this->isAbstract;
262
    }
263
    /**
264
     * @param bool $isAbstract
265
     * @return AbstractModel
266
     */
267 20
    public function setIsAbstract($isAbstract)
268
    {
269 20
        $this->isAbstract = $isAbstract;
270 20
        return $this;
271
    }
272
    /**
273
     * Returns true if the original name is safe to use as a PHP property, variable name or class name
274
     * @uses AbstractModel::getName()
275
     * @uses AbstractModel::getCleanName()
276
     * @return bool
277
     */
278 180
    public function nameIsClean()
279
    {
280 180
        return ($this->getName() !== '' && $this->getName() === $this->getCleanName());
281
    }
282
    /**
283
     * Returns the packaged name
284
     * @uses AbstractModel::getNamespace()
285
     * @uses AbstractModel::getCleanName()
286
     * @uses AbstractModel::getContextualPart()
287
     * @uses AbstractModel::uniqueName()
288
     * @uses AbstractModel::replacePhpReservedKeyword()
289
     * @uses AbstractGeneratorAware::getGenerator()
290
     * @uses Generator::getOptionPrefix()
291
     * @uses Generator::getOptionSuffix()
292
     * @uses AbstractModel::uniqueName() to ensure unique naming of struct case sensitively
293
     * @return string
294
     */
295 512
    public function getPackagedName($namespaced = false)
296
    {
297 512
        $nameParts = array();
298 512
        if ($namespaced && $this->getNamespace() !== '') {
299 200
            $nameParts[] = sprintf('\%s\\', $this->getNamespace());
300 150
        }
301 512
        $cleanName = $this->getCleanName();
302 512
        if ($this->getGenerator()->getOptionPrefix() !== '') {
303 276
            $nameParts[] = $this->getGenerator()->getOptionPrefix();
304 207
        } else {
305 272
            $cleanName = self::replacePhpReservedKeyword($cleanName);
306
        }
307 512
        $nameParts[] = ucfirst(self::uniqueName($cleanName, $this->getContextualPart()));
308 512
        if ($this->getGenerator()->getOptionSuffix() !== '') {
309 24
            $nameParts[] = $this->getGenerator()->getOptionSuffix();
310 18
        }
311 512
        return implode('', $nameParts);
312
    }
313
    /**
314
     * Allows to define the contextual part of the class name for the package
315
     * @return string
316
     */
317 76
    public function getContextualPart()
318
    {
319 76
        return '';
320
    }
321
    /**
322
     * Allows to define from which class the curent model extends
323
     * @param bool $short
324
     * @return string|null
325
     */
326 40
    public function getExtends($short = false)
327
    {
328 40
        return '';
329
    }
330
    /**
331
     * @uses AbstractGeneratorAware::getGenerator()
332
     * @uses Generator::getOptionNamespacePrefix()
333
     * @uses Generator::getOptionPrefix()
334
     * @uses Generator::getOptionSuffix()
335
     * @uses AbstractModel::getSubDirectory()
336
     * @return string
337
     */
338 248
    public function getNamespace()
339
    {
340 248
        $namespaces = array();
341 248
        $namespace = $this->getGenerator()->getOptionNamespacePrefix();
342 248
        if (empty($namespace)) {
343 240
            if ($this->getGenerator()->getOptionPrefix() !== '') {
344 188
                $namespaces[] = $this->getGenerator()->getOptionPrefix();
345 193
            } elseif ($this->getGenerator()->getOptionSuffix() !== '') {
346 66
                $namespaces[] = $this->getGenerator()->getOptionSuffix();
347 6
            }
348 180
        } else {
349 8
            $namespaces[] = $namespace;
350
        }
351 248
        if ($this->getSubDirectory() !== '') {
352 236
            $namespaces[] = $this->getSubDirectory();
353 177
        }
354 248
        return implode('\\', $namespaces);
355
    }
356
    /**
357
     * Returns directory where to store class and create it if needed
358
     * @uses AbstractGeneratorAware::getGenerator()
359
     * @uses AbstractModel::getOptionCategory()
360
     * @uses AbstractGeneratorAware::getContextualPart()
361
     * @uses GeneratorOptions::VALUE_CAT
362
     * @return string
363
     */
364 272
    public function getSubDirectory()
365
    {
366 272
        $subDirectory = '';
367 272
        if ($this->getGenerator()->getOptionCategory() === GeneratorOptions::VALUE_CAT) {
368 268
            $subDirectory = $this->getContextualPart();
369 201
        }
370 272
        return $subDirectory;
371
    }
372
    /**
373
     * Returns the sub package name which the model belongs to
374
     * Must be overridden by sub classes
375
     * @return array
376
     */
377 4
    public function getDocSubPackages()
378
    {
379 4
        return array();
380
    }
381
    /**
382
     * Clean a string to make it valid as PHP variable
383
     * @uses GeneratorUtils::cleanString()
384
     * @param string $string the string to clean
385
     * @param bool $keepMultipleUnderscores optional, allows to keep the multiple consecutive underscores
386
     * @return string
387
     */
388 528
    public static function cleanString($string, $keepMultipleUnderscores = true)
389
    {
390 528
        return GeneratorUtils::cleanString($string, $keepMultipleUnderscores);
391
    }
392
    /**
393
     * Returns a usable keyword for a original keyword
394
     * @uses PhpReservedKeyword::instance()
395
     * @uses PhpReservedKeyword::is()
396
     * @param string $keyword the keyword
397
     * @param string $context the context
398
     * @return string
399
     */
400 508
    public static function replacePhpReservedKeyword($keyword, $context = null)
401
    {
402 508
        if (PhpReservedKeyword::instance()->is($keyword)) {
403 120
            if ($context !== null) {
404 68
                $keywordKey = $keyword . '_' . $context;
405 68
                if (!array_key_exists($keywordKey, self::$replacedPhpReservedKeywords)) {
406 40
                    self::$replacedPhpReservedKeywords[$keywordKey] = 0;
407 30
                } else {
408 28
                    self::$replacedPhpReservedKeywords[$keywordKey]++;
409
                }
410 68
                return '_' . $keyword . (self::$replacedPhpReservedKeywords[$keywordKey] ? '_' . self::$replacedPhpReservedKeywords[$keywordKey] : '');
411
            } else {
412 96
                return '_' . $keyword;
413
            }
414
        } else {
415 508
            return $keyword;
416
        }
417
    }
418
    /**
419
     * @throws \InvalidArgumentException
420
     * @param $filename
421
     * @return AbstractReservedWord
422
     */
423 4
    public function getReservedMethodsInstance($filename = null)
424
    {
425 4
        throw new \InvalidArgumentException(sprintf('The method %s should be defined in the class %s', __FUNCTION__, get_called_class(), __LINE__));
426
    }
427
    /**
428
     * Returns a usable method for a original method
429
     * @uses PhpReservedKeywords::instance()
430
     * @uses PhpReservedKeywords::is()
431
     * @param string $keyword the keyword
0 ignored issues
show
Bug introduced by
There is no parameter named $keyword. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
432
     * @param string $context the context
433
     * @return string
434
     */
435 512
    public function replaceReservedMethod($methodName, $context = null)
436
    {
437 512
        if ($this->getReservedMethodsInstance()->is($methodName)) {
438
            if ($context !== null) {
439
                $methodKey = $methodName . '_' . $context;
440
                if (!array_key_exists($methodKey, $this->replacedReservedMethods)) {
441
                    $this->replacedReservedMethods[$methodKey] = 0;
442
                } else {
443
                    $this->replacedReservedMethods[$methodKey]++;
444
                }
445
                return '_' . $methodName . ($this->replacedReservedMethods[$methodKey] ? '_' . $this->replacedReservedMethods[$methodKey] : '');
446
            } else {
447
                return '_' . $methodName;
448
            }
449
        } else {
450 512
            return $methodName;
451
        }
452
    }
453
    /**
454
     * Static method wich returns a unique name case sensitively
455
     * Useful to name methods case sensitively distinct, see http://the-echoplex.net/log/php-case-sensitivity
456
     * @param string $name the original name
457
     * @param string $context the context where the name is needed unique
458
     * @return string
459
     */
460 516
    protected static function uniqueName($name, $context)
461
    {
462 516
        $insensitiveKey = strtolower($name . '_' . $context);
463 516
        $sensitiveKey = $name . '_' . $context;
464 516
        if (array_key_exists($sensitiveKey, self::$uniqueNames)) {
465 512
            return self::$uniqueNames[$sensitiveKey];
466 444
        } elseif (!array_key_exists($insensitiveKey, self::$uniqueNames)) {
467 440
            self::$uniqueNames[$insensitiveKey] = 0;
468 330
        } else {
469 32
            self::$uniqueNames[$insensitiveKey]++;
470
        }
471 444
        $uniqueName = $name . (self::$uniqueNames[$insensitiveKey] ? '_' . self::$uniqueNames[$insensitiveKey] : '');
472 444
        self::$uniqueNames[$sensitiveKey] = $uniqueName;
473 444
        return $uniqueName;
474
    }
475
    /**
476
     * Gives the availability for test purpose and multiple package generation to purge unique names
477
     * @todo see if it can be removed by reviewing how unique names are generated
478
     */
479 292
    public static function purgeUniqueNames()
480
    {
481 292
        self::$uniqueNames = array();
482 292
    }
483
    /**
484
     * Gives the availability for test purpose and multiple package generation to purge reserved keywords usage
485
     * @todo see if it can be removed by reviewing how reserved keywords are generated
486
     */
487 268
    public static function purgePhpReservedKeywords()
488
    {
489 268
        self::$replacedPhpReservedKeywords = array();
490 268
    }
491
    /**
492
     * Gives the availability for test purpose and multiple package generation to purge reserved methods usage
493
     * @todo see if it can be removed by reviewing how reserved methods are generated
494
     */
495
    public static function purgeReservedMethods()
496
    {
497
        self::$replacedReservedMethods = array();
498
    }
499
}
500