Completed
Push — 1.x ( 257780...f31d1d )
by Mikaël
42:33 queued 33:38
created

AbstractModel::getIsAbstract()   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 748
    public function __construct(Generator $generator, $name)
71
    {
72 748
        parent::__construct($generator);
73 748
        $this->setName($name);
74 748
    }
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 20
        }
88 216
        if (empty($extends)) {
89 204
            $extends = $this->getExtends(true);
90 204
        }
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 AbstractModel
104
     */
105 180
    public function setInheritance($inheritance = '')
106
    {
107 180
        $this->inheritance = $inheritance;
108 180
        return $this;
109
    }
110
    /**
111
     * @uses AbstractGeneratorAware::getGenerator()
112
     * @uses Generator::getStruct()
113
     * @uses AbstractModel::getInheritance()
114
     * @return Struct
115
     */
116 216
    public function getInheritedMoel()
117
    {
118 216
        return $this->getGenerator()->getStruct($this->getInheritance());
119
    }
120
    /**
121
     * Returns the meta
122
     * @return string[]
123
     */
124 296
    public function getMeta()
125
    {
126 296
        return $this->meta;
127
    }
128
    /**
129
     * Sets the meta
130
     * @param string[] $meta
131
     * @return AbstractModel
132
     */
133 4
    public function setMeta(array $meta = array())
134
    {
135 4
        $this->meta = $meta;
136 4
        return $this;
137
    }
138
    /**
139
     * Add meta information to the operation
140
     * @uses AbstractModel::getMeta()
141
     * @throws \InvalidArgumentException
142
     * @param string $metaName
143
     * @param mixed $metaValue
144
     * @return AbstractModel
145
     */
146 372
    public function addMeta($metaName, $metaValue)
147
    {
148 372
        if (!is_scalar($metaName) || (!is_scalar($metaValue) && !is_array($metaValue))) {
149 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__);
150
        }
151 364
        $metaValue = is_scalar($metaValue) ? trim($metaValue) : $metaValue;
152 364
        if ((is_scalar($metaValue) && $metaValue !== '') || is_array($metaValue)) {
153 364
            if (!array_key_exists($metaName, $this->meta)) {
154 360
                $this->meta[$metaName] = $metaValue;
155 364
            } elseif (is_array($this->meta[$metaName]) && is_array($metaValue)) {
156 64
                $this->meta[$metaName] = array_merge($this->meta[$metaName], $metaValue);
157 84
            } elseif (is_array($this->meta[$metaName])) {
158 4
                array_push($this->meta[$metaName], $metaValue);
159 4
            } else {
160 16
                $this->meta[$metaName] = $metaValue;
161
            }
162 364
            ksort($this->meta);
163 364
        }
164 364
        return $this;
165
    }
166
    /**
167
     * Sets the documentation meta value.
168
     * Documentation is set as an array so if multiple documentation nodes are set for an unique element, it will gather them.
169
     * @uses AbstractModel::META_DOCUMENTATION
170
     * @uses AbstractModel::addMeta()
171
     * @param string $documentation the documentation from the WSDL
172
     * @return AbstractModel
173
     */
174 112
    public function setDocumentation($documentation)
175
    {
176 112
        return $this->addMeta(self::META_DOCUMENTATION, is_array($documentation) ? $documentation : array($documentation));
177
    }
178
    /**
179
     * Returns a meta value according to its name
180
     * @uses AbstractModel::getMeta()
181
     * @param string $metaName the meta information name
182
     * @param mixed $fallback the fallback value if unset
183
     * @return mixed the meta information value
184
     */
185 240
    public function getMetaValue($metaName, $fallback = null)
186
    {
187 240
        $meta = $this->getMeta();
188 240
        return array_key_exists($metaName, $meta) ? $meta[$metaName] : $fallback;
189
    }
190
    /**
191
     * Returns the value of the first meta value assigned to the name
192
     * @param array $names the meta names to check
193
     * @param mixed $fallback the fallback value if anyone is set
194
     * @return mixed the meta information value
195
     */
