Completed
Push — 2.x ( 4676c3...e446b3 )
by Mikaël
68:34 queued 33:12
created

AbstractModel::setOwner()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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 740
    public function __construct(Generator $generator, $name)
71
    {
72 740
        parent::__construct($generator);
73 740
        $this->setName($name);
74 740
    }
75
    /**
76
     * @uses AbstractModel::getInheritedMoel()
77
     * @uses AbstractModel::getPackagedName()
78
     * @uses AbstractModel::getExtends()
79
     * @uses Struct::getIsStruct()
80
     * @return string
81
     */
82 208
    public function getExtendsClassName()
83
    {
84 208
        $extends = '';
85 208
        if (($model = $this->getInheritedMoel()) instanceof Struct && $model->getIsStruct()) {
86 20
            $extends = $model->getPackagedName();
87 15
        }
88 208
        if (empty($extends)) {
89 196
            $extends = $this->getExtends(true);
90 147
        }
91 208
        return $extends;
92
    }
93
    /**
94
     * Returns the name of the class the current class inherits from
95
     * @return string
96
     */
97 268
    public function getInheritance()
98
    {
99 268
        return $this->inheritance;
100
    }
101
    /**
102
     * Sets the name of the class the current class inherits from
103
     * @param AbstractModel
104
     */
105 172
    public function setInheritance($inheritance = '')
106
    {
107 172
        $this->inheritance = $inheritance;
108 172
        return $this;
109
    }
110
    /**
111
     * @uses AbstractGeneratorAware::getGenerator()
112
     * @uses Generator::getStruct()
113
     * @uses AbstractModel::getInheritance()
114
     * @return Struct
115
     */
116 208
    public function getInheritedMoel()
117
    {
118 208
        return $this->getGenerator()->getStruct($this->getInheritance());
119
    }
120
    /**
121
     * Returns the meta
122
     * @return string[]
123
     */
124 288
    public function getMeta()
