Completed
Push — develop ( 63df75...505115 )
by Mikaël
657:18 queued 654:48
created

AbstractModelFile::getClassDeclarationLineText()   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\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 string 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 AbstractModel
77
     */
78
    protected $model;
79
    /**
80
     * @param bool $withSrc
81
     * @return string
82
     */
83 390
    public function getFileDestination($withSrc = true)
84
    {
85 390
        return sprintf('%s%s%s', $this->getDestinationFolder($withSrc), $this->getModel()->getSubDirectory(), $this->getModel()->getSubDirectory() !== '' ? '/' : '');
86
    }
87
    /**
88
     * @param bool $withSrc
89
     * @return string
90
     */
91 390
    public function getDestinationFolder($withSrc = true)
92
    {
93 390
        $src = rtrim($this->generator->getOptionSrcDirname(), DIRECTORY_SEPARATOR);
94 390
        return sprintf('%s%s', $this->getGenerator()->getOptionDestination(), (bool) $withSrc && !empty($src) ? $src . DIRECTORY_SEPARATOR : '');
95
    }
96
    /**
97
     * @see \WsdlToPhp\PackageGenerator\File\AbstractFile::writeFile()
98
     * @param bool $withSrc
99
     * @return int|bool
100
     */
101 360
    public function writeFile($withSrc = true)
102
    {
103 360
        if (!$this->getModel() instanceof AbstractModel) {
104 6
            throw new \InvalidArgumentException('You MUST define the model before begin able to generate the file', __LINE__);
105
        }
106 354
        GeneratorUtils::createDirectory($this->getFileDestination($withSrc));
107 354
        $this->defineNamespace()->defineUseStatement()->addAnnotationBlock()->addClassElement();
108 354
        return parent::writeFile();
109
    }
110
    /**
111
     * @return AbstractModelFile
112
     */
113 354
    protected function addAnnotationBlock()
114
    {
115 354
        $this->getFile()->addAnnotationBlockElement($this->getClassAnnotationBlock());
116 354
        return $this;
117
    }
118
    /**
119
     * @param AbstractModel $model
120
     * @return AbstractModelFile
121
     */
122 426
    public function setModel(AbstractModel $model)
123
    {
124 426
        $this->model = $model;
125 426
        $this->getFile()->getMainElement()->setName($model->getPackagedName());
126 426
        return $this;
127
    }
128
    /**
129
     * @return AbstractModel
130
     */
131 432
    public function getModel()
132
    {
133 432
        return $this->model;
134
    }
135
    /**
136
     * @param string $name
137
     * @return StructModel|null
138
     */
139 30
    protected function getModelByName($name)
140
    {
141 30
        return $this->getGenerator()->getStruct($name);
142
    }
143
    /**
144
     * @param PhpAnnotationBlock $block
145
     * @return AbstractModelFile
146
     */
147 324
    protected function definePackageAnnotations(PhpAnnotationBlock $block)
148
    {
149 324
        $packageName = $this->getPackageName();
150 324
        if (!empty($packageName)) {
151 270
            $block->addChild(new PhpAnnotation(self::ANNOTATION_PACKAGE, $packageName));
152 180
        }
153 324
        if (count($this->getModel()->getDocSubPackages()) > 0) {
154 324
            $block->addChild(new PhpAnnotation(self::ANNOTATION_SUB_PACKAGE, implode(',', $this->getModel()->getDocSubPackages())));
155 216
        }
156 324
        return $this;
157
    }
158
    /**
159
     * @return string
160
     */
161 324
    protected function getPackageName()
162
    {
163 324
        $packageName = '';
164 324
        if ($this->getGenerator()->getOptionPrefix() !== '') {
165 258
            $packageName = $this->getGenerator()->getOptionPrefix();
166 238
        } elseif ($this->getGenerator()->getOptionSuffix() !== '') {
167 12
            $packageName = $this->getGenerator()->getOptionSuffix();
168 8
        }
169 324
        return $packageName;
170
    }
171
    /**
172
     * @param PhpAnnotationBlock $block
173
     * @return AbstractModelFile
174
     */
175 324
    protected function defineGeneralAnnotations(PhpAnnotationBlock $block)
176
    {
177 324
        foreach ($this->getGenerator()->getOptionAddComments() as $tagName => $tagValue) {
178 288
            $block->addChild(new PhpAnnotation($tagName, $tagValue));
179 216
        }
180 324
        return $this;
181
    }