196 104
    public function getMetaValueFirstSet(array $names, $fallback = null)
197
    {
198 104
        $meta = $this->getMeta();
199 104
        foreach ($names as $name) {
200 104
            if (array_key_exists($name, $meta)) {
201 80
                return $meta[$name];
202
            }
203 76
        }
204 76
        return $fallback;
205
    }
206
    /**
207
     * Returns the original name extracted from the WSDL
208
     * @return string
209
     */
210 648
    public function getName()
211
    {
212 648
        return $this->name;
213
    }
214
    /**
215
     * Sets the original name extracted from the WSDL
216
     * @param string $name
217
     * @return AbstractModel
218
     */
219 748
    public function setName($name)
220
    {
221 748
        $this->name = $name;
222 748
        return $this;
223
    }
224
    /**
225
     * Returns a valid clean name for PHP
226
     * @uses AbstractModel::getName()
227
     * @uses AbstractModel::cleanString()
228
     * @param bool $keepMultipleUnderscores optional, allows to keep the multiple consecutive underscores
229
     * @return string
230
     */
231 524
    public function getCleanName($keepMultipleUnderscores = true)
232
    {
233 524
        return self::cleanString($this->getName(), $keepMultipleUnderscores);
234
    }
235
    /**
236
     * Returns the owner model object
237
     * @return AbstractModel
238
     */
239 524
    public function getOwner()
240
    {
241 524
        return $this->owner;
242
    }
243
    /**
244
     * Sets the owner model object
245
     * @param AbstractModel $owner object the owner of the current model
246
     * @return AbstractModel
247
     */
248 572
    public function setOwner(AbstractModel $owner)
249
    {
250 572
        $this->owner = $owner;
251 572
        return $this;
252
    }
253
    /**
254
     * @return bool
255
     */
256 220
    public function getIsAbstract()
257
    {
258 220
        return $this->isAbstract;
259
    }
260
    /**
261
     * @param bool $isAbstract
262
     * @return AbstractModel
263
     */
264 20
    public function setIsAbstract($isAbstract)
265
    {
266 20
        $this->isAbstract = $isAbstract;
267 20
        return $this;
268
    }
269
    /**
270
     * Returns true if the original name is safe to use as a PHP property, variable name or class name
271
     * @uses AbstractModel::getName()
272
     * @uses AbstractModel::getCleanName()
273
     * @return bool
274
     */
275 180
    public function nameIsClean()
276
    {
277 180
        return ($this->getName() !== '' && $this->getName() === $this->getCleanName());
278
    }
279
    /**
280
     * Returns the packaged name
281
     * @uses AbstractModel::getNamespace()
282
     * @uses AbstractModel::getCleanName()
283
     * @uses AbstractModel::getContextualPart()
284
     * @uses AbstractModel::uniqueName()
285
     * @uses AbstractModel::replacePhpReservedKeyword()
286
     * @uses AbstractGeneratorAware::getGenerator()
287
     * @uses Generator::getOptionPrefix()
288
     * @uses Generator::getOptionSuffix()
289
     * @uses AbstractModel::uniqueName() to ensure unique naming of struct case sensitively
290
     * @return string
291
     */
292 512
    public function getPackagedName($namespaced = false)
293
    {
294 512
        $nameParts = array();
295 512
        if ($namespaced && $this->getNamespace() !== '') {
296 200
            $nameParts[] = sprintf('\%s\\', $this->getNamespace());
297 200
        }
298 512
        $cleanName = $this->getCleanName();
299 512
        if ($this->getGenerator()->getOptionPrefix() !== '') {
300 276
            $nameParts[] = $this->getGenerator()->getOptionPrefix();
301 276
        } else {
302 272
            $cleanName = self::replacePhpReservedKeyword($cleanName);
303
        }
304 512
        $nameParts[] = ucfirst(self::uniqueName($cleanName, $this->getContextualPart()));
305 512
        if ($this->getGenerator()->getOptionSuffix() !== '') {
306 24
            $nameParts[] = $this->getGenerator()->getOptionSuffix();
307 24
        }
308 512
        return implode('', $nameParts);
309
    }
