Completed
Push — develop ( d22805...7fc434 )
by Mikaël
35:39
created

getRestrictionFromStructAttribute()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 8
ccs 8
cts 8
cp 1
rs 9.4285
cc 3
eloc 5
nc 2
nop 1
crap 3
1
<?php
2
3
namespace WsdlToPhp\PackageGenerator\File;
4
5
use WsdlToPhp\PackageGenerator\Container\PhpElement\Method;
6
use WsdlToPhp\PackageGenerator\Container\PhpElement\Property;
7
use WsdlToPhp\PackageGenerator\Container\PhpElement\Constant;
8
use WsdlToPhp\PackageGenerator\Model\Struct as StructModel;
9
use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel;
10
use WsdlToPhp\PackageGenerator\Model\AbstractModel;
11
use WsdlToPhp\PackageGenerator\File\Utils as FileUtils;
12
use WsdlToPhp\PackageGenerator\Generator\Utils as GeneratorUtils;
13
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
14
use WsdlToPhp\PhpGenerator\Element\PhpAnnotation;
15
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
16
use WsdlToPhp\PhpGenerator\Element\PhpProperty;
17
use WsdlToPhp\PhpGenerator\Element\PhpConstant;
18
use WsdlToPhp\PhpGenerator\Component\PhpClass;
19
use WsdlToPhp\PackageGenerator\ConfigurationReader\XsdTypes;
20
21
abstract class AbstractModelFile extends AbstractFile
22
{
23
    /**
24
     * @var Long annotation string
25
     */
26
    const ANNOTATION_LONG_LENGTH = '250';
27
    /**
28
     * @var string
29
     */
30
    const ANNOTATION_PACKAGE = 'package';
31
    /**
32
     * @var string
33
     */
34
    const ANNOTATION_SUB_PACKAGE = 'subpackage';
35
    /**
36
     * @var string
37
     */
38
    const ANNOTATION_RETURN = 'return';
39
    /**
40
     * @var string
41
     */
42
    const ANNOTATION_USES = 'uses';
43
    /**
44
     * @var string
45
     */
46
    const ANNOTATION_PARAM = 'param';
47
    /**
48
     * @var string
49
     */
50
    const ANNOTATION_VAR = 'var';
51
    /**
52
     * @var string
53
     */
54
    const ANNOTATION_SEE = 'see';
55
    /**
56
     * @var string
57
     */
58
    const ANNOTATION_THROWS = 'throws';
59
    /**
60
     * @var string
61
     */
62
    const METHOD_CONSTRUCT = '__construct';
63
    /**
64
     * @var string
65
     */
66
    const METHOD_SET_STATE = '__set_state';
67
    /**
68
     * @var string
69
     */
70
    const TYPE_STRING = 'string';
71
    /**
72
     * @var string
73
     */
74
    const TYPE_ARRAY = 'array';
75
    /**
76
     * @var string
77
     */
78
    const SRC_FOLDER = 'src/';
79 184
    /**
80
     * @var AbstractModel
81 184
     */
82
    protected $model;
83
    /**
84
     * @param bool $withSrc
85
     * @return string
86
     */
87 184
    public function getFileDestination($withSrc = true)
88
    {
89 184
        return sprintf('%s%s%s', $this->getDestinationFolder($withSrc), $this->getModel()->getSubDirectory(), $this->getModel()->getSubDirectory() !== '' ? '/' : '');
90
    }
91
    /**
92
     * @param bool $withSrc
93
     * @return string
94
     */
95
    public function getDestinationFolder($withSrc = true)
96 164
    {
97
        return sprintf('%s%s', $this->getGenerator()->getOptionDestination(), $withSrc === true ? self::SRC_FOLDER : '');
98 164
    }
99 4
    /**
100
     * @see \WsdlToPhp\PackageGenerator\File\AbstractFile::writeFile()
101 160
     * @param bool $withSrc
102 120
     * @return int|bool
103 160
     */
104 160
    public function writeFile($withSrc = true)
105 160
    {
106 160
        if (!$this->getModel() instanceof AbstractModel) {
107 160
            throw new \InvalidArgumentException('You MUST define the model before begin able to generate the file', __LINE__);
108
        }
109
        GeneratorUtils::createDirectory($this->getFileDestination($withSrc));
110
        $this
111
            ->defineNamespace()
112 160
            ->defineUseStatement()
113
            ->addAnnotationBlock()
114 120
            ->addClassElement();
115 160
        return parent::writeFile();
116 160
    }
117 160
    /**
118
     * @return AbstractModelFile
119
     */
120
    protected function addAnnotationBlock()
121
    {
122
        $this
123 208
            ->getFile()
124
                ->addAnnotationBlockElement($this->getClassAnnotationBlock());
125 208
        return $this;
126 208
    }
127 208
    /**
128
     * @param AbstractModel $model
129
     * @return AbstractModelFile
130
     */
131
    public function setModel(AbstractModel $model)
132 212
    {
133
        $this->model = $model;
134 212
        $this->getFile()->getMainElement()->setName($model->getPackagedName());
135
        return $this;
136
    }
137
    /**
138
     * @return AbstractModel
139
     */
140 16
    public function getModel()
141
    {
142 16
        return $this->model;
143
    }
144
    /**
145
     * @param string $name
146
     * @return StructModel|null
147
     */
148 148
    protected function getModelByName($name)
149
    {
150 148
        return $this->getGenerator()->getStruct($name);
151 148
    }
152 128
    /**
153 96
     * @param PhpAnnotationBlock $block
154 148
     * @return AbstractModelFile
155 148
     */
156 111
    protected function definePackageAnnotations(PhpAnnotationBlock $block)
157 148
    {
158
        $packageName = $this->getPackageName();
159
        if (!empty($packageName)) {
160
            $block->addChild(new PhpAnnotation(self::ANNOTATION_PACKAGE, $packageName));
161
        }
162 148
        if (count($this->getModel()->getDocSubPackages()) > 0) {
163
            $block->addChild(new PhpAnnotation(self::ANNOTATION_SUB_PACKAGE, implode(',', $this->getModel()->getDocSubPackages())));
164 148
        }
165 148
        return $this;
166 120
    }
167 118
    /**
168 8
     * @return string
169 6
     */
170 148
    protected function getPackageName()
171
    {
172
        $packageName = '';
173
        if ($this->getGenerator()->getOptionPrefix() !== '') {
174
            $packageName = $this->getGenerator()->getOptionPrefix();
175
        } elseif ($this->getGenerator()->getOptionSuffix() !== '') {
176 148
            $packageName = $this->getGenerator()->getOptionSuffix();
177
        }
178 148
        return $packageName;
179 128
    }
180 111
    /**
181 148
     * @param PhpAnnotationBlock $block
182
     * @return AbstractModelFile
183
     */
184
    protected function defineGeneralAnnotations(PhpAnnotationBlock $block)
185
    {
186 148
        foreach ($this->getGenerator()->getOptionAddComments() as $tagName => $tagValue) {
187
            $block->addChild(new PhpAnnotation($tagName, $tagValue));
188 148
        }
189 148
        return $this;
190 111
    }
191 148
    /**
192 148
     * @return PhpAnnotationBlock
193 148
     */
194 148
    protected function getClassAnnotationBlock()
195 148
    {
196
        $block = new PhpAnnotationBlock();
197
        $block->addChild($this->getClassDeclarationLine());
198
        $this
199
            ->defineModelAnnotationsFromWsdl($block)
200 148
            ->defineModelAnnotationsFromInheritance($block)
201
            ->definePackageAnnotations($block)
202 148
            ->defineGeneralAnnotations($block);
203
        return $block;
204
    }
205
    /**
206
     * @return string
207 132
     */
208
    protected function getClassDeclarationLine()
209 132
    {
210
        return sprintf($this->getClassDeclarationLineText(), $this->getModel()->getName(), $this->getModel()->getContextualPart());
211
    }
212
    /**
213
     * @return string
214
     */
215
    protected function getClassDeclarationLineText()
216 148
    {
217
        return 'This class stands for %s %s';
218 148
    }
219 148
    /**
220
     * @param PhpAnnotationBlock $block
221
     * @param AbstractModel $model
222
     * @return AbstractModelFile
223
     */
224
    protected function defineModelAnnotationsFromWsdl(PhpAnnotationBlock $block, AbstractModel $model = null)
225 148
    {
226
        FileUtils::defineModelAnnotationsFromWsdl($block, $model instanceof AbstractModel ? $model : $this->getModel());
227 148
        return $this;
228 148
    }
229
    /**
230
     * @param PhpAnnotationBlock $block
231
     * @return AbstractModelFile
232
     */
233
    protected function defineModelAnnotationsFromInheritance(PhpAnnotationBlock $block)
234 148
    {
235
        $struct = $this->getGenerator()->getStruct($this->getModel()->getInheritance());
236
        if ($struct instanceof StructModel && $struct->getIsStruct() === false) {
237
            $validMeta = $this->getValidMetaValues($struct);
238
            foreach ($validMeta as $meta) {
239
                $block->addChild($meta);
240
            }
241
        }
242
        return $this;
243
    }
244
    /**
245
     * @param AbstractModel $model
246
     * @return string[]
247 160
     */
248
    protected function getValidMetaValues(AbstractModel $model)
249 160
    {
250 120
        return FileUtils::getValidMetaValues($model);
251 160
    }
252 160
    /**
253 160
     * @return AbstractModelFile
254 160
     */
255 160
    protected function addClassElement()
256 160
    {
257 160
        $class = new PhpClass($this->getModel()->getPackagedName(), $this->getModel()->getIsAbstract(), $this->getModel()->getExtendsClassName() === '' ? null : $this->getModel()->getExtendsClassName());
258
        $this
259
            ->defineConstants($class)
260
            ->defineProperties($class)
261
            ->defineMethods($class)
262 160
            ->defineStringMethod($class)
263
            ->getFile()
264 160
                ->addClassComponent($class);
265 120
        return $this;
266 160
    }
267 160
    /**
268 120
     * @return AbstractModelFile
269 160
     */
270
    protected function defineNamespace()
271
    {
272
        if ($this->getModel()->getNamespace() !== '') {
273
            $this
274 160
                ->getFile()
275
                    ->setNamespace($this->getModel()->getNamespace());
276 160
        }
277 90
        return $this;
278 120
    }
279 120
    /**
280 90
     * @return AbstractModelFile
281 160
     */
282
    protected function defineUseStatement()
283
    {
284
        if ($this->getModel()->getExtends() !== '') {
285
            $this
286
                ->getFile()
287 160
                    ->addUse($this->getModel()->getExtends(), null, true);
288
        }
289 160
        return $this;
290 160
    }
291 160
    /**
292 48
     * @param PhpClass $class
293 48
     * @return AbstractModelFile
294 48
     */
295 36
    protected function defineConstants(PhpClass $class)
296 48
    {
297 120
        $constants = new Constant($this->getGenerator());
298 160
        $this->getClassConstants($constants);
299
        foreach ($constants as $constant) {
300
            $annotationBlock = $this->getConstantAnnotationBlock($constant);
301
            if (!empty($annotationBlock)) {
302
                $class->addAnnotationBlockElement($annotationBlock);
303
            }
304 160
            $class->addConstantElement($constant);
305
        }
306 160
        return $this;
307 160
    }
308 160
    /**
309 68
     * @param PhpClass $class
310 68
     * @return AbstractModelFile
311 68
     */
312 51
    protected function defineProperties(PhpClass $class)
313 68
    {
314 120
        $properties = new Property($this->getGenerator());
315 160
        $this->getClassProperties($properties);
316
        foreach ($properties as $property) {
317
            $annotationBlock = $this->getPropertyAnnotationBlock($property);
318
            if (!empty($annotationBlock)) {
319
                $class->addAnnotationBlockElement($annotationBlock);
320
            }
321 160
            $class->addPropertyElement($property);
322
        }
323 160
        return $this;
324 160
    }
325 160
    /**
326 160
     * @param PhpClass $class
327 160
     * @return AbstractModelFile
328 160
     */
329 120
    protected function defineMethods(PhpClass $class)
330 160
    {
331 120
        $methods = new Method($this->getGenerator());
332 160
        $this->getClassMethods($methods);
333
        foreach ($methods as $method) {
334
            $annotationBlock = $this->getMethodAnnotationBlock($method);
335
            if (!empty($annotationBlock)) {
336
                $class->addAnnotationBlockElement($annotationBlock);
337
            }
338
            $class->addMethodElement($method);
339
        }
340
        return $this;
341
    }
342
    /**
343
     * @param Constant $constants
344
     */
345
    abstract protected function getClassConstants(Constant $constants);
346
    /**
347
     * @param PhpConstant $constant
348
     * @return PhpAnnotationBlock|null
349
     */
350
    abstract protected function getConstantAnnotationBlock(PhpConstant $constant);
351
    /**
352
     * @param Property $properties
353
     */
354
    abstract protected function getClassProperties(Property $properties);
355
    /**
356
     * @param PhpProperty $property
357
     * @return PhpAnnotationBlock|null
358
     */
359
    abstract protected function getPropertyAnnotationBlock(PhpProperty $property);
360
    /**
361
     * @param Method $methods
362
     */
363
    abstract protected function getClassMethods(Method $methods);
364 148
    /**
365
     * @param PhpMethod $method
366 148
     * @return PhpAnnotationBlock|null
367 148
     */
368 148
    abstract protected function getMethodAnnotationBlock(PhpMethod $method);
369
    /**
370
     * @param PhpClass $class
371
     */
372
    protected function defineStringMethod(PhpClass $class)
373 148
    {
374
        $class->addAnnotationBlockElement($this->getToStringMethodAnnotationBlock());
375 148
        $class->addMethodElement($this->getToStringMethod());
376 148
        return $this;
377 148
    }
378 111
    /**
379
     * @return PhpAnnotationBlock
380
     */
381
    protected function getToStringMethodAnnotationBlock()
382
    {
383 148
        return new PhpAnnotationBlock(array(
384
            'Method returning the class name',
385 148
            new PhpAnnotation(self::ANNOTATION_RETURN, 'string __CLASS__'),
386 148
        ));
387 148
    }
388
    /**
389
     * @return PhpMethod
390
     */
391
    protected function getToStringMethod()
392
    {
393 68
        $method = new PhpMethod('__toString');
394
        $method->addChild('return __CLASS__;');
395 68
        return $method;
396 68
    }
397 28
    /**
398 21
     * @param StructAttributeModel $attribute
399 68
     * @return StructAttributeModel
400
     */
401
    protected function getStructAttribute(StructAttributeModel $attribute = null)
402
    {
403
        $struct = $this->getModel();
404
        if (empty($attribute) && $struct instanceof StructModel && $struct->getAttributes()->count() === 1) {
405 68
            $attribute = $struct->getAttributes()->offsetGet(0);
406
        }
407 68
        return $attribute;
408 68
    }
409 68
    /**
410 68
     * @param StructAttributeModel $attribute
411 51
     * @return StructModel|null
412 68
     */
413
    protected function getModelFromStructAttribute(StructAttributeModel $attribute = null)
414
    {
415
        $model = null;
416
        $attribute = $this->getStructAttribute($attribute);
417
        if ($attribute instanceof StructAttributeModel) {
418
            $model = $this->getGenerator()->getStruct($attribute->getType());
419
        }
420 68
        return $model;
421
    }
422 68
    /**
423 68
     * @param StructAttributeModel $attribute
424 68
     * @return StructModel|null
425 68
     */
426 68
    protected function getRestrictionFromStructAttribute(StructAttributeModel $attribute = null)
427 56
    {
428 56
        $model = $this->getModelFromStructAttribute($attribute);
429 20
        if ($model instanceof StructModel && !$model->getIsRestriction()) {
430 56
            $model = null;
431 36
        }
432 27
        return $model;
433 48
    }
434
    /**
435 42
     * @param StructAttributeModel $attribute
436 68
     * @param bool $namespaced
437 68
     * @return string
438 51
     */
439 68
    protected function getStructAttributeType(StructAttributeModel $attribute = null, $namespaced = false)
440
    {
441
        $attribute = $this->getStructAttribute($attribute);
442
        $inheritance = $attribute->getInheritance();
443
        $type = empty($inheritance) ? $attribute->getType() : $inheritance;
444
        $model = $this->getModelFromStructAttribute($attribute);
445
        if ($model instanceof StructModel) {
446
            $modelInheritance = $model->getInheritance();
447
            if ($model->getIsStruct() === false) {
448 48
                $type = !empty($modelInheritance) ? $modelInheritance : $type;
449
            } elseif ($model->getIsRestriction() === true) {
450 48
                $type = !empty($modelInheritance) ? $modelInheritance : self::TYPE_STRING;
451
            } else {
452
                $type = $model->getPackagedName($namespaced);
453
            }
454
        }
455
        return $type;
456
    }
457
    /**
458
     * @param StructAttributeModel $attribute
459
     * @param bool $returnArrayType
460
     * @return string
461
     */
462
    protected function getStructAttributeTypeGetAnnotation(StructAttributeModel $attribute = null, $returnArrayType = true)
463
    {
464
        $attribute = $this->getStructAttribute($attribute);
465
        return sprintf('%s%s%s', $this->getStructAttributeType($attribute, true), $this->useBrackets($attribute, $returnArrayType) ? '[]' : '', $attribute->isRequired() ? '' : '|null');
466
    }
467
    /**
468
     * @param StructAttributeModel $attribute
469
     * @param bool $returnArrayType
470
     * @return string
471
     */
472
    protected function getStructAttributeTypeSetAnnotation(StructAttributeModel $attribute = null, $returnArrayType = true)
473
    {
474
        $attribute = $this->getStructAttribute($attribute);
475
        return sprintf('%s%s', $this->getStructAttributeType($attribute, true), $this->useBrackets($attribute, $returnArrayType) ? '[]' : '');
476
    }
477
    /**
478
     * @param StructAttributeModel $attribute
479
     * @param string $returnArrayType
480
     * @return bool
481
     */
482
    protected function useBrackets(StructAttributeModel $attribute, $returnArrayType = true)
483
    {
484
        return $returnArrayType && $attribute->isArray();
485
    }
486
    /**
487
     * @param StructAttributeModel $attribute
488
     * @param bool $returnArrayType
489
     * @return string
490
     */
491
    protected function getStructAttributeTypeHint(StructAttributeModel $attribute = null, $returnArrayType = true)
492
    {
493
        $attribute = $this->getStructAttribute($attribute);
494
        return ($returnArrayType && $attribute->isArray()) ? self::TYPE_ARRAY : $this->getStructAttributeType($attribute, true);
495
    }
496
    /**
497
     * See http://php.net/manual/fr/language.oop5.typehinting.php for these cases
498
     * Also see http://www.w3schools.com/schema/schema_dtypes_numeric.asp
499
     * @param mixed $type
500
     * @param mixed $fallback
501
     * @return mixed
502
     */
503
    public static function getValidType($type, $fallback = null)
504
    {
505
        return XsdTypes::instance()->isXsd(str_replace('[]', '', $type)) ? $fallback : $type;
506
    }
507
    /**
508
     * See http://php.net/manual/fr/language.oop5.typehinting.php for these cases
509
     * Also see http://www.w3schools.com/schema/schema_dtypes_numeric.asp
510
     * @param mixed $type
511
     * @param mixed $fallback
512
     * @return mixed
513
     */
514
    public static function getPhpType($type, $fallback = self::TYPE_STRING)
515
    {
516
        return XsdTypes::instance()->isXsd(str_replace('[]', '', $type)) ? XsdTypes::instance()->phpType($type) : $fallback;
517
    }
518
}
519