182
    /**
183
     * @return PhpAnnotationBlock
184
     */
185 324
    protected function getClassAnnotationBlock()
186
    {
187 324
        $block = new PhpAnnotationBlock();
188 324
        $block->addChild($this->getClassDeclarationLine());
189 324
        $this->defineModelAnnotationsFromWsdl($block)->definePackageAnnotations($block)->defineGeneralAnnotations($block);
190 324
        return $block;
191
    }
192
    /**
193
     * @return string
194
     */
195 324
    protected function getClassDeclarationLine()
196
    {
197 324
        return sprintf($this->getClassDeclarationLineText(), $this->getModel()->getName(), $this->getModel()->getContextualPart());
198
    }
199
    /**
200
     * @return string
201
     */
202 300
    protected function getClassDeclarationLineText()
203
    {
204 300
        return 'This class stands for %s %s';
205
    }
206
    /**
207
     * @param PhpAnnotationBlock $block
208
     * @param AbstractModel $model
209
     * @return AbstractModelFile
210
     */
211 324
    protected function defineModelAnnotationsFromWsdl(PhpAnnotationBlock $block, AbstractModel $model = null)
212
    {
213 324
        FileUtils::defineModelAnnotationsFromWsdl($block, $model instanceof AbstractModel ? $model : $this->getModel());
214 324
        return $this;
215
    }
216
    /**
217
     * @return AbstractModelFile
218
     */
219 354
    protected function addClassElement()
220
    {
221 354
        $class = new PhpClass($this->getModel()->getPackagedName(), $this->getModel()->isAbstract(), $this->getModel()->getExtendsClassName() === '' ? null : $this->getModel()->getExtendsClassName());
222 354
        $this->defineConstants($class)
223 354
            ->defineProperties($class)
224 354
            ->defineMethods($class)
225 354
            ->defineStringMethod($class)
226 354
            ->getFile()
227 354
            ->addClassComponent($class);
228 354
        return $this;
229
    }
230
    /**
231
     * @return AbstractModelFile
232
     */
233 354
    protected function defineNamespace()
234
    {
235 354
        if ($this->getModel()->getNamespace() !== '') {
236 342
            $this->getFile()->setNamespace($this->getModel()->getNamespace());
237 228
        }
238 354
        return $this;
239
    }
240
    /**
241
     * @return AbstractModelFile
242
     */
243 354
    protected function defineUseStatement()
244
    {
245 354
        if ($this->getModel()->getExtends() !== '') {
246 282
            $this->getFile()->addUse($this->getModel()->getExtends(), null, true);
247 188
        }
248 354
        return $this;
249
    }
250
    /**
251
     * @param PhpClass $class
252
     * @return AbstractModelFile
253
     */
254 354
    protected function defineConstants(PhpClass $class)
255
    {
256 354
        $constants = new Constant($this->getGenerator());
257 354
        $this->getClassConstants($constants);
258 354
        foreach ($constants as $constant) {
259 78
            $annotationBlock = $this->getConstantAnnotationBlock($constant);
260 78
            if (!empty($annotationBlock)) {
261 78
                $class->addAnnotationBlockElement($annotationBlock);
262 52
            }
263 78
            $class->addConstantElement($constant);
264 236
        }
265 354
        return $this;
266
    }
267
    /**
268
     * @param PhpClass $class
269
     * @return AbstractModelFile
270
     */
271 354
    protected function defineProperties(PhpClass $class)
272
    {
273 354
        $properties = new Property($this->getGenerator());
274 354
        $this->getClassProperties($properties);
275 354
        foreach ($properties as $property) {
276 186
            $annotationBlock = $this->getPropertyAnnotationBlock($property);
277 186
            if (!empty($annotationBlock)) {
278 186
                $class->addAnnotationBlockElement($annotationBlock);
279 124
            }
280 186
            $class->addPropertyElement($property);
281 236
        }
282 354
        return $this;
283
    }
284
    /**
285
     * @param PhpClass $class
286
     * @return AbstractModelFile
287
     */
288 354
    protected function defineMethods(PhpClass $class)
289
    {
290 354
        $methods = new Method($this->getGenerator());
291 354
        $this->getClassMethods($methods);
292 354
        foreach ($methods as $method) {
293 354
            $annotationBlock = $this->getMethodAnnotationBlock($method);
294 354
            if (!empty($annotationBlock)) {
295 354
                $class->addAnnotationBlockElement($annotationBlock);
296 236
            }
297 354
            $class->addMethodElement($method);
298 236
        }
299 354
        return $this;
300
    }