310
    /**
311
     * Allows to define the contextual part of the class name for the package
312
     * @return string
313
     */
314 72
    public function getContextualPart()
315
    {
316 72
        return '';
317
    }
318
    /**
319
     * Allows to define from which class the curent model extends
320
     * @param bool $short
321
     * @return string|null
322
     */
323 40
    public function getExtends($short = false)
324
    {
325 40
        return '';
326
    }
327
    /**
328
     * @uses AbstractGeneratorAware::getGenerator()
329
     * @uses Generator::getOptionNamespacePrefix()
330
     * @uses Generator::getOptionPrefix()
331
     * @uses Generator::getOptionSuffix()
332
     * @uses AbstractModel::getSubDirectory()
333
     * @return string
334
     */
335 244
    public function getNamespace()
336
    {
337 244
        $namespaces = array();
338 244
        $namespace = $this->getGenerator()->getOptionNamespacePrefix();
339 244
        if (empty($namespace)) {
340 236
            if ($this->getGenerator()->getOptionPrefix() !== '') {
341 184
                $namespaces[] = $this->getGenerator()->getOptionPrefix();
342 236
            } elseif ($this->getGenerator()->getOptionSuffix() !== '') {
343 8
                $namespaces[] = $this->getGenerator()->getOptionSuffix();
344 8
            }
345 236
        } else {
346 8
            $namespaces[] = $namespace;
347
        }
348 244
        if ($this->getSubDirectory() !== '') {
349 236
            $namespaces[] = $this->getSubDirectory();
350 236
        }
351 244
        return implode('\\', $namespaces);
352
    }
353
    /**
354
     * Returns directory where to store class and create it if needed
355
     * @uses AbstractGeneratorAware::getGenerator()
356
     * @uses AbstractModel::getOptionCategory()
357
     * @uses AbstractGeneratorAware::getContextualPart()
358
     * @uses GeneratorOptions::VALUE_CAT
359
     * @return string
360
     */
361 268
    public function getSubDirectory()
362
    {
363 268
        $subDirectory = '';
364 268
        if ($this->getGenerator()->getOptionCategory() === GeneratorOptions::VALUE_CAT) {
365 264
            $subDirectory = $this->getContextualPart();
366 264
        }
367 268
        return $subDirectory;
368
    }
369
    /**
370
     * Returns the sub package name which the model belongs to
371
     * Must be overridden by sub classes
372
     * @return array
373
     */
374 4
    public function getDocSubPackages()
375
    {
376 4
        return array();
377
    }
378
    /**
379
     * Clean a string to make it valid as PHP variable
380
     * @uses GeneratorUtils::cleanString()
381
     * @param string $string the string to clean
382
     * @param bool $keepMultipleUnderscores optional, allows to keep the multiple consecutive underscores
383
     * @return string
384
     */
385 528
    public static function cleanString($string, $keepMultipleUnderscores = true)
386
    {
387 528
        return GeneratorUtils::cleanString($string, $keepMultipleUnderscores);
388
    }
389
    /**
390
     * Returns a usable keyword for a original keyword
391
     * @uses PhpReservedKeyword::instance()
392
     * @uses PhpReservedKeyword::is()
393
     * @param string $keyword the keyword
394
     * @param string $context the context
395
     * @return string
396
     */
397 508
    public static function replacePhpReservedKeyword($keyword, $context = null)
398
    {
399 508
        if (PhpReservedKeyword::instance()->is($keyword)) {
400 120
            if ($context !== null) {
401 68
                $keywordKey = $keyword . '_' . $context;
402 68
                if (!array_key_exists($keywordKey, self::$replacedPhpReservedKeywords)) {
403 40
                    self::$replacedPhpReservedKeywords[$keywordKey] = 0;
404 40
                } else {
405 28
                    self::$replacedPhpReservedKeywords[$keywordKey]++;
406
                }
407 68
                return '_' . $keyword . (self::$replacedPhpReservedKeywords[$keywordKey] ? '_' . self::$replacedPhpReservedKeywords[$keywordKey] : '');
408
            } else {
409 96
                return '_' . $keyword;
410
            }
411
        } else {
412 508
            return $keyword;
413
        }
414
    }