125
    {
126 288
        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 364
    public function addMeta($metaName, $metaValue)
147
    {
148 364
        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 356
        $metaValue = is_scalar($metaValue) ? trim($metaValue) : $metaValue;
152 356
        if ((is_scalar($metaValue) && $metaValue !== '') || is_array($metaValue)) {
153 356
            if (!array_key_exists($metaName, $this->meta)) {
154 352
                $this->meta[$metaName] = $metaValue;
155 286
            } elseif (is_array($this->meta[$metaName]) && is_array($metaValue)) {
156 56
                $this->meta[$metaName] = array_merge($this->meta[$metaName], $metaValue);
157 62
            } elseif (is_array($this->meta[$metaName])) {
158 4
                array_push($this->meta[$metaName], $metaValue);
159 3
            } else {
160 16
                $this->meta[$metaName] = $metaValue;
161
            }
162 356
            ksort($this->meta);
163 267
        }
164 356
        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 104
    public function setDocumentation($documentation)
175
    {
176 104
        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 232
    public function getMetaValue($metaName, $fallback = null)
186
    {
187 232
        $meta = $this->getMeta();
188 232
        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 86
                return $meta[$name];
202
            }
203 57
        }
204 76
        return $fallback;
205
    }
206
    /**
207
     * Returns the original name extracted from the WSDL
208
     * @return string
209
     */
210 640
    public function getName()
211
    {
212 640
        return $this->name;
213
    }
214
    /**
215
     * Sets the original name extracted from the WSDL
216
     * @param string $name
217
     * @return AbstractModel
218
     */
219 740
    public function setName($name)
220
    {
221 740
        $this->name = $name;
222 740
        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 516
    public function getCleanName($keepMultipleUnderscores = true)
232
    {
233 516
        return self::cleanString($this->getName(), $keepMultipleUnderscores);
234
    }
235
    /**
236
     * Returns the owner model object
237
     * @return AbstractModel
238
     */
239 516
    public function getOwner()
240
    {
241 516
        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 564
    public function setOwner(AbstractModel $owner)
249
    {
250 564
        $this->owner = $owner;
251 564
        return $this;
252
    }
253
    /**
254
     * @return bool
255
     */
256 212
    public function getIsAbstract()
257
    {
258 212
        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 504
    public function getPackagedName($namespaced = false)
293
    {
294 504
        $nameParts = array();
295 504
        if ($namespaced && $this->getNamespace() !== '') {
296 196
            $nameParts[] = sprintf('\%s\\', $this->getNamespace());
297 147
        }
298 504
        $cleanName = $this->getCleanName();
299 504
        if ($this->getGenerator()->getOptionPrefix() !== '') {
300 268
            $nameParts[] = $this->getGenerator()->getOptionPrefix();
301 201
        } else {
302 264
            $cleanName = self::replacePhpReservedKeyword($cleanName);
303
        }
304 504
        $nameParts[] = ucfirst(self::uniqueName($cleanName, $this->getContextualPart()));
305 504
        if ($this->getGenerator()->getOptionSuffix() !== '') {
306 24
            $nameParts[] = $this->getGenerator()->getOptionSuffix();
307 18
        }
308 504
        return implode('', $nameParts);
309
    }
310
    /**
311
     * Allows to define the contextual part of the class name for the package
312
     * @return string
313
     */
314 64
    public function getContextualPart()
315
    {
316 64
        return '';
317
    }
318
    /**
319
     * Allows to define from which class the curent model extends
320
     * @param bool $short
321
     * @return string|null
322
     */
323 32
    public function getExtends($short = false)
324
    {
325 32
        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 236
    public function getNamespace()
336
    {
337 236
        $namespaces = array();
338 236
        $namespace = $this->getGenerator()->getOptionNamespacePrefix();
339 236
        if (empty($namespace)) {
340 228
            if ($this->getGenerator()->getOptionPrefix() !== '') {
341 184
                $namespaces[] = $this->getGenerator()->getOptionPrefix();
342 182
            } elseif ($this->getGenerator()->getOptionSuffix() !== '') {
343 63
                $namespaces[] = $this->getGenerator()->getOptionSuffix();
344 6
            }
345 171
        } else {
346 8
            $namespaces[] = $namespace;
347
        }
348 236
        if ($this->getSubDirectory() !== '') {
349 232
            $namespaces[] = $this->getSubDirectory();
350 174
        }
351 236
        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 260
    public function getSubDirectory()
362
    {
363 260
        $subDirectory = '';
364 260
        if ($this->getGenerator()->getOptionCategory() === GeneratorOptions::VALUE_CAT) {
365 260
            $subDirectory = $this->getContextualPart();
366 195
        }
367 260
        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 520
    public static function cleanString($string, $keepMultipleUnderscores = true)
386
    {
387 520
        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 500
    public static function replacePhpReservedKeyword($keyword, $context = null)
398
    {
399 500
        if (PhpReservedKeyword::instance()->is($keyword)) {
400 112
            if ($context !== null) {
401 60
                $keywordKey = $keyword . '_' . $context;
402 60
                if (!array_key_exists($keywordKey, self::$replacedPhpReservedKeywords)) {
403 32
                    self::$replacedPhpReservedKeywords[$keywordKey] = 0;
404 24
                } else {
405 28
                    self::$replacedPhpReservedKeywords[$keywordKey]++;
406
                }
407 60
                return '_' . $keyword . (self::$replacedPhpReservedKeywords[$keywordKey] ? '_' . self::$replacedPhpReservedKeywords[$keywordKey] : '');
408
            } else {
409 88
                return '_' . $keyword;
410
            }
411
        } else {
412 500
            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 504
    public function replaceReservedMethod($methodName, $context = null)
433
    {
434 504
        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 504
            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 508
    protected static function uniqueName($name, $context)
458
    {
459 508
        $insensitiveKey = strtolower($name . '_' . $context);
460 508
        $sensitiveKey = $name . '_' . $context;
461 508
        if (array_key_exists($sensitiveKey, self::$uniqueNames)) {
462 504
            return self::$uniqueNames[$sensitiveKey];
463 436
        } elseif (!array_key_exists($insensitiveKey, self::$uniqueNames)) {
464 432
            self::$uniqueNames[$insensitiveKey] = 0;
465 324
        } else {
466 32
            self::$uniqueNames[$insensitiveKey]++;
467
        }
468 436
        $uniqueName = $name . (self::$uniqueNames[$insensitiveKey] ? '_' . self::$uniqueNames[$insensitiveKey] : '');
469 436
        self::$uniqueNames[$sensitiveKey] = $uniqueName;
470 436
        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 284
    public static function purgeUniqueNames()
477
    {
478 284
        self::$uniqueNames = array();
479 284
    }
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 260
    public static function purgePhpReservedKeywords()
485
    {
486 260
        self::$replacedPhpReservedKeywords = array();
487 260
    }
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