301
    /**
302
     * @param Constant $constants
303
     */
304
    abstract protected function getClassConstants(Constant $constants);
305
    /**
306
     * @param PhpConstant $constant
307
     * @return PhpAnnotationBlock|null
308
     */
309
    abstract protected function getConstantAnnotationBlock(PhpConstant $constant);
310
    /**
311
     * @param Property $properties
312
     */
313
    abstract protected function getClassProperties(Property $properties);
314
    /**
315
     * @param PhpProperty $property
316
     * @return PhpAnnotationBlock|null
317
     */
318
    abstract protected function getPropertyAnnotationBlock(PhpProperty $property);
319
    /**
320
     * @param Method $methods
321
     */
322
    abstract protected function getClassMethods(Method $methods);
323
    /**
324
     * @param PhpMethod $method
325
     * @return PhpAnnotationBlock|null
326
     */
327
    abstract protected function getMethodAnnotationBlock(PhpMethod $method);
328
    /**
329
     * @param PhpClass $class
330
     * @return AbstractModelFile
331
     */
332 324
    protected function defineStringMethod(PhpClass $class)
333
    {
334 324
        $class->addAnnotationBlockElement($this->getToStringMethodAnnotationBlock());
335 324
        $class->addMethodElement($this->getToStringMethod());
336 324
        return $this;
337
    }
338
    /**
339
     * @return PhpAnnotationBlock
340
     */
341 324
    protected function getToStringMethodAnnotationBlock()
342
    {
343 324
        return new PhpAnnotationBlock(array(
344 324
            'Method returning the class name',
345 324
            new PhpAnnotation(self::ANNOTATION_RETURN, 'string __CLASS__'),
346 216
        ));
347
    }
348
    /**
349
     * @return PhpMethod
350
     */
351 324
    protected function getToStringMethod()
352
    {
353 324
        $method = new PhpMethod('__toString');
354 324
        $method->addChild('return __CLASS__;');
355 324
        return $method;
356
    }
357
    /**
358
     * @param StructAttributeModel $attribute
359
     * @return StructAttributeModel
360
     */
361 186
    protected function getStructAttribute(StructAttributeModel $attribute = null)
362
    {
363 186
        $struct = $this->getModel();
364 186
        if (empty($attribute) && $struct instanceof StructModel && $struct->getAttributes()->count() === 1) {
365 48
            $attribute = $struct->getAttributes()->offsetGet(0);
366 32
        }
367 186
        return $attribute;
368
    }
369
    /**
370
     * @param StructAttributeModel $attribute
371
     * @return StructModel|null
372
     */
373 186
    public function getModelFromStructAttribute(StructAttributeModel $attribute = null)
374
    {
375 186
        $model = null;
376 186
        $attribute = $this->getStructAttribute($attribute);
377 186
        if ($attribute instanceof StructAttributeModel) {
378 186
            $model = $attribute->getTypeStruct();
379 124
        }
380 186
        return $model;
381
    }
382
    /**
383
     * @param StructAttributeModel $attribute
384
     * @return StructModel|null
385
     */
386 186
    public function getRestrictionFromStructAttribute(StructAttributeModel $attribute = null)
387
    {
388 186
        $model = $this->getModelFromStructAttribute($attribute);
389 186
        if ($model instanceof StructModel && !$model->isRestriction()) {
390 156
            $model = null;
391 104
        }
392 186
        return $model;
393
    }
394
    /**
395
     * @param StructAttributeModel $attribute
396
     * @param bool $namespaced
397
     * @return string
398
     */
399 186
    public function getStructAttributeType(StructAttributeModel $attribute = null, $namespaced = false)