415
    /**
416
     * @throws \InvalidArgumentException
417
     * @param $filename
418
     * @return AbstractReservedWord
419
     */
420 4
    public function getReservedMethodsInstance($filename = null)
421
    {
422 4
        throw new \InvalidArgumentException(sprintf('The method %s should be defined in the class %s', __FUNCTION__, get_called_class(), __LINE__));
423
    }
424
    /**
425
     * Returns a usable method for a original method
426
     * @uses PhpReservedKeywords::instance()
427
     * @uses PhpReservedKeywords::is()
428
     * @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...
429
     * @param string $context the context
430
     * @return string
431
     */
432 512
    public function replaceReservedMethod($methodName, $context = null)
433
    {
434 512
        if ($this->getReservedMethodsInstance()->is($methodName)) {
435
            if ($context !== null) {
436
                $methodKey = $methodName . '_' . $context;
437
                if (!array_key_exists($methodKey, $this->replacedReservedMethods)) {
438
                    $this->replacedReservedMethods[$methodKey] = 0;
439
                } else {
440
                    $this->replacedReservedMethods[$methodKey]++;
441
                }
442
                return '_' . $methodName . ($this->replacedReservedMethods[$methodKey] ? '_' . $this->replacedReservedMethods[$methodKey] : '');
443
            } else {
444
                return '_' . $methodName;
445
            }
446
        } else {
447 512
            return $methodName;
448
        }
449
    }
450
    /**
451
     * Static method wich returns a unique name case sensitively
452
     * Useful to name methods case sensitively distinct, see http://the-echoplex.net/log/php-case-sensitivity
453
     * @param string $name the original name
454
     * @param string $context the context where the name is needed unique
455
     * @return string
456
     */
457 516
    protected static function uniqueName($name, $context)
458
    {
459 516
        $insensitiveKey = strtolower($name . '_' . $context);
460 516
        $sensitiveKey = $name . '_' . $context;
461 516
        if (array_key_exists($sensitiveKey, self::$uniqueNames)) {
462 512
            return self::$uniqueNames[$sensitiveKey];
463 444
        } elseif (!array_key_exists($insensitiveKey, self::$uniqueNames)) {
464 440
            self::$uniqueNames[$insensitiveKey] = 0;
465 440
        } else {
466 32
            self::$uniqueNames[$insensitiveKey]++;
467
        }
468 444
        $uniqueName = $name . (self::$uniqueNames[$insensitiveKey] ? '_' . self::$uniqueNames[$insensitiveKey] : '');
469 444
        self::$uniqueNames[$sensitiveKey] = $uniqueName;
470 444
        return $uniqueName;
471
    }
472
    /**
473
     * Gives the availability for test purpose and multiple package generation to purge unique names
474
     * @todo see if it can be removed by reviewing how unique names are generated
475
     */
476 292
    public static function purgeUniqueNames()
477
    {
478 292
        self::$uniqueNames = array();
479 292
    }
480
    /**
481
     * Gives the availability for test purpose and multiple package generation to purge reserved keywords usage
482
     * @todo see if it can be removed by reviewing how reserved keywords are generated
483
     */
484 268
    public static function purgePhpReservedKeywords()
485
    {
486 268
        self::$replacedPhpReservedKeywords = array();
487 268
    }
488
    /**
489
     * Gives the availability for test purpose and multiple package generation to purge reserved methods usage
490
     * @todo see if it can be removed by reviewing how reserved methods are generated
491
     */
492
    public static function purgeReservedMethods()
493
    {
494
        self::$replacedReservedMethods = array();
495
    }
496
}
497