400
    {
401 186
        $attribute = $this->getStructAttribute($attribute);
402 186
        $inheritance = $attribute->getInheritance();
403 186
        if (empty($inheritance)) {
404 186
            $type = $attribute->getType();
405 124
        } else {
406 12
            $type = $inheritance;
407
        }
408 186
        if (!empty($type) && ($struct = $this->getGenerator()->getStruct($type))) {
409 168
            $inheritance = $struct->getTopInheritance();
410 168
            if (!empty($inheritance)) {
411 84
                $type = str_replace('[]', '', $inheritance);
412 56
            }
413 112
        }
414 186
        $model = $this->getModelFromStructAttribute($attribute);
415 186
        if ($model instanceof StructModel) {
416
            // issue #84: union is considered as string as it would be difficult to have a method that accepts multiple object types.
417
            // If the property has to be an object of multiple types => new issue...
418 168
            if ($model->isRestriction() || $model->isUnion()) {
419 108
                $type = self::TYPE_STRING;
420 164
            } elseif ($model->isStruct()) {
421 138
                $type = $model->getPackagedName($namespaced);
422 126
            } elseif ($model->isArray() && ($inheritanceStruct = $model->getInheritanceStruct()) instanceof StructModel) {
423 18
                $type = $inheritanceStruct->getPackagedName($namespaced);
424 12
            }
425 112
        }
426 186
        return $type;
427
    }
428
    /**
429
     * @param StructAttributeModel $attribute
430
     * @param bool $returnArrayType
431
     * @return string
432
     */
433 186
    protected function getStructAttributeTypeGetAnnotation(StructAttributeModel $attribute = null, $returnArrayType = true)
434
    {
435 186
        $attribute = $this->getStructAttribute($attribute);
436 186
        return sprintf('%s%s%s', $this->getStructAttributeTypeAsPhpType($attribute), $this->useBrackets($attribute, $returnArrayType) ? '[]' : '', $attribute->isRequired() ? '' : '|null');
437
    }
438
    /**
439
     * @param StructAttributeModel $attribute
440
     * @param bool $returnArrayType
441
     * @return string
442
     */
443 186
    protected function getStructAttributeTypeSetAnnotation(StructAttributeModel $attribute = null, $returnArrayType = true)
444
    {
445 186
        $attribute = $this->getStructAttribute($attribute);
446 186
        return sprintf('%s%s', $this->getStructAttributeTypeAsPhpType($attribute), $this->useBrackets($attribute, $returnArrayType) ? '[]' : '');
447
    }
448
    /**
449
     * @param StructAttributeModel $attribute
450
     * @param bool $returnArrayType
451
     * @return bool
452
     */
453 186
    protected function useBrackets(StructAttributeModel $attribute, $returnArrayType = true)
454
    {
455 186
        return $returnArrayType && $attribute->isArray();
456
    }
457
    /**
458
     * @param StructAttributeModel $attribute
459
     * @param bool $returnArrayType
460
     * @return string
461
     */
462 186
    protected function getStructAttributeTypeHint(StructAttributeModel $attribute = null, $returnArrayType = true)
463
    {
464 186
        $attribute = $this->getStructAttribute($attribute);
465 186
        return ($returnArrayType && $attribute->isArray()) ? self::TYPE_ARRAY : $this->getStructAttributeType($attribute, true);
466
    }
467
    /**
468
     * @param StructAttributeModel $attribute
469
     * @return string
470
     */
471 186
    public function getStructAttributeTypeAsPhpType(StructAttributeModel $attribute = null)
472
    {
473 186
        $attribute = $this->getStructAttribute($attribute);
474 186
        $attributeType = $this->getStructAttributeType($attribute, true);
475 186
        if (XsdTypes::instance()->isXsd($attributeType)) {
476 162
            $attributeType = self::getPhpType($attributeType);
477 108
        }
478 186
        return $attributeType;
479
    }
480
    /**
481
     * See http://php.net/manual/fr/language.oop5.typehinting.php for these cases
482
     * Also see http://www.w3schools.com/schema/schema_dtypes_numeric.asp
483
     * @param mixed $type
484
     * @param mixed $fallback
485
     * @return mixed
486
     */
487 216
    public static function getValidType($type, $fallback = null)
488
    {
489 216
        return XsdTypes::instance()->isXsd(str_replace('[]', '', $type)) ? $fallback : $type;
490
    }
491
    /**
492
     * See http://php.net/manual/fr/language.oop5.typehinting.php for these cases
493
     * Also see http://www.w3schools.com/schema/schema_dtypes_numeric.asp
494
     * @param mixed $type
495
     * @param mixed $fallback
496
     * @return mixed
497
     */
498 162
    public static function getPhpType($type, $fallback = self::TYPE_STRING)
499
    {
500 162
        return XsdTypes::instance()->isXsd(str_replace('[]', '', $type)) ? XsdTypes::instance()->phpType($type) : $fallback;
501
    }
502
}
503